Compare commits

...

100 Commits

Author SHA1 Message Date
MaD_CaT
8bb41f9162 Изменено. Актуальные настройки комплекса
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-02 12:48:25 +03:00
Maxim
0b2c101a4b Merge remote-tracking branch 'sasha80/master' into workflows 2026-03-20 11:07:41 +03:00
sasha80
86716437cf Доработка. WIP Отображение кластера в таблице 2026-03-19 16:40:32 +03:00
sasha80
97bbd85622 Доработка. Добавлено важное уточнение 2026-03-16 16:25:39 +03:00
sasha80
df80508592 Исправление. Лишнее действие 2026-03-16 15:42:31 +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
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
MaD_CaT
f4a6a4d465 Исправление. Убран warning при распаковки состояния БПО от КАПС РПБ. 2026-01-12 15:56:35 +03:00
86 changed files with 1569 additions and 607 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)` для доступа к настройкам.
и `ProjectSettings.get_setting('application/config/%s % key_name)` для доступа к настройкам.
- `key_name` брать из таблицы `res://scenes/настройки/настройки.gd/SETTING_TABLE`
- Следовать [общим правилам](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

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

@@ -62,39 +62,40 @@ interfer/closed_sectors=Color(0, 0, 0, 1)
"config/Кнопка «СВ-И1»"=false
"config/Кнопка «СВ-М2»"=false
"config/Ограниченный режим"=false
"config/Отладка контроля"=false
"config/Отладка контроля"=true
"config/Период опроса состояния АФСП, секунды"=""
"config/Период опроса состояния БПО, секунды"=""
"config/Скрыть вкладку ЭМС 2"=true
"config/Список своих протоколов"=""
"config/Текущая версия ПО УАРЭП"="master 3bff1cd Tue Nov 4 15:33:24 2025 +0300"
"config/Цвет кнопки \"Подавление\""="[0.972549021244049,0.0117647061124444,0.423529416322708,1.0]"
"config/Цвет схемы"="[0.972549021244049,0.0117647061124444,0.0274509806185961,1.0]"
"config/Цвет фона схемы"="[0.0941176488995552,0.149019613862038,1.0,1.0]"
"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, true, true]
"config/уарэп-5п28"=["127.0.0.1", 50777]
"config/уарэп-капсрпб"=["127.0.0.1", "127.0.0.1", 42023, 42022, false, true]
"config/уарэп-спт25-1"=["/home/user/tty0", 0, 19200, "N", 8, 1]
"config/уарэп-спт25-2"=["/home/user/tty1", 0, 19200, "N", 8, 1]
"config/уарэп-трасса"=["192.168.11.34", "192.168.11.105", 50200, 10004, false, true]
"config/уарэп-щ3"=["/home/user/tty3", 7, 19200, "N", 8, 1, 50000]
"config/уарэп-эмс"=["10.1.1.52", 50052, false, false]
"config/уарэп-яу07-1в"=["10.1.1.12", 50012, false, false]
"config/уарэп-яу07-1к"=["10.1.1.13", 50013, false, false]
"config/уарэп-яу07-1н"=["10.1.1.11", 50011, false, false]
"config/уарэп-яу07-2в"=["10.1.1.22", 50022, false, false]
"config/уарэп-яу07-2к"=["10.1.1.23", 50023, false, false]
"config/уарэп-яу07-2н"=["10.1.1.21", 50021, false, false]
"config/уарэп-яу07-3в"=["10.1.1.32", 50032, false, false]
"config/уарэп-яу07-3к"=["10.1.1.33", 50033, false, false]
"config/уарэп-яу07-3н"=["10.1.1.31", 50031, false, false]
"config/уарэп-яу07-4в"=["10.1.1.42", 50042, false, false]
"config/уарэп-яу07-4к"=["10.1.1.43", 50043, false, false]
"config/уарэп-яу07-4н"=["10.1.1.41", 50041, false, false]
"config/уарэп-яу07-общий"=["*", 50000, true, true]
"config/уарэп-яу07-частный"=["10.1.1.253", 50253, false, true]
"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]

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,6 +57,9 @@ 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
@@ -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,35 +12,35 @@ 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
$back.strips_rotation = deg_to_rad(val)
if is_inside_tree():
$back.strips_rotation = deg_to_rad(val)
@export var text: String = '':
set(val):
text = val
$button.set_text(val)
if is_inside_tree():
$button.set_text(val)
@export var btn_tooltip: String = '':
set(val):
btn_tooltip = val
$button.set_tooltip_text(val)
if is_inside_tree():
$button.set_tooltip_text(val)
@export var disabled: bool = false:
@@ -70,7 +70,9 @@ var _pressed: = false
@export var font_size: int = 15:
set(val):
$button.add_theme_font_size_override('theme_override_font_sizes/font_size', val)
font_size = val
if is_inside_tree():
$button.add_theme_font_size_override('theme_override_font_sizes/font_size', val)
func set_pressed(val: bool):
@@ -92,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

@@ -1,26 +1,22 @@
class_name Diagram extends ColorRect
const NUM_OF_RANGE = 7
const NUM_OF_DIRECTIONS = 4
const color0_default: Color = Color(0.38, 0.47, 0.51, 1.0)
const color1_default: Color = Color(0.39, 0.44, 0.50, 1.0)
var color0: Color = color0_default
var color1: Color = color1_default
var fs_default_colors: PackedColorArray ## Цвета по умолчанию для блоков ФС
var image: Image
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:
image = Image.create(NUM_OF_RANGE * NUM_OF_DIRECTIONS, 1, false, Image.FORMAT_RGBA8)
signaller.connect('map_mode_changed', Callable(self, 'set_view_mode'))
ProjectSettings.connect('settings_changed', _on_settings_changed)
_on_settings_changed()
set_def_colors()
_init_def_colors()
set_band_colors(fs_default_colors)
func sv(val: float) -> float: return val / ($строб.scale.x / 2.0) * 0.125
@@ -52,9 +48,10 @@ func get_strob_width() -> float: return $строб.get_instance_shader_pa
## Выставляет цвета для секторов
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)
var tex: = ImageTexture.create_from_image(image)
material.set('shader_parameter/sec_colors', tex)
@@ -100,7 +97,7 @@ 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()
@@ -116,17 +113,12 @@ func set_view_mode(val: int):
func _on_settings_changed():
color0 = ProjectSettings.get_setting('application/interfer/default_color0', color0_default)
color1 = ProjectSettings.get_setting('application/interfer/default_color1', color1_default)
color0 *= Color(1.0, 1.0, 1.0, 0.0)
color1 *= Color(1.0, 1.0, 1.0, 0.0)
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 col_arr: PackedColorArray = [color0, color1]
for i in NUM_OF_RANGE:
for j in NUM_OF_DIRECTIONS:
fs_default_colors.append(col_arr[i & 1])
i += 1
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

@@ -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 = {
@@ -40,15 +42,30 @@ const INTERFER_NAMES = {
'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'] ]
## Индексы колонок
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):
var i_row = table_index[ecm.ispp]
$table.set_row_text(i_row, row)
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,7 +147,7 @@ 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.clear_rows_selected()
@@ -149,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):
@@ -164,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
@@ -175,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,7 +5,7 @@ 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 ] ## Описание ряда.
@@ -16,6 +16,8 @@ const TABLE_COLUMN_SIZE = [ 65, 70, 110, 140,
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

@@ -23,7 +23,6 @@ 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

View File

@@ -23,7 +23,6 @@ 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

View File

@@ -7,22 +7,27 @@ class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd'
@export var settings_path_to_url: String = '' ## Должно быть в ProjectSettings
@export var settings_path_to_wait_time: String = '' ## Должно быть в ProjectSettings
signal receive_response_afp_bpo()
static var json_conv: JSON = JSON.new()
static var node_maper = load('res://scenes/контроль/node-maper.gd')
static var node_request: Node
static var node_request_timer: Node
var ctrl_pos = 0
# SystemName: "gen" DevList - там состояние связи с генератором по кан шине
func _ready() -> void:
ProjectSettings.connect('settings_changed', on_settings_chaged)
node_request = $request
node_request_timer = $request/timer
on_settings_chaged()
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)
node_request.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path_to_url)
node_request_timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
tools.allways(node_request.request_url != null)
func _on_request_completed(result, _response_code, headers, body: PackedByteArray):
@@ -30,7 +35,7 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra
var unit_instance: = network.get_unit_instance(unit_name)
if result != 0:
var rs = $request.get_result_string(result)
var rs = node_request.get_result_string(result)
log.error('\"%s\"' % rs)
if unit_instance.online:
unit_instance.online = false
@@ -93,6 +98,8 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra
node_maper.map_value_to_item(json_conv.data, child, 'value1')
node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
emit_signal('receive_response_afp_bpo')
## Вызывается при клике мыши на элементе.
## [param block_a] - Кликнутый элемент.

View File

@@ -10,12 +10,17 @@ 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
signal receive_response_afp_bpo()
static var json_conv: JSON = JSON.new()
static var node_maper = load('res://scenes/контроль/node-maper.gd')
static var node_request_1: Node
static var node_request_timer_1: Node
static var node_request_2: Node
static var node_request_timer_2: Node
var ctrl_pos = 110
var bort_to_node_name = {}
var bort_to_unit_name = {}
@@ -23,6 +28,10 @@ var bort_to_unit_name = {}
func _ready() -> void:
ProjectSettings.connect('settings_changed', on_settings_changed)
node_request_1 = $request1
node_request_timer_1 = $request1/timer
node_request_2 = $request2
node_request_timer_2 = $request2/timer
on_settings_changed()
find_labels(self)
@@ -30,17 +39,17 @@ func _ready() -> void:
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)
node_request_1.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path1_to_url)
node_request_timer_1.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
node_request_2.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path2_to_url)
node_request_timer_2.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
assert(node_request_1.request_url != null)
assert(node_request_2.request_url != null)
func _on_request_completed(result, _response_code, headers, body: PackedByteArray):
if result != 0:
var rs = $request1.get_result_string(result)
var rs = node_request_1.get_result_string(result)
push_error('\"%s\"' % rs)
return
@@ -97,18 +106,20 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra
$mod_pit_g1.state = 1
break
emit_signal('receive_response_afp_bpo')
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

@@ -202,7 +202,6 @@ 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

View File

@@ -41,8 +41,6 @@ func _process(_delta: float) -> void:
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'))
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:
@@ -103,6 +101,7 @@ static func power_fill(pow_dic: Dictionary, fs_result: Dictionary, power_amplifi
func on_press_device(_name_davice: String) -> void:
if not is_inside_tree(): return
var control_data: Dictionary = unit_prd_k.get_control_results()
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')
@@ -138,7 +137,7 @@ static func on_control_result(for_result_dic: Dictionary) -> void:
if block_ip_config_k.has(meta_ip) and block_kasseta_y5_prd_config_k.ug and block_kasseta_y5_prd_config_k.yau07:
power_supply.state = STATE_VAL.GOOD if block_ip_config_k[meta_ip][1] else STATE_VAL.ERROR
else:
power_supply.state = STATE_VAL.NONE
power_supply.state = STATE_VAL.NONE
# Проверяем состояние после установки
if power_supply.state == STATE_VAL.ERROR:
all_y5_good = false
@@ -191,11 +190,11 @@ func find_labels(node1: Node):
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:
$control_result.add_theme_color_override('font_color', Color.RED)
log.message(Logger.INFO, 'Прибор ПРД-%s неисправен' % [unit_prd_k.self_name])

View File

@@ -41,8 +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]
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:
@@ -94,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')
@@ -189,11 +188,11 @@ func find_labels(node1: Node):
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:
$control_result.add_theme_color_override('font_color', Color.RED)
log.message(Logger.INFO, 'Прибор ПРД-%s неисправен' % [unit_prd_n.self_name])

