297 Commits

Author SHA1 Message Date
TotMaxim
56e6aa4bb0 Merge remote-tracking branch 'origin/master'
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 19:43:26 +03:00
TotMaxim
2e6be9b4f1 Исправление качки
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 19:39:12 +03:00
MaD_CaT
a311e3201b Доработка. Доработка__Получить_угол_места_для_помехи_из_параметров_цели 2026-04-09 19:39:12 +03:00
TotMaxim
5032115b5d Добавлен результат проверки РТР в панель исправности комплекса
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 18:28:23 +03:00
TotMaxim
caebd4f05b Добавлены логи ошибок в журнал
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 15:49:06 +03:00
TotMaxim
b4e81218ab Доработка провекри сокетов в контроле 2026-04-09 15:39:39 +03:00
TotMaxim
1633a45c9b Доработка статуса контроля РТР
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 14:24:05 +03:00
TotMaxim
65a0164ec0 Доработка контроля РТР БПО 2026-04-09 13:14:07 +03:00
TotMaxim
0c30572f1e Доработка АФСП провекри 2026-04-09 11:25:18 +03:00
TotMaxim
08597ff7ce Merge remote-tracking branch 'origin/master' 2026-04-09 09:59:08 +03:00
TotMaxim
8abdc957ed Merge remote-tracking branch 'origin/master'
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 09:58:04 +03:00
TotMaxim
85b2f4eadd Доработка адресов ЭМС ТГ и флага изменнена пользователем частоты 2026-04-09 09:55:57 +03:00
TotMaxim
6294730bf8 Корректировка. Сообщения для отладки
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-05 17:25:10 +03:00
TotMaxim
f407578a44 Добавление анимации для прогресс баров в АФСП 2026-04-05 16:36:43 +03:00
TotMaxim
ec21282ba0 Обновление индикатора онлайн в контроле
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-05 16:29:57 +03:00
TotMaxim
38529ac0cc Обновление контроля АФСП
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-05 15:52:50 +03:00
TotMaxim
6db678b163 Смена литер фс в ПРД-К
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-05 10:05:16 +03:00
TotMaxim
124b75dbde Обновленный конфиг для SkySensor
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-05 09:37:05 +03:00
MaD_CaT
803d2eff4f Доработка ЭМС-ТГ, команда 9 для КАПС РПБ 2026-04-04 10:47:13 +03:00
sasha80
29e5382c1e Исправление. WIP Режим ЭМС-ТГ. Шкала не обновляется при запуске
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-02 11:56:20 +03:00
sasha80
96436596d8 Рефактор. Режим ЭМС-ТГ 2026-04-02 10:58:13 +03:00
sasha80
b3455947fd Исправление. Режим ЭМС-ТГ. Неверно вычисляется ширина диапазона 2026-04-02 10:57:43 +03:00
sasha80
57fc201212 Доработка. Режим ЭМС-ТГ. Отображение состояния входов ЭМС 2026-04-02 10:54:51 +03:00
sasha80
2abe5741eb Доработка. Режим ЭМС-ТГ. Добавлен сигнал для изменения состояния входов ЭМС 2026-03-31 16:16:06 +03:00
sasha80
ef063645ee Исправление. Лишний цикл итераций 2026-03-31 15:20:24 +03:00
sasha80
4d0ea0f84e Рефактор 2026-03-31 15:19:07 +03:00
sasha80
d7cba379cc Доработка. Режим ЭМС-ТГ. Добавлен фон 2026-03-31 14:49:42 +03:00
sasha80
f41e59b119 Рефакторинг 2026-03-31 12:41:04 +03:00
sasha80
b919e6498f Merge branch 'эмс-тг' 2026-03-31 12:10:02 +03:00
sasha80
8039e6bcb4 Исправление. Обращение за пределы массива 2026-03-31 12:08:46 +03:00
sasha80
4a928abc37 Рефактор 2026-03-31 11:54:28 +03:00
sasha80
6c46acc6b6 Доработка. Отображение подсказок для оператора 2026-03-31 11:54:13 +03:00
sasha80
94084fead0 Доработка. Обновление таблицы при отключении устройства 2026-03-31 11:53:06 +03:00
sasha80
e4dfdeb899 Доработка. Добавлены надписи в режиме ЭМС-ТГ 2026-03-31 11:31:13 +03:00
sasha80
f41c0ee75c Рефактор. 2026-03-31 11:30:41 +03:00
sasha80
9fd258a745 Исправление. Обновление индикаторов результаты выполнения команды оператора 2026-03-31 10:20:15 +03:00
sasha80
49d7b71072 Исправление. WIP индикатор исполнения не переходит в состояние "Ожидание" 2026-03-30 12:53:48 +03:00
sasha80
ba4d2458af Доработка. Режим ЭМС-ТГ. Отображение состояния кластера Активен/Удалён в таблице 2026-03-30 12:52:39 +03:00
sasha80
407f9956fa Рефактор. 2026-03-30 12:50:57 +03:00
sasha80
33a5dea6a0 Доработка. Режим ЭМС-ТГ. Убраны лишнее элементы 2026-03-30 11:18:31 +03:00
sasha80
446f8b6afc Доработка. Совместимость 2026-03-30 11:17:53 +03:00
sasha80
d00fb92520 Доработка. Рефактор 2026-03-30 11:17:17 +03:00
sasha80
21a0c0c012 Доработка. WIP Формирование команд оператором 2026-03-27 12:10:47 +03:00
sasha80
6f7bf0a5be Доработка. Чистка 2026-03-26 16:16:22 +03:00
sasha80
193f0ab498 Доработка. WIP Отображение конфликтов на матрице 2026-03-26 16:15:58 +03:00
sasha80
5c6b6e80c9 Merge remote-tracking branch 'vika/эмс-тг' into эмс-тг 2026-03-26 15:38:45 +03:00
sasha80
a2d56a7553 Доработка. WIP Отображение разрешённых/запрещённых диапазонов разным цветом 2026-03-26 15:30:37 +03:00
sasha80
3eef38f56a Доработка. WIP Объединить имеющиеся доклады об кластерах с вновь поступившими от устройств 2026-03-26 15:17:04 +03:00
Vika
159956e02f Merge branch 'эмс-тг' of http://gitea.srez.local:3000/sasha80/uarep-ctl into эмс-тг 2026-03-26 15:04:40 +03:00
Vika
fb7853a5be Доработка. Функция поиска пересечений частот для ЭМС. 2026-03-26 14:57:53 +03:00
sasha80
cd34aa9100 Доработка. WIP Сброс матрицы 2026-03-26 11:55:59 +03:00
sasha80
4079d55aa5 Доработка. WIP Отображение разрешённых/запрещённых диапазонов разным цветом 2026-03-26 11:55:23 +03:00
sasha80
7b80852017 Доработка. WIP Управление оператором. Отправка команд 2026-03-26 10:35:27 +03:00
sasha80
68ab1b325d Доработка. WIP Отработка истекания времени кластера 2026-03-23 16:31:41 +03:00
sasha80
1cb3985c70 Доработка. WIP Отображение конфликтов на матрице 2026-03-23 14:33:49 +03:00
sasha80
cf3b02cec2 Доработка. WIP Отображение конфликтов на матрице 2026-03-23 14:21:08 +03:00
sasha80
c5da181fb7 Доработка. WIP Отображение конфликтов на матрице 2026-03-23 14:20:06 +03:00
sasha80
528566e949 Доработка. WIP Отображение кластеров на шкале. Рефактор 2026-03-23 08:24:09 +03:00
sasha80
212ce180d1 Доработка. WIP Отображение кластеров на шкале 2026-03-20 16:36:17 +03:00
sasha80
261a994466 Доработка. WIP Отображение кластеров на шкале 2026-03-20 16:35:17 +03:00
sasha80
07b41211c7 Доработка. WIP Отображение кластеров на шкале 2026-03-20 16:22:15 +03:00
sasha80
0fc98c5e98 Доработка. WIP Отображение кластеров на шкале 2026-03-20 14:58:41 +03:00
sasha80
59da91d98c Доработка. WIP Шкала кластера. Убрано не нужное 2026-03-20 14:57:15 +03:00
sasha80
959ef1192c Доработка. WIP Шкала кластер 2026-03-20 11:15:51 +03:00
Maxim
0b2c101a4b Merge remote-tracking branch 'sasha80/master' into workflows 2026-03-20 11:07:41 +03:00
sasha80
731ce8b3dd Доработка. WIP Добавлено место на шкале для иконки 2026-03-20 10:36:47 +03:00
sasha80
86716437cf Доработка. WIP Отображение кластера в таблице 2026-03-19 16:40:32 +03:00
sasha80
901d160c50 Доработка. WIP Отображение кластера в таблице 2026-03-19 16:39:15 +03:00
sasha80
26bb36a333 Доработка. WIP Отображение кластера в таблице 2026-03-19 16:33:29 +03:00
sasha80
8c4a966654 Доработка. WIP Приём данных из сети 2026-03-19 13:03:32 +03:00
sasha80
aea48c7d9e Доработка. WIP Добавление элементов для ЭМС-ТГ 2026-03-19 10:31:23 +03:00
sasha80
dac7987585 Доработка. WIP Добавление элементов для ЭМС-ТГ 2026-03-19 09:18:32 +03:00
sasha80
190f06b72c Доработка. WIP Добавление элементов для ЭМС-ТГ 2026-03-18 09:40:24 +03:00
sasha80
c5bae21436 Доработка. WIP Добавление элементов для ЭМС-ТГ 2026-03-17 12:44:27 +03:00
sasha80
e48e8767e5 Доработка. WIP Добавление элементов для ЭМС-ТГ 2026-03-17 09:08:21 +03:00
sasha80
97bbd85622 Доработка. Добавлено важное уточнение 2026-03-16 16:25:39 +03:00
sasha80
de92de2994 Доработка. Добавлено важное уточнение 2026-03-16 16:24:07 +03:00
sasha80
df80508592 Исправление. Лишнее действие 2026-03-16 15:42:31 +03:00
sasha80
282a3a5218 Доработка. WIP Добавление элементов для ЭМС-ТГ 2026-03-16 15:41:39 +03:00
sasha80
e52f465654 Исправление. Лишнее действие 2026-03-16 15:40:56 +03:00
Maxim
8dac0449a3 Merge remote-tracking branch 'sasha80/HEAD' into workflows 2026-03-12 08:21:10 +03:00
sasha80
4d1dc7a9c2 Исправление. Может вызвать обращение к несуществующему элементу 2026-03-11 14:49:49 +03:00
sasha80
b27afc854e Доработка. WIP Добавление элементов для ЭМС-ТГ 2026-03-11 14:43:19 +03:00
sasha80
eabc48b95f Доработка. Добавление элементов для ЭМС-ТГ 2026-03-11 14:09:33 +03:00
sasha80
f3be1e39db Доработка. Отобразит размер данных от url, если ошибка возникла 2026-03-11 14:08:56 +03:00
sasha80
2f9ad52a9c Рефактор. Уменьшить количество файлов 2026-03-11 14:07:39 +03:00
sasha80
398ff23291 Исправление. Может вызвать обращение к несуществующему элементу 2026-03-11 08:22:30 +03:00
sasha80
d14d1724af Доработка. Добавлен индикатор диапазонов 2026-03-10 12:56:15 +03:00
sasha80
720cba0ae5 Чистка. 2026-03-10 12:55:19 +03:00
sasha80
609e051e2a Merge remote-tracking branch 'MaD_CaT/master' 2026-03-05 15:45:00 +03:00
sasha80
bd43a6bae1 Чистка. 2026-03-05 11:13:07 +03:00
Maxim
570966c862 Merge remote-tracking branch 'MaD_CaT/master' into workflows 2026-02-27 16:03:35 +03:00
MaD_CaT
3b3f9f7582 Доработка. Применяется рекомендуемый период ЛЧМ для цели. 2026-02-27 15:58:28 +03:00
MaD_CaT
8f2b5aa05b Исправления. Максимальный угол места увеличен с 55.00 до 100.0 2026-02-27 15:57:04 +03:00
Maxim
ed32292bc4 Merge remote-tracking branch 'sasha80/master' into workflows 2026-02-27 13:55:11 +03:00
sasha80
d97f9191a3 Merge remote-tracking branch 'MaD_CaT/master' 2026-02-20 12:54:14 +03:00
MaD_CaT
dd7659b113 Исправления. Убрано лишнее очищение словаря взаимодействия цели и помехи. 2026-02-20 12:39:58 +03:00
sasha80
0d0c52856d Merge remote-tracking branch 'MaD_CaT/master'
# Conflicts:
#	scripts/prd-ctl-config.gd
2026-02-20 12:31:50 +03:00
Maxim
1c8e2aa1d4 Merge remote-tracking branch 'MaD_CaT/master' into workflows 2026-02-17 14:27:12 +03:00
MaD_CaT
7bfa6413ba Доработка. Отключение сигналов для таблицы помех в режимах отличных от режима Работа. 2026-02-17 14:23:01 +03:00
Maxim
645df6d0b7 Изменено имя сигнала на send_http_request 2026-02-16 13:59:50 +03:00
Maxim
5988330ddb Merge remote-tracking branch 'MaD_CaT/master' into workflows 2026-02-11 09:41:10 +03:00
MaD_CaT
1a08b5ae50 Исправления. Состояние линии связи с приборами для передачи в 5П-28. 2026-02-10 11:12:54 +03:00
Maxim
3e0f667fc5 Отладка индикации цвета надписи в режиме контроль 2026-02-06 10:58:57 +03:00
Maxim
1f6b5d8f21 Merge remote-tracking branch 'MaD_CaT/master' into workflows
# Conflicts:
#	scripts/prd-ctl-config.gd
2026-02-06 08:45:09 +03:00
MaD_CaT
996aee4a17 Исправление. Ошибка в работе, когда не найдена нода цели. 2026-02-05 16:03:38 +03:00
Maxim
984b1af114 Отладка отслеживания изменения состояния яу07 2026-02-02 11:53:22 +03:00
Maxim
42ed766c58 Merge remote-tracking branch 'sasha80/master' into workflows
# Conflicts:
#	scripts/prd-ctl-config.gd
2026-02-02 10:25:45 +03:00
MaD_CaT
8f4134a911 Доработка. Обмен с 5П-28 вынесен в отдельный поток. 2026-01-30 11:11:17 +03:00
sasha80
15245b4586 Исправление. Возможно обращение к несуществующему элементу 2026-01-30 10:59:21 +03:00
sasha80
5e9ef98301 Доработка. Теперь пути загрузки сцен управляются редактором 2026-01-30 09:50:53 +03:00
Maxim
9353da816d Тест акт ранера 2026-01-29 15:24:09 +03:00
sasha80
416e93c4e4 Доработка. Теперь пути загрузки сцен управляются редактором 2026-01-28 13:56:23 +03:00
sasha80
23acb2703e Доработка. Теперь пути загрузки сцен управляются редактором 2026-01-28 12:03:43 +03:00
sasha80
3c0fa8be82 Доработка. Теперь цветовая схема инициализируется при создании элемента 2026-01-28 10:16:19 +03:00
sasha80
ef5cffe093 Регрессия. Производительность. Обращение к полю Control.bg_color занимает очень много времени 2026-01-27 16:42:18 +03:00
sasha80
aae9bc6795 Чистка. 2026-01-27 16:40:14 +03:00
sasha80
6bcaf2561c Чистка. 2026-01-26 16:01:19 +03:00
sasha80
ea4e464e9d Чистка. 2026-01-26 15:39:04 +03:00
sasha80
043646a4a8 Исправление. E 0:00:05:248 settings-toggle.gd:11 @ _exit_tree(): Attempt to disconnect a nonexistent connection from '<ProjectSettings#486539292>'. Signal: 'settings_changed', callable: 'LineEdit(settings-toggle.gd)::apply_colors'.
<Ошибка C++>  Condition "!s->slot_map.has(*p_callable.get_base_comparator())" is true. Returning: false
  <Исходный код C++>core/object/object.cpp:1529 @ _disconnect()
  <Трассировка стека>settings-toggle.gd:11 @ _exit_tree()