View File

@@ -41,8 +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]
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:
@@ -93,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')
@@ -186,11 +185,11 @@ func find_labels(node1: Node):
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:
$control_result.add_theme_color_override('font_color', Color.RED)
log.message(Logger.INFO, 'Прибор ПРД-%s неисправен' % [unit_prd_v.self_name])

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 +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,4 +1,4 @@
[gd_scene load_steps=19 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"]
@@ -7,18 +7,10 @@
[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://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"]
@@ -33,17 +25,14 @@ bg_color = Color(0, 100, 0, 1)
[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")

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:
@@ -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
@@ -732,7 +722,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)
@@ -756,7 +746,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 +756,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 +765,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 +792,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()

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

@@ -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'))
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,11 +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("Есть связь")
set_tooltip_text('Есть связь')
else:
$connect_pribor.modulate = modulate # изначальный
set_tooltip_text("Нет связи")
set_tooltip_text('Нет связи')

View File

@@ -21,6 +21,8 @@ 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
@@ -32,3 +34,5 @@ func _on_request_timer():
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

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

View File

@@ -4,13 +4,16 @@ 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)
ProjectSettings.connect("settings_changed", Callable(self, "_on_settings_changed"))
ProjectSettings.connect('settings_changed', Callable(self, '_on_settings_changed'))
_on_settings_changed()
@@ -23,7 +26,62 @@ 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):
@@ -54,12 +112,12 @@ func _on_settings_changed():
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)
@@ -76,6 +134,8 @@ func _on_settings_changed():
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
@@ -108,3 +168,13 @@ func _on_settings_changed():
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)

View File

@@ -18,13 +18,13 @@
[ext_resource type="Texture2D" uid="uid://00871pb6moln" path="res://data/прогресс-фон-1.png" id="9_w6m6a"]
[ext_resource type="Texture2D" uid="uid://c1k856fxhrjnh" path="res://data/прогресс-заполнение-1.png" id="10_lbx5w"]
[ext_resource type="Texture2D" uid="uid://u7h3l0jjrsnp" path="res://data/У-УФ.png" id="11_gjf0t"]
[ext_resource type="Script" uid="uid://bncy1x53jp73d" path="res://scenes/контроль/connect_pribor.gd" id="11_u7tym"]
[ext_resource type="Script" uid="uid://bncy1x53jp73d" path="res://scenes/контроль/connect-pribor.gd" id="11_u7tym"]
[ext_resource type="Texture2D" uid="uid://vdhmga62vjsj" path="res://data/АФСП-РТР.png" id="13_32yvq"]
[ext_resource type="Texture2D" uid="uid://dm350ta8noa0v" path="res://data/У-РЭП-РПД-К.png" id="16_32yvq"]
[ext_resource type="Texture2D" uid="uid://c3cyog3gy24ft" path="res://data/У-ЭП.png" id="16_gjf0t"]
[ext_resource type="Script" uid="uid://xjs7owe2iexn" path="res://scenes/контроль/control_prd.gd" id="18_lbx5w"]
[ext_resource type="Script" uid="uid://xjs7owe2iexn" path="res://scenes/контроль/control-prd.gd" id="18_lbx5w"]
[ext_resource type="Texture2D" uid="uid://b2vf7en1jj8dv" path="res://data/У-РЭП-РПД-В.png" id="20_l5wui"]
[ext_resource type="Script" uid="uid://j16hg3u2uvu5" path="res://scenes/контроль/panel_container.gd" id="21_l5wui"]
[ext_resource type="Script" uid="uid://j16hg3u2uvu5" path="res://scenes/контроль/panel-container.gd" id="21_l5wui"]
[ext_resource type="Texture2D" uid="uid://cllxcfa130vqu" path="res://data/УА-РЭП.png" id="22_1s34a"]
[sub_resource type="GDScript" id="GDScript_iqgf5"]
@@ -166,14 +166,33 @@ func on_pribor_press(pribor_path, header_text, pribor_node):
pribor.add_to_group('pribor_items')
add_child(pribor)
update_pribor_items_visibility()
if pribor_node.get_meta('unit_name')[0] == 'уарэп-афсп-левый' or pribor_node.get_meta('unit_name')[0] == 'уарэп-афсп-правый':
pribor.node_request.connect('send_http_request', Callable(self, 'on_send_http_request').bind(pribor_node, pribor.node_request_timer.wait_time))
pribor.connect('receive_response_afp_bpo', Callable(self, 'on_receive_response_afp_bpo').bind(pribor_node))
if pribor_node.get_meta('unit_name')[0] == 'уарэп-бпо-1' or pribor_node.get_meta('unit_name')[0] == 'уарэп-бпо-2':
pribor.node_request_1.connect('send_http_request', Callable(self, 'on_send_http_request').bind(pribor_node, pribor.node_request_timer_1.wait_time))
pribor.connect('receive_response_afp_bpo', Callable(self, 'on_receive_response_afp_bpo').bind(pribor_node))
#signal receive_response_afp_bpo
# Вызов при отправке запроса на селфтест АФСП
func on_send_http_request(node: Node, time_req: float) -> void:
node.progress_max_value = 100
node.progress_value = 0
node.progress_visible = true
node.timeout_tween = time_req
func on_receive_response_afp_bpo(node: Node) -> void:
node.progress_value = 100
## Прием сигналов о текущем состояниях приборах
func on_serviceability_changed(state: int, prd_pribor_node: Node)-> void:
func on_serviceability_changed(state: int, prd_pribor_node: Node) -> void:
prd_pribor_node.state = state
func on_update_uf_serviceability(uf_serviceaability: int, uf_pribor: Node)-> void:
func on_update_uf_serviceability(uf_serviceaability: int, uf_pribor: Node) -> void:
uf_pribor.state = uf_serviceaability
@@ -643,15 +662,16 @@ frame_progress = 0.72355
[node name="pribor_uf" type="TextureButton" parent="." groups=["pribor_buttons"]]
editor_description = "Кнопка для выбора прибора."
layout_mode = 0
offset_left = 1183.0
offset_top = 558.0
offset_right = 1294.0
offset_bottom = 743.0
offset_left = 1188.0
offset_top = 576.0
offset_right = 1285.0
offset_bottom = 738.0
size_flags_horizontal = 15
size_flags_vertical = 15
toggle_mode = true
action_mode = 0
texture_normal = ExtResource("2_0nvm1")
ignore_texture_size = true
stretch_mode = 0
script = ExtResource("3_4pt7j")
state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)]
@@ -660,9 +680,9 @@ metadata/online_proc = "on_line_changed"
[node name="label" type="Label" parent="pribor_uf"]
layout_mode = 0
offset_left = 15.0
offset_left = -12.0
offset_top = -44.0
offset_right = 91.0
offset_right = 108.0
offset_bottom = -25.0
text = "УФ"
horizontal_alignment = 1
@@ -672,10 +692,10 @@ vertical_alignment = 1
visible = false
self_modulate = Color(0.890196, 0.486275, 0.196078, 1)
layout_mode = 0
offset_left = -14.0
offset_left = -20.0
offset_top = -30.0
offset_right = 126.0
offset_bottom = 200.0
offset_right = 116.0
offset_bottom = 179.0
texture = ExtResource("4_rasbe")
region_rect = Rect2(-3, -3, 89, 89)
patch_margin_left = 16
@@ -698,10 +718,10 @@ texture = ExtResource("11_gjf0t")
[node name="control_progress" type="TextureProgressBar" parent="pribor_uf"]
visible = false
layout_mode = 0
offset_left = 9.0
offset_top = 191.0
offset_right = 102.0
offset_bottom = 201.0
offset_left = 2.0
offset_top = 176.0
offset_right = 95.0
offset_bottom = 186.0
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "
@@ -732,7 +752,7 @@ script = ExtResource("21_l5wui")
[node name="connect_pribor" type="AnimatedSprite2D" parent="pribor_uf/panel_pribor"]
light_mask = 3
position = Vector2(11.4285, 12.8571)
position = Vector2(4.28552, 12.8571)
scale = Vector2(0.6, 0.596)
sprite_frames = SubResource("SpriteFrames_foasq")
frame_progress = 0.72355
@@ -741,9 +761,9 @@ frame_progress = 0.72355
editor_description = "Кнопка для выбора прибора."
layout_mode = 0
offset_left = 1058.0
offset_top = 588.0
offset_top = 580.0
offset_right = 1164.0
offset_bottom = 744.0
offset_bottom = 736.0
pivot_offset = Vector2(-10, -65)
size_flags_horizontal = 15
size_flags_vertical = 15
@@ -758,10 +778,10 @@ metadata/online_proc = "online_change_arr"
[node name="label" type="Label" parent="pribor_rtr"]
layout_mode = 0
offset_left = 11.0
offset_top = -49.0
offset_right = 94.0
offset_bottom = -30.0
offset_left = -10.0
offset_top = -48.0
offset_right = 110.0
offset_bottom = -29.0
text = "РТР"
horizontal_alignment = 1
vertical_alignment = 1
@@ -770,10 +790,10 @@ vertical_alignment = 1
visible = false
self_modulate = Color(0.890196, 0.486275, 0.196078, 1)
layout_mode = 0
offset_left = -13.0
offset_left = -18.0
offset_top = -34.0
offset_right = 117.0
offset_bottom = 171.0
offset_right = 118.0
offset_bottom = 175.0
texture = ExtResource("4_rasbe")
region_rect = Rect2(-3, -3, 89, 89)
patch_margin_left = 16
@@ -781,16 +801,6 @@ patch_margin_top = 16
patch_margin_right = 16
patch_margin_bottom = 16
[node name="label2" type="Label" parent="pribor_rtr"]
layout_mode = 0
offset_left = 11.0
offset_top = -49.0
offset_right = 94.0
offset_bottom = -30.0
text = "РТР"
horizontal_alignment = 1
vertical_alignment = 1
[node name="pic_functional" type="TextureRect" parent="pribor_rtr"]
visible = false
z_index = 1
@@ -822,13 +832,36 @@ scale = Vector2(0.6, 0.596)
sprite_frames = SubResource("SpriteFrames_foasq")
frame_progress = 0.72355
[node name="control_progress" type="TextureProgressBar" parent="pribor_rtr"]
visible = false
layout_mode = 0
offset_left = 6.0
offset_top = 172.0
offset_right = 102.0
offset_bottom = 182.0
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "
Текущее: 0.00"
mouse_filter = 0
max_value = 30.0
nine_patch_stretch = true
stretch_margin_left = 5
stretch_margin_top = 5
stretch_margin_right = 5
stretch_margin_bottom = 5
texture_under = ExtResource("9_w6m6a")
texture_progress = ExtResource("10_lbx5w")
tint_under = Color(1, 1, 1, 0.419608)
tint_progress = Color(0.890196, 0.486275, 0.196078, 1)
[node name="pribor_afsp_1" type="TextureButton" parent="." groups=["pribor_buttons"]]
editor_description = "Кнопка для выбора прибора."
layout_mode = 0
offset_left = 1053.0
offset_top = 425.0
offset_right = 1886.0
offset_bottom = 1065.0
offset_right = 1853.0
offset_bottom = 1025.0
scale = Vector2(0.2, 0.2)
pivot_offset = Vector2(-10, -65)
size_flags_horizontal = 15
@@ -836,6 +869,7 @@ size_flags_vertical = 15
toggle_mode = true
action_mode = 0
texture_normal = ExtResource("9_iqgf5")
ignore_texture_size = true
stretch_mode = 0
script = ExtResource("3_4pt7j")
state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)]
@@ -857,9 +891,9 @@ vertical_alignment = 1
visible = false
self_modulate = Color(0.890196, 0.486275, 0.196078, 1)
layout_mode = 0
offset_left = -60.0
offset_top = -165.0
offset_right = 130.0
offset_left = -55.0
offset_top = -170.0
offset_right = 125.0
offset_bottom = 10.0
scale = Vector2(5, 5)
texture = ExtResource("4_rasbe")
@@ -869,17 +903,6 @@ patch_margin_top = 16
patch_margin_right = 16
patch_margin_bottom = 16
[node name="label2" type="Label" parent="pribor_afsp_1"]
layout_mode = 0
offset_left = 175.0
offset_top = -245.0
offset_right = 272.0
offset_bottom = -225.0
scale = Vector2(5, 5)
text = "АФСП 1"
horizontal_alignment = 1
vertical_alignment = 1
[node name="pic_functional" type="TextureRect" parent="pribor_afsp_1"]
visible = false
z_index = 1
@@ -911,13 +934,37 @@ scale = Vector2(3, 2.981)
sprite_frames = SubResource("SpriteFrames_foasq")
frame_progress = 0.72355
[node name="control_progress" type="TextureProgressBar" parent="pribor_afsp_1"]
visible = false
layout_mode = 0
offset_left = -25.0
offset_top = 735.0
offset_right = 815.0
offset_bottom = 775.0
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "
Текущее: 0.00"
mouse_filter = 0
max_value = 30.0
value = 8.0
nine_patch_stretch = true
stretch_margin_left = 5
stretch_margin_top = 5
stretch_margin_right = 5
stretch_margin_bottom = 5
texture_under = ExtResource("9_w6m6a")
texture_progress = ExtResource("10_lbx5w")
tint_under = Color(1, 1, 1, 0.419608)
tint_progress = Color(0.890196, 0.486275, 0.196078, 1)
[node name="pribor_afsp_2" type="TextureButton" parent="." groups=["pribor_buttons"]]
editor_description = "Кнопка для выбора прибора."
layout_mode = 0
offset_left = 1243.0
offset_top = 425.0
offset_right = 2076.0
offset_bottom = 1065.0
offset_right = 2043.0
offset_bottom = 1025.0
scale = Vector2(0.2, 0.2)
pivot_offset = Vector2(-10, -65)
size_flags_horizontal = 15
@@ -925,6 +972,7 @@ size_flags_vertical = 15
toggle_mode = true
action_mode = 0
texture_normal = ExtResource("9_iqgf5")
ignore_texture_size = true
stretch_mode = 0
flip_h = true
script = ExtResource("3_4pt7j")
@@ -948,8 +996,8 @@ visible = false
self_modulate = Color(0.890196, 0.486275, 0.196078, 1)
layout_mode = 0
offset_left = -50.0
offset_top = -165.0
offset_right = 140.0
offset_top = -170.0
offset_right = 130.0
offset_bottom = 10.0
scale = Vector2(5, 5)
texture = ExtResource("4_rasbe")
@@ -959,17 +1007,6 @@ patch_margin_top = 16
patch_margin_right = 16
patch_margin_bottom = 16
[node name="label2" type="Label" parent="pribor_afsp_2"]
layout_mode = 0
offset_left = 175.0
offset_top = -240.0
offset_right = 272.0
offset_bottom = -220.0
scale = Vector2(5, 5)
text = "АФСП 2"
horizontal_alignment = 1
vertical_alignment = 1
[node name="pic_functional" type="TextureRect" parent="pribor_afsp_2"]
visible = false
z_index = 1
@@ -1001,18 +1038,43 @@ scale = Vector2(3, 2.981)
sprite_frames = SubResource("SpriteFrames_foasq")
frame_progress = 0.72355
[node name="control_progress" type="TextureProgressBar" parent="pribor_afsp_2"]
visible = false
layout_mode = 0
offset_left = -15.0
offset_top = 735.0
offset_right = 825.0
offset_bottom = 775.0
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "
Текущее: 0.00"
mouse_filter = 0
max_value = 30.0
value = 8.0
nine_patch_stretch = true
stretch_margin_left = 5
stretch_margin_top = 5
stretch_margin_right = 5
stretch_margin_bottom = 5
texture_under = ExtResource("9_w6m6a")
texture_progress = ExtResource("10_lbx5w")
tint_under = Color(1, 1, 1, 0.419608)
tint_progress = Color(0.890196, 0.486275, 0.196078, 1)
[node name="pribor_uyep" type="TextureButton" parent="." groups=["pribor_buttons"]]
editor_description = "Кнопка для выбора прибора."
layout_mode = 0
offset_left = 1313.0
offset_top = 558.0
offset_right = 1407.0
offset_bottom = 744.0
offset_left = 1317.0
offset_top = 575.0
offset_right = 1398.0
offset_bottom = 735.0
size_flags_horizontal = 15
size_flags_vertical = 15
toggle_mode = true
action_mode = 0
texture_normal = ExtResource("5_kvnex")
ignore_texture_size = true
stretch_mode = 0
script = ExtResource("3_4pt7j")
state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)]
@@ -1021,10 +1083,10 @@ metadata/online_proc = "online_change_arr"
[node name="label" type="Label" parent="pribor_uyep"]
layout_mode = 0
offset_left = 26.8566
offset_top = -43.3276
offset_right = 66.8566
offset_bottom = -24.3276
offset_left = -13.0
offset_top = -43.0
offset_right = 99.0
offset_bottom = -24.0
text = "У-ЭП"
horizontal_alignment = 1
vertical_alignment = 1
@@ -1033,10 +1095,10 @@ vertical_alignment = 1
visible = false
self_modulate = Color(0.890196, 0.486275, 0.196078, 1)
layout_mode = 0
offset_left = -13.0
offset_left = -21.0
offset_top = -29.0
offset_right = 117.0
offset_bottom = 199.0
offset_right = 107.0
offset_bottom = 180.0
texture = ExtResource("4_rasbe")
region_rect = Rect2(-3, -3, 89, 89)
patch_margin_left = 16
@@ -1070,7 +1132,7 @@ script = ExtResource("21_l5wui")
[node name="connect_pribor" type="AnimatedSprite2D" parent="pribor_uyep/panel_pribor"]
light_mask = 3
position = Vector2(11.4285, 12.8571)
position = Vector2(-0.00012207, 12.8571)
scale = Vector2(0.6, 0.596)
sprite_frames = SubResource("SpriteFrames_foasq")
frame_progress = 0.72355