2026-01-26 15:38:28 +03:00
sasha80
b91d2c6afe Merge remote-tracking branch 'lepshiy/master' 2026-01-26 15:31:22 +03:00
sasha80
1bac9dc496 Рефактор. 2026-01-26 15:10:06 +03:00
sasha80
484ca3f320 WIP Исправление. Производительность 2026-01-26 15:09:52 +03:00
sasha80
36999bf3c1 Чистка. 2026-01-26 14:09:48 +03:00
sasha80
54eb0df9cc Регрессия. Неверное название 2026-01-26 12:37:25 +03:00
Maxim
8a8f9d7649 Merge remote-tracking branch 'sasha80/master' 2026-01-26 08:56:15 +03:00
sasha80
c7fd49eead Регрессия. Лишние запросы плиток на сервер карт 2026-01-23 16:09:55 +03:00
Maxim
61bf491425 Merge remote-tracking branch 'sasha80/master' 2026-01-23 15:01:40 +03:00
Maxim
27adb42238 Merge remote-tracking branch 'sasha80/master'
# Conflicts:
#	scenes/контроль/control-prd.gd
2026-01-23 15:00:33 +03:00
sasha80
abfb98db46 Рефактор. Неуместные двойные кавычки 2026-01-23 14:33:56 +03:00
MaD_CaT
6950b09879 Доработка. Упрощение счётчика опасных целей при работе по своим. 2026-01-23 11:23:36 +03:00
sasha80
4ad5652737 Доработка. Задать максимальный уровень карт на сервере 2026-01-23 11:09:29 +03:00
sasha80
f01b5316a7 Рефактор. Неуместные двойные кавычки 2026-01-23 11:08:42 +03:00
Maxim Astra
7320dd47f2 Регрессия. Переименованы файлы с конфигурациями СТЦ 2026-01-22 15:54:16 +03:00
sasha80
d0d9e2630d Рефактор. 2026-01-22 15:45:03 +03:00
sasha80
f769d761db Рефактор. 2026-01-22 15:16:00 +03:00
sasha80
baff756648 Рефактор. 2026-01-22 14:55:00 +03:00
sasha80
42ca66d61d Доработка. Добавлена информация о версии в журнал проверки 2026-01-22 13:28:48 +03:00
sasha80
abcb5ec40c Исправление. 2026-01-22 13:14:39 +03:00
sasha80
3e7c579a3d Рефактор. 2026-01-22 13:13:05 +03:00
lepshiy
9eb9873c64 Доработка. Светлая тема, перекрас элементов в table.gd. 2026-01-22 10:57:06 +03:00
sasha80
7373685e2a Доработка. Встраивание статической проверки использования кавычек 2026-01-21 16:19:12 +03:00
sasha80
aedc9c3741 Merge remote-tracking branch 'lepshiy/master' 2026-01-21 10:06:09 +03:00
Maxim
ab24add92b Замена кавычек 2026-01-21 09:52:51 +03:00
Maxim
26fbee31c6 Merge remote-tracking branch 'Kira/master' into master-afsp 2026-01-21 09:45:22 +03:00
Maxim
2bf5ead89a Артефакт слияния 2026-01-21 09:43:10 +03:00
Maxim
fa8b4146f0 Merge remote-tracking branch 'origin/master' into master-afsp
# Conflicts:
#	scenes/tabs-switch/tab-switch.tscn
#	scenes/контроль/контроль.tscn
2026-01-21 09:40:56 +03:00
lepshiy
486a2fb8b5 Рефактор. Кавычки 2026-01-21 09:40:43 +03:00
sasha80
dd6393753c Доработка. Добавлен скрипт для проверки неуместного использования двойных кавычек 2026-01-21 09:34:16 +03:00
MaD_CaT
2f37068c61 Merge remote-tracking branch 'sasha/master' 2026-01-20 11:43:22 +03:00
sasha80
6796d17b30 Merge remote-tracking branch 'lepshiy/master'
# Conflicts:
#	scenes/работа/работа.gd
2026-01-20 11:25:41 +03:00
lepshiy
9a5c0122ad Доработка, светлая тема. Решено с нагрузкой 2026-01-20 11:24:00 +03:00
MaD_CaT
98c29329d0 Исправления. Удалён лишний принт. 2026-01-20 10:13:28 +03:00
MaD_CaT
28ab8f05c1 Merge remote-tracking branch 'sasha/master' 2026-01-20 10:11:13 +03:00
MaD_CaT
bbfae5e341 Godot4. Изменение размера отступов. 2026-01-20 10:10:47 +03:00
sasha80
af4d96ed60 Рефактор. 2026-01-20 09:29:45 +03:00
lepshiy
81ae47a3d9 Доработка, светлая тема. 2026-01-19 16:17:40 +03:00
lepshiy
6d46fb5b4c Автоматическое сохранение настроек, убраны излишние обводки при фокусе. 2026-01-19 15:44:40 +03:00
sasha80
f87cb28e9b Регрессия. Артефакты слияния 2026-01-19 13:05:14 +03:00
sasha80
a074ab1b1e Merge remote-tracking branch 'origin/master' 2026-01-19 13:04:33 +03:00
sasha80
5407cb0570 Регрессия. Артефакты слияния 2026-01-19 10:54:37 +03:00
sasha80
8baf727e3f Merge remote-tracking branch 'MaD_CaT/master'
# Conflicts:
#	scenes/работа/работа.gd
2026-01-19 10:51:18 +03:00
sasha80
e2b0f09fb9 Merge branch 'master-lepshiy'
# Conflicts:
#	scenes/настройки/настройки.gd
2026-01-19 10:48:33 +03:00
sasha80
aee7e2d5d3 Рефактор. Большое переименование 2026-01-19 10:41:54 +03:00
sasha80
216c5f1960 Рефактор. Большое переименование 2026-01-19 10:41:19 +03:00
Maxim
6bbd8333f9 Добавлен сигнал завершения прогресс бара при ответе от АФСП 2026-01-16 16:33:35 +03:00
MaD_CaT
e372322806 Доработка. На секторах диапазонов шум при обратном контроле от усилителей мощности. 2026-01-16 15:08:55 +03:00
MaD_CaT
309d23ea2c Доработка. Добавление в таблицу помех контроля выходной мощности с усилителей. 2026-01-16 15:08:21 +03:00
MaD_CaT
fa8d677d37 Доработка. Изменение значка и размера изучения в таблице целей. 2026-01-16 15:06:19 +03:00
MaD_CaT
3b1d11af88 Доработка. Изменение цвета индикаторов излучения через настройку "Цвет кнопки подавления" 2026-01-16 15:05:56 +03:00
lepshiy
8fccaa0e66 Динамическое изменение цвета программы тёмное/светлое. 2026-01-16 11:49:47 +03:00
Maxim
0c85a85d7c Анимация прогресса для БПО 2026-01-16 11:13:22 +03:00
Tot Maxim
f4f290849c Анимация прогресса для афсп 2026-01-16 09:50:42 +03:00
Maxim
2ffb35dd47 Добавление в сцену tab-switch uid="uid://b5ykwyk5vpi6" 2026-01-15 16:01:11 +03:00
Maxim
83549ec2a3 Merge remote-tracking branch 'origin/master' into master-afsp
# Conflicts:
#	scenes/tabs-switch/lbl-ready.gd
#	scripts/pribor-prd.gd
2026-01-15 15:55:23 +03:00
Maxim
d198989ad2 Добавление прогресс бара для афсп левого и для афсп правого при контроле 2026-01-15 15:51:28 +03:00
sasha80
d2f4c8017c Рефактор. 2026-01-15 13:01:59 +03:00
sasha80
e261ada3cd Рефактор. 2026-01-15 12:59:39 +03:00
sasha80
98d0ed1457 Merge remote-tracking branch 'MaD_CaT/master' 2026-01-15 09:56:48 +03:00
sasha80
a06df2b832 Рефактор. 2026-01-15 09:55:39 +03:00
sasha80
2919b0174f Рефактор. 2026-01-14 14:00:35 +03:00
Maxim
7788a664b5 Отладка интегрального контроля 2026-01-13 13:37:40 +03:00
MaD_CaT
f4a6a4d465 Исправление. Убран warning при распаковки состояния БПО от КАПС РПБ. 2026-01-12 15:56:35 +03:00
sasha80
1a72187683 Рефактор. 2025-12-30 13:34:05 +03:00
MaD_CaT
ace3d2abbf Регрессия. Время повторной отправки помехи 2025-12-30 13:31:51 +03:00
MaD_CaT
0ab38309db Merge remote-tracking branch 'sasha/master' 2025-12-30 13:12:04 +03:00
sasha80
cf89c1b1c9 Рефактор. Символ табуляции 2025-12-30 11:56:43 +03:00
sasha80
55cfd32f66 Доработка. Улучшена работа строба 2025-12-30 11:55:58 +03:00
sasha80
5e10632fb6 Регрессия. Ширина штриховки 2025-12-30 11:53:38 +03:00
sasha80
44275fe92d Доработка. Устраненение пикселизации для сетки диаграммы, внешней и внутренней границы 2025-12-30 11:53:17 +03:00
sasha80
1e0d10761a Регрессия. Строб смещён относительно центра 2025-12-29 12:41:07 +03:00
sasha80
97b608a306 Доработка. Добавлено случайной значение из ЦПУ 2025-12-29 10:57:23 +03:00
sasha80
83aa1e3ac0 Регрессия. Границы секторов без пикселизации 2025-12-29 10:56:40 +03:00
sasha80
c244fc70ec Доработка. Цвет секторов по умолчанию 2025-12-29 10:55:30 +03:00
sasha80
dac0c55204 Регрессия. Наклон штриховки для индикации режима сектора (модуля фс) 2025-12-29 09:02:05 +03:00
sasha80
0f15c2f62c Исправление. Очень важное замечание 2025-12-26 13:01:05 +03:00
sasha80
bbe15797ba Регрессия. Неверный размер курсора таблицы 2025-12-26 11:58:33 +03:00
sasha80
72975500c7 Доработка. Добавлено случайное значение для шейдеров 2025-12-26 11:58:33 +03:00
sasha80
906f01fd7a Доработка. Добавлены флаги для отображения режима антенны (модуля ФС) 2025-12-26 11:58:33 +03:00
sasha80
f37578d0bc Исправление. Не тот тип 2025-12-26 11:58:33 +03:00
sasha80
3dc406431b Рефактор. 2025-12-26 11:58:33 +03:00
MaD_CaT
3d9ed1a149 Доработка. Добавлено сообщение с типом 9 для КАПС РПБ с режимом работы комплекса. 2025-12-25 16:03:36 +03:00
c160d84ae6 Merge pull request 'Добавление файлов конфигурации для SkySensor и MP550Service' (#50) from master-prd into master
Reviewed-on: http://169.254.27.70:3000/sasha80/uarep-ctl/pulls/50
2025-12-25 11:00:56 +03:00
Maxim
964d41b822 Добавление файлов конфигурации для SkySensor и MP550Service 2025-12-25 10:57:16 +03:00
sasha80
af90c48694 Merge remote-tracking branch 'MaD_CaT/master'
# Conflicts:
#	scenes/настройки/настройки.gd
2025-12-24 16:14:06 +03:00
sasha80
8a06ab5fc9 Регрессия. Две одинаковые строки 2025-12-24 16:03:08 +03:00
MaD_CaT
d65dc6d0dc Доработка. Начало формирования сообщения для КАПС РПБ №9 в threats.gd 2025-12-24 15:59:27 +03:00
MaD_CaT
57f9494ad4 Регрессия. Остправление пропадания настройки времени отправки помехи. 2025-12-24 15:58:50 +03:00
sasha80
449b3d6e8c Регрессия. Управление стробом работает неверно 2025-12-24 15:26:17 +03:00
MaD_CaT
e7a240bc8a Merge remote-tracking branch 'sasha/master' 2025-12-24 14:53:34 +03:00
MaD_CaT
a2255610b5 Доработка. Помехе ЕЛРС присвоено правильное имя в таблице помех. 2025-12-24 14:30:31 +03:00
sasha80
57e7e0cc0b Рефактор. 2025-12-24 13:41:47 +03:00
sasha80
76a079dd23 Регрессия. Цели отображаются на не правильной частоте 2025-12-24 13:41:27 +03:00
sasha80
fa84118149 Исправление. E 0:00:03:969 эмс-тг.gd:13 @ on_trassa_line_changed(): Node not found: "СкруглённыйПрямоугольникБелый/Label3" (relative to "/root/panel/tab_switch/ЭМС ТГ").
<Ошибка C++>  Method/function failed. Returning: nullptr
  <Исходный код C++>scene/main/node.cpp:1877 @ get_node()
  <Трассировка стека>эмс-тг.gd:13 @ on_trassa_line_changed()
                trassa.gd:57 @ parse()
                network.gd:338 @ poll_receive_udp()
                network.gd:429 @ _process()
2025-12-24 13:40:18 +03:00
sasha80
ff85c6f80a Исправление. E 0:00:02:004 настройки.gd:260 @ button_settings(): In Object of type 'LineEdit': Attempt to connect nonexistent signal 'popup_closed' to callable 'Panel(configure)::on_color_closed_w'.
<Ошибка C++>  Condition "!signal_is_valid" is true. Returning: ERR_INVALID_PARAMETER
  <Исходный код C++>core/object/object.cpp:1439 @ connect()
  <Трассировка стека>настройки.gd:260 @ button_settings()
                настройки.gd:231 @ setting_tab()
                настройки.gd:96 @ _ready()
2025-12-24 12:59:10 +03:00
sasha80
a680537a1b Merge remote-tracking branch 'lepshiy/master'
# Conflicts:
#	scenes/настройки/настройки.gd
2025-12-24 11:53:25 +03:00
sasha80
63d6643475 Регрессия. Вид диаграммы 2025-12-24 11:49:59 +03:00
sasha80
cd39124daa Регрессия. Изменить размер диаграммы в зависимости от режима отображения РТО/обзорная 2025-12-24 11:47:49 +03:00
lepshiy
8d3b80cf4c Динамическое изменение цвета схемы Э2. Изменение значков в ЭМС ТГ и Контроль 2025-12-24 11:17:05 +03:00
sasha80
76ef0d4ac6 Рефактор. 2025-12-24 09:45:45 +03:00
sasha80
0292d2ef71 Исправление. Регрессия. Режим карты не переключается 2025-12-24 09:14:31 +03:00
sasha80
cda50a0e07 Рефактор. 2025-12-24 09:13:36 +03:00
sasha80
3a4a2c1eca Исправление. Неверный индекс 2025-12-24 08:24:02 +03:00
sasha80
a48d45d0b5 Рефактор. 2025-12-23 16:21:43 +03:00
sasha80
5b69f0f53f Регрессия. 2025-12-23 16:21:43 +03:00
sasha80
ea3509ffb0 Чистка. 2025-12-23 16:21:42 +03:00
sasha80
3136fba978 Рефактор. 2025-12-23 16:21:42 +03:00
sasha80
40f0ac7ade Исправление. Проседание частоты кадров в режиме Работа 2025-12-23 16:21:42 +03:00
sasha80
3d161fd37f WIP Исправление. Поиск причины проседания частоты кадров в режиме Работа 2025-12-23 16:21:42 +03:00
sasha80
358fd20f53 Рефактор. 2025-12-23 16:21:42 +03:00
sasha80
f517066638 Доработка. Цвет для диаграммы получить из настроек 2025-12-23 16:21:42 +03:00
MaD_CaT
ffc1cd4c32 Исправления. Исправлен вылет при попытке назначить помеху на несуществующий сектор nmfs 2025-12-19 15:28:56 +03:00
sasha80
9b28fe1352 Merge pull request 'master' (#49) from MaD_CaT/uarep-ctl:master into master
Reviewed-on: http://gitea.srez.local:3000/sasha80/uarep-ctl/pulls/49
2025-12-19 10:51:48 +03:00
MaD_CaT
0a11dac42a Исправления. Убраны объявления переменных необходимых для отладки. 2025-12-18 11:33:09 +03:00
MaD_CaT
f9e00e3976 Исправления. Исправлен вылет, если цель приходит в режиме контроля с отключеными сигналами в работе. 2025-12-18 10:44:29 +03:00
MaD_CaT
bbb119017c Исправление. Убран лишний принт и вызов текущего времени. 2025-12-17 11:31:48 +03:00
MaD_CaT
2ca8e591e7 Исправление. Убран лишний пробел. 2025-12-17 11:28:29 +03:00
MaD_CaT
cd72001881 Доработка. Изменение алгоритма отправки помехи. Теперь таймер для каждой помехи свой. Добавлена настройка времени повторной отправки. 2025-12-17 11:09:02 +03:00
sasha80
802ac0afd7 Рефактор. 2025-12-17 08:12:43 +03:00
MaD_CaT
ef33862d37 Исправление. Название кнопки помехи ЕЛРС. 2025-12-16 14:28:23 +03:00
MaD_CaT
0d67b086ba Доработка. Добавлены тултипы для кнопок помех. 2025-12-16 13:58:41 +03:00
MaD_CaT
3b5bf2ce2c Доработка. Добавлена возможность изменять ширину полосы излучения из настроек. 2025-12-16 11:24:37 +03:00
MaD_CaT
45c19973af Исправления. Восстановлено состояние секторов после постановки помехи. 2025-12-16 11:19:30 +03:00
lepshiy
7e3f1bfb81 Merge remote-tracking branch 'refs/remotes/sasha/master'
# Conflicts:
#	scenes/эмс2/эмс2.tscn
2025-12-16 11:06:20 +03:00
MaD_CaT
f50810a152 Merge remote-tracking branch 'sasha/master'
# Conflicts:
#	scenes/работа/работа.tscn
2025-12-15 15:42:09 +03:00
sasha80
fb6ea53d3c Merge remote-tracking branch 'origin/master-prd' 2025-12-15 15:37:04 +03:00
sasha80
88e0ea58ab Исправление. Не отображается изображение шкалы частот в ЭМС2 2025-12-15 15:35:03 +03:00
sasha80
857d2a9f9d Чистка. 2025-12-15 14:54:05 +03:00
sasha80
814f013da1 Рефактор. 2025-12-15 14:53:54 +03:00
sasha80
5d40fc1e1b Merge remote-tracking branch 'MaD_CaT/master-prd'
# Conflicts:
#	scenes/frame-ecm-list/scroll-ecm-list.gd
#	scenes/настройки/настройки.gd
#	scenes/работа/работа.gd
#	scenes/эмс2/эмс2.tscn
2025-12-15 14:30:48 +03:00
MaD_CaT
69a72ae993 Исправления. Убрано ограничение на время отправки команд в ЯУ-07. 2025-12-15 14:17:24 +03:00
Maxim
a8e7a1c6aa WIP Исправление. Рассинхрон данных во время работы контроля. 2025-12-15 14:09:00 +03:00
MaD_CaT
bbd3f9aa7f Godot4. Автоматически убраны лишние пробелы. 2025-12-15 14:00:24 +03:00
MaD_CaT
f2034a0edd Исправление. Имя power в threats изменено на pow 2025-12-15 14:00:02 +03:00
MaD_CaT
b274a655cd Godot4. Error -> Warn (ShadowNames) 2025-12-15 13:52:02 +03:00
sasha80
36811852fc Исправление.
ERROR: Unable to open file: res://.godot/imported/Окно частот0.png-6b01791c971bddb01337caf9077bf060.ctex.
   at: _load_data (scene/resources/compressed_texture.cpp:41)
ERROR: Unable to open file: res://.godot/imported/Скруглённый квадрат серый.png-4655829309cca3b1dec2c9ae01376d54.ctex.
   at: _load_data (scene/resources/compressed_texture.cpp:41)
2025-12-11 13:39:30 +03:00
sasha80
4057da3b75 Рефактор. 2025-12-11 11:22:56 +03:00
sasha80
304a8c6453 Рефактор. 2025-12-11 11:14:38 +03:00
MaD_CaT
c9304134ca Доработка изменения цвета своей цели на зеленый 2025-12-10 13:15:47 +03:00
sasha80
94f5159ad9 Доработка. В процессее. Проверка входных данных. Здесь не нужно 2025-12-10 10:32:32 +03:00
sasha80
9a8763a9d7 Исправление. Возможно обращение к отсутсвующему элементу 2025-12-10 10:29:24 +03:00
sasha80
788a62505f Рефактор. 2025-12-10 10:28:20 +03:00
TotMaxim
c8e67775a0 Доработка изменения цвета кнопки подавления 2025-12-09 21:48:46 +03:00
TotMaxim
3073d49715 Добавление проверки размера пакетов от ЯУ-07Б 2025-12-09 20:29:35 +03:00
TotMaxim
e2237742b4 Корректировка рабочих температур УМ 2025-12-09 20:10:57 +03:00
TotMaxim
f34984872e Доработка прогресс бара для УФ 2025-12-09 19:42:49 +03:00
MaD_CaT
c0018044a5 Merge remote-tracking branch 'origin/prd-control' into prd-control
# Conflicts:
#	scenes/button-flat/button-flat.tscn
2025-12-09 16:15:31 +03:00
MaD_CaT
cdb884f18d Исправление цвета рамки рекомендуемой помехи 2025-12-09 16:14:07 +03:00
MaD_CaT
2f4ee7be3c Исправление алгоритма взаимодействия с ЯУ-07Б 2025-12-09 15:53:02 +03:00
MaD_CaT
e7076354b4 Исправление. Прием мощности сигнала от цели от СТЦ 2025-12-09 15:51:54 +03:00
MaD_CaT
b44b0aafd1 Исправление. Добавление проверки индекса таблицы помех 2025-12-09 15:51:00 +03:00
MaD_CaT
cb1637e21c Исправление. Обработка рекомендованой помехи от СТЦ 2025-12-09 15:49:49 +03:00
MaD_CaT
115004194b Исправление кнопки ФС-Э2 по рекомендации комиссии 2025-12-09 15:48:54 +03:00
MaD_CaT
9156249e74 Исправление ЭМС-ТГ по рекомендации комиссии 2025-12-09 15:47:25 +03:00
sasha80
b3322ee591 Рефактор. 2025-12-09 12:42:31 +03:00
sasha80
9be115a535 Доработка. Пусть событие "выполнено" вызывается если разбор ответа успешно пройден 2025-12-09 12:19:30 +03:00
sasha80
92ff74efef Рефактор. 2025-12-09 12:17:03 +03:00
sasha80
4ea8a4c254 Доработка. Добавлена настройка цвета для кнопки "Подавление" 2025-12-09 12:16:02 +03:00
sasha80
55253b0915 Godot4.4 2025-12-09 11:17:16 +03:00
MaD_CaT
6dc31afa15 Merge remote-tracking branch 'origin/sasha' into prd-control
# Conflicts:
#	scenes/контроль/контроль.tscn
2025-12-09 10:35:01 +03:00
MaD_CaT
bd78e1010d Рефектор от ide табуляция 2025-12-09 10:26:14 +03:00
TotMaxim
426da5ff04 Объединение исправления Александра 2025-12-07 21:05:41 +03:00
TotMaxim
b69eaa29d9 Merge remote-tracking branch 'origin/sasha80' into prd-control
# Conflicts:
#	scenes/tilemap/tilemap.gd
#	scenes/контроль/кнопка-прибора.gd
#	scenes/работа/работа.tscn
2025-12-07 20:22:20 +03:00
TotMaxim
c74d5ccdad Отладка интегрального контроля УФ 2025-12-07 20:14:51 +03:00
TotMaxim
a7c816e6ca Доработка интегрального контроля УФ 2025-12-07 18:49:03 +03:00
MaD_CaT
f89540dfdc Исправления ящик сундуков 2025-12-05 16:44:31 +03:00
lepshiy
723f6535ac Доработка. Восстановление потерянных таблиц в "ЭМС ТГ" 2025-12-05 13:21:45 +03:00
MaD_CaT
c45842266a Исправления названия столбца в списках целей, корректировка курса 2025-12-05 10:18:21 +03:00
TotMaxim
64703c46dc Исправление опечатки в кнопки включения схем Э2 2025-12-04 20:15:43 +03:00
TotMaxim
b022e9e418 Доработка рекомендации отображении кнопки запуска контроля 2025-12-04 19:58:33 +03:00
MaD_CaT
428831d83f отладка яу 2025-12-04 17:10:27 +03:00
TotMaxim
021eba8a08 Доработка интегрального контроля 2025-12-03 16:51:33 +03:00
TotMaxim
3030eac0c9 Доработка от godot, сам отрефакторил кэш 2025-12-03 12:43:19 +03:00
TotMaxim
b7fa8cca66 Merge remote-tracking branch 'origin/MAD_CAT' into prd-control 2025-12-03 12:34:54 +03:00
MaD_CaT
5dac4fae5e Доработка. Исправность секторов ФС зависит от связи с КАПС РПБ и ЯУ-07. 2025-12-03 12:09:01 +03:00
TotMaxim
02f8a6a8c5 Merge remote-tracking branch 'lepshiy/master-tniis' into prd-control
# Conflicts:
#	scenes/tilemap/tilemap.gd
#	scenes/контроль/кнопка-прибора.gd
#	scenes/работа/работа.tscn
2025-12-03 11:29:02 +03:00
MaD_CaT
9e74a67e86 Доработка. Выключение помехи, если КАПС РПБ не на связи 2025-12-03 10:15:51 +03:00
148 changed files with 9862 additions and 3135 deletions

View File

@@ -0,0 +1,14 @@
name: Локальный тест
on: [push]
jobs:
test:
runs-on: [For testing repo]
steps:
- name: Тестовый шаг 1
run: echo "🎉 Запуск без интернета"
- name: Информация о системе
run: |
uname -a
echo "Рабочая папка: $PWD"
- name: Список файлов
run: ls -la

1
.gitignore vendored
View File

@@ -39,3 +39,4 @@ modbus/serial/__pycache__
/scenes/pribor-prd-n/kasseta-fs-nd.tscn.bak
*.patch
проверка.log

View File

@@ -1,12 +1,15 @@
# Разработка
- После клонирования запустить скрипт `git-hooks-config.sh`
- В среде **Windows** запуск скрипта `git-hooks-config.sh` производить из оболочки `git bash`
- При необходимости обновить `settings.json`
- После клонирования запустить скрипт [`git-hooks-config.sh`](git-hooks-config.sh)
- В среде **Windows** запуск скрипта [`git-hooks-config.sh`](git-hooks-config.sh) производить из оболочки `git bash`
- При необходимости обновить [`settings.json`](settings.json)
- Использовать выражения вида `ProjectSettings.set_setting('application/config/%s' % key_name`
и `ProjectSettings.get_setting('application/config/%s % key_name)` для доступа к настройкам.
- `key_name` брать из таблицы `res://scenes/настройки/настройки.gd/SETTING_TABLE`
- Следовать [общим правилам](http://gitea.srez.local:3000/sasha80/gitea-tniis).
- Следовать [общим правилам](http://gitea.srez.local:3000/sasha80/dev-manual).
- **Windows**: убедиться, что исполняемый файл не заблокирован в брандмауэре.
Обычно блокировка происходит автоматически, а отмена блокировки требует
вмешательства пользователя.
# Ссылки на составные части
@@ -25,6 +28,7 @@
- [ПО 5П28 Пульт П16](http://gitea.srez.local:3000/MaD_CaT/imi-5p28)
- [ПО 5П28 АКНГ](http://gitea.srez.local:3000/sasha80/imi-5p28-navi)
- [Трасса](http://gitea.srez.local:3000/lepshiy/imi-trassa)
- [Информационный ЭМС](http://gitea.srez.local:3000/MaD_CaT/mp550_imi_emstg)
# Автоматизация тестирования
@@ -32,7 +36,7 @@
# Сборка исполняемого файла из консоли
- Запустить скрипт `build.sh`
- Запустить скрипт [`build.sh`](build.sh)
# Взаимодействие с 5П-28

76
check.sh Normal file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
if [ -z "$1" ]; then
echo "Использование: $0 <папка_для_поиска>"
exit 1
fi
TARGET_DIR="$1"
if [ ! -d "$TARGET_DIR" ]; then
echo "Ошибка: папка '$TARGET_DIR' не существует!"
exit 1
fi
echo "Поиск строк в двойных кавычках в файлах .gd (исключая комментарии)..."
echo "Папка: $TARGET_DIR"
echo "=========================================="
FOUND_MATCHES=0
# Используем Process Substitution вместо пайплайна в цикле
while IFS= read -r file; do
# Используем awk для поиска строк с кавычками, исключая комментарии
# и экранированные кавычки
MATCHES=$(awk '
BEGIN { line_num = 0 }
{
line_num++
original_line = $0
line = $0
# Ищем первый #, который не находится внутри кавычек
in_quote = 0
for (i = 1; i <= length(line); i++) {
char = substr(line, i, 1)
prev_char = substr(line, i-1, 1)
# Если находим неэкранированную кавычку, меняем состояние
if (char == "\"" && prev_char != "\\") {
in_quote = !in_quote
}
# Если находим # вне кавычек, обрезаем строку до этого места
if (char == "#" && !in_quote) {
line = substr(line, 1, i-1)
break
}
}
# Удаляем начальные и конечные пробелы
gsub(/^[[:space:]]+|[[:space:]]+$/, "", line)
if (index(original_line, "\"\"\"") == 0) {
# Ищем непустые строки с двойными кавычками
if (line ~ /"[^"\\]*"/) {
print line_num ": " original_line
}
}
}
' "$file")
if [ -n "$MATCHES" ]; then
FOUND_MATCHES=1
echo "Файл: $file"
echo "$MATCHES" | while IFS= read -r match_line; do
echo " Строка $match_line"
done
echo ""
fi
done < <(find "$TARGET_DIR" -type f -name "*.gd" -not -path "./addons/*")
if [ "$FOUND_MATCHES" -eq 0 ]; then
exit 0
fi
exit 1

84
config/banned_ranges.json Normal file
View File

@@ -0,0 +1,84 @@
{
"ranges": [
{
"max": 404993123,
"min": 402777013
},
{
"max": 488584484,
"min": 420111389
},
{
"max": 559113065,
"min": 549071634
},
{
"max": 590394020,
"min": 581828010
},
{
"max": 671113646,
"min": 661072214
},
{
"max": 825534007,
"min": 784914374
},
{
"max": 964027611,
"min": 931531905
},
{
"max": 1097550064,
"min": 1076907893
},
{
"max": 1217532686,
"min": 1173668071
},
{
"max": 1529745530,
"min": 1500072408
},
{
"max": 1790501904,
"min": 1703047870
},
{
"max": 1903884888,
"min": 1798093759
},
{
"max": 1982005472,
"min": 1917112535
},
{
"max": 2174813389,
"min": 2103855925
},
{
"max": 2397985516,
"min": 2299661838
},
{
"max": 2696028220,
"min": 2594107498
},
{
"max": 3627192359,
"min": 3576902218
},
{
"max": 5215200272,
"min": 5186186730
},
{
"max": 5397018474,
"min": 5255819232
},
{
"max": 5967607190,
"min": 5944388619
}
]
}

3391
config/complex.json Normal file

File diff suppressed because it is too large Load Diff

15
config/service_config.ini Normal file
View File

@@ -0,0 +1,15 @@
[MP550]
host=192.168.11.105
port=42023
transmit_interval_ms=100
[RDMP]
host=127.0.0.1
port=55000
identity=MP550Service
keep_alive_interval_ms=9000
[Service]
autorun=false
host=192.168.11.102
port=42022

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bymxiptkbufvs"
path="res://.godot/imported/Скруглённый квадрат серый.png-2111d7338e52a03a41f05d6ffbbc3eb6.ctex"
uid="uid://cwfdur4we51wo"
path="res://.godot/imported/2разъединение.png-a5736ca86ce553a4d764d6fc09130f8a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Скруглённый квадрат серый.png"
dest_files=["res://.godot/imported/Скруглённый квадрат серый.png-2111d7338e52a03a41f05d6ffbbc3eb6.ctex"]
source_file="res://data/2разъединение.png"
dest_files=["res://.godot/imported/2разъединение.png-a5736ca86ce553a4d764d6fc09130f8a.ctex"]
[params]

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://b1dw06ahtftq2"
path="res://.godot/imported/Окно частот0.png-79ada2e7504614b9bdf58bce1aff61fb.ctex"
uid="uid://bajrbvv7twq7m"
path="res://.godot/imported/2соединение.png-b014241f07700023165f09936094354c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Окно частот0.png"
dest_files=["res://.godot/imported/Окно частот0.png-79ada2e7504614b9bdf58bce1aff61fb.ctex"]
source_file="res://data/2соединение.png"
dest_files=["res://.godot/imported/2соединение.png-b014241f07700023165f09936094354c.ctex"]
[params]

View File

@@ -4,19 +4,6 @@
[resource]
fallbacks = Array[Font]([ExtResource("1_cxid7")])
cache/0/17/0/ascent = 0.0
cache/0/17/0/descent = 0.0
cache/0/17/0/underline_position = 0.0
cache/0/17/0/underline_thickness = 0.0
cache/0/17/0/scale = 1.0
cache/0/17/0/kerning_overrides/17/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/16/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/18/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/14/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/8/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/15/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/13/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/20/0 = Vector2(0, 0)
cache/0/16/0/ascent = 0.0
cache/0/16/0/descent = 0.0
cache/0/16/0/underline_position = 0.0
@@ -30,6 +17,24 @@ cache/0/16/0/kerning_overrides/8/0 = Vector2(0, 0)
cache/0/16/0/kerning_overrides/15/0 = Vector2(0, 0)
cache/0/16/0/kerning_overrides/13/0 = Vector2(0, 0)
cache/0/16/0/kerning_overrides/20/0 = Vector2(0, 0)
cache/0/17/0/ascent = 0.0
cache/0/17/0/descent = 0.0
cache/0/17/0/underline_position = 0.0
cache/0/17/0/underline_thickness = 0.0
cache/0/17/0/scale = 1.0
cache/0/17/0/kerning_overrides/17/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/16/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/18/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/14/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/8/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/15/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/13/0 = Vector2(0, 0)
cache/0/17/0/kerning_overrides/20/0 = Vector2(0, 0)
cache/0/22/0/ascent = 0.0
cache/0/22/0/descent = 0.0
cache/0/22/0/underline_position = 0.0
cache/0/22/0/underline_thickness = 0.0
cache/0/22/0/scale = 1.0
cache/0/18/0/ascent = 0.0
cache/0/18/0/descent = 0.0
cache/0/18/0/underline_position = 0.0
@@ -113,8 +118,3 @@ cache/0/19/0/descent = 0.0
cache/0/19/0/underline_position = 0.0
cache/0/19/0/underline_thickness = 0.0
cache/0/19/0/scale = 1.0
cache/0/22/0/ascent = 0.0
cache/0/22/0/descent = 0.0
cache/0/22/0/underline_position = 0.0
cache/0/22/0/underline_thickness = 0.0
cache/0/22/0/scale = 1.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c73tjrn8gr00o"
path="res://.godot/imported/Передатчик.png-a9919ed2f6d748be55f63a536bcda2ff.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Передатчик.png"
dest_files=["res://.godot/imported/Передатчик.png-a9919ed2f6d748be55f63a536bcda2ff.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
data/Приёмник.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c6etralq2tvxg"
path="res://.godot/imported/Приёмник.png-37dec39ffb59b71e3909414fe8f5fd1e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Приёмник.png"
dest_files=["res://.godot/imported/Приёмник.png-37dec39ffb59b71e3909414fe8f5fd1e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://3siondd3feev"
path="res://.godot/imported/Скруглённый прямоугольник белый.png-758adbfc4fc135ed0095e711422b8c0e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Скруглённый прямоугольник белый.png"
dest_files=["res://.godot/imported/Скруглённый прямоугольник белый.png-758adbfc4fc135ed0095e711422b8c0e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,34 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://7ody4v7qy36g"
path="res://.godot/imported/Скруглённый прямоугольник серый.png-318eedc8abeb0fd535304028648863b7.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Скруглённый прямоугольник серый.png"
dest_files=["res://.godot/imported/Скруглённый прямоугольник серый.png-318eedc8abeb0fd535304028648863b7.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://6ar7sux3vcv1"
path="res://.godot/imported/Состояние РЭС 2.png-7acd4e8d9bd67ea07a3eadee4b22c22d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Состояние РЭС 2.png"
dest_files=["res://.godot/imported/Состояние РЭС 2.png-7acd4e8d9bd67ea07a3eadee4b22c22d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b85f1ne2wrwhg"
path="res://.godot/imported/Состояние РЭС 4.png-d46f69e8c351fe747cf68bce4af4b8eb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Состояние РЭС 4.png"
dest_files=["res://.godot/imported/Состояние РЭС 4.png-d46f69e8c351fe747cf68bce4af4b8eb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://docnrxrm2f022"
path="res://.godot/imported/Угловой квадрат3.png-7973b0c96861e98d72e8e1ea32d59204.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Угловой квадрат3.png"
dest_files=["res://.godot/imported/Угловой квадрат3.png-7973b0c96861e98d72e8e1ea32d59204.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

View File

@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://busl8rb38lis"
path="res://.godot/imported/Скруглённый прямоуг салатный.png-e10b4e8820d45ab6e79c4fba522af854.ctex"
path="res://.godot/imported/матрица-конфликт.png-e109709def61ac1d626d23088b556664.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Скруглённый прямоуг салатный.png"
dest_files=["res://.godot/imported/Скруглённый прямоуг салатный.png-e10b4e8820d45ab6e79c4fba522af854.ctex"]
source_file="res://data/матрица-конфликт.png"
dest_files=["res://.godot/imported/матрица-конфликт.png-e109709def61ac1d626d23088b556664.ctex"]
[params]

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://djv8fkddcjucs"
path="res://.godot/imported/Скруглённый квадрат белый.png-4793c453fe49bfbe7c9affd223331345.ctex"
path="res://.godot/imported/матрица-чисто.png-43b162afe88b693461904505b377fae0.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Скруглённый квадрат белый.png"
dest_files=["res://.godot/imported/Скруглённый квадрат белый.png-4793c453fe49bfbe7c9affd223331345.ctex"]
source_file="res://data/матрица-чисто.png"
dest_files=["res://.godot/imported/матрица-чисто.png-43b162afe88b693461904505b377fae0.ctex"]
[params]

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b0wa068b6gl1y"
path="res://.godot/imported/разъединение.png-285b8ee2e2b500484829beae0ee4e16b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/разъединение.png"
dest_files=["res://.godot/imported/разъединение.png-285b8ee2e2b500484829beae0ee4e16b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

BIN
data/связь.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -2,16 +2,16 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://co5xj5uhjfk84"
path="res://.godot/imported/Окно.png-ff4b5eac96df23ad4cd8e06dc32f5bb8.ctex"
uid="uid://blx6c1o1nogks"
path="res://.godot/imported/связь.png-dc3eae4c11f71101d4ba94487cecfaaa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Окно.png"
dest_files=["res://.godot/imported/Окно.png-ff4b5eac96df23ad4cd8e06dc32f5bb8.ctex"]
source_file="res://data/связь.png"
dest_files=["res://.godot/imported/связь.png-dc3eae4c11f71101d4ba94487cecfaaa.ctex"]
[params]

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bf1e2xlk3x1aw"
path="res://.godot/imported/соединение.png-aac09e55b0c5d57ef3c31c34daaf336b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/соединение.png"
dest_files=["res://.godot/imported/соединение.png-aac09e55b0c5d57ef3c31c34daaf336b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -20,9 +20,9 @@ script_export_mode=0
[preset.0.options]
custom_template/debug=""
custom_template/release=""
debug/export_console_wrapper=2
custom_template/debug="/home/user/temp/godot.linuxbsd.template_release.x86_64"
custom_template/release="/home/user/temp/godot.linuxbsd.template_release.x86_64"
debug/export_console_wrapper=0
binary_format/embed_pck=true
texture_format/s3tc_bptc=true
texture_format/etc2_astc=false

View File

@@ -20,8 +20,8 @@
# - выполнение фиксации;
# - выполнение слияния.
GDSCRIPT_FILE="scripts/commit.gd"
LOGFILE="проверка.log"
HEAD="$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short HEAD) $(git log -1 --format=%cd)"
if [ -n "$(git status --porcelain)" ]; then
HEAD="Изменённый ${HEAD}"
@@ -29,3 +29,6 @@ fi
echo "extends Node" > ${GDSCRIPT_FILE}
echo "# Файл сгенерирован автоматически! Не изменять вручную!" >> ${GDSCRIPT_FILE}
echo "const VCS_HEAD = '${HEAD}'" >> ${GDSCRIPT_FILE}
echo "${HEAD}" > ${LOGFILE}
./check.sh . >> ${LOGFILE}

View File

@@ -8,7 +8,6 @@
## ```
## > iptables v1.8.2 (nf_tables)
INI_FILE="/opt/5p28/device.ini" ## Путь к INI-файлу 5п28
SECTION_NAME="navigat" ## Название секции INI-файла 5п28
IP_PORT_NAME="port" ## Имя поля INI-файла 5п28 в котором хранится номер порта назначения

View File

@@ -29,7 +29,6 @@ interfer/default_color0=Color(0.38, 0.47, 0.51, 1)
interfer/default_color1=Color(0.39, 0.44, 0.5, 1)
interfer/select_color=Color(1, 1, 1, 1)
interfer/interfer_color=Color(0.9, 0.1, 0.25, 0.9)
interfer/resend_timeout=1000.0
config/external_cu=false
config/unit_rr_request_period=20.0
config/kems_files_path="user://kems/"
@@ -38,6 +37,65 @@ config/settings_path="user://settings.json"
config/unit_bpo_request_period=20.0
interfer/emit_color=Color(0.9, 0.1, 0.25, 0.5)
interfer/closed_sectors=Color(0, 0, 0, 1)
"config/Адрес АФСП левого борта"=""
"config/Адрес АФСП правого борта"=""
"config/Адрес БПО левого борта"=""
"config/Адрес БПО правого борта"=""
"config/Виртуальная клавиатура"=false
"config/Включить работу по своим целям"=true
"config/Внешнее указание Трасса"=false
"config/Внешнее управление"=false
"config/Кнопка «JTIDS»"=false
"config/Кнопка «К1»"=false
"config/Кнопка «КУПД»"=false
"config/Кнопка «ЛЧМ-1»"=false
"config/Кнопка «МЧМ-1»"=false
"config/Кнопка «ОЗП-1»"=false
"config/Кнопка «ОРН-И1»"=false
"config/Кнопка «ОРН-М2»"=false
"config/Кнопка «ОРН»"=false
"config/Кнопка «ПД-М2»"=false
"config/Кнопка «ПД-М4»"=false
"config/Кнопка «ПД-М4С»"=false
"config/Кнопка «ПД-ЧМ»"=false
"config/Кнопка «Подавление»"=false
"config/Кнопка «СВ-И1»"=false
"config/Кнопка «СВ-М2»"=false
"config/Ограниченный режим"=false
"config/Отладка контроля"=true
"config/Период опроса состояния АФСП, секунды"=""
"config/Период опроса состояния БПО, секунды"=""
"config/Скрыть вкладку ЭМС 2"=true
"config/Список своих протоколов"=""
"config/Текущая версия ПО УАРЭП"="master 3bff1cd Tue Nov 4 15:33:24 2025 +0300"
"config/Цвет кнопки \"Подавление\""="[0.905882358551025,0.00392156885936856,0.0,1.0]"
"config/Цвет схемы"="[0.905954480171204,0.921875,0.8714599609375,1.0]"
"config/Цвет фона схемы"="[0.258926391601563,0.274618297815323,0.27734375,1.0]"
"config/Шаблон адреса сервера карт"="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
"config/навигация"=["*", 60000.0, true, true]
"config/уарэп-5п28"=["127.0.0.1", 50777.0]
"config/уарэп-капсрпб"=["127.0.0.1", "127.0.0.1", 42023.0, 42022.0, false, true]
"config/уарэп-спт25-1"=["/home/user/tty0", 0.0, 19200.0, "N", 8.0, 1.0]
"config/уарэп-спт25-2"=["/home/user/tty1", 0.0, 19200.0, "N", 8.0, 1.0]
"config/уарэп-трасса"=["192.168.11.34", "192.168.11.105", 50200.0, 10004.0, false, true]
"config/уарэп-щ3"=["/home/user/tty3", 7.0, 19200.0, "N", 8.0, 1.0, 50000.0]
"config/уарэп-эмс"=["10.1.1.52", 50052.0, false, false]
"config/уарэп-яу07-1в"=["10.1.1.12", 50012.0, false, false]
"config/уарэп-яу07-1к"=["10.1.1.13", 50013.0, false, false]
"config/уарэп-яу07-1н"=["10.1.1.11", 50011.0, false, false]
"config/уарэп-яу07-2в"=["10.1.1.22", 50022.0, false, false]
"config/уарэп-яу07-2к"=["10.1.1.23", 50023.0, false, false]
"config/уарэп-яу07-2н"=["10.1.1.21", 50021.0, false, false]
"config/уарэп-яу07-3в"=["10.1.1.32", 50032.0, false, false]
"config/уарэп-яу07-3к"=["10.1.1.33", 50033.0, false, false]
"config/уарэп-яу07-3н"=["10.1.1.31", 50031.0, false, false]
"config/уарэп-яу07-4в"=["10.1.1.42", 50042.0, false, false]
"config/уарэп-яу07-4к"=["10.1.1.43", 50043.0, false, false]
"config/уарэп-яу07-4н"=["10.1.1.41", 50041.0, false, false]
"config/уарэп-яу07-общий"=["*", 50000.0, true, true]
"config/уарэп-яу07-частный"=["10.1.1.253", 50253.0, false, true]
config/="[0.215686276555061,0.976470589637756,1.0,1.0]"
"config/Цвет темы программы"=false
[autoload]
@@ -64,6 +122,8 @@ astrakb="*res://scripts/astra-kb.gd"
prd="*res://scripts/prd.gd"
navi="*res://scripts/navigation.gd"
trassa="*res://scripts/trassa.gd"
yemstg="*res://scripts/yemstg.gd"
scouting="*res://scripts/rtr.gd"
[debug]
@@ -74,7 +134,6 @@ gdscript/warnings/unassigned_variable_op_assign=2
gdscript/warnings/unused_signal=0
gdscript/warnings/shadowed_variable=2
gdscript/warnings/shadowed_variable_base_class=2
gdscript/warnings/shadowed_global_identifier=2
gdscript/warnings/unsafe_cast=1
gdscript/warnings/assert_always_true=2
gdscript/warnings/assert_always_false=2
@@ -90,6 +149,7 @@ window/subwindows/embed_subwindows=false
window/frame_pacing/android/enable_frame_pacing=false
window/stretch/mode="canvas_items"
window/dpi/allow_hidpi=false
window/vsync/vsync_mode=0
[editor]
@@ -110,6 +170,7 @@ folder_colors={
"res://scenes/bip/": "blue",
"res://scenes/button-flat/": "blue",
"res://scenes/button-scale/": "blue",
"res://scenes/button-six-state/": "blue",
"res://scenes/cell/": "blue",
"res://scenes/count-all/": "blue",
"res://scenes/count-danger/": "blue",
@@ -121,6 +182,7 @@ folder_colors={
"res://scenes/frame/": "blue",
"res://scenes/grid-buttons-ecm/": "blue",
"res://scenes/grid-side-panel/": "blue",
"res://scenes/hranges/": "blue",
"res://scenes/pribor-afsp/": "purple",
"res://scenes/pribor-externals/": "purple",
"res://scenes/pribor-prd-k/": "purple",
@@ -134,8 +196,8 @@ folder_colors={
"res://scenes/контроль/": "green",
"res://scenes/настройки/": "green",
"res://scenes/работа/": "green",
"res://scenes/эмс-тг/": "green",
"res://scenes/эмс/": "green",
"res://scenes/эмс2/": "green",
"res://scripts/": "pink",
"res://shaders/": "pink",
"res://table/": "blue"
@@ -209,6 +271,8 @@ common/enable_object_picking=false
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"
shader_compiler/shader_cache/strip_debug=true
textures/default_filters/anisotropic_filtering_level=0
anti_aliasing/screen_space_roughness_limiter/enabled=false
quality/driver/fallback_to_gles2=true
[shader_globals]
@@ -217,3 +281,7 @@ tick_curent={
"type": "int",
"value": 0
}
random_value={
"type": "float",
"value": 0.0
}

View File

@@ -1,15 +1,16 @@
[gd_scene load_steps=13 format=3 uid="uid://da7w3vkhadfwe"]
[gd_scene load_steps=14 format=3 uid="uid://da7w3vkhadfwe"]
[ext_resource type="Script" uid="uid://damy6n4u215pu" path="res://scenes/button-flat/nine-patch-button.gd" id="1_ui6sg"]
[ext_resource type="Texture2D" uid="uid://ct0ajcwno03h7" path="res://data/кнопка-квадрат-0.png" id="2_0cn5u"]
[ext_resource type="Shader" uid="uid://cdmmsf161l6yw" path="res://shaders/strips.gdshader" id="2_5ngiq"]
[ext_resource type="Texture2D" uid="uid://cl8h2vaibabyi" path="res://data/кнопка-квадрат-1.png" id="3_tbv1w"]
[sub_resource type="StyleBoxEmpty" id="1"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_hhdyc"]
resource_local_to_scene = true
shader = ExtResource("2_5ngiq")
shader_parameter/rotation = 0.0
shader_parameter/rotation = 0.785398
shader_parameter/color = Vector4(1, 1, 1, 0.1)
shader_parameter/width = 3.0
shader_parameter/speed = 0.0
@@ -56,13 +57,16 @@ offset_right = 20.0
offset_bottom = 20.0
theme_override_styles/panel = SubResource("1")
script = ExtResource("1_ui6sg")
texture_state0 = ExtResource("2_0cn5u")
texture_state1 = ExtResource("3_tbv1w")
strips_rotation = 45.0
[node name="recommend" type="ReferenceRect" parent="."]
visible = false
z_as_relative = false
layout_mode = 2
border_color = Color(0, 0.549509, 0.921779, 1)
border_width = 5.0
border_color = Color(0.0941176, 0.0941176, 0.698039, 1)
border_width = 10.0
editor_only = false
[node name="back" type="Sprite2D" parent="."]
@@ -72,6 +76,7 @@ texture = SubResource("PlaceholderTexture2D_6nup5")
centered = false
script = SubResource("GDScript_uyl5d")
speed = 0.0
strips_rotation = 0.785398
[node name="state" type="NinePatchRect" parent="."]
layout_mode = 2

View File

@@ -12,31 +12,37 @@ func is_toggle_mode(): return $button.is_toggle_mode()
var _pressed: = false
@export var texture_state0: Texture2D = preload('res://data/кнопка-квадрат-0.png'):
@export var texture_state0: Texture2D:
set(val):
texture_state0 = val
$state.set_texture(val)
@export var texture_state1: Texture2D = preload('res://data/кнопка-квадрат-1.png'):
@export var texture_state1: Texture2D:
set(val):
texture_state1 = val
if is_inside_tree():
$state.set_texture(val)
@export var strips_rotation: float = 0.0:
set(val):
strips_rotation = val
if is_inside_tree():
$back.strips_rotation = deg_to_rad(val)
@export var text: String = '':
set(val):
text = val
if is_inside_tree():
$button.set_text(val)
@export var btn_tooltip: String = '':
set(val):
btn_tooltip = val
if is_inside_tree():
$button.set_tooltip_text(val)
@export var disabled: bool = false:
set(val):
disabled = val
@@ -64,6 +70,8 @@ var _pressed: = false
@export var font_size: int = 15:
set(val):
font_size = val
if is_inside_tree():
$button.add_theme_font_size_override('theme_override_font_sizes/font_size', val)
@@ -86,7 +94,19 @@ func _enter_tree() -> void:
$back.scale = size
$back.material.set('shader_parameter/scale', size / Vector2(20.0, 20.0))
$button.connect('toggled', _on_button_toggled)
$button.set_toggle_mode(toggle_mode)
$button.add_theme_font_size_override('theme_override_font_sizes/font_size', font_size)
pressed = _pressed
$button.set_pressed(pressed)
$button.set_disabled(disabled)
$back.disabled = disabled
$state.modulate.a = 0.5 if disabled else 1.0
$button.set_tooltip_text(btn_tooltip)
$button.set_text(text)
func _on_settings_changed():
pass
func _exit_tree() -> void:

View File

@@ -0,0 +1,77 @@
[gd_scene load_steps=3 format=3 uid="uid://cixwl6xi22buo"]
[ext_resource type="Texture2D" uid="uid://c6nve6f8sfyj2" path="res://data/состояние-исправности-0.png" id="1_ufod8"]
[sub_resource type="GDScript" id="GDScript_ufod8"]
script/source = "@tool
extends GridContainer
@export var text_check: Array[String]
@export_file var image_states: Array[String]
var txr_states: Array[CompressedTexture2D]
@export var state: int = 0:
set(val):
state = val % image_states.size()
if is_inside_tree():
val %= txr_states.size()
state = val
$done.texture = txr_states[val]
@export var pressed: bool = false:
set(val):
pressed = val
if is_inside_tree():
$check.button_pressed = pressed
func _enter_tree() -> void:
txr_states.clear()
for fn in image_states:
txr_states.append(load(fn))
$done.texture = txr_states[state]
$check.button_pressed = pressed
func connect_check(signal_name: StringName, callable: Callable):
$check.connect(signal_name, callable)
func disconnect_check(signal_name: StringName, callable: Callable):
$check.disconnect(signal_name, callable)
func _on_check_toggled(toggled_on: bool) -> void:
$text.text = text_check[int(toggled_on)]
"
[node name="six-state" type="GridContainer"]
offset_right = 156.0
offset_bottom = 24.0
columns = 3
script = SubResource("GDScript_ufod8")
text_check = Array[String](["Запрещено", "Разрешено"])
image_states = Array[String](["uid://c6nve6f8sfyj2", "uid://dnreyfh3cd1k2", "uid://c6booa8753u5t"])
[node name="done" type="TextureRect" parent="."]
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 3
texture = ExtResource("1_ufod8")
expand_mode = 3
[node name="text" type="Label" parent="."]
layout_mode = 2
size_flags_horizontal = 6
size_flags_vertical = 6
text = "Запрещено"
horizontal_alignment = 1
[node name="check" type="CheckButton" parent="."]
layout_mode = 2
size_flags_horizontal = 8
action_mode = 0
[connection signal="toggled" from="check" to="." method="_on_check_toggled"]

View File

@@ -1,44 +1,59 @@
class_name Diagram extends Sprite2D
class_name Diagram extends ColorRect
const NUM_OF_RANGE = 7
const NUM_OF_DIRECTIONS = 4
var fs_default_colors: Array[Color] ## Цвета по умолчанию для блоков ФС.
const ANTS_COUNT: = 28
const ANT_COLOR: = Color(0.38, 0.47, 0.51, 1.0)
@export var ant_color: Color = ANT_COLOR
@export var SecZap: PackedScene
@export var inner_radius_0: = 0.36 ## Внутренний радиус диаграммы в режиме РТО
@export var inner_radius_1: = 0.855 ## Внутренний радиус диаграммы в обзора
var fs_default_colors: PackedColorArray ## Цвета по умолчанию для блоков ФС
func _ready() -> void:
signaller.connect('map_mode_changed', Callable(self, 'set_view_mode'))
set_def_colors()
ProjectSettings.connect('settings_changed', _on_settings_changed)
_on_settings_changed()
_init_def_colors()
set_band_colors(fs_default_colors)
func sv(val: float) -> float: return val / ($строб.scale.x / 2.0) * 0.125
func set_canvas_rotation(val: float) -> void: material.set('shader_parameter/rotation', val)
func set_strob_visible(val: bool): $строб.visible = val
func set_strob_center(val: Vector2): $строб.position = val
func set_strob_dir(val: float): $строб.set_instance_shader_parameter('dir', val)
func set_strob_width(val: float): $строб.set_instance_shader_parameter('width', val)
func set_band_failures(val: PackedInt32Array): material.set('shader_parameter/ant_band_m', val)
func set_canvas_rotation(val: float): material.set('shader_parameter/rotation', val)
func set_radius_inner_frac(val: float): material.set('shader_parameter/inner_radius', val)
func set_strob_band(val: float): $строб.set_instance_shader_parameter('band', val / 125.0)
func set_strob_radius(val: float): $строб.set_instance_shader_parameter('radius', sv(val))
func set_strob_center(val: Vector2): $строб.position = val
func set_strob_color(val: Color): $строб.set_instance_shader_parameter('color', val)
func get_strob_center() -> Vector2: return $строб.position
func get_strob_visible() -> bool: return $строб.visible
func get_strob_dir() -> float: return $строб.get_instance_shader_parameter('dir')
func get_strob_width() -> float: return $строб.get_instance_shader_parameter('width')
func get_strob_band() -> float: return $строб.get_instance_shader_parameter('band') * 125.0
func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0
func get_strob_color() -> float: return $строб.get_instance_shader_parameter('color')
func get_canvas_rotation() -> float: return material.get('shader_parameter/rotation')
func get_radius_outter() -> float: return material.get('shader_parameter/radius_outter')
func get_radius_inner_0() -> float: return material.get('shader_parameter/radius_inner_0')
func get_radius_inner_1() -> float: return material.get('shader_parameter/radius_inner_1')
func set_strob_dir(val: float): $строб.set_instance_shader_parameter('dir', val)
func set_strob_radius(val: float): $строб.set_instance_shader_parameter('radius', sv(val))
func set_strob_visible(val: bool): $строб.visible = val
func set_strob_width(val: float): $строб.set_instance_shader_parameter('width', val)
func get_band_colors(_val: Array): return material.get('shader_parameter/ant_band_c')
func get_band_failures(_val: Array): return material.get('shader_parameter/ant_band_m')
func set_band_colors(val: Array): material.set('shader_parameter/ant_band_c', val)
func set_band_failures(val: Array): material.set('shader_parameter/ant_band_m', val)
func get_canvas_rotation() -> float: return material.get('shader_parameter/rotation')
func get_radius_outter() -> float: return size.x / scale.x
func get_radius_inner_frac() -> float: return material.get('shader_parameter/inner_radius')
func get_strob_band() -> float: return $строб.get_instance_shader_parameter('band') * 125.0
func get_strob_center() -> Vector2: return $строб.position
func get_strob_color() -> float: return $строб.get_instance_shader_parameter('color')
func get_strob_dir() -> float: return $строб.get_instance_shader_parameter('dir')
func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0
func get_strob_visible() -> bool: return $строб.visible
func get_strob_width() -> float: return $строб.get_instance_shader_parameter('width')
## Выставляет цвета для секторов
func set_band_colors(val: PackedColorArray):
var image: = Image.create(val.size(), 1, false, Image.FORMAT_RGBA8)
for x in val.size():
image.set_pixel(x, 0, val[x])
var tex: = ImageTexture.create_from_image(image)
material.set('shader_parameter/sec_colors', tex)
## Добавляет сектор запрета[br]
## [param id] - Индекс сектора запрета.[br]
@@ -82,35 +97,28 @@ func set_seczap(id: int, szv: Vector4):
func clear_all_seczap():
for child in get_children():
if child.name.begins_with("SECZAP"):
if child.name.begins_with('SECZAP'):
remove_child(child)
child.queue_free()
func set_seczap_color(id: int, color: Color):
func set_seczap_color(id: int, c: Color):
var seczap: = get_node('SECZAP%d' % id)
seczap.set_instance_shader_parameter('color', color)
seczap.set_instance_shader_parameter('color', c)
func set_view_mode(val: int):
if val == 1:
$строб.hide()
else:
$строб.show()
material.set('shader_parameter/mode', val)
var inner_radius = inner_radius_1 if val == 1 else inner_radius_0
material.set('shader_parameter/inner_radius', inner_radius)
func _on_settings_changed():
ant_color = ProjectSettings.get_setting('application/interfer/ant_color', ANT_COLOR)
ant_color *= Color(1.0, 1.0, 1.0, 0.0)
## Закрашивание по умолчанию блоков ФС цветами из настроек.
func set_def_colors():
var color0: Color = ProjectSettings.get_setting('application/interfer/default_color0', Color(0.38, 0.47, 0.51, 1.0))
var color1: Color = ProjectSettings.get_setting('application/interfer/default_color1', Color(0.39, 0.44, 0.50, 1.0))
color0 *= Color(1.0, 1.0, 1.0, 0.0)
color1 *= Color(1.0, 1.0, 1.0, 0.0)
var col_arr: Array = [color0, color1]
var col = false
for i in NUM_OF_RANGE:
for j in NUM_OF_DIRECTIONS:
fs_default_colors.append(col_arr[int(col)])
col = not col
col = not col
set_band_colors(fs_default_colors)
func _init_def_colors():
fs_default_colors.clear()
for i in ANTS_COUNT:
fs_default_colors.append(ant_color)

View File

@@ -1,25 +1,39 @@
[gd_scene load_steps=7 format=3 uid="uid://b5kjdyxuwsot5"]
[ext_resource type="Material" uid="uid://s6xe8igevnv2" path="res://shaders/antenas.tres" id="1_newdt"]
[ext_resource type="Shader" uid="uid://dhipoo0ju5ebg" path="res://shaders/antenas.gdshader" id="1_8cjpq"]
[ext_resource type="Script" uid="uid://b85scuflwlqom" path="res://scenes/diagram/diagram.gd" id="2_8xjuy"]
[ext_resource type="PackedScene" uid="uid://c73ahpv8uiuc7" path="res://scenes/diagram/sector.tscn" id="3_tgnog"]
[ext_resource type="Shader" uid="uid://k36g8tww5yo" path="res://shaders/sector.gdshader" id="4_obn6s"]
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_2bft1"]
size = Vector2(1600, 1200)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_oqtdt"]
shader = ExtResource("1_8cjpq")
shader_parameter/grid_cells_angle = 4
shader_parameter/grid_layers_radius = 7
shader_parameter/alpha = 0.5
shader_parameter/inner_radius = 0.36
shader_parameter/outer_radius = 1.0
shader_parameter/grid_line_width = 0.0025
shader_parameter/rotation = 0.0
shader_parameter/ffr = 0.15
shader_parameter/sfr = 0.0
shader_parameter/pfr = 0.015
shader_parameter/afr = 0.0
shader_parameter/ant_band_m = PackedInt32Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_lniyv"]
resource_local_to_scene = true
shader = ExtResource("4_obn6s")
[node name="canvas" type="Sprite2D"]
material = ExtResource("1_newdt")
texture = SubResource("PlaceholderTexture2D_2bft1")
centered = false
[node name="canvas" type="ColorRect"]
texture_filter = 1
material = SubResource("ShaderMaterial_oqtdt")
offset_right = 560.0
offset_bottom = 560.0
scale = Vector2(2, 2)
script = ExtResource("2_8xjuy")
SecZap = ExtResource("3_tgnog")
[node name="строб" parent="." instance=ExtResource("3_tgnog")]
material = SubResource("ShaderMaterial_lniyv")
position = Vector2(560, 560)
scale = Vector2(1100, 1100)
position = Vector2(280, 280)
scale = Vector2(560, 560)

View File

@@ -57,6 +57,7 @@ size_flags_vertical = 3
tooltip_text = "Включает принудительную помеху"
strips_rotation = 15.0
text = "СРН"
btn_tooltip = "Включает подавление радионавигации"
metadata/rfi_name = "srn"
[node name="btn_jtids" parent="grd_forced" groups=["группа-принудительно"] instance=ExtResource("4_7ys3c")]
@@ -64,8 +65,10 @@ editor_description = "Кнопка для принудительного вкл
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "Включает подавление каналов связи типа JTIDS"
strips_rotation = 15.0
text = "JTIDS"
btn_tooltip = "Включает подавление радиосвязи типа JTIDS"
metadata/rfi_name = "sprs"
[node name="btn_kupd" parent="grd_forced" groups=["группа-принудительно"] instance=ExtResource("4_7ys3c")]
@@ -75,6 +78,7 @@ size_flags_vertical = 3
tooltip_text = "Кнопка для принудительного включения группы секторов в режим КУПД"
strips_rotation = 15.0
text = "КУПД"
btn_tooltip = "Включает подавление каналов управления передачи данных"
metadata/rfi_name = "kupd"
[node name="btn_panika" parent="grd_forced" groups=["группа-принудительно"] instance=ExtResource("4_7ys3c")]
@@ -84,6 +88,7 @@ size_flags_vertical = 3
tooltip_text = "Кнопка для принудительного включения группы секторов в режим КУПД"
strips_rotation = 15.0
text = "Паника"
btn_tooltip = "Включает подавление JTIDS и КУПД"
metadata/rfi_name = "<off>"
[node name="btn_cancel" parent="grd_forced" groups=["прин-секторы-срн"] instance=ExtResource("4_7ys3c")]
@@ -92,4 +97,5 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 15.0
text = "Очистить"
btn_tooltip = "Выключает все сеансы помех"
metadata/rfi_name = "<off>"

View File

@@ -4,11 +4,13 @@ extends ScrollContainer
## Отображает список помех в таблице.
const CellLineEdit = preload('res://table/ячейка-2.tscn') ## Ячейка таблицы.
const TableHeader = preload('res://table/header.tscn') ## Ячейка заголовок таблицы.
const EmitLed = preload('res://scenes/frame-threats/emit-led.tscn') ## Ячейка символа излучения
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader , TableHeader , TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit , CellLineEdit , EmitLed ] ## Описание ряда.
const TABLE_HEADERS_TEXT = ['', 'Название', 'Пеленг', 'Состояние' , 'Излучение' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 80, 80, 130 , 90 ] ## Ширины колонок.
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader , TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit , CellLineEdit ] ## Описание ряда.
const TABLE_HEADERS_TEXT = ['', 'Название', 'Пеленг', 'Состояние' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 100, 90, 170 ] ## Ширины колонок.
## Состояние выполнения сеанса помехи
const INTERFER_STATE = {
@@ -37,7 +39,17 @@ const INTERFER_NAMES = {
'k1': 'K1',
'svm2': 'СВ-М2',
'ozp1': 'ОЗП-1',
'eprls': 'ЕПРЛС',}
'elrs': 'ЕЛРС' }
var SIGNALS_CONNECTIONS = [
[signaller, 'interfer_new', 'on_interfer_new'],
[signaller, 'interfer_off', 'on_interfer_off'],
[signaller, 'rto_threat_unsel', 'on_rto_threat_unsel'],
[signaller, 'rto_threat_sel', 'on_rto_threat_sel'],
[interfer, 'interfer_update', 'on_interfer_update'],
[interfer, 'interfer_recommendate', 'on_interfer_recommendate'],
[interfer, 'interfer_resized', 'on_interfer_resized'] ]
## Индексы колонок
@@ -45,10 +57,15 @@ const COLUMN_NUMBER = 0
const COLUMN_NAME = 1
const COLUMN_AOA = 2
const COLUMN_STATE = 3
const COLUMN_EMITED = 4
const TABLE_TEXT_ROWS = 4
var course = 0.0 ## Курс корабля
var color_emit: Color
var signal_conections: Array
var ecms: Dictionary ## Словарь с помехами
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()
func on_rto_threat_unsel(_th_id, _tbl_index): $table.clear_rows_selected()
## Вызывается при нажатии указателем мыши на выбранный ряд.
@@ -81,16 +98,20 @@ func on_rto_threat_sel(th_id: int, table_index):
# Called when the node enters the scene tree for the first time.
func _ready():
var table_index: = Dictionary()
signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind(table_index))
signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind(table_index))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(table_index))
interfer.connect('interfer_update', Callable(self, 'on_interfer_update').bind(table_index))
interfer.connect('interfer_recommendate', Callable(self, 'on_interfer_recommendate'))
for item in SIGNALS_CONNECTIONS:
item.append(table_index)
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
call_deferred('init_table')
var unit_nav = network.get_unit_instance('навигация')
unit_nav.connect('data_received', on_navi_data_received)
ProjectSettings.connect('settings_changed', on_settings_changed)
signaller.connect('режим_работа', connect_all)
signaller.connect('режим_контроль', disconnect_all)
signaller.connect('режим_журнал', disconnect_all)
signaller.connect('режим_эмс', disconnect_all)
signaller.connect('режим_эмс2', disconnect_all)
signaller.connect('режим_настройки', disconnect_all)
connect_all()
func init_table():
@@ -102,9 +123,19 @@ func init_table():
func on_interfer_update(ecm, table_index):
var row = map_th_to_row(ecm)
if table_index.has(ecm.ispp):
if not table_index.has(ecm.ispp): return
var i_row = table_index[ecm.ispp]
$table.set_row_text(i_row, row)
var power: bool = prd.get_fs_power(ecm.nmfs)
var emit_node = $table.get_node2(COLUMN_EMITED, i_row)
var emit_txr = emit_node.get_node('texture-led')
emit_txr.position.x = 40.0
ecm.active = power
if power:
emit_txr.visible = true
emit_txr.self_modulate = color_emit
else:
emit_txr.visible = false
func on_interfer_new(ecm, table_index):
@@ -116,18 +147,20 @@ func on_interfer_new(ecm, table_index):
var i_row = $table.get_rows_count()
$table.add_row(TABLE_ROW)
$table.set_row_text(i_row, row)
$table.set_row_editable(i_row, false)
disable_edit($table, TABLE_TEXT_ROWS, i_row)
$table.set_node_user_data(0, i_row, ecm)
table_index[ecm.ispp] = i_row
# Будем надеяться, что отложенные вызовы производятся в том же порядке
$table.call_deferred('clear_rows_selected')
$table.call_deferred('set_row_selected', i_row, true)
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
if not interfer.auto_enabled:
signaller.emit_signal('interfer_selected', ecm)
func on_interfer_off(ecm, table_index):
$table.remove_row(table_index[ecm.ispp])
if not table_index.has(ecm.ispp):
return
var i_row = table_index[ecm.ispp]
$table.remove_row(i_row)
rehash(table_index)
var sel_rows: Array
$table.get_selected_rows(sel_rows)
@@ -147,7 +180,7 @@ func rehash(table_index: Dictionary):
## Преобразует цель в строку таблицы
func map_th_to_row(ecm) -> Array:
var row: = Array()
row.resize(TABLE_ROW.size())
row.resize(TABLE_ROW.size() - 1)
row[COLUMN_NUMBER] = '%s' % ecm.ispp
row[COLUMN_NAME] = ''
if INTERFER_NAMES.has(ecm.krp):
@@ -162,7 +195,7 @@ func map_th_to_row(ecm) -> Array:
return row
func on_interfer_recommendate(ecm):
func on_interfer_recommendate(ecm, _tbl_index):
var sel_rows: Array
$table.get_selected_rows(sel_rows)
if not len(sel_rows): return
@@ -173,3 +206,48 @@ func on_interfer_recommendate(ecm):
func on_navi_data_received(data: Dictionary):
course = data.get('k', 0.0)
func on_settings_changed():
var json_col = ProjectSettings.get_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', '[1.0, 1.0, 1.0, 1.0]')
var arr_col = JSON.parse_string(json_col)
color_emit = Color(arr_col[0], arr_col[1], arr_col[2], arr_col[3])
## Отключает возможность редактирования LineEdit в таблице.[br]
## [param tbl] - таблица,[br]
## [param num_col] - номер колонки,[br]
## [param i_row] - номер столбца.[br]
func disable_edit(tbl, num_col: int, i_row: int):
for col in num_col:
var node: LineEdit = tbl.get_node2(col, i_row)
node.editable = false
func connect_all() -> void:
signal_conections.clear()
var table_index = SIGNALS_CONNECTIONS[0][3]
for item in SIGNALS_CONNECTIONS:
var proc = Callable(self, item[2]).bind(item[3])
var rc = item[0].connect(item[1], proc)
if rc == Error.OK:
signal_conections.append([item[0], item[1], proc])
else:
var ers = error_string(rc)
push_error('%s: %s %s %s' % [ers, item[0], item[1], item[2]])
signaller.emit_signal('connect_work_signal')
for ecm in ecms.values():
on_interfer_new(ecm, table_index)
func disconnect_all() -> void:
var table_index = SIGNALS_CONNECTIONS[0][3]
for item in signal_conections:
item[0].disconnect(item[1], item[2])
signal_conections.clear()
$table.clear_rows()
table_index.clear()
func on_interfer_resized(ecms_dic: Dictionary, _tbl_index) -> void:
ecms = ecms_dic

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://d012h4hxf2anf"]
[ext_resource type="Texture2D" uid="uid://b3woliae871je" path="res://data/отметка-неопред.png" id="1_0a4l0"]
[ext_resource type="Texture2D" uid="uid://blx6c1o1nogks" path="res://data/связь.png" id="1_0a4l0"]
[node name="emit-led" type="Control"]
layout_mode = 3
@@ -14,10 +14,11 @@ layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 26.0
offset_top = 11.0
offset_right = 3.0
offset_bottom = -12.0
offset_left = 25.0
offset_top = 15.0
offset_right = 17.0
offset_bottom = 7.0
grow_horizontal = 2
grow_vertical = 2
scale = Vector2(0.3, 0.3)
texture_normal = ExtResource("1_0a4l0")

View File

@@ -5,17 +5,19 @@ class_name scroll_threats extends ScrollContainer
const CellLineEdit = preload('res://table/ячейка-2.tscn') ## Ячейка таблицы.
const TableHeader = preload('res://table/header.tscn') ## Ячейка заголовок таблицы.
const EmitLed = preload('res://scenes/frame-threats/emit-led.tscn') ## Ячейка заголовок таблицы.
const EmitLed = preload('res://scenes/frame-threats/emit-led.tscn') ## Ячейка символа излучения
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader, TableHeader , TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit, EmitLed ] ## Описание ряда.
const TABLE_COLUMN_PARAM = ['id', 'aoa', 'freq', 'proto', 'emit' ] ## Параметры цели отображаемые в таблице.
const TABLE_HEADERS_TEXT = ['', 'Пеленг', 'Частота, МГц', 'Протокол', 'Помеха' ] ## Заголовки таблицы.
const TABLE_HEADERS_TEXT = ['Номер', 'Пеленг', 'Частота, МГц', 'Протокол', 'Помеха' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 70, 110, 140, 65] ## Ширины колонок.
const TABLE_TEXT_ROWS = 4
const EMIT_STATE_COL = 4
var color_emit: Color
## Снимает выделение цели.
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()
@@ -49,6 +51,7 @@ func _ready() -> void:
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind($table))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
ProjectSettings.connect('settings_changed', on_settings_changed)
call_deferred('init_table')
@@ -74,7 +77,7 @@ func on_threat_update(th, table_index: Dictionary):
emit_txr.self_modulate = Color.ORANGE
elif th.emit_state == 2:
emit_txr.visible = true
emit_txr.self_modulate = Color.RED
emit_txr.self_modulate = color_emit
@@ -128,3 +131,9 @@ func disable_edit(tbl, num_col: int, i_row: int):
for col in num_col:
var node: LineEdit = tbl.get_node2(col, i_row)
node.editable = false
func on_settings_changed():
var json_col = ProjectSettings.get_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', '[1.0, 1.0, 1.0, 1.0]')
var arr_col = JSON.parse_string(json_col)
color_emit = Color(arr_col[0], arr_col[1], arr_col[2], arr_col[3])

View File

@@ -13,6 +13,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "Откл."
btn_tooltip = "Выключает помеху"
disabled = true
metadata/rfi_name = "off"
@@ -22,6 +23,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "МЧМ-1"
btn_tooltip = "Включает помеху МЧМ-1"
disabled = true
metadata/rfi_name = "mchm1"
@@ -31,6 +33,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "СРН-И1"
btn_tooltip = "Включает помеху СРН-И1"
disabled = true
metadata/rfi_name = "srni1"
@@ -40,6 +43,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "СРН-М2"
btn_tooltip = "Включает помеху СРН-М2"
disabled = true
metadata/rfi_name = "srnm2"
@@ -49,6 +53,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "СРН-GPS"
btn_tooltip = "Включает помеху СРН-GPS"
disabled = true
metadata/rfi_name = "srngps"
@@ -58,6 +63,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ПД-М4"
btn_tooltip = "Включает помеху МП-М4"
disabled = true
metadata/rfi_name = "pdm4"
@@ -67,6 +73,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ПД-М2"
btn_tooltip = "Включает помеху МП-М2"
disabled = true
metadata/rfi_name = "pdm2"
@@ -76,6 +83,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ЛЧМ-1"
btn_tooltip = "Включает помеху ЛЧМ-1"
disabled = true
metadata/rfi_name = "lchm1"
@@ -85,6 +93,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ЛЧМ-2"
btn_tooltip = "Включает помеху ЛЧМ-2"
disabled = true
metadata/rfi_name = "lchm2"
@@ -94,6 +103,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ПД-М4С"
btn_tooltip = "Включает помеху ПД-М4C"
disabled = true
metadata/rfi_name = "pdm4s"
@@ -103,6 +113,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ПД-ЧМ"
btn_tooltip = "Включает помеху ПД-ЧМ"
disabled = true
metadata/rfi_name = "pdchm"
@@ -112,6 +123,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "СВ-И1"
btn_tooltip = "Включает помеху СВ-И1"
disabled = true
metadata/rfi_name = "svi1"
@@ -121,6 +133,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "K1"
btn_tooltip = "Включает помеху К1"
disabled = true
metadata/rfi_name = "k1"
@@ -130,6 +143,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "СВ-М2"
btn_tooltip = "Включает помеху СВ-М2"
disabled = true
metadata/rfi_name = "svm2"
@@ -139,6 +153,7 @@ size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ОЗП-1"
btn_tooltip = "Включает помеху ОЗП-1"
disabled = true
metadata/rfi_name = "ozp1"
@@ -147,6 +162,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 30.0
text = "ЕРЛС"
text = "ЕЛРС"
btn_tooltip = "Включает помеху ЕЛРС"
disabled = true
metadata/rfi_name = "eprls"
metadata/rfi_name = "elrs"

101
scenes/hranges/panel.gd Normal file
View File

@@ -0,0 +1,101 @@
@tool
extends PanelContainer
## Предназначено для отображения диапазонов на горизонтальной шкале
@export_range(0.0, 1.0) var gap_top: float = 0.05 ## Зазор сверху
@export_range(0.0, 1.0) var gap_bottom: float = 0.05 ## Зазор снизу
var ranges_save: Dictionary[StringName, Array] ## <имя диапазона>: [диапазон(x - начало, y - конец), цвет]
@export_file var image_file: String:
set(val):
image_file = val
if is_inside_tree():
_enter_tree()
@export var back_color: Color:
set(val):
back_color = val
if is_inside_tree():
_enter_tree()
func _enter_tree() -> void:
if ResourceLoader.exists(image_file):
$grid/image.texture = load(image_file)
$grid/canvas.self_modulate = back_color
## Добавляет новый диапазон.
func set_range(nm: StringName, x0: float, x1: float, col: Color) -> void:
ranges_save[nm] = [Vector2(x0, x1), col]
_on_resized()
func set_range_color(nm: StringName, col: Color):
if not ranges_save.has(nm):
push_error('нет такого диапазона: \"%s\"' % nm)
return false
ranges_save[nm][1] = col
var rng: = get_node_or_null(NodePath(nm))
if not rng:
push_error('нет такого элемента: \"%s\"' % nm)
return false
rng.color = col
return true
func clear_ranges():
var l0 = ranges_save.size()
ranges_save.clear()
var l1 = ranges_save.size()
_on_resized()
return l1 < l0
func del_range(nm: StringName) -> bool:
var rc = ranges_save.erase(nm)
_on_resized()
return rc
func _add_range_view(nm: StringName, x0: float, x1: float, col: Color):
var rng = Polygon2D.new()
var canvas = $grid/canvas
var canvas_size = canvas.size
var point0 = canvas_size * Vector2(x0, gap_bottom) ## лево низ
var point1 = canvas_size * Vector2(x0, 1.0 - gap_top) ## лево верх
var point2 = canvas_size * Vector2(x1, 1.0 - gap_top) ## право верх
var point3 = canvas_size * Vector2(x1, gap_bottom) ## право низ
rng.polygon = [point0, point1, point2, point3]
rng.name = nm
rng.color = col
canvas.add_child(rng)
## Удаляет заданный диапазон.
func _del_range_view(nm: StringName) -> void:
var canvas: = $grid/canvas
var rng: = canvas.get_node(NodePath(nm))
canvas.remove_child(rng)
rng.queue_free()
func _clear_ranges_view():
var canvas: = $grid/canvas
var range_views: = canvas.get_children()
for rng in range_views:
canvas.remove_child(rng)
rng.queue_free()
func _on_resized() -> void:
_clear_ranges_view()
for nm in ranges_save:
var range_save = ranges_save[nm]
var rng = range_save[0]
var col = range_save[1]
_add_range_view(nm, rng.x, rng.y, col)

View File

@@ -0,0 +1 @@
uid://jtio1scc72bl

38
scenes/hranges/panel.tscn Normal file
View File

@@ -0,0 +1,38 @@
[gd_scene load_steps=5 format=3 uid="uid://hr55mkcneaer"]
[ext_resource type="Script" uid="uid://jtio1scc72bl" path="res://scenes/hranges/panel.gd" id="1_pg3d7"]
[ext_resource type="Texture2D" uid="uid://c73tjrn8gr00o" path="res://data/Передатчик.png" id="2_ajqhv"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ajqhv"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_56wj8"]
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
[node name="panel" type="PanelContainer"]
offset_right = 400.0
offset_bottom = 45.0
theme_override_styles/panel = SubResource("StyleBoxEmpty_ajqhv")
script = ExtResource("1_pg3d7")
back_color = Color(0.601223, 0.601223, 0.601223, 1)
[node name="grid" type="GridContainer" parent="."]
layout_mode = 2
columns = 2
[node name="image" type="TextureRect" parent="grid"]
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 3
texture = ExtResource("2_ajqhv")
expand_mode = 3
[node name="canvas" type="PanelContainer" parent="grid"]
self_modulate = Color(0.601223, 0.601223, 0.601223, 1)
layout_mode = 2
size_flags_horizontal = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_56wj8")
[connection signal="resized" from="." to="." method="_on_resized"]

View File

@@ -97,8 +97,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 2"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[1]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[1]['TestPassed']"]
@@ -122,8 +122,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 3"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[2]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[2]['TestPassed']"]
@@ -147,8 +147,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 4"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[3]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[3]['TestPassed']"]
@@ -172,8 +172,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 5"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[4]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[4]['TestPassed']"]
@@ -197,8 +197,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 6"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[5]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[5]['TestPassed']"]
@@ -222,8 +222,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 7"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[6]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[6]['TestPassed']"]
@@ -247,8 +247,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 8"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[7]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[7]['TestPassed']"]
@@ -800,7 +800,7 @@ offset_right = 580.0
offset_bottom = 115.0
tooltip_text = "Плата АЦП ADCS500"
fname = "АЦП"
metadata/state = ["SelfTest[4].SystemList[0].DevList[1]['TestPassed']"]
metadata/state = ["SelfTest[0].SystemList[0].DevList[1]['TestPassed']"]
[node name="dsp" parent="." instance=ExtResource("4_mtf2n")]
layout_mode = 0
@@ -809,7 +809,7 @@ offset_right = 580.0
offset_bottom = 60.0
tooltip_text = "Плата цифровой обработки сигналов BPL"
fname = "Сигн. проц."
metadata/state = ["SelfTest[4].SystemList[0].DevList[0]['TestPassed']"]
metadata/state = ["SelfTest[0].SystemList[0].DevList[0]['TestPassed']"]
[node name="gen" parent="." instance=ExtResource("2_dmhrm")]
layout_mode = 2
@@ -827,8 +827,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Генератор"
metadata/value0 = "SelfTest[1].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/state = ["SelfTest[0].SystemList[2].DevList[0]['TestPassed']"]
[node name="rpu" parent="." instance=ExtResource("2_dmhrm")]
@@ -848,8 +848,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Приёмник 20...1000 МГц"
metadata/value0 = "SelfTest[1].SystemList[0].DevList[0]['TestPassed']"
metadata/value1 = "SelfTest[2].SystemList[0].DevList[0]['TestPassed']"
metadata/value0 = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']"
metadata/value1 = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[0].DevList[3]['TestPassed']"]
[connection signal="pressed" from="konverter/grid/kanal1" to="." method="_on_item_pressed"]

View File

@@ -1,7 +1,6 @@
[gd_scene load_steps=4 format=3 uid="uid://8ll27id5ajq1"]
[gd_scene load_steps=3 format=3 uid="uid://8ll27id5ajq1"]
[ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_151rh"]
[ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_4vyhj"]
[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_d7iti"]
[node name="pribor_afsp" type="Control"]
@@ -20,14 +19,6 @@ settings_path_to_url = "Адрес АФСП левого борта"
settings_path_to_wait_time = "Период опроса состояния АФСП, секунды"
metadata/DeviceName = &"Устройство РР левого борта"
[node name="request" type="HTTPRequest" parent="."]
use_threads = true
script = ExtResource("2_4vyhj")
request_url = null
[node name="timer" type="Timer" parent="request"]
autostart = true
[node name="bort" parent="." instance=ExtResource("3_d7iti")]
layout_mode = 0
offset_left = 24.0
@@ -36,7 +27,4 @@ offset_right = 604.0
offset_bottom = 1216.78
metadata/DeviceName = &"Устройство РР левого борта"
[connection signal="child_entered_tree" from="request" to="request" method="_on_child_entered_tree"]
[connection signal="request_completed" from="request" to="." method="_on_request_completed"]
[connection signal="timeout" from="request/timer" to="request" method="_on_request_timer"]
[connection signal="pressed" from="bort" to="." method="_on_item_pressed"]

View File

@@ -1,7 +1,6 @@
[gd_scene load_steps=4 format=3 uid="uid://5uv1idl3lqet"]
[gd_scene load_steps=3 format=3 uid="uid://5uv1idl3lqet"]
[ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_tfses"]
[ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_miwrd"]
[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_xpxb5"]
[node name="pribor_afsp" type="Control"]
@@ -20,14 +19,6 @@ settings_path_to_url = "Адрес АФСП правого борта"
settings_path_to_wait_time = "Период опроса состояния АФСП, секунды"
metadata/DeviceName = &"Устройство РР правого борта"
[node name="request" type="HTTPRequest" parent="."]
use_threads = true
script = ExtResource("2_miwrd")
request_url = null
[node name="timer" type="Timer" parent="request"]
autostart = true
[node name="bort" parent="." instance=ExtResource("3_xpxb5")]
layout_mode = 0
offset_left = 12.0
@@ -36,7 +27,4 @@ offset_right = 592.0
offset_bottom = 1130.0
metadata/DeviceName = &"Устройство РР правого борта"
[connection signal="child_entered_tree" from="request" to="request" method="_on_child_entered_tree"]
[connection signal="request_completed" from="request" to="." method="_on_request_completed"]
[connection signal="timeout" from="request/timer" to="request" method="_on_request_timer"]
[connection signal="pressed" from="bort" to="." method="_on_item_pressed"]

View File

@@ -10,88 +10,142 @@ class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd'
static var json_conv: JSON = JSON.new()
static var node_maper = load('res://scenes/контроль/node-maper.gd')
var ctrl_pos = 0
# SystemName: "gen" DevList - там состояние связи с генератором по кан шине
func _ready() -> void:
ProjectSettings.connect('settings_changed', on_settings_chaged)
on_settings_chaged()
# Подключаемся к сигналам в зависимости от борта
if this_afsp_name == 'Устройство РР левого борта':
scouting.response_received_afsp_left.connect(_on_response_received)
else:
scouting.response_received_afsp_right.connect(_on_response_received)
# При старте отрисовываем последние данные (если есть)
_on_press_device()
func on_settings_chaged():
$request.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path_to_url)
$request/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
tools.allways($request.request_url != null)
func _on_request_completed(result, _response_code, headers, body: PackedByteArray):
var unit_instance: = network.get_unit_instance(unit_name)
if result != 0:
var rs = $request.get_result_string(result)
log.error('\"%s\"' % rs)
if unit_instance.online:
unit_instance.online = false
unit_instance.emit_signal('line_changed', unit_instance)
# Обработка полученного ответа от rtr
func _on_response_received(response: String, success: bool) -> void:
if not success:
log.error('Ошибка запроса или нет связи: %s' % response)
_reset_ui_to_zero()
return
var json_str: String = body.get_string_from_utf8()
if not json_str:
push_error('не удаётся получить строку utf8 из данных (%s)' % headers)
if unit_instance.online:
unit_instance.online = false
unit_instance.emit_signal('line_changed', unit_instance)
return
var rc: = json_conv.parse(json_str)
if rc != Error.OK:
var err: = json_conv.get_error_message()
push_error('разбор json прерван - \"%s\" (%s)' % [err, headers])
if unit_instance.online:
unit_instance.online = false
unit_instance.emit_signal('line_changed', unit_instance)
# Парсим JSON строку
var parse_result = json_conv.parse(response)
if parse_result != OK:
var err = json_conv.get_error_message()
push_error('разбор json прерван - "%s"' % err)
_reset_ui_to_zero()
return
# Ищем имя прибора в JSON
var pp = []
tools.map_solid_to_array(prefix_path, pp)
var ret_val = [null, false, 0]
var pp_copy = pp.duplicate(true)
tools.get_value_by_path(json_conv.data, pp, ret_val)
if not ret_val[1]:
push_error('путь %s не найден (%s)' % [pp_copy, ret_val[2]])
_reset_ui_to_zero()
return
var received_afsp_name: StringName = ret_val[0]
# Проверяем, что ответ от нужного прибора
if this_afsp_name != received_afsp_name:
# TODO: Сюда попадаем, когда приходит от другого борта
#push_error('не известное устройство: \"%s\", ожидадось: \"%s\"' % [received_afsp_name, this_afsp_name])
# Ответ от другого борта - игнорируем
return
unit_instance.rx_tick = Time.get_ticks_msec()
if not unit_instance.online:
unit_instance.online = true
unit_instance.emit_signal('line_changed', unit_instance)
# Обновляем UI элементы из JSON
_update_ui(json_conv.data)
# Обновление интерфейса из JSON данных
func _update_ui(json_data: Dictionary) -> void:
# Конвертер
for child in $bort.get_node('konverter/grid').get_children():
node_maper.map_value_to_item(json_conv.data, child, 'value0')
node_maper.map_value_to_item(json_conv.data, child, 'value1')
node_maper.map_value_to_item(json_conv.data, child, 'value2')
node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
node_maper.map_value_to_item_animated(json_data, child, 'value0')
node_maper.map_value_to_item_animated(json_data, child, 'value1')
node_maper.map_value_to_item_animated(json_data, child, 'value2')
node_maper.map_error_codes_to_item_animated(json_data, child, 'state', 0)
# Антенна 1
for child in $bort.get_node('antenna1/grid').get_children():
node_maper.map_value_to_item(json_conv.data, child, 'value0')
node_maper.map_value_to_item(json_conv.data, child, 'value1')
node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
node_maper.map_value_to_item_animated(json_data, child, 'value0')
node_maper.map_value_to_item_animated(json_data, child, 'value1')
node_maper.map_error_codes_to_item_animated(json_data, child, 'state', 0)
# Антенна 2
for child in $bort.get_node('antenna2/grid').get_children():
node_maper.map_value_to_item(json_conv.data, child, 'value0')
node_maper.map_value_to_item(json_conv.data, child, 'value1')
node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
node_maper.map_value_to_item_animated(json_data, child, 'value0')
node_maper.map_value_to_item_animated(json_data, child, 'value1')
node_maper.map_error_codes_to_item_animated(json_data, child, 'state', 0)
# Остальные элементы
for child in $bort.get_children():
node_maper.map_value_to_item(json_conv.data, child, 'value0')
node_maper.map_value_to_item(json_conv.data, child, 'value1')
node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
node_maper.map_value_to_item_animated(json_data, child, 'value0')
node_maper.map_value_to_item_animated(json_data, child, 'value1')
node_maper.map_error_codes_to_item_animated(json_data, child, 'state', 0)
# Сброс всех UI элементов в 0 (при отсутствии данных)
func _reset_ui_to_zero() -> void:
# Конвертер
for child in $bort.get_node('konverter/grid').get_children():
_reset_item_value(child)
# Антенна 1
for child in $bort.get_node('antenna1/grid').get_children():
_reset_item_value(child)
# Антенна 2
for child in $bort.get_node('antenna2/grid').get_children():
_reset_item_value(child)
# Остальные элементы
for child in $bort.get_children():
_reset_item_value(child)
# Сброс конкретного элемента в 0
func _reset_item_value(item) -> void:
item.set('value0', 0)
item.set('value1', 0)
item.set('value2', 0)
item.set('state', 0)
# Отрисовывание при нажатии на прибор
func _on_press_device() -> void:
# Проверяем, есть ли сохраненные данные в rtr
var has_data = false
var last_response = ""
if this_afsp_name == 'Устройство РР левого борта':
has_data = scouting.has_afsp_left_success()
if has_data: last_response = scouting.get_afsp_left_response()
else:
has_data = scouting.has_afsp_right_success()
if has_data: last_response = scouting.get_afsp_right_response()
# Если есть данные - парсим и отображаем
if has_data and not last_response.is_empty():
var parse_result = json_conv.parse(last_response)
if parse_result == OK:
# Проверяем, что это данные именно от этого прибора
var pp = []
tools.map_solid_to_array(prefix_path, pp)
var ret_val = [null, false, 0]
tools.get_value_by_path(json_conv.data, pp, ret_val)
if ret_val[1] and ret_val[0] == this_afsp_name:
_update_ui(json_conv.data)
return
# Если данных нет или они не подходят - сбрасываем в 0
_reset_ui_to_zero()
## Вызывается при клике мыши на элементе.

View File

@@ -10,49 +10,47 @@ class_name pribor_rtr extends 'res://scenes/контроль/прибор.gd'
@export var settings_path2_to_url: String = '' ## Должно быть в ProjectSettings
@export var settings_path_to_wait_time: String = '' ## Должно быть в ProjectSettings
static var json_conv: JSON = JSON.new()
static var node_maper = load('res://scenes/контроль/node-maper.gd')
var ctrl_pos = 110
var bort_to_node_name = {}
var bort_to_unit_name = {}
func _ready() -> void:
ProjectSettings.connect('settings_changed', on_settings_changed)
scouting.response_received_bpo_left.connect(_on_response_received_left)
scouting.response_received_bpo_right.connect(_on_response_received_right)
on_settings_changed()
find_labels(self)
_on_press_device()
func on_settings_changed():
bort_to_node_name.merge({this_bpo1_name: 'grid_bpo_a1', this_bpo2_name: 'grid_bpo_a2'}, true)
bort_to_unit_name.merge({this_bpo1_name: unit_name1, this_bpo2_name: unit_name2})
$request1.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path1_to_url)
$request1/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
$request2.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path2_to_url)
$request2/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
assert($request1.request_url != null)
assert($request2.request_url != null)
bort_to_unit_name.merge({this_bpo1_name: unit_name1, this_bpo2_name: unit_name2}, true)
func _on_request_completed(result, _response_code, headers, body: PackedByteArray):
if result != 0:
var rs = $request1.get_result_string(result)
push_error('\"%s\"' % rs)
# Обработка ответа от первого бпо
func _on_response_received_left(response: String, success: bool) -> void:
if not success:
log.error('Ошибка запроса или нет связи (левый): %s' % response)
_reset_grid('grid_bpo_a1')
return
_parse_and_update_ui(response)
var json_str: = body.get_string_from_utf8()
if not json_str:
push_error('не удаётся получить строку из utf8-данных (%s)' % headers)
# Обработка ответа от второго бпо
func _on_response_received_right(response: String, success: bool) -> void:
if not success:
log.error('Ошибка запроса или нет связи (правый): %s' % response)
_reset_grid('grid_bpo_a2')
return
_parse_and_update_ui(response)
# Оригинальный парсинг из _on_request_completed
func _parse_and_update_ui(json_str: String) -> void:
var rc: = json_conv.parse(json_str)
if rc != Error.OK:
var err = json_conv.get_error_message()
push_error('разбор json прерван - \"%s\" (%s)' % [err, headers])
push_error('разбор json прерван - %s' % err)
return
var pp: = []
@@ -60,55 +58,114 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra
var ret_val = [null, false, 0]
var pp_copy = pp.duplicate(true)
tools.get_value_by_path(json_conv.data, pp, ret_val)
if not ret_val[1]:
push_error('путь %s не найден (%s)' % [pp_copy, ret_val[2]])
return
if not bort_to_node_name.has(ret_val[0]):
push_error('не известное устройство: \"%s\"' % ret_val[0])
var device_name: String = ret_val[0]
if not bort_to_node_name.has(device_name):
push_error('не известное устройство: %s' % device_name)
return
var node_name = bort_to_node_name[ret_val[0]]
var node_name = bort_to_node_name[device_name]
var bort_node = get_node(node_name)
var unit_name = bort_to_unit_name[ret_val[0]]
var unit_instance = network.get_unit_instance(unit_name)
unit_instance.rx_tick = Time.get_ticks_msec()
if not unit_instance.online:
unit_instance.online = true
unit_instance.emit_signal('line_changed', unit_instance)
# Обновляем UI только для конкретного грида
for item in bort_node.get_children():
node_maper.map_value_to_item(json_conv.data, item, 'state')
# Обновляем групповые индикаторы
_update_group_indicators_original()
# Оригинальное обновление групповых индикаторов
func _update_group_indicators_original() -> void:
# Сначала сбрасываем все
if has_node('yas_bpo_a1'):
$yas_bpo_a1.state = 0
if has_node('yas_bpo_a2'):
$yas_bpo_a2.state = 0
if has_node('mod_pit_g1'):
$mod_pit_g1.state = 0
# Проверяем обе группы и устанавливаем если есть активные
var items = get_tree().get_nodes_in_group('управляется-по-шине-1')
for node in items:
if node.state == 1:
if node.has_method('get') and node.get('state') == 1:
if has_node('yas_bpo_a1'):
$yas_bpo_a1.state = 1
break
items = get_tree().get_nodes_in_group('управляется-по-шине-2')
for node in items:
if node.state == 1:
if node.has_method('get') and node.get('state') == 1:
if has_node('yas_bpo_a2'):
$yas_bpo_a2.state = 1
break
items = get_tree().get_nodes_in_group('потребитель-питания')
for node in items:
if node.state == 1:
if node.has_method('get') and node.get('state') == 1:
if has_node('mod_pit_g1'):
$mod_pit_g1.state = 1
break
# Сброс конкретного грида
func _reset_grid(grid_name: String) -> void:
if has_node(grid_name):
for item in get_node(grid_name).get_children():
_reset_item_value(item)
_update_group_indicators_original()
# Сброс всех UI элементов в 0 (при отсутствии данных)
func _reset_ui_to_zero() -> void:
_reset_grid('grid_bpo_a1')
_reset_grid('grid_bpo_a2')
# Сброс конкретного элемента в 0
func _reset_item_value(item) -> void:
if item.has_method('set'):
item.set('value0', 0)
item.set('value1', 0)
item.set('value2', 0)
item.set('state', 0)
# Отрисовывание при нажатии на прибор
func _on_press_device() -> void:
# Проверяем левый борт
if scouting.has_bpo_left_success():
var response = scouting.get_bpo_left_response()
if not response.is_empty():
_parse_and_update_ui(response)
else:
_reset_grid('grid_bpo_a1')
# Проверяем правый борт
if scouting.has_bpo_right_success():
var response = scouting.get_bpo_right_response()
if not response.is_empty():
_parse_and_update_ui(response)
else:
_reset_grid('grid_bpo_a2')
func find_labels(node1: Node):
if node1 is Label:
if node1.name in ["lbl_rname", "rname"]:
if not node1.has_meta("tooltip_set"):
if node1.name in ['lbl_rname', 'rname']:
if not node1.has_meta('tooltip_set'):
ctrl_pos += 1
var box_number = ceili(float(ctrl_pos) / 10.0)
var position_number = ctrl_pos % 10
if position_number == 0:
position_number = 10
node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number]
node1.tooltip_text = 'Ящик - %d, Позиция - %d' % [box_number, position_number]
node1.mouse_filter = Control.MOUSE_FILTER_STOP
node1.set_meta("tooltip_set", true)
node1.set_meta('tooltip_set', true)
for child in node1.get_children():
find_labels(child)
## Вызывается при клике мыши на элементе.
func _on_item_pressed(block_a: Control):
var metas = block_a.get_meta_list()
for n in metas:
var _v = block_a.get_meta(n)

View File

@@ -1,9 +1,8 @@
[gd_scene load_steps=5 format=3 uid="uid://5uv1idl3lqea"]
[gd_scene load_steps=4 format=3 uid="uid://5uv1idl3lqea"]
[ext_resource type="Script" uid="uid://d0jwv5opi3mrk" path="res://scenes/pribor-afsp/pribor-bpo.gd" id="1_bhc4e"]
[ext_resource type="PackedScene" uid="uid://d3iqb5e4g81m5" path="res://scenes/контроль/элемент-г.tscn" id="2_jp6m0"]
[ext_resource type="PackedScene" uid="uid://p2suppildvq0" path="res://scenes/контроль/элемент-в.tscn" id="3_jcpjs"]
[ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="4_crej3"]
[node name="pribor_bpo" type="Control"]
layout_mode = 3
@@ -198,23 +197,3 @@ offset_bottom = 362.0
show_rname = false
self_size = Vector2i(50, 145)
fname = "Яч. связи"
[node name="request1" type="HTTPRequest" parent="."]
use_threads = true
script = ExtResource("4_crej3")
request_url = null
[node name="timer" type="Timer" parent="request1"]
autostart = true
[node name="request2" type="HTTPRequest" parent="."]
use_threads = true
script = ExtResource("4_crej3")
[node name="timer" type="Timer" parent="request2"]
autostart = true
[connection signal="request_completed" from="request1" to="." method="_on_request_completed"]
[connection signal="timeout" from="request1/timer" to="request1" method="_on_request_timer"]
[connection signal="request_completed" from="request2" to="." method="_on_request_completed"]
[connection signal="timeout" from="request2/timer" to="request2" method="_on_request_timer"]

View File

@@ -58,7 +58,7 @@ offset_right = 205.0
offset_bottom = 183.0
fname = "Модуль ФС"
rname = "A3"
metadata/fs = "fs_6"
metadata/fs = "fs_7"
[node name="ref_A5" parent="." groups=["default_reset", "fs_group"] instance=ExtResource("3_kqnvt")]
offset_left = 205.0
@@ -67,7 +67,7 @@ offset_right = 255.0
offset_bottom = 183.0
fname = "Модуль ФС"
rname = "A2"
metadata/fs = "fs_7"
metadata/fs = "fs_6"
[node name="ref_A7" parent="." groups=["default_reset"] instance=ExtResource("3_kqnvt")]
offset_left = 255.0

View File

@@ -16,11 +16,12 @@ func _ready() -> void:
unit_prd_k = prd_k_module.unit_control
var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier')
for temp in power_amplifier:
temp.value1 = -70
temp.value1 = -100
# Подписываемся на сигналы
signaller.conn(signaller.start_contol_device, Callable(self, '_on_start_control'))
unit_prd_k.connect('control_is_over', Callable(self, 'on_press_device'))
unit_prd_k.connect('status_updated', Callable(self, '_on_status_updated'))
find_labels(self)
# Устанавливаем начальный статус
_update_status_text(unit_prd_k.get_current_status())
on_press_device(unit_prd_k.self_name)
@@ -29,23 +30,17 @@ func _ready() -> void:
func _process(_delta: float) -> void:
if Engine.is_editor_hint():
return
set_frame($input_0, unit_prd_k.ems_g_sock_dic.ems_input_1)
set_frame($input_1, unit_prd_k.ems_g_sock_dic.ems_input_2)
set_frame($input_2, unit_prd_k.ems_g_sock_dic.ems_input_lit_1)
set_frame($output_0, unit_prd_k.ems_g_sock_dic.ems_output_1)
set_frame($output_1, unit_prd_k.ems_g_sock_dic.ems_output_2)
set_frame($output_2, unit_prd_k.ems_g_sock_dic.ems_output_lit_1)
func set_frame(node_frame: Node, val: int): node_frame.set_frame(val)
$input_0.set_frame(unit_prd_k.ems_g_sock_dic.ems_input_1)
$input_1.set_frame(unit_prd_k.ems_g_sock_dic.ems_input_2)
$input_2.set_frame(unit_prd_k.ems_g_sock_dic.ems_input_lit_1)
$output_0.set_frame(unit_prd_k.ems_g_sock_dic.ems_output_1)
$output_1.set_frame(unit_prd_k.ems_g_sock_dic.ems_output_2)
$output_2.set_frame(unit_prd_k.ems_g_sock_dic.ems_output_lit_1)
func _on_start_control() -> void:
set_default_state(get_tree().get_nodes_in_group('default_reset'))
set_default_state(get_tree().get_nodes_in_group('power_amplifier'))
find_labels(self)
await get_tree().create_timer(1.0).timeout
on_press_device(unit_prd_k.self_name)
static func set_default_state(default_reset_array_node: Array) -> void:
@@ -60,12 +55,6 @@ func _enter_tree() -> void:
_update_status_text(unit_prd_k.get_current_status())
func _exit_tree() -> void:
if Engine.is_editor_hint():
return
#prd_k_module.cmd_array.append([unit_prd_k.CmdCode.WRITE_ISA, [constants_k.ADDR_UG_LITERA_1, ug_work_1, constants_k.ADDR_UG_LITERA_2, ug_work_2, constants_k.ADDR_UG_LITERA_3, ug_work_3]])
static func temperature_fill(temperature_arr_node: Array, temperature_dic: Dictionary)->void:
for i_node_temperature in temperature_arr_node:
var temperature_meta: String = i_node_temperature.get_meta('um')
@@ -112,31 +101,19 @@ static func power_fill(pow_dic: Dictionary, fs_result: Dictionary, power_amplifi
func on_press_device(_name_davice: String) -> void:
var nodes_y5: Array = get_tree().get_nodes_in_group('y-5')
var node_ip_power_arr: Array = get_tree().get_nodes_in_group('power_supply')
var fs_nodes: Array = get_tree().get_nodes_in_group('fs_group')
var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier')
var default_reset_array_node: Array = get_tree().get_nodes_in_group('default_reset')
var module_fs_1: Node = $kasseta_fs_kd/ref_A2
var module_fs_6: Node = $kasseta_fs_kd/ref_A4
var dou_6: Node = $dou6_A7
var module_fs_7: Node = $kasseta_fs_kd/ref_A7
var dou_7: Node = $dou7_A8
if not is_inside_tree(): return
var control_data: Dictionary = unit_prd_k.get_control_results()
var for_control_result: Dictionary = {
'nodes_y5': nodes_y5,
'node_ip_power_arr': node_ip_power_arr,
'fs_nodes': fs_nodes,
'power_amplifier': power_amplifier,
'default_reset_array_node': default_reset_array_node,
'module_fs_1': module_fs_1,
'module_fs_6': module_fs_6,
'dou_6': dou_6,
'module_fs_7': module_fs_7,
'dou_7': dou_7,
}
for_control_result.merge(control_data, true)
on_control_result(for_control_result)
control_data['nodes_y5'] = get_tree().get_nodes_in_group('y-5')
control_data['node_ip_power_arr'] = get_tree().get_nodes_in_group('power_supply')
control_data['fs_nodes'] = get_tree().get_nodes_in_group('fs_group')
control_data['power_amplifier'] = get_tree().get_nodes_in_group('power_amplifier')
control_data['default_reset_array_node'] = get_tree().get_nodes_in_group('default_reset')
control_data['module_fs_1'] = $kasseta_fs_kd/ref_A2
control_data['module_fs_6'] = $kasseta_fs_kd/ref_A7
control_data['dou_6'] = $dou6_A7
control_data['module_fs_7'] = $kasseta_fs_kd/ref_A4
control_data['dou_7'] = $dou7_A8
on_control_result(control_data)
static func on_control_result(for_result_dic: Dictionary) -> void:
@@ -169,6 +146,7 @@ static func on_control_result(for_result_dic: Dictionary) -> void:
set_default_state(for_result_dic.default_reset_array_node)
set_default_state(for_result_dic.power_amplifier)
return
var result_dic: Dictionary = for_result_dic.result_dic
for f in for_result_dic.fs_nodes:
var fs_meta: String = f.get_meta('fs')
@@ -196,33 +174,33 @@ static func on_control_result(for_result_dic: Dictionary) -> void:
func find_labels(node1: Node):
if node1 is Label:
if node1.name in ["lbl_rname", "rname"]:
if not node1.has_meta("tooltip_set"):
if node1.name in ['lbl_rname', 'rname']:
if not node1.has_meta('tooltip_set'):
ctrl_pos += 1
var box_number = ceili(float(ctrl_pos) / 10.0)
var position_number = ctrl_pos % 10
if position_number == 0:
position_number = 10
node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number]
node1.tooltip_text = 'Ящик - %d, Позиция - %d' % [box_number, position_number]
node1.mouse_filter = Control.MOUSE_FILTER_STOP
node1.set_meta("tooltip_set", true)
node1.set_meta('tooltip_set', true)
for child in node1.get_children():
find_labels(child)
func _on_status_updated(status_text: String) -> void:
_update_status_text(status_text)
on_press_device(unit_prd_k.self_name)
func _update_status_text(text: String) -> void:
$control_result.text = text
# Можно добавить смену цвета в зависимости от статуса
if "Ошибка" in text or "неисправен" in text:
if 'Ошибка' in text or 'неисправен' in text:
$control_result.add_theme_color_override('font_color', Color.RED)
log.message(Logger.INFO, 'Прибор ПРД-%s неисправен' % [unit_prd_k.self_name])
elif "Ограничена" in text or "Предупреждение" in text:
elif 'Ограничена' in text or 'Предупреждение' in text:
$control_result.add_theme_color_override('font_color', Color.YELLOW)
elif "исправен" in text or "завершён" in text:
elif 'исправен' in text or 'завершён' in text:
$control_result.add_theme_color_override('font_color', Color.GREEN)
log.message(Logger.INFO, 'Прибор ПРД-%s исправен' % [unit_prd_k.self_name])
else:

View File

@@ -16,11 +16,12 @@ func _ready() -> void:
unit_prd_n = prd_n_module.unit_control
var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier')
for temp in power_amplifier:
temp.value1 = -70
temp.value1 = -100
# Подписываемся на сигналы
signaller.conn(signaller.start_contol_device, Callable(self, '_on_start_control'))
unit_prd_n.connect('control_is_over', Callable(self, 'on_press_device'))
unit_prd_n.connect('status_updated', Callable(self, '_on_status_updated'))
find_labels(self)
# Устанавливаем начальный статус
_update_status_text(unit_prd_n.get_current_status())
on_press_device(unit_prd_n.self_name)
@@ -29,13 +30,10 @@ func _ready() -> void:
func _process(_delta: float) -> void:
if Engine.is_editor_hint():
return
set_frame($input_0, unit_prd_n.ems_g_sock_dic.ems_input_1)
set_frame($input_1, unit_prd_n.ems_g_sock_dic.ems_input_2)
set_frame($output_0, unit_prd_n.ems_g_sock_dic.ems_output_1)
set_frame($output_1, unit_prd_n.ems_g_sock_dic.ems_output_2)
func set_frame(node_frame: Node, val: int): node_frame.set_frame(val)
$input_0.set_frame(unit_prd_n.ems_g_sock_dic.ems_input_1)
$input_1.set_frame(unit_prd_n.ems_g_sock_dic.ems_input_2)
$output_0.set_frame(unit_prd_n.ems_g_sock_dic.ems_output_1)
$output_1.set_frame(unit_prd_n.ems_g_sock_dic.ems_output_2)
func _on_start_control() -> void:
@@ -43,9 +41,6 @@ func _on_start_control() -> void:
set_default_state(get_tree().get_nodes_in_group('power_amplifier'))
for um in get_tree().get_nodes_in_group('power_amplifier'):
um.value0 = [0, 0, 0, 0, 0, 0]
find_labels(self)
await get_tree().create_timer(1.0).timeout
on_press_device(unit_prd_n.self_name)
static func set_default_state(default_reset_array_node: Array) -> void:
@@ -60,12 +55,6 @@ func _enter_tree() -> void:
_update_status_text(unit_prd_n.get_current_status())
func _exit_tree() -> void:
if Engine.is_editor_hint():
return
#prd_n_module.cmd_array.append([unit_prd_n.CmdCode.WRITE_ISA, [constants_n.ADDR_UG_LITERA_1, ug_work_1, constants_n.ADDR_UG_LITERA_2, ug_work_2]])
static func temperature_fill(temperature_arr_node: Array, temperature_dic: Dictionary)->void:
for i_node_temperature in temperature_arr_node:
var temperature_meta: String = i_node_temperature.get_meta('um')
@@ -103,6 +92,7 @@ static func power_fill(pow_dic: Dictionary, fs_result: Dictionary, power_amplifi
func on_press_device(_device_name: String) -> void:
if not is_inside_tree(): return
var nodes_y5: Array = get_tree().get_nodes_in_group('y-5')
var node_ip_power_arr: Array = get_tree().get_nodes_in_group('power_supply')
var fs_nodes: Array = get_tree().get_nodes_in_group('fs_group')
@@ -182,33 +172,33 @@ static func on_control_result(for_result_dic: Dictionary) -> void:
func find_labels(node1: Node):
if node1 is Label:
if node1.name in ["lbl_rname", "rname"]:
if not node1.has_meta("tooltip_set"):
if node1.name in ['lbl_rname', 'rname']:
if not node1.has_meta('tooltip_set'):
ctrl_pos += 1
var box_number = ceili(float(ctrl_pos) / 10.0)
var position_number = ctrl_pos % 10
if position_number == 0:
position_number = 10
node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number]
node1.tooltip_text = 'Ящик - %d, Позиция - %d' % [box_number, position_number]
node1.mouse_filter = Control.MOUSE_FILTER_STOP
node1.set_meta("tooltip_set", true)
node1.set_meta('tooltip_set', true)
for child in node1.get_children():
find_labels(child)
func _on_status_updated(status_text: String) -> void:
_update_status_text(status_text)
on_press_device(unit_prd_n.self_name)
func _update_status_text(text: String) -> void:
$control_result.text = text
# Можно добавить смену цвета в зависимости от статуса
if "Ошибка" in text or "неисправен" in text:
if 'Ошибка' in text or 'неисправен' in text:
$control_result.add_theme_color_override('font_color', Color.RED)
log.message(Logger.INFO, 'Прибор ПРД-%s неисправен' % [unit_prd_n.self_name])
elif "Ограничена" in text or "Предупреждение" in text:
elif 'Ограничена' in text or 'Предупреждение' in text:
$control_result.add_theme_color_override('font_color', Color.YELLOW)
elif "исправен" in text or "завершён" in text:
elif 'исправен' in text or 'завершён' in text:
$control_result.add_theme_color_override('font_color', Color.GREEN)
log.message(Logger.INFO, 'Прибор ПРД-%s исправен' % [unit_prd_n.self_name])
else:

View File

@@ -16,11 +16,12 @@ func _ready() -> void:
unit_prd_v = prd_v_module.unit_control
var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier')
for temp in power_amplifier:
temp.value1 = -70
temp.value1 = -100
# Подписываемся на сигналы
signaller.conn(signaller.start_contol_device, Callable(self, '_on_start_control'))
unit_prd_v.connect('control_is_over', Callable(self, 'on_press_device'))
unit_prd_v.connect('status_updated', Callable(self, '_on_status_updated'))
find_labels(self)
# Устанавливаем начальный статус
_update_status_text(unit_prd_v.get_current_status())
on_press_device(unit_prd_v.self_name)
@@ -29,13 +30,10 @@ func _ready() -> void:
func _process(_delta: float) -> void:
if Engine.is_editor_hint():
return
set_frame($input_0, unit_prd_v.ems_g_sock_dic.ems_input_1)
set_frame($input_1, unit_prd_v.ems_g_sock_dic.ems_input_2)
set_frame($output_0, unit_prd_v.ems_g_sock_dic.ems_output_1)
set_frame($output_1, unit_prd_v.ems_g_sock_dic.ems_output_2)
func set_frame(node_frame: Node, val: int): node_frame.set_frame(val)
$input_0.set_frame(unit_prd_v.ems_g_sock_dic.ems_input_1)
$input_1.set_frame(unit_prd_v.ems_g_sock_dic.ems_input_2)
$output_0.set_frame(unit_prd_v.ems_g_sock_dic.ems_output_1)
$output_1.set_frame(unit_prd_v.ems_g_sock_dic.ems_output_2)
func _on_start_control() -> void:
@@ -43,9 +41,6 @@ func _on_start_control() -> void:
set_default_state(get_tree().get_nodes_in_group('power_amplifier'))
for um in get_tree().get_nodes_in_group('power_amplifier'):
um.value0 = [0, 0, 0, 0, 0, 0]
find_labels(self)
await get_tree().create_timer(1.0).timeout
on_press_device(unit_prd_v.self_name)
static func set_default_state(default_reset_array_node: Array) -> void:
@@ -60,11 +55,6 @@ func _enter_tree() -> void:
_update_status_text(unit_prd_v.get_current_status())
func _exit_tree() -> void:
if Engine.is_editor_hint():
return
static func temperature_fill(temperature_arr_node: Array, temperature_dic: Dictionary)->void:
for i_node_temperature in temperature_arr_node:
var temperature_meta: String = i_node_temperature.get_meta('um')
@@ -101,6 +91,7 @@ static func power_fill(pow_dic: Dictionary, fs_result: Dictionary, power_amplifi
func on_press_device(_device_name: String) -> void:
if not is_inside_tree(): return
var nodes_y5: Array = get_tree().get_nodes_in_group('y-5')
var node_ip_power_arr: Array = get_tree().get_nodes_in_group('power_supply')
var fs_nodes: Array = get_tree().get_nodes_in_group('fs_group')
@@ -178,33 +169,33 @@ static func on_control_result(for_result_dic: Dictionary) -> void:
func find_labels(node1: Node):
if node1 is Label:
if node1.name in ["lbl_rname", "rname"]:
if not node1.has_meta("tooltip_set"):
if node1.name in ['lbl_rname', 'rname']:
if not node1.has_meta('tooltip_set'):
ctrl_pos += 1
var box_number = ceili(float(ctrl_pos) / 10.0)
var position_number = ctrl_pos % 10
if position_number == 0:
position_number = 10
node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number]
node1.tooltip_text = 'Ящик - %d, Позиция - %d' % [box_number, position_number]
node1.mouse_filter = Control.MOUSE_FILTER_STOP
node1.set_meta("tooltip_set", true)
node1.set_meta('tooltip_set', true)
for child in node1.get_children():
find_labels(child)
func _on_status_updated(status_text: String) -> void:
_update_status_text(status_text)
on_press_device(unit_prd_v.self_name)
func _update_status_text(text: String) -> void:
$control_result.text = text
# Можно добавить смену цвета в зависимости от статуса
if "Ошибка" in text or "неисправен" in text:
if 'Ошибка' in text or 'неисправен' in text:
$control_result.add_theme_color_override('font_color', Color.RED)
log.message(Logger.INFO, 'Прибор ПРД-%s неисправен' % [unit_prd_v.self_name])
elif "Ограничена" in text or "Предупреждение" in text:
elif 'Ограничена' in text or 'Предупреждение' in text:
$control_result.add_theme_color_override('font_color', Color.YELLOW)
elif "исправен" in text or "завершён" in text:
elif 'исправен' in text or 'завершён' in text:
$control_result.add_theme_color_override('font_color', Color.GREEN)
log.message(Logger.INFO, 'Прибор ПРД-%s исправен' % [unit_prd_v.self_name])
else:

View File

@@ -1,126 +1,116 @@
@tool
class_name pribor_uf extends 'res://scenes/контроль/прибор.gd'
signal control_is_over(device_name: String) # Когда контроль завершен
enum STATE_VAL {NONE = 0, GOOD = 1, ERROR = 2}
const DEV_LIST: Array = ['00:1f.6', '07:00.0', '08:00.0', '0b:00.0']
const USB_TRACKERBALL: String = '13ba:0018'
const REVFF: String = '(rev ff)'
var unit_uf: Object
var uf_control: Object
var ctrl_pos = 100
func _ready() -> void:
if Engine.is_editor_hint(): return
signaller.conn(signaller.start_contol_device, Callable(self, '_on_start_contol_device'))
unit_uf = network.get_unit_instance('уарэп-эмс')
unit_uf.connect('line_changed', on_line_changed)
on_line_changed()
#control_vk()
control_ems(unit_uf.status)
status_uf()
uf_control = get_parent().uf_control
signaller.connect('update_uf_serviceability', on_update_uf_serviceability)
var uf_status = uf_control.get_current_status()
control_ems(uf_status)
find_labels(self)
func _on_start_contol_device():
on_line_changed()
control_ems(unit_uf.status) # проверка ЭМС ячеек
status_uf() # отслеживание состояния прибора
func on_update_uf_serviceability(_state: int):
control_ems(uf_control.get_current_status())
func on_line_changed():
if unit_uf.online: # проверка ЯУ, внутреннего коммутатора и ИП-5Б
#func control_vk() -> void:
#var out_usb_str = ''
#var out_pci_str = ''
#var out_usb = []
#var out_pci = []
#
#OS.execute('lsusb', [], out_usb) # TODO: Не переносимое, платформозависимое
#for element in out_usb:
#out_usb_str += element
#
#OS.execute('lspci', [], out_pci) # TODO: Не переносимое, платформозависимое
#for element in out_pci:
#out_pci_str += element
#
#out_usb_str = out_usb_str.split('\n')
#out_pci_str = out_pci_str.split('\n')
#
#var i: int = 0
#
#for string in out_usb_str:
#if USB_TRACKERBALL in string:
#i += 1
#break
#for string in out_pci_str:
#for item in DEV_LIST:
#if item in string:
#i += 1
#if REVFF in string:
#i -= 1
#break
#
#if i == (DEV_LIST.size() + 1):
#$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.GOOD
#else:
#$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.ERROR
func control_ems(status: Dictionary) -> void:
if status['УФ-онлайн']:
$ref_uf/ref_kassetav13/ref_A7_YAU07.state = STATE_VAL.GOOD
$ref_uf/ref_kassetav13/ref_A3_IP5B.state = STATE_VAL.GOOD
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.GOOD
$ref_uf/ref_kassetav13/ref_A9_ESW.state = STATE_VAL.GOOD
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.GOOD ## заглушка для зеленения ВК-110
$ref_uf/ref_kassetav13/ref_A4_KEMS.state = STATE_VAL.GOOD if status['КЭМС-Б1'] else STATE_VAL.ERROR
$ref_uf/ref_kassetav13/ref_A5_EMS.state = STATE_VAL.GOOD if status['ЭМС-Б1'] else STATE_VAL.ERROR
$ref_uf/ref_kassetav13/ref_A6_EMS.state = STATE_VAL.GOOD if status['ЭМС-Б2'] else STATE_VAL.ERROR
$ref_uf/ref_kassetav13/ref_A12_IP27B.state = STATE_VAL.GOOD if status['ИП220-27Б'] else STATE_VAL.ERROR
else:
$ref_uf/ref_kassetav13/ref_A7_YAU07.state = STATE_VAL.ERROR
$ref_uf/ref_kassetav13/ref_A3_IP5B.state = STATE_VAL.NONE
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.NONE
$ref_uf/ref_kassetav13/ref_A9_ESW.state = STATE_VAL.NONE
$ref_uf/ref_kassetav13/ref_A4_KEMS.state = STATE_VAL.NONE
$ref_uf/ref_kassetav13/ref_A5_EMS.state = STATE_VAL.NONE
$ref_uf/ref_kassetav13/ref_A6_EMS.state = STATE_VAL.NONE
$ref_uf/ref_kassetav13/ref_A3_IP5B.state = STATE_VAL.NONE
$ref_uf/ref_kassetav13/ref_A9_ESW.state = STATE_VAL.NONE
$ref_uf/ref_kassetav13/ref_A12_IP27B.state = STATE_VAL.NONE
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.NONE
status_uf(status)
func control_vk() -> void:
var out_usb_str = ''
var out_pci_str = ''
var out_usb = []
var out_pci = []
OS.execute('lsusb', [], out_usb) # TODO: Не переносимое, платформозависимое
for element in out_usb:
out_usb_str += element
OS.execute('lspci', [], out_pci) # TODO: Не переносимое, платформозависимое
for element in out_pci:
out_pci_str += element
out_usb_str = out_usb_str.split('\n')
out_pci_str = out_pci_str.split('\n')
var i: int = 0
for string in out_usb_str:
if USB_TRACKERBALL in string:
i += 1
break
for string in out_pci_str:
for item in DEV_LIST:
if item in string:
i += 1
if REVFF in string:
i -= 1
break
if i == (DEV_LIST.size() + 1):
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.GOOD
else:
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.ERROR
func control_ems(status: Array) -> void:
if status:
$ref_uf/ref_kassetav13/ref_A4_KEMS.state = STATE_VAL.GOOD if ((status[0] >> 0) & 1) and ((status[0] >> 3) & 1) else STATE_VAL.ERROR
$ref_uf/ref_kassetav13/ref_A5_EMS.state = STATE_VAL.GOOD if ((status[0] >> 1) & 1) and ((status[0] >> 4) & 1) else STATE_VAL.ERROR
$ref_uf/ref_kassetav13/ref_A6_EMS.state = STATE_VAL.GOOD if ((status[0] >> 2) & 1) and ((status[0] >> 5) & 1) else STATE_VAL.ERROR
$ref_uf/ref_kassetav13/ref_A12_IP27B.state = STATE_VAL.GOOD if ((status[2] >> 6) & 1) else STATE_VAL.ERROR
func status_uf() -> void:
var status_bu: int = $ref_uf/ref_bu1/ref_A8_BU.state
var status_yau: int = $ref_uf/ref_kassetav13/ref_A7_YAU07.state
var status_kyems: int = $ref_uf/ref_kassetav13/ref_A4_KEMS.state
var status_yems0: int = $ref_uf/ref_kassetav13/ref_A5_EMS.state
var status_yems1: int = $ref_uf/ref_kassetav13/ref_A6_EMS.state
var status_ip5: int = $ref_uf/ref_kassetav13/ref_A3_IP5B.state
var status_ip27: int = $ref_uf/ref_kassetav13/ref_A12_IP27B.state
if (status_yau == 1) and (status_bu == 1) and (status_kyems == 1) \
and (status_yems0 == 1) and (status_yems1 == 1) and (status_ip5 == 1) and (status_ip27 == 1):
func status_uf(status_uf_dic: Dictionary) -> void:
var is_ok: bool = true
if not status_uf_dic['УФ-онлайн']:
$lbl_header2.text = 'Ожидание связи с ЯУ-07Б'
$lbl_header2.modulate = Color.WHITE
elif status_uf_dic['УФ-онлайн']:
for socket in status_uf_dic:
if not status_uf_dic[socket]:
is_ok = false
if is_ok:
$lbl_header2.text = 'Прибор исправен'
$lbl_header2.modulate = Color.GREEN
else:
elif not is_ok:
$lbl_header2.text = 'Прибор неисправен'
$lbl_header2.modulate = Color.RED
$lbl_header2.visible = true
emit_signal('control_is_over', unit_uf.name)
func find_labels(node1: Node):
if node1 is Label:
if node1.name in ["lbl_rname", "rname"]:
if not node1.has_meta("tooltip_set"):
if node1.name in ['lbl_rname', 'rname']:
if not node1.has_meta('tooltip_set'):
ctrl_pos += 1
var box_number = ceili(float(ctrl_pos) / 10.0)
var position_number = ctrl_pos % 10
if position_number == 0:
position_number = 10
node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number]
node1.tooltip_text = 'Ящик - %d, Позиция - %d' % [box_number, position_number]
node1.mouse_filter = Control.MOUSE_FILTER_STOP
node1.set_meta("tooltip_set", true)
node1.set_meta('tooltip_set', true)
for child in node1.get_children():
find_labels(child)

View File

@@ -0,0 +1,93 @@
class_name UFControl extends Node
signal update_uf_serviceability(status: int)
#region Константы и переменные
enum StatusIndex {SOCKETS = 0, IP_220_27B = 2}
enum STATE_VAL {NONE = 0, GOOD = 1, ERROR = 2}
var unit_uf: Object
var uf_status: Dictionary = {'УФ-онлайн': false, 'КЭМС-Б1': false, 'ЭМС-Б1': false, 'ЭМС-Б2': false, 'ИП220-27Б': false}
var _self_name: String
var _serviceability: int = STATE_VAL.NONE
var serviceability_uf: int:
get:
return _serviceability
set(value):
if value != _serviceability:
_serviceability = value
signaller.emit_signal('update_uf_serviceability', value)
#endregion
#region Инициализация
func _init(name_uf: String) -> void:
_self_name = name_uf
unit_uf = network.get_unit_instance(_self_name)
unit_uf.connect('line_changed', on_line_changed)
unit_uf.connect('data_received', on_data_received)
#endregion
#region Обработчики сигналов
func on_line_changed(status: Object) -> void:
'''Обработка изменения состояния линии связи'''
uf_status['УФ-онлайн'] = status.online
update_serviceability()
func on_data_received(yau: Object) -> void:
'''Обработка полученных данных от УФ'''
var new_ems_status = control_ems(yau.status)
var status_changed = false
# Обновляем только ключи КЭМС/ЭМС, сохраняя 'УФ-онлайн'
for key in ['КЭМС-Б1', 'ЭМС-Б1', 'ЭМС-Б2', 'ИП220-27Б']:
var old_value = uf_status.get(key, false)
var new_value = new_ems_status.get(key, false)
if old_value != new_value:
uf_status[key] = new_value
status_changed = true
if status_changed:
update_serviceability()
#endregion
#region Статус и сервисабельность
func get_current_status() -> Dictionary:
'''Получение текущего статуса (только для чтения)'''
return uf_status.duplicate(true)
func is_operational() -> bool:
'''Проверка, все ли системы работают нормально'''
return serviceability_uf and uf_status.get('УФ-онлайн', false)
func update_serviceability() -> void:
'''Обновление общего статуса сервисабельности'''
var new_serviceability: int = STATE_VAL.GOOD
# Проверяем онлайн-статус
if uf_status.get('УФ-онлайн', false) == false:
new_serviceability = STATE_VAL.NONE
else:
# Проверяем все статусы КЭМС/ЭМС
for key in ['КЭМС-Б1', 'ЭМС-Б1', 'ЭМС-Б2', 'ИП220-27Б']:
if uf_status.get(key, true) == false:
new_serviceability = STATE_VAL.ERROR
break
# Новое значение через setter
self.serviceability_uf = new_serviceability
#endregion
#region Вспомогательные методы
static func control_ems(status: Array) -> Dictionary:
'''Анализ статусов КЭМС/ЭМС'''
var status_dic: Dictionary = {}
if status.is_empty() or status.size() < 3:
return status_dic
status_dic['КЭМС-Б1'] = bool((status[StatusIndex.SOCKETS] >> 0) & 1) and bool((status[StatusIndex.SOCKETS] >> 3) & 1)
status_dic['ЭМС-Б1'] = bool((status[StatusIndex.SOCKETS] >> 1) & 1) and bool((status[StatusIndex.SOCKETS] >> 4) & 1)
status_dic['ЭМС-Б2'] = bool((status[StatusIndex.SOCKETS] >> 2) & 1) and bool((status[StatusIndex.SOCKETS] >> 5) & 1)
status_dic['ИП220-27Б'] = bool((status[StatusIndex.IP_220_27B] >> 6) & 1)
return status_dic
#endregion

View File

@@ -0,0 +1 @@
uid://b6avo0uvwrxnj

View File

@@ -0,0 +1,285 @@
extends Label
enum DEVICE_STATE {
NONE, # Нет связи
GOOD, # Исправно
ERR # Отказ
}
enum DEVICE_STATUS {
ONLINE, # Связь есть
STATUS, # Статус исправности
CONTROL # Контроль завершен
}
const STATUS_CONFIG := {
DEVICE_STATE.NONE: {'text': 'Нет связи', 'color': Color.WHITE, 'font_color': Color.BLACK},
DEVICE_STATE.GOOD: {'text': 'Исправно', 'color': Color.GREEN, 'font_color': Color.BLACK},
DEVICE_STATE.ERR: {'text': 'Отказ', 'color': Color.RED, 'font_color': Color.WHITE}
}
class DeviceObserver:
var device_name: String
var status: Array = [false, false, false] # [online, operational, control_complete]
var last_results: Dictionary = {}
func update_online_state(online: bool) -> bool:
if status[DEVICE_STATUS.ONLINE] != online:
status[DEVICE_STATUS.ONLINE] = online
return true
return false
func update_control_results(results: Dictionary) -> bool:
var changed := false
if results.get('is_over_control', false):
# Контроль завершен - проверяем все результаты
var all_ok := true
for key in results:
if key != 'is_over_control' and not results[key]:
all_ok = false
break
if status[DEVICE_STATUS.STATUS] != all_ok or status[DEVICE_STATUS.CONTROL] != true:
status[DEVICE_STATUS.STATUS] = all_ok
status[DEVICE_STATUS.CONTROL] = true
changed = true
else:
# Контроль в процессе - проверяем базовые параметры
var basic_ok: bool = results.get('block_kasseta', false) and \
results.get('block_ip', false) and \
results.get('temperature', true)
if status[DEVICE_STATUS.STATUS] != basic_ok or status[DEVICE_STATUS.CONTROL] != false:
status[DEVICE_STATUS.STATUS] = basic_ok
status[DEVICE_STATUS.CONTROL] = false
changed = true
return changed
var device_observers: Dictionary = {}
var overall_prd_state: DEVICE_STATE = DEVICE_STATE.NONE
var status_uf: int = DEVICE_STATE.NONE # Статус УФ (УАРЭП-ЭМС)
func _ready() -> void:
tooltip_text = 'Нет связи с приборами комплекса'
add_theme_color_override('font_color', Color.BLACK)
# Инициализация наблюдателей
_initialize_observers()
# Подписка на сигналы ПРД модулей
for prd_module in prd.prd_dict.values():
# Подключаемся к контролю ПРД
if prd_module.unit_control:
prd_module.unit_control.connect('control_results_updated', Callable(self, '_on_prd_control_results').bind(prd_module))
# Подключаемся к онлайн-статусу ЯУ-07
if prd_module.unit_yau07:
prd_module.unit_yau07.connect('line_changed', Callable(self, '_on_prd_online_changed').bind(prd_module))
# Подписка на УФ
signaller.connect('update_uf_serviceability', _on_uf_status_receive)
# Инициализация начального состояния
_recalculate_overall_state()
func _initialize_observers() -> void:
var device_names := [
'уарэп-яу07-1н', 'уарэп-яу07-1в', 'уарэп-яу07-1к',
'уарэп-яу07-2н', 'уарэп-яу07-2в', 'уарэп-яу07-2к',
'уарэп-яу07-3н', 'уарэп-яу07-3в', 'уарэп-яу07-3к',
'уарэп-яу07-4н', 'уарэп-яу07-4в', 'уарэп-яу07-4к'
]
for device_name in device_names:
device_observers[device_name] = DeviceObserver.new()
device_observers[device_name].device_name = device_name
func _on_prd_online_changed(line_status: Object, prd_module: Object) -> void:
var online: bool = line_status.online
var observer: DeviceObserver = device_observers.get(prd_module.prd_name)
if observer and observer.update_online_state(online):
_recalculate_overall_state()
func _on_prd_control_results(results: Dictionary, prd_module: Object) -> void:
var observer: DeviceObserver = device_observers.get(prd_module.prd_name)
if observer and observer.update_control_results(results):
_recalculate_overall_state()
func _on_uf_status_receive(unit_uf_status: int) -> void:
if status_uf != unit_uf_status:
status_uf = unit_uf_status
_recalculate_overall_state()
func _recalculate_overall_state() -> void:
var new_state := DEVICE_STATE.NONE
# Проверяем статус ПРД
var prd_state := DEVICE_STATE.NONE
var has_online_prd := false
var all_prd_operational := true
for observer in device_observers.values():
if observer.status[DEVICE_STATUS.ONLINE]:
has_online_prd = true
if observer.status[DEVICE_STATUS.CONTROL]:
if not observer.status[DEVICE_STATUS.STATUS]:
all_prd_operational = false
break
else:
if not observer.status[DEVICE_STATUS.STATUS]:
all_prd_operational = false
if has_online_prd:
if all_prd_operational:
prd_state = DEVICE_STATE.GOOD
else:
prd_state = DEVICE_STATE.ERR
else:
prd_state = DEVICE_STATE.NONE
# Комбинируем статусы по правилу:
# 1. Если хоть один ERROR → ERROR
# 2. Если нет ERROR и хоть один GOOD → GOOD
# 3. Иначе → NONE
if prd_state == DEVICE_STATE.ERR or status_uf == DEVICE_STATE.ERR:
new_state = DEVICE_STATE.ERR
elif prd_state == DEVICE_STATE.GOOD or status_uf == DEVICE_STATE.GOOD:
new_state = DEVICE_STATE.GOOD
else:
new_state = DEVICE_STATE.NONE
if overall_prd_state != new_state:
overall_prd_state = new_state
_update_display()
func _update_display() -> void:
var config: Dictionary = STATUS_CONFIG[overall_prd_state].duplicate()
text = config.text
modulate = config.color
add_theme_color_override('font_color', config.font_color)
tooltip_text = _get_tooltip_text()
func _get_tooltip_text() -> String:
var tooltip := ''
# Получаем статистику по ПРД
var prd_summary = _get_prd_summary()
var uf_status_str = _get_uf_status_text()
match overall_prd_state:
DEVICE_STATE.NONE:
tooltip = 'Нет исправных систем в комплексе'
DEVICE_STATE.GOOD:
tooltip = 'Комплекс исправен'
DEVICE_STATE.ERR:
tooltip = 'Обнаружены неисправности в комплексе'
tooltip += '\n\nСтатус ПРД систем: ' + prd_summary
tooltip += '\nСтатус УФ: ' + uf_status_str
# Детализация по источникам статуса
tooltip += '\n\nСостояние систем:'
# ПРД системы
var prd_ok_count = 0
var prd_total = 0
for observer in device_observers.values():
if observer.status[DEVICE_STATUS.ONLINE]:
prd_total += 1
if observer.status[DEVICE_STATUS.STATUS]:
prd_ok_count += 1
tooltip += '\nПРД: %d/%d исправно' % [prd_ok_count, prd_total]
# УФ система
tooltip += '\nУФ: ' + _get_uf_status_text()
return tooltip
func _get_prd_summary() -> String:
var online_count := 0
var operational_count := 0
for observer in device_observers.values():
if observer.status[DEVICE_STATUS.ONLINE]:
online_count += 1
if observer.status[DEVICE_STATUS.STATUS]:
operational_count += 1
if online_count == 0:
return 'Нет связи'
else:
return '%d/%d исправно' % [operational_count, online_count]
func _get_uf_status_text() -> String:
match status_uf:
DEVICE_STATE.NONE:
return 'Нет данных'
DEVICE_STATE.GOOD:
return 'Исправен'
DEVICE_STATE.ERR:
return 'Неисправен'
_:
return 'Неизвестно'
func _has_prd_errors() -> bool:
for observer in device_observers.values():
if observer.status[DEVICE_STATUS.ONLINE] and not observer.status[DEVICE_STATUS.STATUS]:
return true
return false
func _has_operational_prd() -> bool:
for observer in device_observers.values():
if observer.status[DEVICE_STATUS.ONLINE] and observer.status[DEVICE_STATUS.STATUS]:
return true
return false
# Публичные методы для получения информации
func get_device_status(device_name: String) -> Dictionary:
var observer: DeviceObserver = device_observers.get(device_name)
if observer:
return {
'online': observer.status[DEVICE_STATUS.ONLINE],
'operational': observer.status[DEVICE_STATUS.STATUS],
'control_complete': observer.status[DEVICE_STATUS.CONTROL],
'last_results': observer.last_results.duplicate(),
'status_uf': status_uf
}
return {}
func get_overall_status() -> Dictionary:
var online_count := 0
var operational_count := 0
var control_complete_count := 0
for observer in device_observers.values():
if observer.status[DEVICE_STATUS.ONLINE]:
online_count += 1
if observer.status[DEVICE_STATUS.STATUS]:
operational_count += 1
if observer.status[DEVICE_STATUS.CONTROL]:
control_complete_count += 1
return {
'overall_state': overall_prd_state,
'online_devices': online_count,
'operational_devices': operational_count,
'total_devices': device_observers.size(),
'control_complete_devices': control_complete_count,
'uf_status': status_uf
}

View File

@@ -0,0 +1 @@
uid://b5ykwyk5vpi6

View File

@@ -1,6 +1,6 @@
extends Label
enum PRD_STATE {
enum DEVICE_STATE {
NONE, # Нет связи
GOOD, # Исправно
ERR # Отказ
@@ -12,10 +12,17 @@ enum DEVICE_STATUS {
CONTROL # Контроль завершен
}
# Состояния сервиса для RTR устройств
enum RTR_SERVICEABILITY {
NO_CONNECTION = 0, # Нет связи
PASSED = 1, # Все тесты пройдены
ERROR = 2 # Есть ошибки
}
const STATUS_CONFIG := {
PRD_STATE.NONE: {"text": "Нет связи", "color": Color.WHITE, "font_color": Color.BLACK},
PRD_STATE.GOOD: {"text": "Исправно", "color": Color.GREEN, "font_color": Color.BLACK},
PRD_STATE.ERR: {"text": "Отказ", "color": Color.RED, "font_color": Color.WHITE}
DEVICE_STATE.NONE: {'text': 'Нет связи', 'color': Color.WHITE, 'font_color': Color.BLACK},
DEVICE_STATE.GOOD: {'text': 'Исправно', 'color': Color.GREEN, 'font_color': Color.BLACK},
DEVICE_STATE.ERR: {'text': 'Отказ', 'color': Color.RED, 'font_color': Color.WHITE}
}
class DeviceObserver:
@@ -23,6 +30,9 @@ class DeviceObserver:
var status: Array = [false, false, false] # [online, operational, control_complete]
var last_results: Dictionary = {}
# Для RTR устройств
var rtr_serviceability: int = RTR_SERVICEABILITY.NO_CONNECTION
func update_online_state(online: bool) -> bool:
if status[DEVICE_STATUS.ONLINE] != online:
status[DEVICE_STATUS.ONLINE] = online
@@ -31,7 +41,6 @@ class DeviceObserver:
func update_control_results(results: Dictionary) -> bool:
var changed := false
last_results = results.duplicate()
if results.get('is_over_control', false):
# Контроль завершен - проверяем все результаты
@@ -57,12 +66,30 @@ class DeviceObserver:
changed = true
return changed
func update_rtr_serviceability(state: int) -> bool:
if rtr_serviceability != state:
rtr_serviceability = state
# Обновляем operational статус на основе RTR
var new_operational = (state == RTR_SERVICEABILITY.PASSED)
if status[DEVICE_STATUS.STATUS] != new_operational:
status[DEVICE_STATUS.STATUS] = new_operational
return true
return false
var device_observers: Dictionary = {}
var overall_prd_state: PRD_STATE = PRD_STATE.NONE
var overall_prd_state: DEVICE_STATE = DEVICE_STATE.NONE
var status_uf: int = DEVICE_STATE.NONE # Статус УФ (УАРЭП-ЭМС)
# Добавляем наблюдателей для RTR устройств
var rtr_device_names := [
'rtr_afsp_left',
'rtr_afsp_right',
'rtr_bpo' # Общий для левого и правого БПО
]
func _ready() -> void:
tooltip_text = 'Нет связи с приборами комплекса'
add_theme_color_override("font_color", Color.BLACK)
add_theme_color_override('font_color', Color.BLACK)
# Инициализация наблюдателей
_initialize_observers()
@@ -77,14 +104,21 @@ func _ready() -> void:
prd_module.unit_yau07.connect('line_changed', Callable(self, '_on_prd_online_changed').bind(prd_module))
# Подписка на УФ
var unit_uf = network.get_unit_instance('уарэп-эмс')
if unit_uf:
unit_uf.data_received.connect(Callable(self, '_on_uf_status_receive'))
signaller.connect('update_uf_serviceability', _on_uf_status_receive)
# Подписка на сигналы RTR (через signaller или напрямую)
_connect_rtr_signals()
# Инициализация начального состояния
_recalculate_overall_state()
func _connect_rtr_signals() -> void:
scouting.connect('serviceability_rtr_afsp_left', Callable(self, '_on_rtr_afsp_left_serviceability'))
scouting.connect('serviceability_rtr_afsp_right', Callable(self, '_on_rtr_afsp_right_serviceability'))
scouting.connect('serviceability_rtr_bpo', Callable(self, '_on_rtr_bpo_serviceability'))
func _initialize_observers() -> void:
var device_names := [
'уарэп-яу07-1н', 'уарэп-яу07-1в', 'уарэп-яу07-1к',
@@ -97,6 +131,69 @@ func _initialize_observers() -> void:
device_observers[device_name] = DeviceObserver.new()
device_observers[device_name].device_name = device_name
# Инициализируем наблюдателей для RTR устройств
for rtr_name in rtr_device_names:
device_observers[rtr_name] = DeviceObserver.new()
device_observers[rtr_name].device_name = rtr_name
# Обработчики сигналов RTR
func _on_rtr_afsp_left_serviceability(state: int) -> void:
var observer: DeviceObserver = device_observers.get('rtr_afsp_left')
if not observer:
return
var changed = false
if observer.update_rtr_serviceability(state):
changed = true
var is_online = (state != RTR_SERVICEABILITY.NO_CONNECTION)
if observer.update_online_state(is_online):
changed = true
if changed:
_recalculate_overall_state()
else:
_update_display()
func _on_rtr_afsp_right_serviceability(state: int) -> void:
var observer: DeviceObserver = device_observers.get('rtr_afsp_right')
if not observer:
return
var changed = false
if observer.update_rtr_serviceability(state):
changed = true
var is_online = (state != RTR_SERVICEABILITY.NO_CONNECTION)
if observer.update_online_state(is_online):
changed = true
if changed:
_recalculate_overall_state()
else:
_update_display()
func _on_rtr_bpo_serviceability(state: int) -> void:
var observer: DeviceObserver = device_observers.get('rtr_bpo')
if not observer:
return
var changed = false
if observer.update_rtr_serviceability(state):
changed = true
var is_online = (state != RTR_SERVICEABILITY.NO_CONNECTION)
if observer.update_online_state(is_online):
changed = true
if changed:
_recalculate_overall_state()
else:
_update_display()
func _on_prd_online_changed(line_status: Object, prd_module: Object) -> void:
var online: bool = line_status.online
@@ -111,41 +208,76 @@ func _on_prd_control_results(results: Dictionary, prd_module: Object) -> void:
_recalculate_overall_state()
func _on_uf_status_receive(_unit_uf: Object) -> void:
# Логика для УФ (раскомментируй если нужно)
# var KEMS_B = ((unit_uf.status[0] >> 0) & 1) and ((unit_uf.status[0] >> 3) & 1)
# var EMS_B_1 = ((unit_uf.status[0] >> 1) & 1) and ((unit_uf.status[0] >> 4) & 1)
# var EMS_B_2 = ((unit_uf.status[0] >> 2) & 1) and ((unit_uf.status[0] >> 5) & 1)
# var IP27B = ((unit_uf.status[2] >> 6) & 1)
# var uf_operational = KEMS_B and EMS_B_1 and EMS_B_2 and IP27B
# signaller.emit_signal('update_uf_serviceability', uf_operational)
pass
func _on_uf_status_receive(unit_uf_status: int) -> void:
if status_uf != unit_uf_status:
status_uf = unit_uf_status
_recalculate_overall_state()
func _recalculate_overall_state() -> void:
var new_state := PRD_STATE.NONE
var has_online_devices := false
var all_operational := true
var new_state := DEVICE_STATE.NONE
for observer in device_observers.values():
# Проверяем статус ПРД
var prd_state := DEVICE_STATE.NONE
var has_online_prd := false
var all_prd_operational := true
for observer_key in device_observers.keys():
# Пропускаем RTR устройства при подсчете ПРД
if observer_key.begins_with('rtr_'):
continue
var observer = device_observers[observer_key]
if observer.status[DEVICE_STATUS.ONLINE]:
has_online_devices = true
has_online_prd = true
if observer.status[DEVICE_STATUS.CONTROL]:
# Если контроль завершен - строгая проверка
if not observer.status[DEVICE_STATUS.STATUS]:
all_operational = false
all_prd_operational = false
break
else:
# Если контроль в процессе - мягкая проверка
if not observer.status[DEVICE_STATUS.STATUS]:
all_operational = false
# Не прерываем, чтобы проверить все устройства
all_prd_operational = false
if has_online_devices:
new_state = PRD_STATE.GOOD if all_operational else PRD_STATE.ERR
if has_online_prd:
if all_prd_operational:
prd_state = DEVICE_STATE.GOOD
else:
new_state = PRD_STATE.NONE
prd_state = DEVICE_STATE.ERR
else:
prd_state = DEVICE_STATE.NONE
# Проверяем статус RTR устройств
var rtr_state := DEVICE_STATE.NONE
var has_online_rtr := false
var all_rtr_operational := true
for rtr_name in rtr_device_names:
var observer = device_observers.get(rtr_name)
if observer and observer.status[DEVICE_STATUS.ONLINE]:
has_online_rtr = true
if not observer.status[DEVICE_STATUS.STATUS]:
all_rtr_operational = false
if has_online_rtr:
if all_rtr_operational:
rtr_state = DEVICE_STATE.GOOD
else:
rtr_state = DEVICE_STATE.ERR
else:
rtr_state = DEVICE_STATE.NONE
# Комбинируем статусы по правилу:
# 1. Если хоть один ERROR → ERROR
# 2. Если нет ERROR и хоть один GOOD → GOOD
# 3. Иначе → NONE
if prd_state == DEVICE_STATE.ERR or status_uf == DEVICE_STATE.ERR or rtr_state == DEVICE_STATE.ERR:
new_state = DEVICE_STATE.ERR
elif prd_state == DEVICE_STATE.GOOD or status_uf == DEVICE_STATE.GOOD or rtr_state == DEVICE_STATE.GOOD:
new_state = DEVICE_STATE.GOOD
else:
new_state = DEVICE_STATE.NONE
if overall_prd_state != new_state:
overall_prd_state = new_state
@@ -154,23 +286,153 @@ func _recalculate_overall_state() -> void:
func _update_display() -> void:
var config: Dictionary = STATUS_CONFIG[overall_prd_state].duplicate()
text = config.text
modulate = config.color
add_theme_color_override("font_color", config.font_color)
add_theme_color_override('font_color', config.font_color)
tooltip_text = _get_tooltip_text()
func _get_tooltip_text() -> String:
var tooltip := ''
# Получаем статистику по ПРД
var prd_summary = _get_prd_summary()
var uf_status_str = _get_uf_status_text()
var rtr_summary = _get_rtr_summary()
match overall_prd_state:
PRD_STATE.NONE:
return "Нет связи с приборами комплекса"
PRD_STATE.GOOD:
return "Все приборы комплекса исправны"
PRD_STATE.ERR:
return "Обнаружены неисправности в комплексе"
DEVICE_STATE.NONE:
tooltip = 'Нет исправных систем в комплексе'
DEVICE_STATE.GOOD:
tooltip = 'Комплекс исправен'
DEVICE_STATE.ERR:
tooltip = 'Обнаружены неисправности в комплексе'
tooltip += '\n\nСтатус ПРД систем: ' + prd_summary
tooltip += '\nСтатус УФ: ' + uf_status_str
tooltip += '\nСтатус RTR: ' + rtr_summary
# Детализация по источникам статуса
tooltip += '\n\nСостояние систем:'
# ПРД системы
var prd_ok_count = 0
var prd_total = 0
for observer_key in device_observers.keys():
if observer_key.begins_with('rtr_'):
continue
var observer = device_observers[observer_key]
if observer.status[DEVICE_STATUS.ONLINE]:
prd_total += 1
if observer.status[DEVICE_STATUS.STATUS]:
prd_ok_count += 1
tooltip += '\nПРД: %d/%d исправно' % [prd_ok_count, prd_total]
# УФ система
tooltip += '\nУФ: ' + _get_uf_status_text()
# RTR системы
tooltip += '\nRTR:'
for rtr_name in rtr_device_names:
var observer = device_observers.get(rtr_name)
if observer:
var status_text = _get_rtr_status_text(observer.rtr_serviceability)
var display_name = _get_rtr_display_name(rtr_name)
tooltip += '\n - %s: %s' % [display_name, status_text]
return tooltip
func _get_rtr_summary() -> String:
var online_count := 0
var operational_count := 0
for rtr_name in rtr_device_names:
var observer = device_observers.get(rtr_name)
if observer and observer.status[DEVICE_STATUS.ONLINE]:
online_count += 1
if observer.status[DEVICE_STATUS.STATUS]:
operational_count += 1
if online_count == 0:
return 'Нет связи'
else:
return '%d/%d исправно' % [operational_count, online_count]
func _get_rtr_status_text(state: int) -> String:
match state:
RTR_SERVICEABILITY.NO_CONNECTION:
return 'Нет связи'
RTR_SERVICEABILITY.PASSED:
return 'Исправен'
RTR_SERVICEABILITY.ERROR:
return 'Ошибка'
_:
return "Неизвестное состояние"
return 'Неизвестно'
func _get_rtr_display_name(rtr_key: String) -> String:
match rtr_key:
'rtr_afsp_left':
return 'АФСП Л'
'rtr_afsp_right':
return 'АФСП П'
'rtr_bpo':
return 'РТР'
_:
return rtr_key.replace('rtr_', '')
func _get_prd_summary() -> String:
var online_count := 0
var operational_count := 0
for observer_key in device_observers.keys():
if observer_key.begins_with('rtr_'):
continue
var observer = device_observers[observer_key]
if observer.status[DEVICE_STATUS.ONLINE]:
online_count += 1
if observer.status[DEVICE_STATUS.STATUS]:
operational_count += 1
if online_count == 0:
return 'Нет связи'
else:
return '%d/%d исправно' % [operational_count, online_count]
func _get_uf_status_text() -> String:
match status_uf:
DEVICE_STATE.NONE:
return 'Нет данных'
DEVICE_STATE.GOOD:
return 'Исправен'
DEVICE_STATE.ERR:
return 'Неисправен'
_:
return 'Неизвестно'
func _has_prd_errors() -> bool:
for observer_key in device_observers.keys():
if observer_key.begins_with('rtr_'):
continue
var observer = device_observers[observer_key]
if observer.status[DEVICE_STATUS.ONLINE] and not observer.status[DEVICE_STATUS.STATUS]:
return true
return false
func _has_operational_prd() -> bool:
for observer_key in device_observers.keys():
if observer_key.begins_with('rtr_'):
continue
var observer = device_observers[observer_key]
if observer.status[DEVICE_STATUS.ONLINE] and observer.status[DEVICE_STATUS.STATUS]:
return true
return false
# Публичные методы для получения информации
@@ -178,10 +440,12 @@ func get_device_status(device_name: String) -> Dictionary:
var observer: DeviceObserver = device_observers.get(device_name)
if observer:
return {
"online": observer.status[DEVICE_STATUS.ONLINE],
"operational": observer.status[DEVICE_STATUS.STATUS],
"control_complete": observer.status[DEVICE_STATUS.CONTROL],
"last_results": observer.last_results.duplicate()
'online': observer.status[DEVICE_STATUS.ONLINE],
'operational': observer.status[DEVICE_STATUS.STATUS],
'control_complete': observer.status[DEVICE_STATUS.CONTROL],
'last_results': observer.last_results.duplicate(),
'status_uf': status_uf,
'rtr_serviceability': observer.rtr_serviceability if device_name.begins_with('rtr_') else -1
}
return {}
@@ -191,7 +455,10 @@ func get_overall_status() -> Dictionary:
var operational_count := 0
var control_complete_count := 0
for observer in device_observers.values():
for observer_key in device_observers.keys():
if observer_key.begins_with('rtr_'):
continue
var observer = device_observers[observer_key]
if observer.status[DEVICE_STATUS.ONLINE]:
online_count += 1
if observer.status[DEVICE_STATUS.STATUS]:
@@ -200,9 +467,11 @@ func get_overall_status() -> Dictionary:
control_complete_count += 1
return {
"overall_state": overall_prd_state,
"online_devices": online_count,
"operational_devices": operational_count,
"total_devices": device_observers.size(),
"control_complete_devices": control_complete_count
'overall_state': overall_prd_state,
'online_devices': online_count,
'operational_devices': operational_count,
'total_devices': device_observers.size() - len(rtr_device_names), # Исключаем RTR
'control_complete_devices': control_complete_count,
'uf_status': status_uf,
'rtr_status': _get_rtr_summary()
}

View File

@@ -1 +1 @@
uid://b5ykwyk5vpi6
uid://q7k2yihg057j

View File

@@ -23,3 +23,17 @@ func _enter_tree() -> void:
func on_setting_changed():
var ext_cu = ProjectSettings.get_setting('application/config/Внешнее управление', false)
get_parent().get_node('remote_control').visible = ext_cu
apply_colors()
func apply_colors():
var is_light: bool = ProjectSettings.get_setting('application/config/Цвет темы программы', false)
var style = StyleBoxFlat.new()
if is_light:
style.bg_color = Color.DARK_GRAY
add_theme_stylebox_override('tabbar_background', style)
add_theme_stylebox_override('panel', style)
else:
style.bg_color = Color(0.12, 0.12, 0.12)
add_theme_stylebox_override('tabbar_background', style)
add_theme_stylebox_override('panel', style)

View File

@@ -1,52 +1,38 @@
[gd_scene load_steps=20 format=3 uid="uid://3slb0i3pvowc"]
[gd_scene load_steps=15 format=3 uid="uid://3slb0i3pvowc"]
[ext_resource type="Script" uid="uid://bvo6tcreqyuex" path="res://scenes/tabs-switch/tab-switch.gd" id="1_fg0vd"]
[ext_resource type="PackedScene" uid="uid://b276iygic5itk" path="res://scenes/работа/работа.tscn" id="2_u7p16"]
[ext_resource type="PackedScene" uid="uid://lwmw4egynmd1" path="res://scenes/контроль/контроль.tscn" id="3_txp0s"]
[ext_resource type="PackedScene" uid="uid://trt0q8th3bn2" path="res://scenes/журнал/журнал.tscn" id="4_cu5k8"]
[ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/эмс/эмс.tscn" id="5_u71bh"]
[ext_resource type="PackedScene" uid="uid://musb21x2u0xs" path="res://scenes/эмс2/эмс2.tscn" id="6_41d34"]
[ext_resource type="PackedScene" uid="uid://musb21x2u0xs" path="res://scenes/эмс-тг/эмс-тг.tscn" id="6_41d34"]
[ext_resource type="PackedScene" uid="uid://bnptm4rlp60dq" path="res://scenes/настройки/настройки.tscn" id="6_i8iv3"]
[ext_resource type="Script" uid="uid://b5ykwyk5vpi6" path="res://scenes/tabs-switch/lbl_ready.gd" id="8_tidwt"]
[ext_resource type="Script" uid="uid://roajn6c6wvc1" path="res://scenes/tabs-switch/тренаж_режим.gd" id="9_41d34"]
[ext_resource type="Script" uid="uid://q7k2yihg057j" path="res://scenes/tabs-switch/lbl_ready.gd" id="8_tidwt"]
[ext_resource type="Script" uid="uid://roajn6c6wvc1" path="res://scenes/tabs-switch/тренаж-режим.gd" id="9_41d34"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tidwt"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_41d34"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_cw2ss"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nmdfd"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_vap7n"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_vap7n"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_o1r22"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nmdfd"]
bg_color = Color(0.061, 100, 0.051, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cw2ss"]
bg_color = Color(0.473976, 0.473976, 0.473976, 1)
bg_color = Color(0.47451, 0.47451, 0.47451, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nmdfd"]
bg_color = Color(0, 100, 0, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_41d34"]
bg_color = Color(0.39, 100, 0.327, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_imu1q"]
[node name="panel" type="Panel"]
offset_right = 1600.0
offset_bottom = 1200.0
theme_override_styles/panel = SubResource("StyleBoxEmpty_tidwt")
[node name="tab_switch" type="TabContainer" parent="."]
layout_mode = 0
offset_right = 1600.0
offset_bottom = 1200.0
tooltip_text = "Переключает режимы работы программы"
theme_override_styles/tab_focus = SubResource("StyleBoxEmpty_41d34")
theme_override_styles/tab_disabled = SubResource("StyleBoxEmpty_cw2ss")
theme_override_styles/tabbar_background = SubResource("StyleBoxEmpty_nmdfd")
theme_override_styles/panel = SubResource("StyleBoxEmpty_vap7n")
theme_override_styles/tabbar_background = SubResource("StyleBoxFlat_vap7n")
theme_override_styles/panel = SubResource("StyleBoxFlat_vap7n")
current_tab = 0
script = ExtResource("1_fg0vd")
@@ -102,10 +88,9 @@ focus_mode = 0
theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_colors/font_pressed_color = Color(0, 0, 0, 1)
theme_override_styles/hover_pressed = SubResource("StyleBoxFlat_nmdfd")
theme_override_styles/hover = SubResource("StyleBoxFlat_cw2ss")
theme_override_styles/pressed = SubResource("StyleBoxFlat_41d34")
theme_override_styles/normal = SubResource("StyleBoxFlat_imu1q")
theme_override_styles/pressed = SubResource("StyleBoxFlat_nmdfd")
theme_override_styles/normal = SubResource("StyleBoxFlat_41d34")
toggle_mode = true
text = "Тренаж"
script = ExtResource("9_41d34")

View File

@@ -1,11 +1,11 @@
extends Button
func _ready():
connect("toggled", Callable(self, "_on_button_toggled"))
connect('toggled', Callable(self, '_on_button_toggled'))
func _on_button_toggled(mode: bool):
if mode:
tooltip_text = "Режим \"Тренаж\" задействован\nТекущее состояние: включено"
tooltip_text = 'Режим \"Тренаж\" задействован\nТекущее состояние: включено'
else:
tooltip_text = "Задейстовать режим \"Тренаж\"\nТекущее состояние: отключено"
tooltip_text = 'Задейстовать режим \"Тренаж\"\nТекущее состояние: отключено'

View File

@@ -2,6 +2,9 @@
extends CanvasGroup
class_name MercatorTileMap
const VECTOR00: = Vector2(0, 0)
const VECTOR11: = Vector2(1, 1)
## Отображение карт WEB Mercator
#http://10.1.1.220/osm_tiles/0/0/0.png
@@ -26,10 +29,9 @@ const TILE_REQUEST_NAME: = 'tile_request_%d'
@export_color_no_alpha() var back_color: = Color.BLACK
@export var show_ship_radius: bool = true
@export var ship_radius_km: float = 8.0
@onready var scale_label: String
@onready var coordinates_label: String
@onready var threat_mark: PackedScene = load("res://scenes/tilemap/threat.tscn")
@onready var ship_mark: PackedScene = load("res://scenes/tilemap/ship_mark.tscn")
@onready var threat_mark: PackedScene = load('res://scenes/tilemap/threat.tscn')
@onready var ship_mark: PackedScene = load('res://scenes/tilemap/ship-mark.tscn')
var ship_id := 9999
var ship_instance: Node2D = null
const default_size: = 400.0
@@ -89,7 +91,7 @@ var _marks: Dictionary = {}
var _req_count: = 0
var image: = Image.new()
var image_load_proc: Callable
var now: = 0
var now: = 0.0
var visible_marks_count: = 0
var border1: ImageTexture
var border2: ImageTexture
@@ -227,9 +229,11 @@ func _input(e) -> void:
if e.button_index == MOUSE_BUTTON_WHEEL_DOWN:
if (not is_out_border1) and (not is_out_border2):
increment_zoom(-zoom_step, lmp)
update_scale_label()
queue_redraw()
elif e.button_index == MOUSE_BUTTON_WHEEL_UP:
increment_zoom( zoom_step, lmp)
update_scale_label()
queue_redraw()
if e.button_index == MOUSE_BUTTON_LEFT:
_dragging = e.pressed
@@ -256,22 +260,12 @@ func _input(e) -> void:
signaller.emmit(signaller.map_user_panning)
func multiply_zoom(multiplier: float, pivot: Vector2) -> void:
var p1: = screen_to_world(_xyz, pivot)
_xyz.z = clampf(_xyz.z * multiplier, min_zoom_level, max_zoom_level)
var p2: = screen_to_world(_xyz, pivot)
_xyz.x -= p2.x - p1.x
_xyz.y -= p2.y - p1.y
update_scale_label()
func increment_zoom(increment: float, pivot: Vector2) -> void:
var p1: = screen_to_world(_xyz, pivot)
_xyz.z = clampf(_xyz.z + increment, min_zoom_level, max_zoom_level)
var p2: = screen_to_world(_xyz, pivot)
_xyz.x -= p2.x - p1.x
_xyz.y -= p2.y - p1.y
update_scale_label()
func set_zoom(zoom: float, pivot: Vector2) -> void:
@@ -280,14 +274,13 @@ func set_zoom(zoom: float, pivot: Vector2) -> void:
var p2: = screen_to_world(_xyz, pivot)
_xyz.x -= p2.x - p1.x
_xyz.y -= p2.y - p1.y
update_scale_label()
func _draw() -> void:
# Рисование плиток
var z: float = min(max_zoom_level, _xyz.z)
var t1: = screen_to_tile(Vector2(0, 0), z)
var t2: = screen_to_tile($canvas.size, z) + Vector2(1, 1)
var t1: = screen_to_tile(VECTOR00, z)
var t2: = screen_to_tile($canvas.size, z) + VECTOR11
is_out_border1 = true
is_out_border2 = true
for tx in range(t1.x, t2.x):
@@ -373,17 +366,15 @@ func _process(delta) -> void:
remove_child(req)
req.queue_free()
_req_count -= 1
push_error('запрос \"%s\" не отправлен' % tile.url) #TODO: For Deugs
push_error('запрос \"%s\" не отправлен' % tile.url)
if _queue.is_empty():
emit_signal('load_completed')
update_scale_label()
func process_online(result):
# ERROR: res://scenes/tilemap/tilemap.gd:396 - Invalid access to property or key 'online' on a base object of type 'Nil'.
var unit_instance: = network.get_unit_instance('уарэп-карта')
if not unit_instance: return
if not unit_instance: return true
if result != HTTPRequest.RESULT_SUCCESS:
if unit_instance.online:
@@ -403,9 +394,8 @@ func _response(result, code, _headers: Array, body: PackedByteArray, req, tile:
remove_child(req)
req.queue_free()
if process_online(result):
if not process_online(result):
_queue[tile.i] = tile
else:
return
if code == 404:
@@ -413,7 +403,7 @@ func _response(result, code, _headers: Array, body: PackedByteArray, req, tile:
return
if Error.OK != image_load_proc.call(body):
push_error('не удалось получить изображение (неверный формат?) из \"%s\"' % tile.url)
push_error('не удалось получить изображение (неверный формат?) из \"%s\" (%d байт)' % [tile.url, body.size()])
return
tile.texture = ImageTexture.create_from_image(image)
@@ -642,7 +632,7 @@ class Tile:
var x: int = 0
var y: int = 0
var z: int = 0
var t: int = 0
var t: float = 0.0
var url: String = ''
var texture: Texture2D = null
@@ -652,29 +642,6 @@ class Tile:
self.y = y0
self.z = z0
# Возвращает расстояние в метрах между двумя точками на карте
func haversine_m(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
# Радиус Земли в метрах
const R: = 6372795.0
# Преобразование градусов в радианы
var rlat1: = deg_to_rad(lat1)
var rlon1: = deg_to_rad(lon1)
var rlat2: = deg_to_rad(lat2)
var rlon2: = deg_to_rad(lon2)
# вычисление длины большого круга
var cl1: = cos(rlat1)
var cl2: = cos(rlat2)
var sl1: = sin(rlat1)
var sl2: = sin(rlat2)
var delta: = rlon2 - rlon1
var cdelta: = cos(delta)
var sdelta: = sin(delta)
var y: = sqrt(pow(cl2 * sdelta, 2.0) + pow(cl1 * sl2 - sl1 * cl2 * cdelta, 2.0))
var x: = sl1 * sl2 + cl1 * cl2 * cdelta
var ad: = atan2(y, x)
var dist: = ad * R
return dist
func remove_closest_dot(screen_pos: Vector2) -> bool:
var closest_dot = find_at_screen_position(screen_pos)
@@ -732,7 +699,7 @@ func update_coordinates_label(lon: float, lat: float) -> void:
func update_scale_label() -> void:
scale_label = 'Масштаб: ' + str(round(_xyz.z))
var scale_label: = 'Масштаб: %f' % round(_xyz.z)
signaller.emit_signal('update_scale_map', scale_label)
@@ -745,7 +712,7 @@ func _on_threat_new(th) -> void:
func _on_threat_update(th) -> void:
var target = get_parent().get_node(str(th.id))
var target = get_parent().get_node_or_null(str(th.id))
if not target:
return
var new_position = lonlat_to_world(th.lon, th.lat)
@@ -756,7 +723,7 @@ func _on_threat_update(th) -> void:
func _on_threat_lost(th) -> void:
var target = get_parent().get_node(str(th.id))
var target = get_parent().get_node_or_null(str(th.id))
if target:
target.queue_free()
@@ -766,6 +733,7 @@ func zoom_in() -> void:
return
var center: Vector2 = $canvas.size / 2.0
increment_zoom(zoom_step, center)
update_scale_label()
queue_redraw()
@@ -774,23 +742,24 @@ func zoom_out() -> void:
return
var center: Vector2 = $canvas.size / 2.0
increment_zoom(-zoom_step, center)
update_scale_label()
queue_redraw()
func _on_zoom_plus_button_down() -> void:
zoom_action = "in"
zoom_action = 'in'
perform_zoom()
zoom_timer.start(0.3)
func _on_zoom_minus_button_down() -> void:
zoom_action = "out"
zoom_action = 'out'
perform_zoom()
zoom_timer.start(0.3)
func _on_zoom_button_up() -> void:
zoom_action = ""
zoom_action = ''
zoom_timer.stop()
@@ -800,8 +769,8 @@ func _on_zoom_timeout():
func perform_zoom():
if zoom_action != "":
if zoom_action == "in":
if zoom_action != '':
if zoom_action == 'in':
zoom_in()
else:
zoom_out()
@@ -834,5 +803,4 @@ func draw_ship_radius() -> void:
var radius_point_world = Vector2(ship_world_pos.x + radius_world, ship_world_pos.y)
var radius_point_screen = world_to_screen(radius_point_world)
var radius_screen = ship_screen_pos.distance_to(radius_point_screen)
#draw_arc(ship_screen_pos, radius_screen, 0, TAU, 64, Color.ORANGE, 2.0) # отрисовка контура
draw_circle(ship_screen_pos, radius_screen, Color.ORANGE_RED * Color(1, 1, 1, 0.1)) # отрисовка заливки

View File

@@ -28,6 +28,7 @@ size = Vector2(400, 400)
[node name="tilemap" type="CanvasGroup" groups=["gui_items"]]
script = ExtResource("1_l64tp")
max_zoom_level_server = 11
[node name="canvas" type="TextureRect" parent="." groups=["gui_items"]]
clip_contents = true

View File

@@ -3,5 +3,7 @@ extends AnimatedSprite2D
## Изменяет состояние значка "прибор на связи"
func set_val(val: bool):
set_frame(val)
if val: modulate = Color(0.3, 1.0, 0.3, 1)
else: modulate = Color(0.5, 0.5, 0.5, 1)
if val:
modulate = Color(0.3, 1.0, 0.3, 1)
else:
modulate = Color(0.5, 0.5, 0.5, 1)

View File

@@ -30,18 +30,14 @@ func _setup_styles() -> void:
func _setup_signals() -> void:
connect('pressed', Callable(self, '_on_pressed'))
if not signaller:
return
var signals_to_connect := ['режим_работа', 'режим_журнал', 'режим_эмс', 'режим_настройки", "режим_контроль']
var signals_to_connect := ['режим_работа', 'режим_журнал', 'режим_эмс', 'режим_настройки', 'режим_контроль']
for signal_name in signals_to_connect:
if signaller.has_signal(signal_name):
signaller.connect(signal_name, Callable(self, '_on_status_change'))
func _on_pressed():
disabled = true
text = 'Идет выполнение контроля'
text = 'Контроль выполняется ...'
flag_control_is_over = false
_start_pulse()

View File

@@ -1,6 +1,5 @@
extends Node
static func map_value_to_item(data, item, value_name: StringName):
var meta = item.get_meta(value_name, '')
if meta == '':
@@ -17,7 +16,6 @@ static func map_value_to_item(data, item, value_name: StringName):
else:
push_error('не найден путь %s (%s) для $%s.%s (%s)' % [paths_copy, ret_val[2], item.name, value_name, item.tooltip_text])
static func map_error_codes_to_item(data, item, value_name: StringName, value_init: int):
var metas = item.get_meta(value_name, '')
if not (metas is Array):
@@ -38,3 +36,52 @@ static func map_error_codes_to_item(data, item, value_name: StringName, value_in
item.set(value_name, test_res)
else:
item.set(value_name, value_init)
# Плавное обновление с анимацией
static func map_value_to_item_animated(data, item, value_name: StringName):
var meta = item.get_meta(value_name, '')
if meta == '' or not (meta is String): return
var paths: = Array()
tools.map_solid_to_array(meta, paths)
var ret_val: = [null, false, 0]
tools.get_value_by_path(data, paths, ret_val)
if ret_val[1]:
_animate_property(item, value_name, ret_val[0])
else:
push_error('не найден путь для $%s.%s' % [item.name, value_name])
static func map_error_codes_to_item_animated(data, item, value_name: StringName, value_init: int):
var metas = item.get_meta(value_name, '')
if not (metas is Array): return
var paths: = Array()
var values: = Array()
for meta in metas:
tools.map_solid_to_array(meta, paths)
var ret_val: = [null, false, 0]
tools.get_value_by_path(data, paths, ret_val)
if ret_val[1]:
values.append(ret_val[0])
else:
push_error('не найден путь для $%s.%s' % [item.name, value_name])
var target_value: int
if values.size() == metas.size():
target_value = 1 if values.count(true) == values.size() else 2
else:
target_value = value_init
_animate_property(item, value_name, target_value)
static func _animate_property(item, property: StringName, target_value):
var current = item.get(property)
if typeof(current) != typeof(target_value): return
if current == target_value: return
# Исправление: преобразуем StringName в String для NodePath
var tween = item.create_tween()
tween.set_trans(Tween.TRANS_QUINT)
tween.set_ease(Tween.EASE_OUT)
tween.tween_property(item, NodePath(String(property)), target_value, 0.3)

View File

@@ -0,0 +1,11 @@
extends PanelContainer
## Изменяет состояние значка 'прибор на связи'
func set_val(val: bool):
$connect_pribor.set_frame(val)
if val:
$connect_pribor.modulate = Color(0.3, 1.0, 0.3, 1) # зелёный
set_tooltip_text('Есть связь')
else:
$connect_pribor.modulate = modulate # изначальный
set_tooltip_text('Нет связи')

View File

@@ -0,0 +1 @@
uid://j16hg3u2uvu5

View File

@@ -21,14 +21,19 @@ const RESULT_STRINGS = {
@export var request_url: String = ''
signal send_http_request() ## Отправка запроса
func get_result_string(result: Result):
return RESULT_STRINGS[result] if RESULT_STRINGS.has(result) else '<неизвестный код результата HTTPRequest - %d>' % result
func _on_request_timer():
print('_on_request_timer: ', Time.get_ticks_msec())
if HTTPClient.Status.STATUS_DISCONNECTED != get_http_client_status():
return
var rc: = request(request_url)
if rc != Error.OK:
push_error('%s: \"%s\"' % [error_string(rc), request_url])
else:
emit_signal('send_http_request')

View File

@@ -163,8 +163,6 @@ func _enter_tree() -> void:
vals[2] = get_theme_constant('margin_bottom')
vals[3] = get_theme_constant('margin_right')
return vals
"
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_kqhju"]

View File

@@ -35,7 +35,7 @@ signal pressed(control: PanelContainer)
if not is_inside_tree():
return
$margin/vbox/grid1/level7.value = v
$margin/vbox/grid1/level7.tint_progress = Color.RED if v >= 50 else Color.GOLD if v >= 40 else Color.WHITE
$margin/vbox/grid1/level7.tint_progress = Color.RED if v >= 70 else Color.GOLD if v >= 55 else Color.WHITE
on_level_changed(v, $margin/vbox/grid1/level7, value1_info)
@@ -273,9 +273,9 @@ theme_override_styles/panel = SubResource("StyleBoxEmpty_3nd2u")
script = SubResource("GDScript_oj3k3")
textures = [ExtResource("1_n1aqt"), ExtResource("2_rim3u"), ExtResource("3_3w8fg")]
value0 = [20.0, 30.0, 40.0, 50.0, 60.0, 70.0]
min_value1 = -40.0
min_value1 = -60.0
max_value0 = 1400.0
max_value1 = 55.0
max_value1 = 75.0
step0 = 1.0
step1 = 1.0
value_name0 = "P,%"
@@ -478,8 +478,8 @@ tooltip_text = "
Текущее: 0.00
Диапазон: -40.00…55.00"
mouse_filter = 0
min_value = -40.0
max_value = 55.0
min_value = -60.0
max_value = 75.0
fill_mode = 3
nine_patch_stretch = true
stretch_margin_left = 8

View File

@@ -35,7 +35,7 @@ signal pressed(control: PanelContainer)
if not is_inside_tree():
return
$margin/vbox/grid1/level7.value = v
$margin/vbox/grid1/level7.tint_progress = Color.RED if v >= 50 else Color.GOLD if v >= 40 else Color.WHITE
$margin/vbox/grid1/level7.tint_progress = Color.RED if v >= 70 else Color.GOLD if v >= 55 else Color.WHITE
on_level_changed(v, $margin/vbox/grid1/level7, value1_info)
@@ -259,10 +259,10 @@ theme_override_styles/panel = SubResource("StyleBoxEmpty_3nd2u")
script = SubResource("GDScript_oj3k3")
textures = [ExtResource("1_uojqc"), ExtResource("2_a8ar3"), ExtResource("3_xwd13")]
value0 = [20.0, 30.0, 40.0, 50.0, 60.0, 70.0]
value1 = -40.0
min_value1 = -40.0
value1 = -100.0
min_value1 = -60.0
max_value0 = 1400.0
max_value1 = 55.0
max_value1 = 75.0
step0 = 1.0
step1 = 1.0
value_name0 = "P,%"
@@ -365,12 +365,12 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "
Текущее: -40.00
Диапазон: -40.00…55.00"
Текущее: -100.00
Диапазон: -60.00…75.00"
mouse_filter = 0
min_value = -40.0
max_value = 55.0
value = -40.0
min_value = -60.0
max_value = 75.0
value = -60.0
fill_mode = 3
nine_patch_stretch = true
stretch_margin_left = 8

View File

@@ -9,4 +9,4 @@ func _ready() -> void:
func on_line_changed(unit_instance: unit.Unit):
$connect_pribor.set_val(unit_instance.online)
$panel_pribor.set_val(unit_instance.online)

View File

@@ -1,4 +1,4 @@
extends "res://scenes/контроль/кассета.gd"
extends 'res://scenes/контроль/кассета.gd'
enum STATE_VAL {
NONE = 0,

View File

@@ -4,16 +4,21 @@ extends TextureButton
@onready var tween: Tween
@export var state_colors: Array
var progress_tween: Tween = null
var current_timeout: float = 0.0
func _ready():
toggle_mode = true
focus_mode = Control.FOCUS_ALL
connect("focus_entered", _on_focus_entered)
connect("focus_exited", _on_focus_exited)
connect('focus_entered', _on_focus_entered)
connect('focus_exited', _on_focus_exited)
ProjectSettings.connect('settings_changed', Callable(self, '_on_settings_changed'))
_on_settings_changed()
func _enter_tree() -> void:
if has_node("label"):
if is_inside_tree():
$label.self_modulate = state_colors[state]
@@ -21,11 +26,66 @@ func update_progress_bar(target_value) -> void:
if tween:
tween.kill()
tween = create_tween()
tween.tween_property($control_progress, "value", target_value, 0.3)
tween.tween_property($control_progress, 'value', target_value, 0.3 if target_value > 0 else 0.0)
# Функция для анимации прогресса от 0 до 100 за указанное время
func animate_progress_from_zero(time_req: float) -> void:
_reset_progress_animation()
$control_progress.value = 0
$control_progress.visible = true
current_timeout = time_req
progress_tween = create_tween()
progress_tween.set_trans(Tween.TRANS_LINEAR)
progress_tween.set_ease(Tween.EASE_IN_OUT)
progress_tween.tween_method(
_update_progress_with_tooltip, # Метод для вызова каждый кадр
0.0, # Начальное значение
$control_progress.max_value, # Конечное значение
time_req # Длительность
)
progress_tween.finished.connect(_on_progress_animation_finished.bind())
# Метод для обновления прогресса и tooltip во время анимации
func _update_progress_with_tooltip(value: float) -> void:
# Устанавливаем значение прогресс-бара
$control_progress.value = value
# Вычисляем процент и обновляем tooltip
var max_val = $control_progress.get('max_value')
var percentage = (value / max_val) * 100.0
$control_progress.tooltip_text = 'Процесс контроля %01d%%' % percentage
# Функция для полного сброса анимации
func _reset_progress_animation() -> void:
if progress_tween:
progress_tween.kill()
progress_tween = null
$control_progress.value = 0
current_timeout = 0.0
# Функция вызывается при завершении анимации
func _on_progress_animation_finished() -> void:
$control_progress.visible = false
# Функция для принудительной остановки анимации с сохранением текущего значения
func stop_progress_animation() -> void:
if progress_tween:
progress_tween.stop()
progress_tween = null
func _on_toggled(toggled_on):
if has_node("frame"):
if has_node('frame'):
$frame.visible = toggled_on
@@ -40,24 +100,42 @@ func _on_focus_exited():
func enter_press():
var enter_event = InputEventAction.new()
enter_event.action = "ui_accept"
enter_event.action = 'ui_accept'
enter_event.pressed = true
Input.parse_input_event(enter_event)
func _on_settings_changed():
if not is_inside_tree(): return
var white_color = ProjectSettings.get_setting('application/config/%s' % 'Цвет фона схемы', Color.DIM_GRAY)
var json_col_w = ProjectSettings.get_setting('application/config/%s' % 'Цвет фона схемы', '[0.0, 0.0, 0.0, 0.0]')
var arr_col_w = JSON.parse_string(json_col_w)
white_color = Color(arr_col_w[0], arr_col_w[1], arr_col_w[2], arr_col_w[3]) if arr_col_w else Color.DIM_GRAY
var black_color = ProjectSettings.get_setting('application/config/%s' % 'Цвет схемы', Color.WHITE_SMOKE)
var json_col_b = ProjectSettings.get_setting('application/config/%s' % 'Цвет схемы', '[1.0, 1.0, 1.0, 1.0]')
var arr_col_b = JSON.parse_string(json_col_b)
black_color = Color(arr_col_b[0], arr_col_b[1], arr_col_b[2], arr_col_b[3]) if arr_col_b else Color.WHITE_SMOKE
$pic_functional.material.set('shader_parameter/white', white_color)
$pic_functional.material.set('shader_parameter/black', black_color)
@export var state: int:
set(v):
v = 0 if v < 0 else v % state_colors.size()
state = v
if is_inside_tree() and has_node("label"):
if is_inside_tree():
$label.self_modulate = state_colors[v]
@export var progress_value: float = 0.0:
set(v):
progress_value = v
if is_inside_tree():
if progress_tween:
stop_progress_animation()
update_progress_bar(v)
var max_val = $control_progress.get('max_value')
var percentage = (v / max_val) * 100.0
@@ -90,3 +168,13 @@ func enter_press():
show_functional = v
if is_inside_tree():
$pic_functional.visible = v
@export var timeout_tween: float:
set(v):
if v <= 0:
_reset_progress_animation()
$control_progress.visible = false
return
animate_progress_from_zero(v)

File diff suppressed because it is too large Load Diff

View File

@@ -54,7 +54,7 @@ func _on_resized() -> void:
func _enter_tree() -> void:
if Engine.is_editor_hint(): return
var unit_any = network.get_unit_instance(unit_name)
var unit_any: = network.get_unit_instance(unit_name)
unit_any.connect('data_received', Callable(self, 'on_data_received'))
unit_any.connect('line_changed', Callable(self, 'on_line_changed'))
$margin/vbox.alignment = alignment
@@ -65,6 +65,6 @@ func _enter_tree() -> void:
func _exit_tree() -> void:
if Engine.is_editor_hint(): return
var unit_any = network.get_unit_instance(unit_name)
var unit_any: = network.get_unit_instance(unit_name)
unit_any.disconnect('data_received', Callable(self, 'on_data_received'))
unit_any.disconnect('line_changed', Callable(self, 'on_line_changed'))

View File

@@ -1,69 +1,14 @@
class_name configure extends Panel
const TableHeader = preload('res://table/header.tscn')
const TableToggle = preload('res://table/settings-toggle.tscn')
const TableEdit = preload('res://table/ячейка-2.tscn')
const TableColorPick = preload('res://table/ячейка-цвет.tscn')
@export var TableHeader: PackedScene
@export var TableToggle: PackedScene
@export var TableEdit: PackedScene
@export var TableColorPick: PackedScene
const ALIGNMENT = [HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER]
const HEADER_ROW = [TableHeader, TableHeader]
const HEADER_ROW_TEXT = ['Параметр', 'Значение']
const SETTING_TABLE = [
['Ограниченный режим', TableEdit, TableToggle, 'Ограничть возможности по постановке помех'],
['Кнопка «ПД-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ПД-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОЗП-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «МЧМ-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОРН-И1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОРН-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ЛЧМ-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ПД-М4С»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ПД-ЧМ»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «СВ-И1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «К', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «СВ-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОРН»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «JTIDS»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «КУПД»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Внешнее управление', TableEdit, TableToggle, 'Передать управление в 5П28'],
['Внешнее указание Трасса', TableEdit, TableToggle, 'Разрешить постановку помех от Трасса'],
['Кнопка «Подавление»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Виртуальная клавиатура', TableEdit, TableToggle, 'Включить отображение экранной клавиатуры'],
['Скрыть вкладку ЭМС 2', TableEdit, TableToggle, 'Отображать вкладку \"ЭМС-2\"'],
['Отладка контроля', TableEdit, TableToggle, 'Отображать отладку контроля'],
['Текущая версия ПО УАРЭП', TableEdit, TableEdit, 'Время сборки, версия и номер фиксации'],
['уарэп-яу07-частный', TableEdit, TableEdit, 'IP-адрес для получения частных сообщений от ЯУ-07'],
['уарэп-яу07-общий', TableEdit, TableEdit, 'IP-адрес для получения широковещательных сообщений от ЯУ-07'],
['уарэп-капсрпб', TableEdit, TableEdit, 'IP-адрес для связи с КАПС-РПБ [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'],
['уарэп-эмс', TableEdit, TableEdit, 'IP-адрес для связи с ЭМС'],
['уарэп-яу07-2в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 2'],
['уарэп-яу07-2н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 2'],
['уарэп-яу07-2к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 2'],
['уарэп-яу07-4в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 4'],
['уарэп-яу07-4н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 4'],
['уарэп-яу07-4к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 4'],
['уарэп-яу07-1в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 1'],
['уарэп-яу07-1н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 1'],
['уарэп-яу07-1к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 1'],
['уарэп-яу07-3в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 3'],
['уарэп-яу07-3н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 3'],
['уарэп-яу07-3к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 3'],
['уарэп-5п28', TableEdit, TableEdit, 'IP-адрес для связи с 5П28'],
['навигация', TableEdit, TableEdit, 'Порт назначения для получения данных от АКНГ'],
['уарэп-щ3', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором Щ3'],
['уарэп-спт25-1', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором СПТ-25 1'],
['уарэп-спт25-2', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором СПТ-25 2'],
['Шаблон адреса сервера карт', TableEdit, TableEdit, 'Шаблон URL-адреса сервера карт, должен содержать поля \"{x}\", \"{y}\", \"{z}\" для подстановки индекса плитки'],
['Адрес АФСП левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'],
['Адрес АФСП правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'],
['Адрес БПО левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'],
['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'],
['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ],
['Период опроса состояния АФСП, секунды', TableEdit, TableEdit, 'Время в секундах' ],
['уарэп-трасса', TableEdit, TableEdit, 'IP-адрес для связи с Трассой [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'],
['Включить работу по своим целям', TableEdit, TableToggle, 'Разрешает работу в секторе со своей целью'],
['Список своих протоколов', TableEdit, TableEdit, 'Список протоколов целей, по которым запрещено работать' ],
['Цвет кнопки \"Подавление\"', TableEdit, TableColorPick, 'Цвет кнопки. Введено по требованию ПЗ' ] ]
const HEADER_ROW_TEXT: = ['Параметр', 'Значение']
var HEADER_ROW: Array
## TODO: Придумать как избавиться от индексов
## Индексы строк таблицы.
@@ -76,49 +21,126 @@ const DEBAG_CONTROL = 21 ## Строка - Отладка контроля
const COMMIT = 22 ## Строка - Версия УАРЭП
const GOS_BTN = 52 ## Разрешить работу по своим целям
const COLOR_BTN_ACT = 54 ## Цвет кнопки "Подавление"
const COLOR_WHITE = 55 ## Цвет фона схемы
const COLOR_BLACK = 56 ## Цвет схемы
const COLOR_THEME = 57 ## Цвет темы
var SETTING_TABLE: Array
var name_to_line_index: = {} ## Для преобразования названия параметра в номер строки
var table_color_instance: Node ## Нода цвета кнопки подавления
func on_checkbutton_pressed(i_row: int): on_row_pressed(i_row)
func on_checkbutton_pressed(i_row: int):
on_row_pressed(i_row)
func _init_scene_arrays():
HEADER_ROW = [TableHeader, TableHeader]
SETTING_TABLE = [
['Ограниченный режим', TableEdit, TableToggle, 'Ограничть возможности по постановке помех'], # 0
['Кнопка «ПД-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 1
['Кнопка «ПД-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 2
['Кнопка «ОЗП-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 3
['Кнопка «МЧМ-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 4
['Кнопка «ОРН-И1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 5
['Кнопка «ОРН-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 6
['Кнопка «ЛЧМ-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 7
['Кнопка «ПД-М4С»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 8
['Кнопка «ПД-ЧМ»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 9
['Кнопка «СВ-И1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 10
['Кнопка «К', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 11
['Кнопка «СВ-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 12
['Кнопка «ОРН»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 13
['Кнопка «JTIDS»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 14
['Кнопка «КУПД»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 15
['Внешнее управление', TableEdit, TableToggle, 'Передать управление в 5П28'], # 16
['Внешнее указание Трасса', TableEdit, TableToggle, 'Разрешить постановку помех от Трасса'], # 17
['Кнопка «Подавление»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 18
['Виртуальная клавиатура', TableEdit, TableToggle, 'Включить отображение экранной клавиатуры'], # 19
['Скрыть вкладку ЭМС 2', TableEdit, TableToggle, 'Отображать вкладку \"ЭМС-2\"'], # 20
['Отладка контроля', TableEdit, TableToggle, 'Отображать отладку контроля'], # 21
['Текущая версия ПО УАРЭП', TableEdit, TableEdit, 'Время сборки, версия и номер фиксации'], # 22
['уарэп-яу07-частный', TableEdit, TableEdit, 'IP-адрес для получения частных сообщений от ЯУ-07'], # 23
['уарэп-яу07-общий', TableEdit, TableEdit, 'IP-адрес для получения широковещательных сообщений от ЯУ-07'], # 24
['уарэп-капсрпб', TableEdit, TableEdit, 'IP-адрес для связи с КАПС-РПБ [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'], # 25
['уарэп-эмс', TableEdit, TableEdit, 'IP-адрес для связи с ЭМС'], # 26
['уарэп-яу07-2в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 2'], # 27
['уарэп-яу07-2н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 2'], # 28
['уарэп-яу07-2к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 2'], # 29
['уарэп-яу07-4в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 4'], # 30
['уарэп-яу07-4н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 4'], # 31
['уарэп-яу07-4к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 4'], # 32
['уарэп-яу07-1в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 1'], # 33
['уарэп-яу07-1н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 1'], # 34
['уарэп-яу07-1к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 1'], # 35
['уарэп-яу07-3в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 3'], # 36
['уарэп-яу07-3н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 3'], # 37
['уарэп-яу07-3к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 3'], # 38
['уарэп-5п28', TableEdit, TableEdit, 'IP-адрес для связи с 5П28'], # 39
['навигация', TableEdit, TableEdit, 'Порт назначения для получения данных от АКНГ'], # 40
['уарэп-щ3', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором Щ3'], # 41
['уарэп-спт25-1', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором СПТ-25 1'], # 42
['уарэп-спт25-2', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором СПТ-25 2'], # 43
['Шаблон адреса сервера карт', TableEdit, TableEdit, 'Шаблон URL-адреса сервера карт, должен содержать поля \"{x}\", \"{y}\", \"{z}\" для подстановки индекса плитки'], # 44
['Адрес АФСП левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'], # 45
['Адрес АФСП правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'], # 46
['Адрес БПО левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], # 47
['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], # 48
['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ], # 49
['Период опроса состояния АФСП, секунды', TableEdit, TableEdit, 'Время в секундах' ], # 50
['уарэп-трасса', TableEdit, TableEdit, 'IP-адрес для связи с Трассой [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'], # 51
['Включить работу по своим целям', TableEdit, TableToggle, 'Разрешает работу в секторе со своей целью'], # 52
['Список своих протоколов', TableEdit, TableEdit, 'Список протоколов целей, по которым запрещено работать' ], # 53
['Цвет кнопки \"Подавление\"', TableEdit, TableColorPick, 'Цвет кнопки. Введено по требованию ПЗ' ], # 54
['Цвет фона схемы', TableEdit, TableColorPick, 'Схема прибора Э2. Изменение цвет фона'], # 55
['Цвет схемы', TableEdit, TableColorPick, 'Схема прибора Э2. Изменение цвет схемы '], # 56
['Цвет темы программы', TableEdit, TableToggle, 'ВЫКЛ - темная тема, ВКЛ - светлая тема'], # 57
['Коэффициент ширины полосы излучения', TableEdit, TableEdit, 'Изменение ширины полосы излучения помехи в зависимости от цели'], # 58
['Время повторной отправки помехи', TableEdit, TableEdit, 'Изменение времени повторной отправки помехи'] ] # 59
## Вызывается, когда узел впервые попадает в дерево сцены.
func _ready() -> void:
setting_tab()
if not OS.get_cmdline_args().has('++ограниченный'):
return
if OS.get_cmdline_args().has('++ограниченный'):
$Label2.text = 'Текущий режим доступа: ограниченный'
for node in $GridContainer.get_children().filter(func(b): return b is Button):
node.disabled = true
ProjectSettings.emit_signal('settings_changed')
func on_external_cu_btn_pressed(btn) -> void:
ProjectSettings.set_setting('application/config/Внешнее управление', btn.button_pressed)
ProjectSettings.set_setting('application/config/%s' % 'Внешнее управление', btn.button_pressed)
if btn.button_pressed:
signaller.emit_signal('interfer_off_all')
_autosave_now()
func on_trassa_btn_pressed(btn) -> void:
ProjectSettings.set_setting('application/config/Внешнее указание Трасса', btn.button_pressed)
ProjectSettings.set_setting('application/config/%s' % 'Внешнее указание Трасса', btn.button_pressed)
_autosave_now()
func on_vk_pressed(btn) -> void:
signaller.emit_signal('kb_pressed', btn.button_pressed)
_autosave_now()
func on_gos_pressed(btn) -> void:
ProjectSettings.set_setting('application/config/Включить работу по своим целям', btn.button_pressed)
_autosave_now()
func on_ems2_pressed(btn) -> void:
var state = btn.button_pressed
signaller.emit_signal('ems2_hide_pressed', state)
_autosave_now()
func on_debag_control_pressed(btn) -> void:
var state = btn.button_pressed
signaller.emit_signal("debag_control_pressed", state)
signaller.emit_signal('debag_control_pressed', state)
_autosave_now()
func on_row_pressed(i_row: int):
@@ -163,6 +185,7 @@ func parse_cmd_line_args(settings_data: Dictionary):
func setting_tab():
_init_scene_arrays()
$heard_table.set_header(HEADER_ROW)
$heard_table.set_header_text(HEADER_ROW_TEXT)
$heard_table.set_columns_min_size([600, 950])
@@ -191,6 +214,7 @@ func setting_tab():
child.connect('pressed', Callable(self, 'on_checkbutton_pressed').bind(i))
var val = ProjectSettings.get_setting('application/config/%s' % param_name, true)
child.set_pressed(val)
child.pressed.connect(_autosave_now)
else:
if settings_data.has(param_name):
var val = settings_data[param_name]
@@ -199,6 +223,7 @@ func setting_tab():
if edit_node:
if edit_node is LineEdit:
$scroll_set/table.set_node_control(1, i, true)
edit_node.focus_exited.connect(_autosave_now)
$scroll_set/table.set_node_editable(1, COMMIT, false)
$scroll_set/table.set_columns_min_size([600, 950])
$scroll_set/table.set_columns_alignments(ALIGNMENT)
@@ -244,14 +269,62 @@ func button_settings():
on_debag_control_pressed(debag_control)
var color_btn_act = $scroll_set/table.get_node2(1, COLOR_BTN_ACT)
color_btn_act.connect('popup_closed', on_color_closed.bind(color_btn_act))
var json_col = ProjectSettings.get_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', '[1.0, 1.0, 1.0, 1.0]')
var arr_col = JSON.parse_string(json_col)
color_btn_act.color = Color(arr_col[0], arr_col[1], arr_col[2], arr_col[3]) if arr_col else Color.WHITE
color_btn_act.text = JSON.stringify(arr_col)
var color_white = $scroll_set/table.get_node2(1, COLOR_WHITE)
color_white.connect('popup_closed', on_color_closed_w.bind(color_white))
var json_col_w = ProjectSettings.get_setting('application/config/%s' % 'Цвет фона схемы', '[0.0, 0.0, 0.0, 0.0]')
var arr_col_w = JSON.parse_string(json_col_w)
color_white.color = Color(arr_col_w[0], arr_col_w[1], arr_col_w[2], arr_col_w[3]) if arr_col_w else Color.DIM_GRAY
color_white.text = JSON.stringify(arr_col_w)
var color_black = $scroll_set/table.get_node2(1, COLOR_BLACK)
color_black.connect('popup_closed', on_color_closed_b.bind(color_black))
var json_col_b = ProjectSettings.get_setting('application/config/%s' % 'Цвет схемы', '[1.0, 1.0, 1.0, 1.0]')
var arr_col_b = JSON.parse_string(json_col_b)
color_black.color = Color(arr_col_b[0], arr_col_b[1], arr_col_b[2], arr_col_b[3]) if arr_col_b else Color.WHITE_SMOKE
color_black.text = JSON.stringify(arr_col_b)
var theme_node = $scroll_set/table.get_node2(1, COLOR_THEME).get_children()[0]
theme_node.connect('pressed', on_theme_toggle_pressed.bind(theme_node))
on_theme_toggle_pressed(theme_node)
func on_theme_toggle_pressed(btn: CheckButton) -> void:
var is_light = btn.button_pressed
ProjectSettings.set_setting('application/config/Цвет темы программы', is_light)
_autosave_now()
func _update_theme_colors():
var color_white = $scroll_set/table.get_node2(1, COLOR_WHITE)
var color_black = $scroll_set/table.get_node2(1, COLOR_BLACK)
on_color_closed_w(color_white)
on_color_closed_b(color_black)
func on_color_closed_w(color_white: ColorPickerButton):
var col_w = [color_white.color.r, color_white.color.g, color_white.color.b, color_white.color.a]
color_white.text = JSON.stringify(col_w)
ProjectSettings.set_setting('application/config/%s' % 'Цвет фона схемы', color_white.text)
_autosave_now()
func on_color_closed_b(color_black: ColorPickerButton):
var col_b = [color_black.color.r, color_black.color.g, color_black.color.b, color_black.color.a]
color_black.text = JSON.stringify(col_b)
ProjectSettings.set_setting('application/config/%s' % 'Цвет схемы', color_black.text)
_autosave_now()
func on_color_closed(color_btn_act: ColorPickerButton):
var col = [color_btn_act.color.r, color_btn_act.color.g, color_btn_act.color.b, 1.0]
ProjectSettings.set_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', col)
var col = [color_btn_act.color.r, color_btn_act.color.g, color_btn_act.color.b, color_btn_act.color.a]
color_btn_act.text = JSON.stringify(col)
ProjectSettings.set_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', color_btn_act.text)
_autosave_now()
func _on_btn_save_settings_pressed():
func _autosave_now() -> void:
var json_data = {}
for i in SETTING_TABLE.size():
var parameter = SETTING_TABLE[i][0]

View File

@@ -2,23 +2,17 @@
[ext_resource type="Script" uid="uid://dabpum5iqxc7y" path="res://scenes/настройки/настройки.gd" id="1_60bya"]
[ext_resource type="Script" uid="uid://c5pq0hbrij34d" path="res://table/table.gd" id="2_6sx73"]
[ext_resource type="Texture2D" uid="uid://csnts8f155sf7" path="res://data/save1.png" id="3_dbpks"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_pyq6h"]
texture = ExtResource("3_dbpks")
modulate_color = Color(0.8, 0.533333, 0.27451, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_l5g3r"]
texture = ExtResource("3_dbpks")
expand_margin_left = 20.0
expand_margin_top = 20.0
modulate_color = Color(0.8, 0.533333, 0.27451, 1)
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_tbxk6"]
texture = ExtResource("3_dbpks")
[ext_resource type="PackedScene" uid="uid://ch14g46swx74h" path="res://table/header.tscn" id="2_l8r7w"]
[ext_resource type="PackedScene" uid="uid://5rw652cmnybi" path="res://table/settings-toggle.tscn" id="3_6e5sv"]
[ext_resource type="PackedScene" uid="uid://dspa16ufrpanp" path="res://table/ячейка-2.tscn" id="4_i0f0r"]
[ext_resource type="PackedScene" uid="uid://cug5xjbfdm7x7" path="res://table/ячейка-цвет.tscn" id="5_h2mq4"]
[node name="Настройки" type="Panel"]
script = ExtResource("1_60bya")
TableHeader = ExtResource("2_l8r7w")
TableToggle = ExtResource("3_6e5sv")
TableEdit = ExtResource("4_i0f0r")
TableColorPick = ExtResource("5_h2mq4")
[node name="heard_table" type="GridContainer" parent="."]
layout_mode = 0
@@ -33,26 +27,8 @@ layout_mode = 0
offset_left = 16.0
offset_top = 44.0
offset_right = 1584.0
offset_bottom = 988.0
offset_bottom = 1144.0
[node name="table" type="GridContainer" parent="scroll_set"]
layout_mode = 2
script = ExtResource("2_6sx73")
[node name="btn_save" type="Button" parent="."]
layout_mode = 0
offset_left = 1523.0
offset_top = 1057.0
offset_right = 2035.0
offset_bottom = 1569.0
scale = Vector2(0.1, 0.1)
tooltip_text = "Сохранить настройки"
focus_mode = 0
theme_override_styles/focus = SubResource("StyleBoxTexture_pyq6h")
theme_override_styles/disabled = SubResource("StyleBoxTexture_pyq6h")
theme_override_styles/hover_pressed = SubResource("StyleBoxTexture_pyq6h")
theme_override_styles/hover = SubResource("StyleBoxTexture_pyq6h")
theme_override_styles/pressed = SubResource("StyleBoxTexture_l5g3r")
theme_override_styles/normal = SubResource("StyleBoxTexture_tbxk6")
[connection signal="pressed" from="btn_save" to="." method="_on_btn_save_settings_pressed"]

View File

@@ -58,7 +58,7 @@ var fs_selected: Dictionary ## Словарь выбранных сектор
var fs_active: Dictionary ## Словарь секторов назначенных на подавление
var fs_emit: Dictionary ## Словарь секторов назначенных на подавление
var fs_closed: Dictionary ## Словарь для секторов запрета
var fs_failed: Array ## Индикация сломанных секторов (модули ФС). AntBandState.ANT_BAND_READY - исправен, AntBandState.ANT_BAND_FAILURE - сломан.
var fs_failed: PackedInt32Array ## Индикация сломанных секторов (модули ФС). AntBandState.ANT_BAND_READY - исправен, AntBandState.ANT_BAND_FAILURE - сломан.
## Состояние перетаскивания.
enum DragFSM {
@@ -83,8 +83,9 @@ enum MapViewMode {
enum AntBandState {
ANT_BAND_FAILED = 0,
ANT_BAND_READY = 1,
ANT_BAND_FAILED = 0
ANT_BAND_ASSIGNED = 2
}
const VAL_TO_EVENT = {
@@ -105,7 +106,7 @@ var SIGNALS_CONNECTIONS = [
[signaller, 'interfer_prinuditelno', 'on_interfer_prinuditelno'],
[signaller, 'interfer_selected', 'on_interfer_selected'],
[signaller, 'map_user_panning', 'on_user_panning'],
[signaller, 'on_prog_ecm_off', 'on_interfer_new'],
[signaller, 'prog_ecm_off', 'on_interfer_new'],
[signaller, 'rto_threat_sel', 'on_rto_threat_sel'],
[signaller, 'rto_threat_unsel', 'on_rto_threat_unsel'],
[signaller, 'sector_klaster', 'sector_klaster'],
@@ -134,9 +135,13 @@ func on_user_panning(): $btn_center.button_pressed = false
func on_settings_changed():
var json_col = ProjectSettings.get_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', '[1.0, 1.0, 1.0, 1.0]')
var arr_col = JSON.parse_string(json_col)
col_btn_act = Color(arr_col[0], arr_col[1], arr_col[2], arr_col[3]) if arr_col else Color.WHITE
gos_flag = ProjectSettings.get_setting('application/config/Включить работу по своим целям', true)
color_emit = ProjectSettings.get_setting('application/interfer/emit_color', Color(0.58, 0.47, 0.51, 1.0))
color_ecm = ProjectSettings.get_setting('application/interfer/interfer_color', Color(0.58, 0.47, 0.51, 1.0))
color_emit = Color(arr_col[0], arr_col[1], arr_col[2], 1.0)
color_ecm = Color(arr_col[0], arr_col[1], arr_col[2], 1.0)
color_select = ProjectSettings.get_setting('application/interfer/select_color', Color(1.0, 1.0, 1.0, 1.0))
color_closed = ProjectSettings.get_setting('application/interfer/closed_sectors', Color(0.0, 0.0, 0.0, 1.0))
min_zoom = ProjectSettings.get_setting('application/config/map_minimum_zoom', 5)
@@ -150,8 +155,6 @@ func on_settings_changed():
color_closed *= Color(1.0, 1.0, 1.0, 0.0)
color_closed_emit *= Color(1.0, 1.0, 1.0, 1.0)
col_btn_act = ProjectSettings.get_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', Color.WHITE)
## Обработчик сигнала изменения списка целей.
func on_threats_resized(ths: Dictionary):
@@ -169,6 +172,9 @@ func on_button_view_toggled(toggled: bool):
view_mode = MapViewMode.RLS if toggled else MapViewMode.RTO
if view_mode != MapViewMode.RTO:
fs_selected.clear()
$btns_select/btn_strob.disabled = toggled
$btns_select/btn_fs_sector.disabled = toggled
$'canvas/строб'.visible = $btns_select/btn_strob.pressed and (not toggled)
## Встроенный обратный вызов.
@@ -192,7 +198,7 @@ func init_fs_failed():
var sectors_count = $canvas.fs_default_colors.size()
fs_failed.resize(sectors_count)
for i in fs_failed.size():
fs_failed[i] = AntBandState.ANT_BAND_READY
fs_failed[i] = AntBandState.ANT_BAND_FAILED
## Производит инициализацию.
@@ -231,12 +237,22 @@ func connect_all() -> void:
else:
var ers = error_string(rc)
push_error('%s: %s %s %s' % [ers, item[0], item[1], item[2]])
signaller.emit_signal('connect_work_signal')
for th in thrs_dict.values():
var bip = Bip.instantiate()
bip.name = '%d' % th.id
map_threat_to_bip(th, bip)
add_child(bip)
func disconnect_all() -> void:
for item in signal_conections:
item[0].disconnect(item[1], item[2])
signal_conections.clear()
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for bip in bips:
remove_child(bip)
bip.free()
func sector_klaster(sector_data):
@@ -302,6 +318,9 @@ func map_threat_to_bip(th: threats.Threat, bip: Control) -> bool:
func on_threat_update(th: threats.Threat):
var bip = get_node('%d' % th.id)
bip.update(th.tick_rx)
if th.gos:
bip.set_bip_color(Color.GREEN)
else:
bip.set_bip_color(Color.CORAL if th.proto else Color.WHITE)
bip.visible = map_threat_to_bip(th, bip)
@@ -310,7 +329,7 @@ func on_threat_update(th: threats.Threat):
func on_interfer_new(ecm):
if not interfer.thrs.has(ecm.ispp): return
var th_id = interfer.thrs[ecm.ispp]
var bip = get_node('%d' % th_id)
var bip = get_node_or_null('%d' % th_id)
if bip != null:
if ecm.krp!= interfer.INTERFER_OFF:
bip.set_track_visible(true)
@@ -321,7 +340,6 @@ func on_interfer_new(ecm):
bip.set_ecm_visible(false)
bip.set_track_visible(false)
else:
interfer.thrs.erase(ecm.ispp)
update_fs_colors()
@@ -452,7 +470,7 @@ func get_strob_band(pos: Vector2, prev: float) -> float:
## Устанавливает центр строба по частоте и направлению.
func set_strob(pos: Vector2) -> void:
var radp: Vector2 = tools.map_dec_to_rad(radius_center, pos)
var radp: Vector2 = tools.map_dec_to_rad(radius_center / 2.0, pos / 2.0)
if radp.y < $canvas.get_radius_outter():
$canvas.set_strob_dir(radp.x)
$canvas.set_strob_radius(radp.y)
@@ -548,7 +566,7 @@ func set_fs_color(ecms):
continue
if ecm.krp != interfer.INTERFER_OFF:
fs_active[prd.fs_caps_id[ecm.nmfs]] = null
if ecm.svk == SVK_EMIT:
if ecm.active:
fs_emit[prd.fs_caps_id[ecm.nmfs]] = null
update_fs_colors()
@@ -615,12 +633,12 @@ func set_btns_disabled(value: bool, btn):
func on_interfer_prinuditelno(prenuditelno_sectors):
for key in prenuditelno_sectors:
var sectors = []
var sectors: = []
for sector in prenuditelno_sectors[key]:
sectors.append(prd.get_fs_param(sector))
signaller.emit_signal('interfer_init', key, sectors, interfer.POW_DEFAULT)
update_fs_colors()
var btns: Array = get_tree().get_nodes_in_group('группа-режим-помехи')
var btns: = get_tree().get_nodes_in_group('группа-режим-помехи')
for btn in btns:
btn.set_pressed(false)
set_btns_disabled(true, btn)
@@ -629,7 +647,7 @@ func on_interfer_prinuditelno(prenuditelno_sectors):
## Вызывается при получении информации о состоянии модулей ФС от КАПС РПБ.
func on_fs_update_state(fs_dict: Dictionary):
for key in fs_dict.keys():
fs_failed[key] = fs_dict[key].isg
fs_failed[key] = AntBandState.ANT_BAND_READY if fs_dict[key].ready else AntBandState.ANT_BAND_FAILED
func on_btn_center_toggled(toggled_on: bool) -> void:
@@ -644,12 +662,12 @@ func on_btn_activate_toggled(toggled_on: bool) -> void:
$btn_activate.self_modulate = Color.WHITE
func on_update_coordinates_label(coordinates_label) -> void:
$coordinates_map.text = str(coordinates_label)
func on_update_coordinates_label(coordinates_label: String) -> void:
$coordinates_map.text = coordinates_label
func on_update_scale_label(scale_label) -> void:
$scale_map.text = str(scale_label)
func on_update_scale_label(scale_label: String) -> void:
$scale_map.text = scale_label
func on_btn_close():
@@ -679,10 +697,11 @@ func on_th_aoa_update(ths):
func count_threats(ths):
$count_all_pad/count_all.text = '%02d' % ths.size()
var c0: int = ths.size() if ths.size() < 100 else 99
$count_all_pad/count_all.text = '%02d' % c0
var c: int = 0
if gos_flag:
c = ths.values().filter(func(th: threats.Threat): return th.proto != '').size()
else:
c = ths.values().filter(func(th: threats.Threat): return ((th.proto != '') and th.proto not in interfer.gos_protocols)).size()
c = ths.values().filter(func(th: threats.Threat): return not th.gos).size()
$count_danger_pad/count_danger.text = '%02d' % c

View File

@@ -5,7 +5,7 @@
[ext_resource type="PackedScene" uid="uid://dem3fcec25awh" path="res://scenes/grid-side-panel/grid-side-panel.tscn" id="3_s2j0e"]
[ext_resource type="PackedScene" uid="uid://cnkbk53mi7viu" path="res://scenes/grid-buttons-ecm/grid-buttons-ecm.tscn" id="5_2jnbs"]
[ext_resource type="PackedScene" uid="uid://dymo732qc2doa" path="res://scenes/count-all/count-all-pad.tscn" id="6_e3re7"]
[ext_resource type="PackedScene" uid="uid://bwti82byphl68" path="res://scenes/count-danger/count_danger_pad.tscn" id="7_2arls"]
[ext_resource type="PackedScene" uid="uid://bwti82byphl68" path="res://scenes/count-danger/count-danger-pad.tscn" id="7_2arls"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button-flat/button-flat.tscn" id="8_k0iv2"]
[ext_resource type="Texture2D" uid="uid://c1785x8wf1hdg" path="res://data/power-0.png" id="10_cnr1s"]
[ext_resource type="PackedScene" uid="uid://ceknxxfu1loo5" path="res://scenes/tilemap/tilemap.tscn" id="10_gtwyg"]
@@ -74,23 +74,28 @@ strob_min_band = 0.1
strob_min_width = 5.0
metadata/_edit_vertical_guides_ = []
[node name="btn_view" type="CheckBox" parent="."]
[node name="canvas" parent="." instance=ExtResource("11_b6su4")]
layout_mode = 0
offset_left = 835.0
offset_top = 5.0
offset_right = 994.0
offset_bottom = 32.0
offset_left = 280.0
offset_top = 280.0
offset_right = 840.0
offset_bottom = 840.0
pivot_offset = Vector2(280, 280)
[node name="btn_view" type="CheckBox" parent="canvas"]
layout_mode = 0
offset_left = 417.5
offset_top = 2.5
offset_right = 576.5
offset_bottom = 29.5
scale = Vector2(0.5, 0.5)
action_mode = 0
text = "Обзорная карта"
[node name="canvas" parent="." instance=ExtResource("11_b6su4")]
metadata/_edit_lock_ = true
[node name="tilemap" parent="." instance=ExtResource("10_gtwyg")]
self_modulate = Color(1, 1, 1, 0.415686)
position = Vector2(360, 360)
min_zoom_level = 3
max_zoom_level_server = 11
ship_radius_km = 3.0
az = 3.0
@@ -378,9 +383,8 @@ texture_normal = ExtResource("14_ggrwd")
[connection signal="drag_begin" from="." to="." method="_on_drag_begin"]
[connection signal="drag_continue" from="." to="." method="_on_drag_continue"]
[connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"]
[connection signal="toggled" from="canvas/btn_view" to="." method="on_button_view_toggled"]
[connection signal="toggled" from="chk_auto" to="." method="on_value_changed"]
[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"]
[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"]
[connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"]
[connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"]

View File

@@ -0,0 +1,557 @@
@tool
extends Panel
## Выполнение функций информационного ЭМС (ЭМС-ТГ)
#region Определяемое при использовании
## Индекс -> Имя устройства. Нужен для предсказуемого
## порядка отображения: верх->вниз или лево->право.
## Имя устройства должно быть взято из settings.gd
@export var index_to_unit_names: Array[StringName]
## Минимальная частота, МГЦ
@export var freq_min: float
## Максимальная частота, МГЦ
@export var freq_max: float
## Время достоверности кластера по умолчанию (если не указано в докладе)
@export var default_ttl: float
## Цвет диапазона если включен (разрешён)
@export_color_no_alpha var color_enabled: Color
## Цвет диапазона если выключен (запрещён)
@export_color_no_alpha var color_disabled: Color
## Прозрачность диапазон на шкале (диапазоны могут накладываться, что бы было видно наложения)
@export_range(0, 1.0) var color_alpha: float
## Цвет нечётных строк шкалы
@export_color_no_alpha var color_odd: Color
## Цвет чётных строк шкалы
@export_color_no_alpha var color_even: Color
## Индекс колонки в таблице для управления работой приёмников
@export var column_cmd_rx: int
## Индекс колонки в таблице для управления работой передатчиков
@export var column_cmd_tx: int
## Максимальное количество кластеров на одно устройство
@export var max_clasters_per_unit: int
## Сообщение пользователю
@export var msg_select_unit: String
## Сообщение пользователю
@export var msg_waiting_data: String
#endregion
#region Загружаемые ресурсы
@export_file('*.tscn') var table_headers: Array[String]
@export_file('*.tscn') var table_cells: Array[String]
@export_file('*.png') var image_file_rx: String
@export_file('*.png') var image_file_tx: String
@export var table_rows_hight: int
@export var table_column_widths: Array[int]
@export var table_header_widths: Array[int]
@export var table_header_text: Array[String]
#endregion
#region Заполняется автоматически при запуске
## Имя устройства -> Индекс устройства
var name_to_index: Dictionary[StringName, int]
## Имя устройства -> Шкала
var name_to_scale: Dictionary[StringName, GridContainer]
var table_cell_row: Array
## Образец параметров кластера
var ref_cls: = {'cname': '<имя>', 'ttl': 1.0, 'daa': 360.0, 'dap': 0.0,
'cfb': (freq_min + freq_max) / 2.0,
'wfb': freq_max - freq_min}
#endregion
#region Заполняется во время работы
var yems_info: Dictionary[StringName, Dictionary] ## Доклады
var yems_cmd: Dictionary[StringName, Dictionary] ## Команды
## Порядок следования кластеров в таблице.
## {имя_устройства: {имя_кластера: индекс_в_таблице}}
var cnames_table: Dictionary[StringName, Dictionary]
## Текущее выбранное оператором устройство на шкале
var selected_unit: Dictionary[StringName, bool]
## Состояния кластеров в соответствии с докладами и командами
#endregion
## Состояние кластера
enum ClasterStatus {
DELETED, ## Удалён (время ожидания обновления истекло)
RUNNING ## Работает (информация обновляется)
}
## Режим управления кластером
enum ClasterMode {
MANUAL, ## Ручной, управляется операторром
AUTO, ## Автоматический, управляется программой
IGNORE ## Игнорируемый, не управляется
}
## Состояние кластера. Значения должны соответствовать
## состояниям [b]six-state-button[/b]
enum ClasterResult {
WAITING = 0, ## Ожидание даннных
DONE = 1, ## Выполнено
MISSMATCH = 2 ## Несоответствие
}
func _ready() -> void:
# Инициализировать переменные
color_enabled.a = color_alpha
color_disabled.a = color_alpha
for i in index_to_unit_names.size():
var nm: = index_to_unit_names[i]
name_to_index[nm] = i
yems_info[nm] = {'mcls': []}
yems_cmd[nm] = {}
cnames_table[nm] = {}
selected_unit[nm] = false
var btns_scales = get_tree().get_nodes_in_group('кнопки-шкалы')
for node in btns_scales:
var nm: = node.get_meta('unit_name') as StringName
node.connect('toggled', _on_scale_selected.bind(nm))
var claster_scales = get_tree().get_nodes_in_group('шкалы-кластеров')
for node in claster_scales:
var nm: = node.get_meta('unit_name') as StringName
name_to_scale[nm] = node
# Расскрасить чётные-нечётные
for node in get_tree().get_nodes_in_group('нечётные'):
node.get_node('panel_rx').back_color = color_odd
node.get_node('panel_tx').back_color = color_odd
for node in get_tree().get_nodes_in_group('чётные'):
node.get_node('panel_rx').back_color = color_even
node.get_node('panel_tx').back_color = color_even
# Подключить обработчик для приёма данных
for nm in yems_info:
var yems_unit = network.get_unit_instance(nm)
yems_unit.connect('data_received', on_data_received.bind(nm))
# Настроить таблицу
var header_row: = []
for cell_scn in table_headers:
header_row.append(load(cell_scn))
for cell_scn in table_cells:
table_cell_row.append(load(cell_scn))
var ctable: = $'таблица/сетка'
ctable.set_header(header_row)
ctable.set_header_text(table_header_text)
ctable.set_header_property(column_cmd_rx, 'image_file', image_file_rx)
ctable.set_header_property(column_cmd_tx, 'image_file', image_file_tx)
ctable.set_headers_min_size(table_header_widths)
ctable.set_columns_min_size(table_column_widths)
ctable.set_rows_min_hight(table_rows_hight)
ctable.set_header_min_hight(table_rows_hight)
ctable.pin_header2()
# Описатель для отображения импульсного ЭМС:
# { идентификаторхода: { 'node_path': путь_к_узлу, 'pname': название_устройства, 'dcls': { имя_кластера: {параметры_кластера}}}}
# Здесь поля txe и rxe - отвечают за конфигурацию:
# txe - вход связан с управлением передатчиком
# rxe - вход связан с управлением приёмника
##TODO: Должна быть возможность для изменения оператором
var imp_yems_descr = {
0: { 'pname': 'эмс-изделие7', # соответствие названия устройства идентификатору входа
'dcls': {'УИЗП1': {'wfb': 300.0, 'cfb': 4000, 'ttl': -1.0, 'txe': false, 'rxe': false}} },
1: { 'pname': 'эмс-изделие8', # соответствие названия устройства идентификатору входа
'dcls': {'УИЗП2': {'wfb': 200.0, 'cfb': 5000, 'ttl': -1.0, 'txe': false, 'rxe': false}} } }
signaller.connect('yems_input_changed', _on_yems_input_changed.bind(imp_yems_descr))
for id in imp_yems_descr:
var descr = imp_yems_descr[id]
var unit_info = yems_info[descr.pname]
for cname in descr.dcls:
var incls = descr.dcls[cname]
var cls = {'cname': cname, 'status': ClasterStatus.RUNNING}
cls.merge(incls)
unit_info.mcls.append(cls)
call_deferred('_on_defer_ready', imp_yems_descr)
func _on_defer_ready(imp_yems_descr: Dictionary):
for id in imp_yems_descr:
var descr = imp_yems_descr[id]
var unit_info = yems_info[descr.pname]
on_data_received(unit_info, descr.pname)
## Вызывается при изменении состояния входа ЭМС.[br]
## [param id] - идентификатор входа ЭМС[br]
## [param state] - новое состояние входа ЭМС[br]
## [param imp_yems_sescr] - описатель входов ЭМС[br]
func _on_yems_input_changed(id: int, state: int, imp_yems_descr):
# Проверить, есть ли в описателе этот вход
if not imp_yems_descr.has(id):
return
var descr = imp_yems_descr[id]
# Проверить, есть ли такое устройство
if not yems_info.has(descr.pname):
return
# Получить доклад устройства
var unit_info = yems_info[descr.pname]
# Вход один, но кластеров может быть несколько,
# поэтому нужно пробежать по всем кластерам
for cls in unit_info.mcls:
var incls = descr.dcls[cls.cname]
# Выставить в докладе разрешение работы приёмника
# или передатчика соответственно состоянию входа
if incls.rxe:
cls.rxe = true if state == 1 else false
if incls.txe:
cls.txe = true if state == 1 else false
# Выполнить то же, что и для приёма данных, поэтому:
on_data_received(unit_info, descr.pname)
## Вызывается при выборе оператором устройства на шкале
## [param val] - состояние кнопки переключателя устройств
## [param nm] - имя выбранного устройства
func _on_scale_selected(val: bool, nm: StringName):
selected_unit[nm] = val
if not val:
$'таблица/сетка'.clear_rows()
cnames_table[nm].clear()
$label_msg.text = msg_select_unit
$label_msg.show()
return
var unit_info = yems_info[nm]
if not unit_info.mcls: # проверить, есть ли данные
$label_msg.text = msg_waiting_data
$label_msg.show()
return # данных ещё нет, ничего не далать
else:
$label_msg.hide()
var ctable = $'таблица/сетка'
var indexes: = cnames_table[nm]
update_cvi(nm)
var new_indexes = update_indexes(unit_info, indexes)
update_table(ctable, new_indexes)
map_yems_info_to_table(unit_info, ctable, indexes)
connect_cmd_handlers(nm, ctable, new_indexes)
## Обновляет результат выполнения команды оператора
## [param nm] - имя устройства
func update_cvi(nm: StringName):
var unit_info = yems_info[nm]
var unit_cmd = yems_cmd[nm]
for cls_info in unit_info.mcls:
var result_rxe: = ClasterResult.WAITING
var result_txe: = ClasterResult.WAITING
if unit_cmd.has(cls_info.cname):
var cls_cmd = unit_cmd[cls_info.cname]
if cls_info.status == ClasterStatus.RUNNING:
if cls_cmd.has('rxe'):
result_rxe = ClasterResult.DONE \
if (cls_info.rxe == cls_cmd.rxe) \
else ClasterResult.MISSMATCH
else:
result_rxe = ClasterResult.DONE
if cls_cmd.has('txe'):
result_txe = ClasterResult.DONE \
if (cls_info.txe == cls_cmd.txe) \
else ClasterResult.MISSMATCH
else:
result_txe = ClasterResult.DONE
else:
result_rxe = ClasterResult.DONE
result_txe = ClasterResult.DONE
cls_info['result_rxe'] = result_rxe
cls_info['result_txe'] = result_txe
## Подключает обработчики команд к таблице кластеров
## [param nm] - имя устройства
## [param new_indexes] - новые индексы рядов таблицы
## [param cls_table] - таблица для отображения кластеров
func connect_cmd_handlers(nm: StringName, ctable: GDTable, new_indexes: Array):
for icls in new_indexes:
var i_row = icls[0]
# Имя устройства и имя кластера
var cls = icls[1]
# Подключить обработчки разрешения передатчиков
var node = ctable.get_node2(column_cmd_tx, i_row)
node.connect_check('toggled', _on_user_cmd.bind(nm, cls.cname, 'txe'))
# Подключить обработчки разрешения приёмников
node = ctable.get_node2(column_cmd_rx, i_row)
node.connect_check('toggled', _on_user_cmd.bind(nm, cls.cname, 'rxe'))
## Вызывается при переключении оператором разрешений для кластера
func _on_user_cmd(val: bool, nm: StringName, cname: String, param_name: StringName):
var unit_cmd = yems_cmd[nm]
if cname in unit_cmd:
unit_cmd[cname][param_name] = val
else:
unit_cmd[cname] = {param_name: val}
## Обрабатывает событие [b]data_received[/b]
## [param data] - данные принятые от устройства
## [param nm] - имя устройства
func on_data_received(data: Dictionary, nm: StringName):
set_timeouts(nm, data)
var unit_info: = yems_info[nm]
unit_info_merge(unit_info, data)
if not unit_info:
# для устройства нет данных
return
var ctable: GDTable = $'таблица/сетка'
var cscale: = name_to_scale[nm] as GridContainer # Шкала устройства
var indexes: = cnames_table[nm] # Индексы строк устройства в таблице
update_cvi(nm)
# Если текущее устройство отображается в таблице,
# обновить таблицу новыми данными
if selected_unit[nm]:
var new_indexes = update_indexes(unit_info, indexes)
update_table(ctable, new_indexes)
map_yems_info_to_table(unit_info, ctable, indexes)
connect_cmd_handlers(nm, ctable, new_indexes)
map_yems_info_to_scale(unit_info, cscale)
var inters: = find_inters()
reset_matrix()
map_inters_to_matrix(inters, $'матрица')
cmd_to_unit(nm)
## Создаёт новые ряды в таблице
func update_table(ctable: GDTable, new_indexes: Array):
# Добавить новые ряды. Два прохода нужно потому,
# что порядок элементов в словаре не определён.
for icls in new_indexes:
ctable.add_row(table_cell_row)
# Заполнить новые ряды данными
for icls in new_indexes:
var i_row = icls[0]
var cls = icls[1]
# Установить высоту ряда (можно пропустить, если нужная высота будет выставлена по умолчанию)
ctable.set_row_min_hight(i_row, table_rows_hight)
# Установить новый текст
ctable.set_node_property(column_cmd_rx, i_row, 'pressed', cls.rxe)
ctable.set_node_property(column_cmd_tx, i_row, 'pressed', cls.txe)
ctable.set_node_property(column_cmd_rx, i_row, 'state', cls.result_rxe)
ctable.set_node_property(column_cmd_tx, i_row, 'state', cls.result_txe)
## Обновляет индексы строк в таблице
func update_indexes(unit_info: Dictionary, indexes: Dictionary) -> Array:
var new_indexes: = []
for cls in unit_info.mcls:
# Проверить, есть ли уже такой индекс
if indexes.has(cls.cname):
continue
# Записать индекс нового ряда (связать с именем кластера)
var i_row = indexes.size()
indexes[cls.cname] = i_row
new_indexes.append([i_row, cls])
return new_indexes
## Объединяет список кластеров принятых от устройства со списком сохранённым
## [param unit_info] - доклад ранее полученный
## [param data_rx] - доклад принятый от устройства
func unit_info_merge(unit_info: Dictionary, data_rx: Dictionary):
var drx: = {}
for cls_rx in data_rx.mcls:
ref_cls.cname = 'неопр.№%d' % (drx.size() + 1)
cls_rx.merge(ref_cls, false) # Объеденить без перезаписи
drx[cls_rx.cname] = cls_rx
var dinfo: = {}
for cls in unit_info.mcls:
dinfo[cls.cname] = cls
dinfo.merge(drx, true)
unit_info.merge(data_rx, true)
unit_info.mcls = dinfo.values()
## Отправляет команду в сетевой стек
## [param nm] - имя устройства
func cmd_to_unit(nm: StringName):
var unit_yemstg: = network.get_unit_instance(nm)
# Проверить, что сетевой стек отправил предидущую команду
if unit_yemstg.cmd_state != unit.Unit.CmdState.DONE:
return
# Сформировать команду из докладов (данных принятых из сети от устройств)
var unit_info_copy = yems_info[nm].duplicate(true)
var unit_cmd = yems_cmd[nm]
unit_info_copy.mtype = 'cmd'
# Выбрать только работающие кластеры (время которых ещё не истекло)
var mcls = unit_info_copy.mcls.filter(func(c): return c.status == ClasterStatus.RUNNING)
for cls_info in mcls:
# Если для этого кластера есть команда оператора ...
if unit_cmd.has(cls_info.cname):
# ... переписать значениями из команды оператора
var cmd_cls = unit_cmd[cls_info.cname]
cls_info.rxe = unit_cmd.get('rxe', cls_info.rxe)
cls_info.txe = unit_cmd.get('txe', cls_info.txe)
# Передать команду сетевому стеку
unit_yemstg.cmd.merge(unit_info_copy, true)
unit_yemstg.cmd_state = unit.Unit.CmdState.SEND
## Запускает таймер достоверности кластера
## [param nm] - имя устройства
## [param unit_info] - доклады устройства
func set_timeouts(nm: StringName, unit_info: Dictionary):
for cls in unit_info.mcls:
var timer_name = NodePath('%s_%s' % [nm, cls.cname])
var timer = get_node_or_null(timer_name)
cls['status'] = ClasterStatus.RUNNING
if cls.ttl < 0.0:
continue
if not timer:
timer = Timer.new()
timer.name = timer_name
timer.one_shot = true
timer.connect('timeout', _on_timeout_ttl.bind(nm, cls.cname))
add_child(timer)
timer.start(cls.ttl)
## Обработчик истечения времени достоверности кластера
## [param nm] - имя устройства
## [param cname] - имя кластера
func _on_timeout_ttl(nm: StringName, cname: StringName):
var timer_name = NodePath('%s_%s' % [nm, cname])
var timer = get_node_or_null(timer_name)
if timer:
remove_child(timer)
timer.queue_free()
var unit_info = yems_info[nm]
for cls in unit_info.mcls:
if cname == cls.cname:
cls.status = ClasterStatus.DELETED
cls.result_rxe = ClasterResult.WAITING
cls.result_txe = ClasterResult.WAITING
var ctable: GDTable = $'таблица/сетка'
var indexes: = cnames_table[nm]
if indexes:
map_yems_info_to_table(unit_info, ctable, indexes)
var claster_scale: = name_to_scale[nm] as GridContainer
map_yems_info_to_scale(unit_info, claster_scale)
reset_matrix()
## Сбрасывает элементы матрицы в исходное состояние
func reset_matrix():
var nodes = get_tree().get_nodes_in_group('матрица-к')
for node in nodes:
node.button_pressed = false
## Отображает пересечения на матрице
## [param inters] - пересечения
## [param matrix] - матрица
func map_inters_to_matrix(inters: Array, matrix: GridContainer) -> void:
var nodes = matrix.get_children()
for item in inters:
var tx_unit_name = item[0]
var rx_unit_name = item[1]
var i_col = 1 + name_to_index[tx_unit_name] # (1 +) - одна колонка для значков приёмников
var i_row = 1 + name_to_index[rx_unit_name] # (1 +) - один ряд для значков передатчиков
var idx = i_col + i_row * matrix.columns # последовательный индекс в GridContainer
var node = nodes[idx] # Искомый элемент
node.button_pressed = true
## Отображает кластеры в таблицу
## [param unit_info] - доклад от устройства
## [param ctable] - таблица
## [param indexes] - индексы в таблице
func map_yems_info_to_table(unit_info: Dictionary, ctable: GDTable, indexes: Dictionary):
# Обойти все кластеры устройства
for cls in unit_info.mcls:
# Строки для заполнения ряда
var status_str: = 'Активен' if cls.status == ClasterStatus.RUNNING else 'Удалён'
var row_text: = [cls.cname, status_str, '%.1f' % cls.ttl, '%.1f' % cls.daa, '%.1f' % cls.dap, '%.1f-%.1f' % [cls.cfb - cls.wfb / 2.0, cls.cfb + cls.wfb / 2.0]]
# Получить индекс строки кластера в таблице
var i_row = indexes[cls.cname]
# Установить новый текст
ctable.set_row_text(i_row, row_text)
# Результат выполнения
ctable.set_node_property(column_cmd_rx, i_row, 'state', cls.result_rxe)
ctable.set_node_property(column_cmd_tx, i_row, 'state', cls.result_txe)
## Находит пересечения диапазонов всех устройств и кластеров
func find_inters() -> Array:
var result = []
var all_clusters = []
# Собираем все кластеры из всех устройств в один массив
for nm in yems_info:
# nm - имя устройства
var unit_data = yems_info[nm]
if not unit_data: continue
var clasters = unit_data.mcls.filter \
(func(c): return c.status == ClasterStatus.RUNNING)
for cls in clasters:
# cls - один кластер
var cfb = float(cls.cfb)
var wfb = float(cls.wfb) / 2.0
# расчёт границ частотных диапазонов
var freq_min1 = cfb - wfb
var freq_max1 = cfb + wfb
all_clusters.append([nm, cls.cname, freq_min1, freq_max1, cls.txe, cls.rxe])
for i in all_clusters.size():
var cl1 = all_clusters[i]
var dev1 = cl1[0]
var name1 = cl1[1]
var min1 = cl1[2]
var max1 = cl1[3]
var txe1 = cl1[4]
var rxe1 = cl1[5]
# Сравниваем текущий кластер со всеми последующими,
# чтобы избежать дублей и самопересечений
for j in all_clusters.size():
var cl2 = all_clusters[j]
var dev2 = cl2[0]
var name2 = cl2[1]
var min2 = cl2[2]
var max2 = cl2[3]
var txe2 = cl2[4]
var rxe2 = cl2[5]
# Если нет пары TR(RT) то пропускаем эту комбинацию
if not ((txe1 and rxe2) or (rxe1 and txe2)):
continue
# Проверка на пересечение диапазонов, пересечение
# есть если начало одного диапазона меньше конца другого
if max1 > min2 and max2 > min1:
#Вычисляем точные границы пересечения
var inter_start = max(min1, min2)
var inter_end = min(max1, max2)
# Формируем результат в требуемом формате
result.append([dev1, dev2, name1, name2, inter_start, inter_end])
return result
## Отображает кластеры на шкале
## [param unit_info] - доклад устройства
## [param cscale] - шкала кластера
func map_yems_info_to_scale(unit_info: Dictionary, cscale: GridContainer):
# Обойти все кластеры устройства
for cls in unit_info.mcls:
# Преобразовать диапазоны частот в диапазоны отображения
var c: = remap(cls.cfb, freq_min, freq_max, 0.0, 1.0)
var w: = remap(cls.wfb, freq_min * 0.5, freq_max * 0.5, 0.0, 0.5)
# Чтобы диапазон всегда был виден, даже если он слишком узкий
w = clampf(w, 0.005, 0.5)
# Отсечь значения по границам
var l: = clampf(c - w, 0.0, 1.0)
var h: = clampf(c + w, 0.0, 1.0)
# Получить шкалу приёмника
var scale_rx: = cscale.get_node('panel_rx')
# Получить шкалу передатчика
var scale_tx: = cscale.get_node('panel_tx')
# Диапазон работает (информация обновляется)
if cls.status == ClasterStatus.RUNNING:
# Отобразить диапазон приёмника, в соответствии с разрешением
var color_rxe: = color_enabled if cls.rxe else color_disabled
scale_rx.set_range(cls.cname, l, h, color_rxe)
# Отобразить диапазон передатчика, в соответствии с разрешением
var color_txe: = color_enabled if cls.txe else color_disabled
scale_tx.set_range(cls.cname, l, h, color_txe)
# Диапазон удалён (информация не обновляется)
elif cls.status == ClasterStatus.DELETED:
scale_rx.del_range(cls.cname)
scale_tx.del_range(cls.cname)

Some files were not shown because too many files have changed in this diff Show More