View File

@@ -1,14 +1,42 @@
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 = [
const HEADER_ROW_TEXT: = ['Параметр', 'Значение']
var HEADER_ROW: Array
## TODO: Придумать как избавиться от индексов
## Индексы строк таблицы.
const EXTERNAL_CU = 16 ## Внешнее целеуказание
const TRASSA = 17 ## Строка - Трасса
const SUPPRESS = 18 ## Строка - Подавление
const KEYBOARD = 19 ## Строка - Виртуальная клавиатура
const HIDE_EMS2 = 20 ## Строка - Скрыть вкладку ЭМС 2
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 _init_scene_arrays():
HEADER_ROW = [TableHeader, TableHeader]
SETTING_TABLE = [
['Ограниченный режим', TableEdit, TableToggle, 'Ограничть возможности по постановке помех'], # 0
['Кнопка «ПД-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 1
['Кнопка «ПД-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'], # 2
@@ -66,67 +94,53 @@ const SETTING_TABLE = [
['Цвет кнопки \"Подавление\"', TableEdit, TableColorPick, 'Цвет кнопки. Введено по требованию ПЗ' ], # 54
['Цвет фона схемы', TableEdit, TableColorPick, 'Схема прибора Э2. Изменение цвет фона'], # 55
['Цвет схемы', TableEdit, TableColorPick, 'Схема прибора Э2. Изменение цвет схемы '], # 56
['Коэффициент ширины полосы излучения', TableEdit, TableEdit, 'Изменение ширины полосы излучения помехи в зависимости от цели'], # 57
['Время повторной отправки помехи', TableEdit, TableEdit, 'Изменение времени повторной отправки помехи'] ] # 58
## TODO: Придумать как избавиться от индексов
## Индексы строк таблицы.
const EXTERNAL_CU = 16 ## Внешнее целеуказание
const TRASSA = 17 ## Строка - Трасса
const SUPPRESS = 18 ## Строка - Подавление
const KEYBOARD = 19 ## Строка - Виртуальная клавиатура
const HIDE_EMS2 = 20 ## Строка - Скрыть вкладку ЭМС 2
const DEBAG_CONTROL = 21 ## Строка - Отладка контроля
const COMMIT = 22 ## Строка - Версия УАРЭП
const GOS_BTN = 52 ## Разрешить работу по своим целям
const COLOR_BTN_ACT = 54 ## Цвет кнопки "Подавление"
const COLOR_WHITE = 55 ## Цвет фона схемы
const COLOR_BLACK = 56 ## Цвет схемы
var name_to_line_index: = {} ## Для преобразования названия параметра в номер строки
var table_color_instance: Node ## Нода цвета кнопки подавления
func on_checkbutton_pressed(i_row: int): on_row_pressed(i_row)
['Цвет темы программы', TableEdit, TableToggle, 'ВЫКЛ - темная тема, ВКЛ - светлая тема'], # 57
['Коэффициент ширины полосы излучения', TableEdit, TableEdit, 'Изменение ширины полосы излучения помехи в зависимости от цели'], # 58
['Время повторной отправки помехи', TableEdit, TableEdit, 'Изменение времени повторной отправки помехи'] ] # 59
## Вызывается, когда узел впервые попадает в дерево сцены.
func _ready() -> void:
setting_tab()
if not OS.get_cmdline_args().has('++ограниченный'):
return
$Label2.text = 'Текущий режим доступа: ограниченный'
for node in $GridContainer.get_children().filter(func(b): return b is Button):
node.disabled = true
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):
@@ -171,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])
@@ -199,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]
@@ -207,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)
@@ -268,6 +285,15 @@ func button_settings():
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():
@@ -281,21 +307,24 @@ 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, 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

@@ -135,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)
@@ -151,10 +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)
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
## Обработчик сигнала изменения списка целей.
func on_threats_resized(ths: Dictionary):
@@ -329,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)
@@ -340,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()
@@ -567,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()
@@ -634,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)
@@ -663,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():
@@ -698,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"]
@@ -96,7 +96,6 @@ text = "Обзорная карта"
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
@@ -389,8 +388,8 @@ texture_normal = ExtResource("14_ggrwd")
[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"]
[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"]
[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"]
[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"]
[connection signal="button_down" from="zoom_minus" to="tilemap" method="_on_zoom_minus_button_down"]
[connection signal="button_up" from="zoom_minus" to="tilemap" method="_on_zoom_button_up"]
[connection signal="pressed" from="btn_all_work" to="." method="_on_btn_all_work_pressed"]

View File

@@ -3,21 +3,33 @@
extends PanelContainer
@export var texture_state0: Texture2D = preload('res://data/кнопка-эмс-1.png'):
set(val): $state.set_texture(val)
@export var texture_state0: Texture2D:
set(val):
texture_state0 = val
if is_inside_tree():
$state.set_texture(val)
@export var texture_state1: Texture2D = preload('res://data/кнопка-эмс-0.png'):
set(val): $state.set_texture(val)
@export var texture_state1: Texture2D:
set(val):
texture_state1 = val
if is_inside_tree():
$state.set_texture(val)
@export var text: String = '':
set(val): $button.set_text(val)
set(val):
text = val
if is_inside_tree():
$button.set_text(val)
get: return $button.get_text()
@export var pressed: bool = false:
set(val): $button.set_pressed(val)
set(val):
pressed = val
if is_inside_tree():
$button.set_pressed(val)
get: return $button.is_pressed()
@@ -28,6 +40,14 @@ extends PanelContainer
get: return $button.is_toggle_mode()
func _enter_tree() -> void:
var tst = texture_state1 if $button.pressed else texture_state0
$state.set_texture(tst)
$button.set_text(text)
$button.set_pressed(pressed)
$button.set_toggle_mode(toggle_mode)
func set_text (val: String): $button.set_text(val)
func set_pressed (val: bool): $button.set_pressed(val)

View File

@@ -1,7 +1,8 @@
[gd_scene load_steps=9 format=3 uid="uid://gh3wqymu7cub"]
[gd_scene load_steps=10 format=3 uid="uid://gh3wqymu7cub"]
[ext_resource type="Script" uid="uid://dhqqyf2pd1scs" path="res://scenes/эмс/кнопка-эмс.gd" id="1_pmsh3"]
[ext_resource type="Texture2D" uid="uid://nfpish471rjj" path="res://data/кнопка-эмс-1.png" id="2_0o537"]
[ext_resource type="Texture2D" uid="uid://bvxv33noium2h" path="res://data/кнопка-эмс-0.png" id="3_okiyh"]
[sub_resource type="StyleBoxEmpty" id="1"]
@@ -16,23 +17,19 @@
[sub_resource type="StyleBoxEmpty" id="6"]
[node name="container" type="PanelContainer"]
offset_right = 30.0
offset_bottom = 30.0
offset_right = 23.0
offset_bottom = 19.0
theme_override_styles/panel = SubResource("1")
script = ExtResource("1_pmsh3")
texture_state0 = ExtResource("2_0o537")
texture_state1 = ExtResource("3_okiyh")
toggle_mode = true
[node name="state" type="NinePatchRect" parent="."]
show_behind_parent = true
layout_mode = 2
texture = ExtResource("2_0o537")
region_rect = Rect2(-1.60803, -1.94625, 31.9305, 25.9868)
patch_margin_left = 6
patch_margin_top = 5
patch_margin_right = 7
patch_margin_bottom = 5
axis_stretch_horizontal = 2
axis_stretch_vertical = 2
texture = ExtResource("3_okiyh")
region_rect = Rect2(3, 2, 22, 18)
[node name="button" type="Button" parent="."]
layout_mode = 2

View File

@@ -1,24 +1,24 @@
class_name ems extends Panel
## Предзагрузка ячеек таблиц.
const TableHeader = preload('res://table/header.tscn')
const TableLabel = preload('res://table/lable.tscn')
const CellYemsButton = preload('res://scenes/эмс/кнопка-эмс.tscn')
const CellLineEdit = preload('res://table/ячейка-2.tscn')
const CellState = preload('res://scenes/эмс/состояния-эмс.tscn')
const CellOptBtn = preload('res://scenes/эмс/кнопка-5.tscn')
const CellLEEmpty = preload('res://scenes/эмс/line-edit-empty.tscn')
const CellFront = preload('res://scenes/cell/cell-front.tscn')
const CellFrontRear = preload('res://scenes/cell/cell-front-rear.tscn')
@export var TableHeader: PackedScene
@export var TableLabel: PackedScene
@export var CellYemsButton: PackedScene
@export var CellLineEdit: PackedScene
@export var CellState: PackedScene
@export var CellOptBtn: PackedScene
@export var CellLEEmpty: PackedScene
@export var CellFront: PackedScene
@export var CellFrontRear: PackedScene
## Режимы работы выходов.
const OUT_MODE: Array = ['Работа', 'Контроль', '0', '1'] #
const COLUMN_OPTS_BTN: Array = [5]
const TABLE_ENTRY_COLUMNS: Array = [2,3]
const OUT_SET_ROW: Array = [CellLineEdit, CellLEEmpty, CellLEEmpty, CellLEEmpty, CellLEEmpty, CellLEEmpty]
const IN_SET_ROW: Array = [CellLineEdit, CellLEEmpty, CellLEEmpty, CellLEEmpty, CellLEEmpty]
var OUT_SET_ROW: Array
var IN_SET_ROW: Array
var FILES_ROWS_TYPES = [CellLineEdit, CellLineEdit, CellLineEdit ]
var FILES_ROWS_TYPES: Array
var g_boards: Dictionary ## Словарь плат ЭМС.
var active_board = null ## Активная плата ЭМС
@@ -32,6 +32,9 @@ func _ready() -> void:
## Инициализация основных элементов экрана ЭМС.
func init_boards():
OUT_SET_ROW = [CellLineEdit, CellLEEmpty, CellLEEmpty, CellLEEmpty, CellLEEmpty, CellLEEmpty]
IN_SET_ROW = [CellLineEdit, CellLEEmpty, CellLEEmpty, CellLEEmpty, CellLEEmpty]
FILES_ROWS_TYPES = [CellLineEdit, CellLineEdit, CellLineEdit ]
var unit_ems = network.get_unit_instance('уарэп-эмс')
# Выставление позиций элементов ЭМС на экране

View File

@@ -1,12 +1,20 @@
[gd_scene load_steps=20 format=3 uid="uid://dab6loryocc73"]
[gd_scene load_steps=28 format=3 uid="uid://dab6loryocc73"]
[ext_resource type="Script" uid="uid://do1s7qg4bmxqy" path="res://scenes/эмс/эмс.gd" id="1_mk57x"]
[ext_resource type="PackedScene" uid="uid://ch14g46swx74h" path="res://table/header.tscn" id="2_1fbmy"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button-flat/button-flat.tscn" id="2_eju8r"]
[ext_resource type="PackedScene" uid="uid://dwphmxstaxn4v" path="res://table/lable.tscn" id="3_31xk8"]
[ext_resource type="Texture2D" uid="uid://csnts8f155sf7" path="res://data/save1.png" id="3_onafb"]
[ext_resource type="Texture2D" uid="uid://o8mam0a060d8" path="res://data/load1.png" id="4_afjfs"]
[ext_resource type="PackedScene" uid="uid://dspa16ufrpanp" path="res://table/ячейка-2.tscn" id="4_o3av6"]
[ext_resource type="PackedScene" uid="uid://by22sta8tt8dn" path="res://scenes/эмс/состояния-эмс.tscn" id="5_owc4r"]
[ext_resource type="Texture2D" uid="uid://bdlbqs88bki8x" path="res://data/connect-a.png" id="5_wk8og"]
[ext_resource type="Texture2D" uid="uid://u3tnejvpm8it" path="res://data/disconnect-a.png" id="6_1fbmy"]
[ext_resource type="PackedScene" uid="uid://dwcol6jg2syof" path="res://scenes/эмс/кнопка-5.tscn" id="6_k0fjr"]
[ext_resource type="PackedScene" uid="uid://c480ipkjckkdn" path="res://scenes/эмс/line-edit-empty.tscn" id="7_k0fjr"]
[ext_resource type="PackedScene" uid="uid://bccr42bckei41" path="res://scenes/cell/cell-front.tscn" id="8_k30d1"]
[ext_resource type="Script" uid="uid://c5pq0hbrij34d" path="res://table/table.gd" id="8_qcl30"]
[ext_resource type="PackedScene" uid="uid://b8txs4xi722wt" path="res://scenes/cell/cell-front-rear.tscn" id="9_js36y"]
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_mu34x"]
texture = ExtResource("3_onafb")
@@ -64,6 +72,15 @@ texture = ExtResource("6_1fbmy")
offset_right = 1598.0
offset_bottom = 1201.0
script = ExtResource("1_mk57x")
TableHeader = ExtResource("2_1fbmy")
TableLabel = ExtResource("3_31xk8")
CellYemsButton = ExtResource("4_o3av6")
CellLineEdit = ExtResource("4_o3av6")
CellState = ExtResource("5_owc4r")
CellOptBtn = ExtResource("6_k0fjr")
CellLEEmpty = ExtResource("7_k0fjr")
CellFront = ExtResource("8_k30d1")
CellFrontRear = ExtResource("9_js36y")
[node name="lbl_online" type="Label" parent="."]
layout_mode = 0

View File

@@ -7,9 +7,9 @@ func _ready() -> void:
signaller.connect('sector_klaster', Callable(self, 'on_sector_klaster').bind(unit_trassa))
func on_trassa_line_changed(unit_trassa):
func on_trassa_line_changed(_unit_trassa):
pass
func on_sector_klaster(_data, unit_trassa):
func on_sector_klaster(_data, _unit_trassa):
pass

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=3 uid="uid://cyhrdjoylh8tj"]
[gd_scene load_steps=11 format=3 uid="uid://0uv7tfkx2tec"]
[ext_resource type="Texture2D" uid="uid://hkcvl2waf63s" path="res://data/вид сверху.png" id="1_4em3i"]
[ext_resource type="Texture2D" uid="uid://0w6q4vfst0ry" path="res://data/OP-63.png" id="3_eq8fj"]

View File

@@ -135,6 +135,7 @@ class Interfer:
var um: float ## Угол места для помехи.
var nmfs: int = 0 ## Номер модуля ФС в нумерации СТЦ
var priority: int = 0 ## Приоритет помехи
var active: bool = false ## Флаг, что фиксируется мощность на выходном усилителе
func _to_string() -> String:
return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni]
@@ -385,6 +386,8 @@ func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> v
var id = item.id
param['freq'] = item.freq
param['width'] = item.width * width_coef
if item.rparams.has('period'):
param['period'] = item.rparams['period']
if (item.rkrp != '') and item.fflags.rkrp and auto_enabled:
var krp = get_krp(item)
if krp != '':
@@ -615,6 +618,8 @@ func set_rparams(threat: threats.Threat, params: Dictionary):
params['width'] = threat.rparams['width'] * width_coef
else:
params['width'] = threat.width * width_coef
if threat.rparams.has('period'):
params['period'] = threat.rparams['period']
check_width(params)
if threat.rparams.has('filename'):
params['filename'] = threat.rparams['filename']

View File

@@ -110,24 +110,6 @@ class SocketUDP extends PacketPeerUDP:
push_error('%s: %s', [error_string(rc), addr])
class SocketTCP extends TCPServer:
const RX_TIMEOUT: int = 1000 ## Время сброса счётчика принятия части пакета.
var peerstream: = PacketPeerStream.new()
var unit_name: StringName ## Уникальное имя устройства
var head_len: int = 8 ## Длина заголовка команды.
var len_place: int = 4 ## Номер начального байта с длинной блока данных.
var type_len: int = 4 ## Количество байт в размере длинны.
var rx_tick: int ## Время приёма последнего пакета.
var rx_all: bool = true ## Флаг, что пакет принят полностью.
var rx_len: int ## Количество принятых байт.
var rx_data: PackedByteArray ## Принятые данные.
var data_len: int ## Размер ожидаемых данных.
func send_to(data: PackedByteArray):
var peer = peerstream.get_stream_peer()
peer.put_data(data)
var poll_sockets: Array[SocketUDP] ## Сокеты для непрерывного опроса наличия новых данных
var tcp_sockets: Array[Array] ## Сокеты для TCP-соединений
var units: Dictionary[StringName, unit.Unit] ## Экземпляры всех сетевых устройств
@@ -187,21 +169,6 @@ func create_socket_caps(unit_name: StringName) -> SocketUDP:
return sock
## [param unit_name] - Уникальное имя устройства[br]
func create_socket_tcp(unit_name: StringName) -> SocketTCP:
var st = settings.UnitProfiles[unit_name][1]
var addr = st[0]
var port = st[1]
var sock: = SocketTCP.new()
sock.unit_name = unit_name
var rc: = sock.listen(port, addr)
if rc == Error.OK:
log.message(log.INFO, '\"%s\" слушает на %s:%d' % [unit_name, addr, port])
else:
log.message(log.ERROR, '\"%s\" %s:%d \"%s\"' % [unit_name, addr, port, error_string(rc)])
return sock
## [param unit_name] - Уникальное имя устройства[br]
func create_serial(unit_instance: unit.Unit) -> SocketSerial:
var st = settings.UnitProfiles[unit_instance.name][1]
@@ -279,9 +246,11 @@ func _ready() -> void:
dst_ports[unit_name] = unit_profile[3]
if proto in TCP_PROTO:
var addr = settings.UnitProfiles[unit_name][1]
var unit_tcp = TCP_PROTO[proto].new(unit_name)
units[unit_name] = unit_tcp
units_tcp[unit_name] = unit_tcp
unit_tcp.open(addr[0], addr[1])
if proto in MODBUS_PROTO:
var unit_modbus = MODBUS_PROTO[proto].new(unit_name)
@@ -305,7 +274,6 @@ func _ready() -> void:
units_nullp[unit_name] = unit_null
tcp_sockets.append([create_socket_tcp('уарэп-5п28'), units_tcp['уарэп-5п28']])
for key: StringName in dst_ports:
port_to_unit_name[dst_ports[key]] = key
if logger_page:
@@ -347,55 +315,6 @@ func poll_receive_udp(sock: SocketUDP) -> bool:
return false
func poll_receive_tcp(sock: SocketTCP) -> bool:
if sock.is_connection_available(): # Проверить, если кто то пытается подключиться
var client: = sock.take_connection() # Принять соединение
sock.peerstream.set_stream_peer(client) # Привязать поток к новому клиенту
log.info('подключен: %s:%d к порту: %d' % [ client.get_connected_host(), client.get_connected_port(), client.get_local_port() ])
var peer = sock.peerstream.get_stream_peer()
if peer:
while true:
var peer_len_data: = peer.get_available_bytes()
if peer_len_data <= 0:
break
get_client_data(sock, peer, peer_len_data)
if sock.unit_name in units_tcp and sock.rx_all:
units_tcp[sock.unit_name].parse(sock.rx_data, tick)
return false
func get_client_data(sock: SocketTCP, peer: StreamPeer, peer_len_data: int) -> void:
if tick - sock.rx_tick > sock.RX_TIMEOUT:
sock.rx_all = true
sock.rx_tick = tick
if sock.rx_all:
if peer_len_data >= sock.head_len:
sock.rx_all = false
sock.rx_len = sock.head_len
var head = peer.get_data(sock.head_len)
sock.data_len = head[1].decode_u32(sock.len_place)
var len_data_in_buf = peer.get_available_bytes()
if len_data_in_buf > 0:
sock.rx_data = head[1]
var len_rx = len_data_in_buf
if len_data_in_buf >= sock.data_len:
len_rx = sock.data_len
get_tcp_data(sock, peer, len_rx)
else:
var len_rx = (sock.head_len + sock.data_len) - sock.rx_len
if peer_len_data < len_rx:
len_rx = peer_len_data
get_tcp_data(sock, peer, len_rx)
func get_tcp_data(sock: SocketTCP, peer: StreamPeer, len_rx: int):
var temp_data = peer.get_data(len_rx)[1]
sock.rx_data.append_array(temp_data)
sock.rx_len += len_rx
if sock.rx_len == sock.head_len + sock.data_len:
sock.rx_all = true
func _process(_delta: float) -> void:
if Engine.is_editor_hint(): return
tick = Time.get_ticks_msec()
@@ -421,12 +340,6 @@ func _process(_delta: float) -> void:
for unit_name: StringName in units_modbus:
var unit_modbus: = units_modbus[unit_name]
unit_modbus.process(tick)
for sock_unit: Array in tcp_sockets:
var sock = sock_unit[0]
var unit_tcp = sock_unit[1]
if Error.OK == unit_tcp.process(tick):
sock.send_to(unit_tcp.tx_data)
poll_receive_tcp(sock)
poll_sockets.any(poll_receive_udp)

View File

@@ -1,33 +1,33 @@
class_name PRDConfigManager
extends RefCounted
## Менеджер конфигурации для системы контроля ПРД
## Загружает и управляет настройками из JSON-конфигурации
## Менеджер конфигурации для системы контроля ПРД.
## Загружает и управляет настройками из JSON-конфигурации.
#region CONSTANTS
const CONFIG_PATH = "user://config/setting_prd_control.json"
const DEFAULT_CONFIG_PATH = "res://config/setting_prd_control.json"
const CONFIG_VERSION = "1.0.0" # Версия конфигурации - увеличивать при изменениях
const CONFIG_PATH = 'user://config/setting-prd-control.json'
const DEFAULT_CONFIG_PATH = 'res://config/setting-prd-control.json'
const CONFIG_VERSION = '1.0.0' # Версия конфигурации - увеличивать при изменениях
#endregion
#region PRIVATE_VARIABLES
var _config_data: Dictionary # Все данные конфигурации
var _device_constants: Dictionary # Константы устройств
var _base_configs: Dictionary # Базовые конфигурации
var _device_configs: Dictionary # Конфигурации устройств
var _data_indices: Dictionary # Индексы данных
var _fs_keys: Dictionary # Ключи ФС (функциональных систем)
var _temperature_constants: Dictionary # Константы температуры
var _ems_input_bits_config: Dictionary # Конфигурация битов ввода ЭМС
var _fs_rules: Array # Правила ФС
var _config_data: Dictionary ## Все данные конфигурации
var _device_constants: Dictionary ## Константы устройств
var _base_configs: Dictionary ## Базовые конфигурации
var _device_configs: Dictionary ## Конфигурации устройств
var _data_indices: Dictionary ## Индексы данных
var _fs_keys: Dictionary ## Ключи ФС (функциональных систем)
var _temperature_constants: Dictionary ## Константы температуры
var _ems_input_bits_config: Dictionary ## Конфигурация битов ввода ЭМС
var _fs_rules: Array ## Правила ФС
var _is_loaded: bool = false # Флаг успешной загрузки
var _current_version: String = "" # Текущая версия загруженной конфигурации
var _is_loaded: bool = false ## Флаг успешной загрузки
var _current_version: String ## Текущая версия загруженной конфигурации
#endregion
#region INITIALIZATION
func _init() -> void:
"""Инициализация менеджера конфигурации"""
'''Инициализация менеджера конфигурации'''
_load_configuration()
#endregion
@@ -101,27 +101,27 @@ func _load_configuration() -> void:
var parse_result = json.parse(json_text)
if parse_result == OK:
_config_data = json.data
_current_version = _config_data.get("config_version", "0.0.0")
_current_version = _config_data.get('config_version', '0.0.0')
_parse_config_data()
_is_loaded = true
else:
push_error("Ошибка разбора JSON конфигурации: " + json.get_error_message())
push_error('Ошибка разбора JSON конфигурации: ' + json.get_error_message())
_is_loaded = false
else:
push_error("Ошибка загрузки файла конфигурации: " + CONFIG_PATH)
push_error('Ошибка загрузки файла конфигурации: ' + CONFIG_PATH)
_is_loaded = false
## Парсит данные конфигурации по секциям
func _parse_config_data() -> void:
_device_constants = _convert_numbers(_config_data.get("device_constants", {}))
_base_configs = _convert_numbers(_config_data.get("base_configs", {}))
_device_configs = _convert_numbers(_config_data.get("device_configs", {}))
_data_indices = _convert_numbers(_config_data.get("data_indices", {}))
_fs_keys = _convert_numbers(_config_data.get("fs_keys", {}))
_temperature_constants = _convert_numbers(_config_data.get("temperature_constants", {}))
_ems_input_bits_config = _convert_numbers(_config_data.get("ems_input_bits_config", {}))
_fs_rules = _convert_numbers(_config_data.get("fs_rules", []))
_device_constants = _convert_numbers(_config_data.get('device_constants', {}))
_base_configs = _convert_numbers(_config_data.get('base_configs', {}))
_device_configs = _convert_numbers(_config_data.get('device_configs', {}))
_data_indices = _convert_numbers(_config_data.get('data_indices', {}))
_fs_keys = _convert_numbers(_config_data.get('fs_keys', {}))
_temperature_constants = _convert_numbers(_config_data.get('temperature_constants', {}))
_ems_input_bits_config = _convert_numbers(_config_data.get('ems_input_bits_config', {}))
_fs_rules = _convert_numbers(_config_data.get('fs_rules', []))
## Конвертирует числовые значения в правильные типы (float -> int если возможно)
@@ -149,12 +149,12 @@ static func _convert_numbers(value):
## Создает папку и копирует дефолтный файл если нужно
func _ensure_config_exists() -> bool:
# Создаем папку конфигурации если не существует
DirAccess.make_dir_recursive_absolute("user://config")
DirAccess.make_dir_recursive_absolute('user://config')
# Проверяем, нужно ли обновить конфигурацию
if _should_update_config():
return _update_config()
# Если файл уже существует - все ок
if FileAccess.file_exists(CONFIG_PATH):
return true
@@ -172,40 +172,40 @@ func _should_update_config() -> bool:
# Если файла конфигурации нет - нужно создать
if not FileAccess.file_exists(CONFIG_PATH):
return true
# Проверяем версию существующей конфигурации
var config_file = FileAccess.open(CONFIG_PATH, FileAccess.READ)
if config_file:
var json_text = config_file.get_as_text()
config_file.close()
var json = JSON.new()
if json.parse(json_text) == OK:
var existing_version = json.data.get("config_version", "0.0.0")
var existing_version = json.data.get('config_version', '0.0.0')
# Сравниваем версии
return _compare_versions(existing_version, CONFIG_VERSION) < 0
else:
# Если ошибка парсинга - нужно обновить
return true
return false
## Сравнивает две версии (semantic versioning)
## Возвращает -1 если version1 < version2, 0 если равны, 1 если version1 > version2
static func _compare_versions(version1: String, version2: String) -> int:
var v1_parts = version1.split(".")
var v2_parts = version2.split(".")
var v1_parts = version1.split('.')
var v2_parts = version2.split('.')
for i in range(max(v1_parts.size(), v2_parts.size())):
var v1_part = int(v1_parts[i]) if i < v1_parts.size() else 0
var v2_part = int(v2_parts[i]) if i < v2_parts.size() else 0
if v1_part < v2_part:
return -1
elif v1_part > v2_part:
return 1
return 0
@@ -213,10 +213,9 @@ static func _compare_versions(version1: String, version2: String) -> int:
func _update_config() -> bool:
# Создаем резервную копию старой конфигурации
if FileAccess.file_exists(CONFIG_PATH):
var backup_path = CONFIG_PATH + ".backup_v" + _current_version
var backup_path = CONFIG_PATH + '.backup_v' + _current_version
DirAccess.copy_absolute(CONFIG_PATH, backup_path)
print("Создана резервная копия: ", backup_path)
# Копируем актуальную конфигурацию
return _copy_default_config()
@@ -224,13 +223,13 @@ func _update_config() -> bool:
## Копирует дефолтную конфигурацию в user директорию
func _copy_default_config() -> bool:
if not FileAccess.file_exists(DEFAULT_CONFIG_PATH):
push_error("Дефолтный файл конфигурации не найден: " + DEFAULT_CONFIG_PATH)
push_error('Файл конфигурации не найден: ' + DEFAULT_CONFIG_PATH)
return false
var src := FileAccess.open(DEFAULT_CONFIG_PATH, FileAccess.READ)
var dst := FileAccess.open(CONFIG_PATH, FileAccess.WRITE)
if src == null or dst == null:
push_error("Ошибка копирования конфигурации")
push_error('Ошибка копирования конфигурации')
return false
dst.store_string(src.get_as_text())

View File

@@ -3,6 +3,7 @@ extends Node
enum PrdState {WORK, CONTROL}
const TIME_YAU07_SEND = 50
const MIN_UM_POWER = 200 ## минимальная мощность с усилителя, что бы отобразить значёк излучения
## Границы секторов блоков ФС по частоте в режиме РТО.
const FS_BAND_RTO: Dictionary = {
@@ -86,10 +87,10 @@ const FS_PRD: Dictionary = {
26: ['уарэп-яу07-3к', 37],
27: ['уарэп-яу07-2к', 27], }
var fs_dict: Dictionary ## Словарь с модулями ФС
var prd_dict: Dictionary ## Словарь с приборами ПРД
var course = 0.0 ## Курс корабля
var fs_caps_id: Dictionary ## Словарь соответствия номеров ФС от КАПС РПБ внутрипрограммной нумерации
var fs_dict: Dictionary ## Словарь с модулями ФС
var prd_dict: Dictionary ## Словарь с приборами ПРД
var course = 0.0 ## Курс корабля
var fs_caps_id: Dictionary ## Словарь соответствия номеров ФС от КАПС РПБ внутрипрограммной нумерации
class Fs:
@@ -124,14 +125,17 @@ class Fs:
var ready: bool = false ## Готовность сектора к излучению
var caps_online: bool = false ## Состояние связи с КАПС РПБ
var yau_07_online: bool = false ## Состояние связи ЯУ-07
var lit: int ## Литера ФС
var power: bool = false ## Признак излучения усилителей
signal update_modulation(index)
func _init(i, p_name):
prd_name = p_name
index = i
if UM_PORTS.has(index/4):
um_port = UM_PORTS[index/4]
lit = index/4
if UM_PORTS.has(lit):
um_port = UM_PORTS[lit]
func set_modulation(val):
modulation = val
@@ -158,6 +162,14 @@ class Fs:
func set_ready():
ready = isg and caps_online and yau_07_online
func set_power(power_arr: Array):
power = false
for val in power_arr:
if val > MIN_UM_POWER:
power = true
break
class PRD:
enum STATE_DEVICE {
NONE,
@@ -268,6 +280,7 @@ class PRD:
# Определение состояния обслуживания
if unit_control:
if unit_control.flags.control_is_over:
serviceability = 0 # Перед результатом контроля необходимо сбросить значение
serviceability = _set_serviceability_from_control_results(unit_control)
else:
serviceability = _set_serviceability_from_online_status(check_dic)
@@ -502,3 +515,13 @@ func on_yau07_line_changed(unit_yau07, prd_pribor):
fs.yau_07_online = unit_yau07.online
fs.set_ready()
signaller.emit_signal('fs_update_state', fs_dict)
func get_fs_power(nmfs: int):
if not fs_caps_id.has(nmfs): return false
var fs_index: int = fs_caps_id[nmfs]
var prd_obj: PRD = prd_dict[FS_PRD[fs_index][0]]
var fs: Fs = prd_obj.fs_dic[fs_index]
var power_arr: Array = prd_obj.unit_control.power_um_ukp(prd_obj.unit_yau07.status, fs.lit + 1, [], true)
fs.set_power(power_arr)
return fs.power

View File

@@ -310,7 +310,7 @@ func on_data_received(unit_pribor: Object) -> void:
if interes == 'RAY_CTRL':
count_packets_power += 1
elif interes != '':
tek_litera[_get_ray_key(state)] = power_um_ukp(status, current_litera, tek_litera[_get_ray_key(state)])
tek_litera[_get_ray_key(state)] = power_um_ukp(status, current_litera, tek_litera[_get_ray_key(state)], false)
power_for_litera[current_litera] = tek_litera
count_packets_power += 1
@@ -432,6 +432,7 @@ static func take_ecm_id(ecm_dic: Dictionary, device_name: String, current_lit: i
## Обработка состояния FS_WORK - проверка работы ФС
func _handle_fs_work_state() -> void:
_set_status('Проверка связи сервиса КАПС РПБ')
if not ecms.has(current_ecm_key): push_error('Нет текущей ecm: %s' % current_ecm_key); return
_set_status('Ожидание выполнения помехи состояние %s литеры %s' % [ecms[current_ecm_key].svk, current_litera])
if current_ecm_key > 0 and ecms[current_ecm_key].svk == 1:
if not flags.si_fs_input:
@@ -883,11 +884,15 @@ func on_mode_changed(in_tree: bool) -> void:
# Вызывается при смене связи я ячейков ЯУ-07Б
func on_line_changed_yau07(_status: Object)->void:
_set_status('Ожидание запуска контроля')
flags.control_is_over = false
flags.no_trust_yau07 = false
flags.only_fs = false
restore_default_states()
block_kasseta_y5_config.yau07 = _status.online
if _status.online:
_set_status('Ожидание запуска контроля')
else:
_set_status('Ячейка ЯУ-07Б: Нет связи')
#endregion
@@ -1158,50 +1163,52 @@ static func _should_apply_rule(fs_num: int, rule: Dictionary, results: Dictionar
## Получение мощности при выполнении контроля
static func power_um_ukp(status: PackedByteArray, litera: int, pwr_result: Array) -> Array:
static func power_um_ukp(status: PackedByteArray, litera: int, pwr_result: Array, mode_work: bool) -> Array:
const Constants: Dictionary = {'POWER_UKP_1' : 31, 'POWER_UKP_2': 63}
var power_values: Array = []
var base_offset = 0
var iteration: int = 6
var ug_valid: bool = (status[0] >> 2) & 1
if not len(status): return power_values
var ukp1_valid: bool = (status[0] >> 2) & 1
var ukp2_valid: bool = (status[0] >> 3) & 1
match litera:
1:
var value = status.decode_u16(Constants.POWER_UKP_1 + 2 * 7)
if ug_valid:
if ukp1_valid:
power_values = [value]
2:
base_offset = Constants.POWER_UKP_1
if ug_valid:
if ukp1_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
3:
base_offset = Constants.POWER_UKP_2
if ug_valid:
if ukp2_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
4:
base_offset = Constants.POWER_UKP_1
if ug_valid:
if ukp1_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
5:
base_offset = Constants.POWER_UKP_2
if ug_valid:
if ukp2_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
6:
base_offset = Constants.POWER_UKP_1
if ug_valid:
if ukp1_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
7:
base_offset = Constants.POWER_UKP_2
if ug_valid:
if ukp2_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
power_values = update_max_power_values(power_values, pwr_result)
if not mode_work:
power_values = update_max_power_values(power_values, pwr_result)
return power_values
@@ -1288,7 +1295,7 @@ static func check_dou_result(control_dic: Dictionary, power_dic: Dictionary, pri
var ray_dic: Dictionary = power_dic[litera]
# Проверка наличия данных
if ray_dic[RAY_m5].size() == 0 or \
if ray_dic[RAY_m5].size() == 0 or \
ray_dic[RAY_5 ].size() == 0 or \
ray_dic[RAY_15].size() == 0 or \
ray_dic[RAY_25].size() == 0 or \
@@ -1301,7 +1308,7 @@ static func check_dou_result(control_dic: Dictionary, power_dic: Dictionary, pri
var low_power_by_position: Array = [0, 0, 0, 0, 0, 0] # Счетчики для 6 позиций
for ray_key in [RAY_m5, RAY_5, RAY_15, RAY_25, RAY_35, RAY_45]:
var power_array: Array = ray_dic[ray_key]
for i in range(power_array.size()):
for i in power_array.size():
if power_array[i] < cnst.POWER_THRESHOLD:
low_power_by_position[i] += 1
@@ -1356,7 +1363,8 @@ func restore_default_states() -> void:
ems_6666_timer.stop()
machine_timer.stop()
_set_status('Состояния сброшены к значениям по умолчанию')
#'Состояния сброшены к значениям по умолчанию'
## Получение текущих состояний для отладки
func get_current_states() -> Dictionary:

View File

@@ -55,7 +55,7 @@ const WIDTH_MIN: = 5.0
const DUR_MAX: = 1000000.0
const PERIOD_MAX: = 1000000.0
const UM_MIN: = -5.0
const UM_MAX: = 55.0
const UM_MAX: = 100.0
func _ready() -> void:

View File

@@ -197,7 +197,7 @@ signal emit_changed(state)
## Вызывается при изменении детализации карты.[br]
## [param new_scale] - обновленное значение масштаба ([b]true[/b]
signal update_scale_map(new_scale)
signal update_scale_map(new_scale: String)
## Вызывается при изменении текущих координат.[br]

View File

@@ -3,7 +3,6 @@ class_name tcp5_p28 extends Node
## Реализация "Протокол информационного сопряжения.
## СПО АСУ изделия МП-550 с СПО 5П-28
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от 5П-28, мс.
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм.
## Тип модуляции для запаковки в пакет для 5П-28.
@@ -56,27 +55,176 @@ class TCP5P28 extends unit.Unit:
'уарэп-яу07-4в': [8, 7],
'уарэп-яу07-4к': [16, 15] }
signal data_sended()
signal disconnected(rc: Array)
signal connected(rc: Array)
signal get_threats(unit: TCP5P28) ## Сигнал запрос целей.
signal get_interfers(unit: TCP5P28) ## Запрос состояния выполнения целеуказания.
var tx_stack: Array ## Массив пакетов для отправки.
var uarep_state: int = 1 ## Флаги состояния прибора, 0 бит, состояние ПО
var uarep_line: int = 3 ## Состояние линии связи с прибором
var ext_cu: bool = false
var tx_queue: Array ## Очередь пакетов для отправки
var tx_mutex: Mutex ## Мютекс для очереди передачи
var thread: Thread ## Рабочий поток
var tctl_mutex: Mutex ## Мютекс для управления потоком
var tctl_run: bool ## Управление потоком
enum STREAM_STATE {
IDLE,
CONNECT,
WAIT,
RX_START,
RX_DONE,
TX_START,
TX_DONE,
ERROR
}
func _init(nm) -> void:
super._init(nm)
ext_cu = ProjectSettings.get_setting('application/config/Внешнее управление', false)
ProjectSettings.connect('settings_changed', on_setting_changed)
tx_mutex = Mutex.new()
tctl_mutex = Mutex.new()
connect('data_received', on_data_received)
connect('data_sended', on_data_sended)
connect('connected', on_connected)
connect('disconnected', on_disconnected)
init_state()
func on_connected(rc: Array):
log.info('Клиент 5П-28 подключен: %s:%s' % [ rc[0], rc[1]] )
func on_data_sended(): pass
func on_data_received(data: PackedByteArray):
var tick: = Time.get_ticks_msec()
parse(data, tick)
func on_disconnected(rc: Array):
log.info('Клиент 5П-28 отключен: %s:%s' % [ rc[0], rc[1]] )
if online:
online = false
emit_signal('line_changed', self)
tx_mutex.lock()
tx_queue.clear()
tx_mutex.unlock()
func init_state():
for key in PR_STATE.keys():
var unit_pribor = network.get_unit_instance(key)
unit_pribor.connect('line_changed', Callable(self, 'pribor_line_changed').bind(key))
func open(host: String, port: int):
tctl_run = true
thread = Thread.new()
thread.start(thread_proc.bind(host, port))
func close():
tctl_mutex.lock()
tctl_run = false
tctl_mutex.unlock()
func thread_proc(host: String, port: int):
var sock = TCPServer.new()
var stream: = StreamPeerTCP.new()
var fsm: = STREAM_STATE.CONNECT
var rx_buff: PackedByteArray
var rx_bytes: int = 0
var head_len: int = 8 ## Длина заголовка команды.
var len_place: int = 4 ## Номер начального байта с длинной блока данных.
var status: = StreamPeerTCP.Status.STATUS_NONE
var rc: = sock.listen(port, host)
var cl_host: String
var cl_port: int
while true:
stream.poll()
var new_status = stream.get_status()
if status != new_status:
status = new_status
match status:
stream.STATUS_NONE:
call_deferred('emit_signal', 'disconnected', [cl_host, cl_port])
fsm = STREAM_STATE.ERROR
stream.STATUS_CONNECTED:
cl_host = stream.get_connected_host()
cl_port = stream.get_connected_port()
call_deferred('emit_signal', 'connected', [cl_host, cl_port])
stream.STATUS_ERROR:
fsm = STREAM_STATE.ERROR
if fsm == STREAM_STATE.CONNECT:
if sock.is_connection_available(): # Проверить, если кто то пытается подключиться
stream = sock.take_connection() # Принять соединение
new_status = stream.get_status()
if new_status == stream.STATUS_CONNECTED:
fsm = STREAM_STATE.WAIT
else:
fsm = STREAM_STATE.ERROR
elif fsm == STREAM_STATE.WAIT:
if status == stream.STATUS_CONNECTED:
fsm = STREAM_STATE.RX_START
else:
OS.delay_msec(50)
fsm = STREAM_STATE.CONNECT
elif fsm == STREAM_STATE.ERROR:
stream.disconnect_from_host()
fsm = STREAM_STATE.WAIT
OS.delay_msec(1000)
elif fsm == STREAM_STATE.IDLE:
OS.delay_msec(50)
fsm = STREAM_STATE.RX_START
elif fsm == STREAM_STATE.RX_START:
rx_buff.clear()
rx_bytes = 0
var sz = stream.get_available_bytes()
if sz <= 0:
fsm = STREAM_STATE.TX_START
continue
var rxd = stream.get_data(head_len)
if rxd[0] == Error.OK:
rx_buff.append_array(rxd[1])
else:
fsm = STREAM_STATE.ERROR
continue
var pay: = rx_buff.decode_u32(len_place)
rx_bytes = pay + head_len
if rx_buff.size() == rx_bytes:
fsm = STREAM_STATE.RX_DONE
else:
rxd = stream.get_data(rx_bytes - rx_buff.size())
rc = rxd[0]
if rc == Error.OK:
rx_buff.append_array(rxd[1])
fsm = STREAM_STATE.RX_DONE
else:
fsm = STREAM_STATE.ERROR
elif fsm == STREAM_STATE.RX_DONE:
var rx_data: = rx_buff.duplicate()
call_deferred('emit_signal', 'data_received', rx_data)
fsm = STREAM_STATE.TX_START
elif fsm == STREAM_STATE.TX_START:
tx_mutex.lock()
if not tx_queue.size():
fsm = STREAM_STATE.IDLE
tx_mutex.unlock()
continue
var data = tx_queue.pop_front()
tx_mutex.unlock()
rc = stream.put_data(data)
if rc == Error.OK:
fsm = STREAM_STATE.TX_DONE
else:
fsm = STREAM_STATE.ERROR
elif fsm == STREAM_STATE.TX_DONE:
call_deferred('emit_signal', 'data_sended')
fsm = STREAM_STATE.RX_START
func pribor_line_changed(u, key):
uarep_state = tools.set_bit(uarep_state, PR_STATE[key][0], u.online)
uarep_line = tools.set_bit(uarep_state, PR_STATE[key][1], u.online)
uarep_line = tools.set_bit(uarep_line, PR_STATE[key][1], u.online)
func _to_string() -> String: return String('5П-28: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
@@ -95,16 +243,10 @@ class TCP5P28 extends unit.Unit:
if cmd_type == CMD_TYPE_IN and ext_cu:
set_interfer(data)
func process(tick: int):
if online and ((tick - rx_tick) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
if len(tx_stack):
tx_data = tx_stack[0]
tx_stack.remove_at(0)
return Error.OK
else:
return Error.ERR_UNAVAILABLE
func queue_packet(packet: PackedByteArray):
tx_mutex.lock()
tx_queue.append(packet)
tx_mutex.unlock()
func pack_threats(ths: Dictionary):
var data = PackedByteArray()
@@ -117,7 +259,7 @@ class TCP5P28 extends unit.Unit:
data.append_array(get_threats_data(th, tick0))
var data_to_send: PackedByteArray = create_header(data_len)
data_to_send.append_array(data)
tx_stack.append(data_to_send)
queue_packet(data_to_send)
func pack_interfers(interfers: Dictionary, ecms: Dictionary):
var data = PackedByteArray()
@@ -141,7 +283,7 @@ class TCP5P28 extends unit.Unit:
data.append_array(cu_data)
var data_to_send: PackedByteArray = create_header(data_len + 4 * interfers.size())
data_to_send.append_array(data)
tx_stack.append(data_to_send)
queue_packet(data_to_send)
func create_header(data_len: int):
var head_data = PackedByteArray()
@@ -210,7 +352,7 @@ class TCP5P28 extends unit.Unit:
data_tx.encode_u16(0, err) # Код ошибки
var data_to_send: PackedByteArray = create_header(data_len)
data_to_send.append_array(data_tx)
tx_stack.append(data_to_send)
queue_packet(data_to_send)
func on_setting_changed():
ext_cu = ProjectSettings.get_setting('application/config/Внешнее управление', false)

View File

@@ -152,7 +152,7 @@ func on_data_capsrpb_received(unit: capsrpb.CapsRpb, threats: Dictionary):
if not unit.json_dic.has('sa'): return
var mis = unit.json_dic['mis']
bpo_mode_rx = int(unit.json_dic['sa'])
bpo_mode_rx = int(unit.json_dic['sa']) as AFSP_BPO_MODE
var sz: = threats.size()
for dic_th in mis:
if dic_th is not Dictionary:

View File

@@ -7,6 +7,7 @@
"Включить работу по своим целям": true,
"Внешнее указание Трасса": false,
"Внешнее управление": false,
"Время повторной отправки помехи": "1",
"Кнопка «JTIDS»": false,
"Кнопка «К1»": false,
"Кнопка «КУПД»": false,
@@ -23,15 +24,19 @@
"Кнопка «Подавление»": false,
"Кнопка «СВ-И1»": false,
"Кнопка «СВ-М2»": false,
"Коэффициент ширины полосы излучения": "1.5",
"Ограниченный режим": false,
"Период опроса состояния АФСП, секунды": "30",
"Период опроса состояния БПО, секунды": "30",
"Отладка контроля": false,
"Период опроса состояния АФСП, секунды": "",
"Период опроса состояния БПО, секунды": "",
"Скрыть вкладку ЭМС 2": true,
"Список своих протоколов": "j11",
"Схема прибора. Белый цвет": [1.0, 1.0, 1.0],
"Схема прибора. Чёрный цвет": [0.0, 0.0, 0.0],
"Текущая версия ПО УАРЭП": "master b2633d8 Thu Sep 11 16:26:39 2025 +0300",
"Шаблон адреса сервера карт": "http://169.254.27.71:8001/osm_tiles/{z}/{x}/{y}.png",
"Список своих протоколов": "",
"Текущая версия ПО УАРЭП": "master 3bff1cd Tue Nov 4 15:33:24 2025 +0300",
"Цвет кнопки \"Подавление\"": "[0.905882358551025,0.00392156885936856,0.0,1.0]",
"Цвет схемы": "[0.905954480171204,0.921875,0.8714599609375,1.0]",
"Цвет темы программы": false,
"Цвет фона схемы": "[0.258926391601563,0.274618297815323,0.27734375,1.0]",
"Шаблон адреса сервера карт": "http://192.168.11.109:8001/osm_tiles/{z}/{x}/{y}.png",
"навигация": [
"*",
60000,
@@ -39,19 +44,19 @@
true
],
"уарэп-5п28": [
"127.0.0.1",
"192.168.11.105",
50777
],
"уарэп-капсрпб": [
"127.0.0.1",
"127.0.0.1",
"192.168.11.102",
"192.168.11.105",
42023,
42022,
false,
true
],
"уарэп-спт25-1": [
"/home/sasha/dev/tty0",
"/home/user/tty0",
0,
19200,
"N",
@@ -59,7 +64,7 @@
1
],
"уарэп-спт25-2": [
"/home/sasha/dev/tty4",
"/home/user/tty1",
0,
19200,
"N",
@@ -67,15 +72,15 @@
1
],
"уарэп-трасса": [
"127.0.0.1",
"127.0.0.1",
"192.168.11.34",
"192.168.11.105",
50200,
10004,
false,
true
],
"уарэп-щ3": [
"/home/sasha/dev/tty2",
"/dev/ttyUSB0",
7,
19200,
"N",
@@ -168,8 +173,8 @@
true
],
"уарэп-яу07-частный": [
"10.1.1.253",
50253,
"10.1.1.2",
50002,
false,
true
]

View File

@@ -1,7 +0,0 @@
[gd_scene format=3 uid="uid://bvbvtgwps54yr"]
[node name="Editl" type="LineEdit"]
offset_right = 59.875
offset_bottom = 33.0
caret_blink = true
caret_blink_interval = 0.5

24
table/lable.gd Normal file
View File

@@ -0,0 +1,24 @@
extends Label
static var styles: = [null, null]
static var init_done: = false
func _init() -> void:
if init_done:
init_done = true
var style_light: = get_theme_stylebox('normal')
style_light.bg_color = Color.GRAY
styles[1] = style_light
var style_dark: = style_light.duplicate(true)
style_dark.bg_color = Color(0.12, 0.12, 0.12)
styles[0] = style_dark
ProjectSettings.connect('settings_changed', apply_colors)
apply_colors()
func apply_colors():
if ProjectSettings.get_setting('application/config/%s' % 'Цвет темы программы', false):
add_theme_stylebox_override('normal', styles[1])
else:
add_theme_stylebox_override('normal', styles[0])

1
table/lable.gd.uid Normal file
View File

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

View File

@@ -1,4 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dwphmxstaxn4v"]
[gd_scene load_steps=3 format=3 uid="uid://dwphmxstaxn4v"]
[ext_resource type="Script" uid="uid://bjw0gwcqxx30d" path="res://table/lable.gd" id="1_xk0u2"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yign5"]
bg_color = Color(0.117647, 0.117647, 0.117647, 0.85098)
@@ -14,3 +16,4 @@ offset_right = 104.0
offset_bottom = 27.0
theme_override_colors/font_color = Color(1, 0.596078, 0.4, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_yign5")
script = ExtResource("1_xk0u2")

28
table/node.gd Normal file
View File

@@ -0,0 +1,28 @@
extends LineEdit
static var styles: = [null, null]
static var init_done: = false
func _init() -> void:
if not init_done:
init_done = true
var style_light: = get_theme_stylebox('read_only')
style_light.bg_color = Color.GRAY
styles[1] = style_light
var style_dark: = style_light.duplicate(true)
style_dark.bg_color = Color(0.12, 0.12, 0.12)
styles[0] = style_dark
ProjectSettings.connect('settings_changed', apply_colors)
apply_colors()
func apply_colors():
if ProjectSettings.get_setting('application/config/%s' % 'Цвет темы программы', false):
add_theme_color_override('font_color_readonly', Color.BLACK)
add_theme_color_override('font_color_placeholder', Color(0, 0, 0, 0.5))
add_theme_stylebox_override('read_only', styles[1])
else:
add_theme_color_override('font_color_readonly', Color('#D8731A')) # тёмно-оранжевый
add_theme_color_override('font_color_placeholder', Color(1, 1, 1, 0.5))
add_theme_stylebox_override('read_only', styles[0])

1
table/node.gd.uid Normal file
View File

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

View File

@@ -1,4 +1,6 @@
[gd_scene format=3 uid="uid://c1i4rwaajq7d5"]
[gd_scene load_steps=2 format=3 uid="uid://c1i4rwaajq7d5"]
[ext_resource type="Script" uid="uid://c71233c2tqc2u" path="res://table/node.gd" id="1_oh3pj"]
[node name="Label" type="LineEdit"]
offset_right = 121.0
@@ -8,3 +10,4 @@ editable = false
context_menu_enabled = false
caret_blink = true
caret_blink_interval = 0.1
script = ExtResource("1_oh3pj")

33
table/set-toggle.gd Normal file
View File

@@ -0,0 +1,33 @@
extends LineEdit
static var styles: = [null, null]
static var init_done: = false
var checkbutton_material: Material
func _init() -> void:
if not init_done:
init_done = true
var style_light: = get_theme_stylebox('read_only')
style_light.bg_color = Color.GRAY
styles[1] = style_light
var style_dark: = style_light.duplicate(true)
style_dark.bg_color = Color(0.12, 0.12, 0.12)
styles[0] = style_dark
ProjectSettings.connect('settings_changed', on_setting_changed)
call_deferred('on_setting_changed')
func on_setting_changed():
checkbutton_material = $CheckButton.material
apply_colors()
func apply_colors():
if ProjectSettings.get_setting('application/config/%s' % 'Цвет темы программы', false):
add_theme_stylebox_override('read_only', styles[1])
$CheckButton.material = null
else:
add_theme_stylebox_override('read_only', styles[0])
$CheckButton.material = checkbutton_material

1
table/set-toggle.gd.uid Normal file
View File

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

View File

@@ -1,22 +1,33 @@
[gd_scene load_steps=4 format=3 uid="uid://dgidt8lifm7xe"]
[gd_scene load_steps=8 format=3 uid="uid://dgidt8lifm7xe"]
[ext_resource type="Script" uid="uid://btvrqnnjjum20" path="res://table/set-toggle.gd" id="1_kvru5"]
[ext_resource type="Shader" uid="uid://bw5mmbgeycwua" path="res://shaders/color-invers.gdshader" id="2_wrw87"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_f4oye"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_wrw87"]
shader = ExtResource("2_wrw87")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_t3fqw"]
[sub_resource type="Theme" id="Theme_odxqp"]
CheckButton/styles/focus = SubResource("StyleBoxEmpty_t3fqw")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_kvru5"]
[node name="LineEdit" type="LineEdit"]
offset_right = 85.0
offset_bottom = 27.0
theme_override_styles/focus = SubResource("StyleBoxEmpty_f4oye")
editable = false
script = ExtResource("1_kvru5")
[node name="CheckButton" type="CheckButton" parent="."]
material = SubResource("ShaderMaterial_wrw87")
layout_mode = 0
offset_left = 21.0
offset_top = 1.0
offset_right = 65.0
offset_bottom = 25.0
theme = SubResource("Theme_odxqp")
theme_override_styles/focus = SubResource("StyleBoxEmpty_kvru5")

33
table/settings-toggle.gd Normal file
View File

@@ -0,0 +1,33 @@
extends LineEdit
static var styles: = [null, null]
static var init_done: = false
var checkbutton_material: Material
func _init() -> void:
ProjectSettings.connect('settings_changed', on_setting_changed)
if not init_done:
init_done = true
var style_light: = get_theme_stylebox('read_only')
style_light.bg_color = Color.GRAY
styles[1] = style_light
var style_dark: = style_light.duplicate(true)
style_dark.bg_color = Color(0.12, 0.12, 0.12)
styles[0] = style_dark
func on_setting_changed():
checkbutton_material = $CheckButton.material
apply_colors()
func apply_colors():
var is_light: bool = ProjectSettings.get_setting('application/config/%s' % 'Цвет темы программы', false)
if is_light:
add_theme_stylebox_override('read_only', styles[1])
$CheckButton.material = null
else:
add_theme_stylebox_override('read_only', styles[0])
$CheckButton.material = checkbutton_material

View File

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

View File

@@ -1,32 +1,34 @@
[gd_scene load_steps=5 format=3 uid="uid://5rw652cmnybi"]
[gd_scene load_steps=6 format=3 uid="uid://5rw652cmnybi"]
[ext_resource type="Script" uid="uid://bh7mb1aeu1uk6" path="res://table/settings-toggle.gd" id="1_8lkgc"]
[ext_resource type="Shader" uid="uid://bw5mmbgeycwua" path="res://shaders/color-invers.gdshader" id="1_anyuq"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_7hsq1"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_il5wc"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_xxfw6"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_8lkgc"]
shader = ExtResource("1_anyuq")
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_y8485"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8lkgc"]
[node name="LineEdit" type="LineEdit"]
offset_right = 950.0
offset_bottom = 27.0
theme_override_colors/font_uneditable_color = Color(1, 0.596078, 0.4, 1)
theme_override_colors/font_color = Color(1, 0.596078, 0.4, 1)
theme_override_styles/focus = SubResource("StyleBoxEmpty_7hsq1")
theme_override_styles/focus = SubResource("StyleBoxEmpty_il5wc")
editable = false
context_menu_enabled = false
shortcut_keys_enabled = false
middle_mouse_paste_enabled = false
selecting_enabled = false
deselect_on_focus_loss_enabled = false
script = ExtResource("1_8lkgc")
[node name="CheckButton" type="CheckButton" parent="."]
material = SubResource("ShaderMaterial_xxfw6")
material = SubResource("ShaderMaterial_8lkgc")
layout_mode = 0
offset_left = 453.0
offset_top = 1.5
offset_right = 497.0
offset_bottom = 25.5
theme_override_styles/focus = SubResource("StyleBoxEmpty_y8485")
theme_override_styles/focus = SubResource("StyleBoxEmpty_8lkgc")

View File

@@ -333,7 +333,7 @@ func _set_row_selected(i_row: int, selected: bool = true) -> void:
push_warning('обращение к удалённому элементу \"%s\"' % selector_key)
elif (not nodes.has(selector_key)) and selected:
var selector = ScnSelector.instantiate()
call_deferred('_set_selector_size', selector, i_row)
_set_selector_size(selector, i_row)
selector.modulate = selector_color_proc.call(i_row)
selector.z_index = z_index + 1
nodes[selector_key] = selector
@@ -430,7 +430,6 @@ func set_header(header_types: Array):
else:
var childrens = header.get_children()
for node in childrens:
childrens.erase(node.name)
childrens.remove_child(node)
node.queue_free()
for i_col in columns:

39
table/ячейка-2.gd Normal file
View File

@@ -0,0 +1,39 @@
extends LineEdit
static var styles = [[null, null], [null, null]]
static var init_done: = false
func _init() -> void:
if not init_done:
init_done = true
var style_0_light = get_theme_stylebox('normal')
var style_1_light = get_theme_stylebox('read_only')
style_0_light.bg_color = Color(0.12, 0.12, 0.12)
style_1_light.bg_color = Color(0.12, 0.12, 0.12)
styles[1][0] = style_0_light
styles[1][1] = style_1_light
var style_0_dark = style_0_light.duplicate(true)
var style_1_dark = style_1_light.duplicate(true)
style_0_light.bg_color = Color.GRAY
style_1_light.bg_color = Color.GRAY
styles[0][0] = style_0_dark
styles[0][1] = style_1_dark
ProjectSettings.connect('settings_changed', apply_colors)
apply_colors()
func apply_colors():
if ProjectSettings.get_setting('application/config/%s' % 'Цвет темы программы', false):
add_theme_color_override('font_color', Color.BLACK)
add_theme_color_override('font_uneditable_color', Color.BLACK)
add_theme_stylebox_override('normal', styles[1][0])
add_theme_stylebox_override('read_only', styles[1][1])
else:
add_theme_color_override('font_color', Color(1.0, 0.596, 0.4))
add_theme_color_override('font_uneditable_color', Color(1.0, 0.596, 0.4))
add_theme_stylebox_override('normal', styles[0][0])
add_theme_stylebox_override('read_only', styles[0][1])

View File

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

View File

@@ -1,4 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dspa16ufrpanp"]
[gd_scene load_steps=3 format=3 uid="uid://dspa16ufrpanp"]
[ext_resource type="Script" uid="uid://dqexdg24cp6rq" path="res://table/ячейка-2.gd" id="1_0fmuf"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_mla3y"]
@@ -16,3 +18,4 @@ selecting_enabled = false
deselect_on_focus_loss_enabled = false
caret_blink = true
caret_blink_interval = 0.1
script = ExtResource("1_0fmuf")

View File

@@ -0,0 +1,24 @@
extends ColorPickerButton
static var styles = [null, null]
static var init_done: = false
func _init() -> void:
if not init_done:
init_done = true
var style_light: = get_theme_stylebox('normal')
style_light.bg_color = Color.GRAY
styles[1] = style_light
var style_dark: = style_light.duplicate(true)
style_dark.bg_color = Color(0.12, 0.12, 0.12)
styles[0] = style_dark
ProjectSettings.connect('settings_changed', apply_colors)
apply_colors()
func apply_colors():
if ProjectSettings.get_setting('application/config/%s' % 'Цвет темы программы', false):
add_theme_stylebox_override('normal', styles[1])
else:
add_theme_stylebox_override('normal', styles[0])

View File

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

View File

@@ -1,4 +1,8 @@
[gd_scene format=3 uid="uid://cug5xjbfdm7x7"]
[gd_scene load_steps=3 format=3 uid="uid://cug5xjbfdm7x7"]
[ext_resource type="Script" uid="uid://b36c83manfems" path="res://table/ячейка-цвет.gd" id="1_ce8lu"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ce8lu"]
[node name="ячейка-цвет" type="ColorPickerButton"]
anchors_preset = 15
@@ -6,3 +10,5 @@ anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/focus = SubResource("StyleBoxEmpty_ce8lu")
script = ExtResource("1_ce8lu")