Merge branch 'эмс-тг'

This commit is contained in:
sasha80
2026-03-31 12:10:02 +03:00
58 changed files with 1983 additions and 1854 deletions

View File

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

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

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

View File

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

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

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

View File

@@ -5,7 +5,7 @@
[ext_resource type="PackedScene" uid="uid://lwmw4egynmd1" path="res://scenes/контроль/контроль.tscn" id="3_txp0s"]
[ext_resource type="PackedScene" uid="uid://trt0q8th3bn2" path="res://scenes/журнал/журнал.tscn" id="4_cu5k8"]
[ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/эмс/эмс.tscn" id="5_u71bh"]
[ext_resource type="PackedScene" uid="uid://musb21x2u0xs" path="res://scenes/эмс2/эмс2.tscn" id="6_41d34"]
[ext_resource type="PackedScene" uid="uid://musb21x2u0xs" path="res://scenes/эмс-тг/эмс-тг.tscn" id="6_41d34"]
[ext_resource type="PackedScene" uid="uid://bnptm4rlp60dq" path="res://scenes/настройки/настройки.tscn" id="6_i8iv3"]
[ext_resource type="Script" uid="uid://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"]

View File

@@ -403,7 +403,7 @@ func _response(result, code, _headers: Array, body: PackedByteArray, req, tile:
return
if Error.OK != image_load_proc.call(body):
push_error('не удалось получить изображение (неверный формат?) из \"%s\"' % tile.url)
push_error('не удалось получить изображение (неверный формат?) из \"%s\" (%d байт)' % [tile.url, body.size()])
return
tile.texture = ImageTexture.create_from_image(image)

View File

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

View File

@@ -0,0 +1,872 @@
[gd_scene load_steps=22 format=3 uid="uid://musb21x2u0xs"]
[ext_resource type="Script" uid="uid://bvlqgv7aapebl" path="res://scenes/эмс-тг/эмс-тг.gd" id="1_b7tfl"]
[ext_resource type="Texture2D" uid="uid://djv8fkddcjucs" path="res://data/матрица-чисто.png" id="2_s28jr"]
[ext_resource type="Texture2D" uid="uid://busl8rb38lis" path="res://data/матрица-конфликт.png" id="3_its7t"]
[ext_resource type="Script" uid="uid://c5pq0hbrij34d" path="res://table/table.gd" id="4_bhff3"]
[ext_resource type="PackedScene" uid="uid://hr55mkcneaer" path="res://scenes/hranges/panel.tscn" id="5_6hay3"]
[ext_resource type="Texture2D" uid="uid://docnrxrm2f022" path="res://data/Угловой квадрат3.png" id="6_a0vpj"]
[ext_resource type="Texture2D" uid="uid://cxrggrvx6l22q" path="res://data/Квадрат марс ОР-63.png" id="7_xr3ub"]
[ext_resource type="Texture2D" uid="uid://d3qui21aom1ac" path="res://data/Квадрат марс 454.png" id="8_saoyo"]
[ext_resource type="Texture2D" uid="uid://36xjgea2n22q" path="res://data/Квадрат марс ГО.png" id="9_bqil1"]
[ext_resource type="Texture2D" uid="uid://by6a12oahbg82" path="res://data/Квадрат марс РЛС1.png" id="10_ggqgc"]
[ext_resource type="Texture2D" uid="uid://pfoscstbm025" path="res://data/эмс-бланк-перем.png" id="10_wdb1k"]
[ext_resource type="Texture2D" uid="uid://dwgqofj6yae1v" path="res://data/Квадрат марс РЛС2.png" id="11_xothm"]
[ext_resource type="Texture2D" uid="uid://dsuiytxdnole7" path="res://data/Квадрат марс с трубкой.png" id="12_4rjt3"]
[ext_resource type="Texture2D" uid="uid://d3v1r4r62na8" path="res://data/Квадрат салатный ОР-63.png" id="13_g0j2q"]
[ext_resource type="Texture2D" uid="uid://b1kuhj03yigih" path="res://data/Квадрат салатный 454.png" id="14_crrpm"]
[ext_resource type="Texture2D" uid="uid://cyb60nh23ys6k" path="res://data/Квадрат салатный ГО.png" id="15_0dspi"]
[ext_resource type="Texture2D" uid="uid://ddm55bo28sxcs" path="res://data/Квадрат салатный РЛС1.png" id="16_6042y"]
[ext_resource type="Texture2D" uid="uid://dneqjcul4ipub" path="res://data/Квадрат салатный РЛС2.png" id="17_gvsi1"]
[ext_resource type="Texture2D" uid="uid://cw8sd7v5f31ww" path="res://data/Квадрат салатный с трубкой.png" id="18_p3gp1"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_niy1n"]
[sub_resource type="ButtonGroup" id="ButtonGroup_vwsbs"]
allow_unpress = true
[node name="эмс-тг" type="Panel"]
offset_top = 35.0
offset_bottom = 35.0
script = ExtResource("1_b7tfl")
index_to_unit_names = Array[StringName]([&"эмс-ор63", &"эмс-454", &"эмс-го", &"эмс-рлс1", &"эмс-рлс2", &"эмс-ннвс", &"эмс-изделие7", &"эмс-изделие8"])
freq_min = 300.0
freq_max = 6000.0
color_enabled = Color(0.898039, 0.458824, 0.239216, 0.7)
color_disabled = Color(0.601223, 0.601223, 0.601223, 0.7)
color_alpha = 0.7
color_odd = Color(0.31863, 0.32773, 0.327729, 1)
color_even = Color(0.258824, 0.266667, 0.266667, 1)
column_cmd_rx = 6
column_cmd_tx = 7
max_clasters_per_unit = 32
msg_select_unit = "Выберите устройство"
msg_waiting_data = "Ожидание данных"
table_headers = Array[String](["uid://ch14g46swx74h", "uid://ch14g46swx74h", "uid://ch14g46swx74h", "uid://ch14g46swx74h", "uid://ch14g46swx74h", "uid://ch14g46swx74h", "uid://cymcld4mjmlhj", "uid://cymcld4mjmlhj"])
table_cells = Array[String](["uid://dwphmxstaxn4v", "uid://dwphmxstaxn4v", "uid://dwphmxstaxn4v", "uid://dwphmxstaxn4v", "uid://dwphmxstaxn4v", "uid://dwphmxstaxn4v", "uid://cixwl6xi22buo", "uid://cixwl6xi22buo"])
image_file_rx = "uid://c6etralq2tvxg"
image_file_tx = "uid://c73tjrn8gr00o"
table_rows_hight = 32
table_column_widths = Array[int]([133, 133, 133, 133, 133, 133, 133, 133])
table_header_widths = Array[int]([136, 136, 136, 136, 136, 136, 136, 136])
table_header_text = Array[String](["Кластер", "Состояние", "Время", "Азимут", "Угол места", "Диапазон", "Приём", "Передача"])
[node name="таблица" type="ScrollContainer" parent="."]
layout_mode = 0
offset_left = 20.0
offset_top = 765.0
offset_right = 1180.0
offset_bottom = 1145.0
theme_override_styles/focus = SubResource("StyleBoxEmpty_niy1n")
draw_focus_border = true
vertical_scroll_mode = 2
[node name="сетка" type="GridContainer" parent="таблица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
columns = 8
script = ExtResource("4_bhff3")
[node name="шкала" type="GridContainer" parent="."]
layout_mode = 0
offset_left = 20.0
offset_top = 10.0
offset_right = 1668.0
offset_bottom = 736.0
scale = Vector2(0.95, 0.95)
columns = 2
[node name="label0" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "ОР-63"
icon = ExtResource("7_xr3ub")
icon_alignment = 1
vertical_icon_alignment = 0
expand_icon = true
metadata/unit_name = &"эмс-ор63"
[node name="sub0" type="GridContainer" parent="шкала" groups=["чётные", "шкалы-кластеров"]]
self_modulate = Color(0.258824, 0.266667, 0.266667, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-ор63"
[node name="panel_rx" parent="шкала/sub0" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="panel_tx" parent="шкала/sub0" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="label1" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_horizontal = 5
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "454"
icon = ExtResource("8_saoyo")
icon_alignment = 1
vertical_icon_alignment = 0
expand_icon = true
metadata/unit_name = &"эмс-454"
[node name="sub1" type="GridContainer" parent="шкала" groups=["нечётные", "шкалы-кластеров"]]
self_modulate = Color(0.294118, 0.294118, 0.294118, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-454"
[node name="panel_rx" parent="шкала/sub1" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="panel_tx" parent="шкала/sub1" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="label2" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_horizontal = 5
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "ГО"
icon = ExtResource("9_bqil1")
icon_alignment = 1
vertical_icon_alignment = 0
expand_icon = true
metadata/unit_name = &"эмс-го"
[node name="sub2" type="GridContainer" parent="шкала" groups=["чётные", "шкалы-кластеров"]]
self_modulate = Color(0.258824, 0.266667, 0.266667, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-го"
[node name="panel_rx" parent="шкала/sub2" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="panel_tx" parent="шкала/sub2" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="label3" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_horizontal = 5
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "РЛС1"
icon = ExtResource("10_ggqgc")
icon_alignment = 1
vertical_icon_alignment = 0
expand_icon = true
metadata/unit_name = &"эмс-рлс1"
[node name="sub3" type="GridContainer" parent="шкала" groups=["нечётные", "шкалы-кластеров"]]
self_modulate = Color(0.294118, 0.294118, 0.294118, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-рлс1"
[node name="panel_rx" parent="шкала/sub3" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="panel_tx" parent="шкала/sub3" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="label4" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_horizontal = 5
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "РЛС2"
icon = ExtResource("11_xothm")
icon_alignment = 1
vertical_icon_alignment = 0
expand_icon = true
metadata/unit_name = &"эмс-рлс2"
[node name="sub4" type="GridContainer" parent="шкала" groups=["чётные", "шкалы-кластеров"]]
self_modulate = Color(0.258824, 0.266667, 0.266667, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-рлс2"
[node name="panel_rx" parent="шкала/sub4" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="panel_tx" parent="шкала/sub4" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="label5" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_horizontal = 5
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "ННВС"
icon = ExtResource("12_4rjt3")
icon_alignment = 1
vertical_icon_alignment = 0
expand_icon = true
metadata/unit_name = &"эмс-ннвс"
[node name="sub5" type="GridContainer" parent="шкала" groups=["нечётные", "шкалы-кластеров"]]
self_modulate = Color(0.294118, 0.294118, 0.294118, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-ннвс"
[node name="panel_rx" parent="шкала/sub5" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="panel_tx" parent="шкала/sub5" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="label6" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_horizontal = 5
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "Изделие 7"
icon = ExtResource("10_wdb1k")
icon_alignment = 1
vertical_icon_alignment = 0
metadata/unit_name = &"эмс-изделие7"
[node name="sub6" type="GridContainer" parent="шкала" groups=["чётные", "шкалы-кластеров"]]
self_modulate = Color(0.258824, 0.266667, 0.266667, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-изделие7"
[node name="panel_rx" parent="шкала/sub6" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="panel_tx" parent="шкала/sub6" instance=ExtResource("5_6hay3")]
self_modulate = Color(0.830335, 0.830335, 0.830335, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.258824, 0.266667, 0.266667, 1)
[node name="label7" type="Button" parent="шкала" groups=["кнопки-шкалы"]]
layout_mode = 2
size_flags_horizontal = 5
size_flags_vertical = 7
toggle_mode = true
action_mode = 0
button_group = SubResource("ButtonGroup_vwsbs")
text = "Изделие 8"
icon = ExtResource("10_wdb1k")
icon_alignment = 1
vertical_icon_alignment = 0
metadata/unit_name = &"эмс-изделие8"
[node name="sub7" type="GridContainer" parent="шкала" groups=["нечётные", "шкалы-кластеров"]]
self_modulate = Color(0.294118, 0.294118, 0.294118, 1)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
metadata/unit_name = &"эмс-изделие8"
[node name="panel_rx" parent="шкала/sub7" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c73tjrn8gr00o"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="panel_tx" parent="шкала/sub7" instance=ExtResource("5_6hay3")]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
image_file = "uid://c6etralq2tvxg"
back_color = Color(0.31863, 0.32773, 0.327729, 1)
[node name="матрица" type="GridContainer" parent="."]
layout_mode = 0
offset_left = 1195.0
offset_top = 735.0
offset_right = 1585.0
offset_bottom = 1145.0
columns = 7
[node name="прм-прд" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("6_a0vpj")
[node name="прд-0" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("7_xr3ub")
metadata/unit_name = &""
[node name="прд-1" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("8_saoyo")
metadata/unit_name = &""
[node name="прд-2" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("9_bqil1")
metadata/unit_name = &""
[node name="прд-3" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("10_ggqgc")
metadata/unit_name = &""
[node name="прд-4" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("11_xothm")
metadata/unit_name = &""
[node name="прд-5" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("12_4rjt3")
metadata/unit_name = &""
[node name="прм-0" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("13_g0j2q")
metadata/unit_name = &"эмс-ор63"
[node name="матрица-0-0" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
action_mode = 0
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-0-1" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-0-2" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-0-3" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-0-4" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-0-5" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="прм-1" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("14_crrpm")
metadata/unit_name = &""
[node name="матрица-1-0" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-1-1" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-1-2" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-1-3" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-1-4" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-1-5" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="прм-2" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("15_0dspi")
metadata/unit_name = &""
[node name="матрица-2-0" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-2-1" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-2-5" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-2-2" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-2-3" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-2-4" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="прм-3" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("16_6042y")
metadata/unit_name = &""
[node name="матрица-3-0" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-3-1" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-3-2" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-3-3" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-3-4" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-3-5" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="прм-4" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("17_gvsi1")
metadata/unit_name = &""
[node name="матрица-4-0" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-4-1" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-4-2" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-4-3" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-4-4" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-4-5" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="прм-5" type="TextureRect" parent="матрица"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("18_p3gp1")
metadata/unit_name = &""
[node name="матрица-5-0" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-5-1" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-5-2" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-5-3" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-5-5" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="матрица-5-6" type="TextureButton" parent="матрица" groups=["матрица-к"]]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
toggle_mode = true
button_mask = 0
texture_normal = ExtResource("2_s28jr")
texture_pressed = ExtResource("3_its7t")
stretch_mode = 0
[node name="label_msg" type="Label" parent="."]
layout_mode = 0
offset_left = 25.0
offset_top = 765.0
offset_right = 1180.0
offset_bottom = 1155.0
text = "Выберите устройство"
horizontal_alignment = 1
vertical_alignment = 1
[node name="label1" type="Label" parent="."]
layout_mode = 2
offset_left = 20.0
offset_top = -20.0
offset_right = 142.0
offset_bottom = -1.0
text = "Устройства"
horizontal_alignment = 1
vertical_alignment = 1
[node name="label3" type="Label" parent="."]
layout_mode = 2
offset_left = 1195.0
offset_top = 702.0
offset_right = 1585.0
offset_bottom = 725.0
text = "Индикатор конфликтов"
horizontal_alignment = 1
vertical_alignment = 1
[node name="label2" type="Label" parent="."]
layout_mode = 2
offset_left = 145.0
offset_top = -20.0
offset_right = 1585.0
offset_bottom = 3.0
text = "Рабочие диапазоны"
horizontal_alignment = 1
vertical_alignment = 1
[node name="label4" type="Label" parent="."]
layout_mode = 2
offset_left = 20.0
offset_top = 702.0
offset_right = 1190.0
offset_bottom = 725.0
text = "Кластеры устройства"
horizontal_alignment = 1
vertical_alignment = 1

View File

@@ -74,7 +74,7 @@ class OutDev extends InDev:
if btns_state.has(i_dev):
btns_state[i_dev] = val
var data = 0
for i in range(yemsconsts.NUM_INPUT):
for i in yemsconsts.NUM_INPUT:
data = data | (int(btns_state[i+1]) << i)
ports_data[isa_addr + 4] = data & 0xffff
ports_data[isa_addr + 6] = (data >> 16) & 0xffff

View File

@@ -63,17 +63,16 @@ func init_boards():
init_tbl_files()
$scrl_files/tbl_files.pin_header($scrl_files, self)
unit_ems.connect('data_received', Callable(self, 'on_data_ems_received'))
unit_ems.connect('command_done', Callable(self, 'on_command_done'))
unit_ems.connect('line_changed', Callable(self, 'on_line_changed'))
unit_ems.connect('data_received', on_data_ems_received)
unit_ems.connect('command_done', on_command_done)
unit_ems.connect('line_changed', on_line_changed)
for board in g_boards.values():
board.connect('upd_delay_offset', Callable(self, 'on_upd_delay_offset'))
board.connect('upd_o_state', Callable(self, 'on_upd_o_state'))
$btn_connect.connect('pressed', Callable(self, 'on_btn_connect'))
$btn_disconnect.connect('pressed', Callable(self, 'on_btn_disconnect').bind(unit_ems))
$btn_flash_read.button_connect('pressed', Callable(self, 'on_btn_flash_read').bind($btn_flash_read))
$btn_flash_write.button_connect('pressed', Callable(self, 'on_btn_flash_write').bind($btn_flash_write))
board.connect('upd_delay_offset', on_upd_delay_offset)
board.connect('upd_o_state', on_upd_o_state)
$btn_connect.connect('pressed', on_btn_connect)
$btn_disconnect.connect('pressed', on_btn_disconnect.bind(unit_ems))
$btn_flash_read.button_connect('pressed', on_btn_flash_read.bind($btn_flash_read))
$btn_flash_write.button_connect('pressed', on_btn_flash_write.bind($btn_flash_write))
## Обработчик нажатия кнопки disconnect.
@@ -140,7 +139,7 @@ func init_tbl_files():
tools.fill_files_table($scrl_files/tbl_files, yemsconsts.files_folder, FILES_ROWS_TYPES)
$scrl_files/tbl_files.set_columns_alignments(yemsconsts.FILES_ROWS_ALIGNMENT)
$scrl_files/tbl_files.set_columns_min_size(yemsconsts.FILES_COLUMN_WIDTHS)
$scrl_files/tbl_files.connect('row_pressed', Callable(self, 'on_pressed_file'))
$scrl_files/tbl_files.connect('row_pressed', on_pressed_file)
for i_row in $scrl_files/tbl_files.get_rows_count():
disable_edit($scrl_files/tbl_files, len(FILES_ROWS_TYPES), i_row)
@@ -179,8 +178,8 @@ func init_tbl_in():
$scrollin/tbl_in.set_node_user_data(i, row_index, [in_dev, board])
$scrollin/tbl_in.set_columns_alignments(yams_alligment_in)
$scrollin/tbl_in.set_columns_min_size(column_size)
$scrollin/tbl_in.connect('row_pressed', Callable(self, 'on_row_pressed_in'))
$scrollin/tbl_in.connect('selected_changed', Callable(self, 'on_selected_changed_in'))
$scrollin/tbl_in.connect('row_pressed', on_row_pressed_in)
$scrollin/tbl_in.connect('selected_changed', on_selected_changed_in)
# Инициализация таблицы изменения параметров входа и списка выходов связанных с ним
header_text[0] = 'Вход'
@@ -188,8 +187,8 @@ func init_tbl_in():
$scrl_in_set/tbl_in_set.set_header_text(header_text)
$scrl_in_set/tbl_in_set.set_columns_alignments(yams_alligment_in)
$scrl_in_set/tbl_in_set.set_columns_min_size(column_size)
$scrl_in_set/tbl_in_set.connect('row_pressed', Callable(self, 'on_row_pressed_si'))
$scrl_in_set/tbl_in_set.connect('selected_changed', Callable(self, 'on_selected_changed_si'))
$scrl_in_set/tbl_in_set.connect('row_pressed', on_row_pressed_si)
$scrl_in_set/tbl_in_set.connect('selected_changed', on_selected_changed_si)
## Обработчик редактирования Entry в таблице параметров входов/выходов.
@@ -302,16 +301,16 @@ func init_tbl_out():
cell.editable = false
$scrollout/tbl_out.set_columns_min_size([250, 100, 70, 70, 70, 100])
$scrollout/tbl_out.set_columns_alignments(yams_alligment_out)
$scrollout/tbl_out.connect('row_pressed', Callable(self, 'on_row_pressed_out'))
$scrollout/tbl_out.connect('selected_changed', Callable(self, 'on_selected_changed_out'))
$scrollout/tbl_out.connect('row_pressed', on_row_pressed_out)
$scrollout/tbl_out.connect('selected_changed', on_selected_changed_out)
# Инициализация таблицы изменения параметров выхода и списка входов связанных с ним
header_text[0] = 'Выход'
$scrl_out_set/tbl_out_set.set_header([TableHeader, TableHeader, CellFront, CellFrontRear, TableHeader, TableHeader])
$scrl_out_set/tbl_out_set.set_header_text(header_text)
$scrl_out_set/tbl_out_set.set_columns_min_size([250, 100, 70, 70, 70, 100])
$scrl_out_set/tbl_out_set.connect('row_pressed', Callable(self, 'on_row_pressed_so'))
$scrl_out_set/tbl_out_set.connect('selected_changed', Callable(self, 'on_selected_changed_so'))
$scrl_out_set/tbl_out_set.connect('row_pressed', on_row_pressed_so)
$scrl_out_set/tbl_out_set.connect('selected_changed', on_selected_changed_so)
## Обработчик выбора строки в таблице соединений выхода и изменения параметров.
@@ -357,7 +356,7 @@ func set_out_dev(dev):
var mode = $scrl_out_set/tbl_out_set.get_node2(5, 0)
for opt in OUT_MODE:
mode.add_item(opt)
mode.connect('item_selected', Callable(self, 'on_switch_done').bind(dev))
mode.connect('item_selected', on_switch_done.bind(dev))
mode.select(dev.mode)
@@ -532,20 +531,20 @@ func on_upd_delay_offset(_board, dev):
tbl = $scrollout/tbl_out
var le_delay = tbl.get_node2(TABLE_ENTRY_COLUMNS[0], dev.tbl_row_id)
var le_offset = tbl.get_node2(TABLE_ENTRY_COLUMNS[1], dev.tbl_row_id)
le_delay.set_text(str('%3.1f' % dev.delay))
le_offset.set_text(str('%3.1f' % dev.offset))
le_delay.set_text('%3.1f' % dev.delay)
le_offset.set_text('%3.1f' % dev.offset)
if $scrl_in_set/tbl_in_set.get_rows_count():
var sel_dev = $scrl_in_set/tbl_in_set.get_node_user_data(0, 0)
var l_delay = $scrl_in_set/tbl_in_set.get_node2(2, 0)
var l_offset = $scrl_in_set/tbl_in_set.get_node2(3, 0)
l_delay.set_text(str('%3.1f' % sel_dev.delay))
l_offset.set_text(str('%3.1f' % sel_dev.offset))
l_delay.set_text('%3.1f' % sel_dev.delay)
l_offset.set_text('%3.1f' % sel_dev.offset)
if $scrl_out_set/tbl_out_set.get_rows_count():
var sel_dev = $scrl_out_set/tbl_out_set.get_node_user_data(0, 0)
var l_delay = $scrl_out_set/tbl_out_set.get_node2(2, 0)
var l_offset = $scrl_out_set/tbl_out_set.get_node2(3, 0)
l_delay.set_text(str('%3.1f' % sel_dev.delay))
l_offset.set_text(str('%3.1f' % sel_dev.offset))
l_delay.set_text('%3.1f' % sel_dev.delay)
l_offset.set_text('%3.1f' % sel_dev.offset)
## Вызывается по обновлению информации о режиме выходов
@@ -662,4 +661,4 @@ func _on_btn_load_pressed() -> void:
board.need_write = true
log.message(log.INFO, 'Произведено чтение настроек ЭМС из файла: %s, для платы %s' %[fl_name, board.id_board])
else:
log.message(log.ERROR, 'Ошибка чтение настроек ЭМС из файла: %s' %fl_name)
log.message(log.ERROR, 'Ошибка чтение настроек ЭМС из файла: %s' % fl_name)

View File

@@ -1,15 +0,0 @@
extends Panel
func _ready() -> void:
var unit_trassa = network.get_unit_instance('уарэп-трасса')
unit_trassa.connect('line_changed', Callable(self, 'on_trassa_line_changed'))
signaller.connect('sector_klaster', Callable(self, 'on_sector_klaster').bind(unit_trassa))
func on_trassa_line_changed(_unit_trassa):
pass
func on_sector_klaster(_data, _unit_trassa):
pass

View File

@@ -1,96 +0,0 @@
[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"]
[ext_resource type="Texture2D" uid="uid://073el51yholj" path="res://data/454.png" id="4_528aa"]
[ext_resource type="Texture2D" uid="uid://cckk3jk5r32bh" path="res://data/ГО.png" id="5_qxr47"]
[ext_resource type="Texture2D" uid="uid://kyrnn1mqpc08" path="res://data/РЛС1.png" id="6_8sxps"]
[ext_resource type="Texture2D" uid="uid://cx0f3wcx76u1k" path="res://data/РЛС2.png" id="7_0bfmy"]
[ext_resource type="Texture2D" uid="uid://csxruavk0s40l" path="res://data/Окно частот0.png" id="8_4em3i"]
[ext_resource type="Texture2D" uid="uid://duu8q7sv0jwfh" path="res://data/ННВС.png" id="8_aiy4x"]
[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_5u4bk"]
[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_pd85g"]
[node name="Control" type="Panel"]
[node name="Sprite2D" type="Sprite2D" parent="."]
modulate = Color(1, 0.596078, 0.4, 1)
position = Vector2(801, 131)
rotation = 1.5708
scale = Vector2(0.353264, 0.353264)
texture = ExtResource("1_4em3i")
[node name="частоты" type="TextureRect" parent="."]
visible = false
layout_mode = 0
offset_left = 72.0
offset_top = 264.0
offset_right = 1621.0
offset_bottom = 870.0
scale = Vector2(0.95, 0.95)
texture = SubResource("CompressedTexture2D_5u4bk")
[node name="Op-63" type="TextureRect" parent="."]
layout_mode = 0
offset_left = 128.0
offset_top = 91.0
offset_right = 341.0
offset_bottom = 383.0
scale = Vector2(0.312207, 0.312207)
texture = ExtResource("3_eq8fj")
[node name="454" type="TextureRect" parent="."]
layout_mode = 0
offset_left = 288.0
offset_top = 91.0
offset_right = 501.0
offset_bottom = 383.0
scale = Vector2(0.312, 0.312)
texture = ExtResource("4_528aa")
[node name="Го" type="TextureRect" parent="."]
layout_mode = 0
offset_left = 464.0
offset_top = 91.0
offset_right = 677.0
offset_bottom = 383.0
scale = Vector2(0.312, 0.312)
texture = ExtResource("5_qxr47")
[node name="Рлс1" type="TextureRect" parent="."]
layout_mode = 0
offset_left = 728.0
offset_top = 91.0
offset_right = 941.0
offset_bottom = 383.0
scale = Vector2(0.312, 0.312)
texture = ExtResource("6_8sxps")
[node name="Рлс2" type="TextureRect" parent="."]
layout_mode = 0
offset_left = 920.0
offset_top = 91.0
offset_right = 1133.0
offset_bottom = 383.0
scale = Vector2(0.312, 0.312)
texture = ExtResource("7_0bfmy")
[node name="Ннвс" type="TextureRect" parent="."]
layout_mode = 0
offset_left = 1280.0
offset_top = 91.0
offset_right = 1493.0
offset_bottom = 383.0
scale = Vector2(0.312, 0.312)
texture = ExtResource("8_aiy4x")
[node name="ТаблицаОбмена" type="Sprite2D" parent="."]
position = Vector2(568, 1024)
scale = Vector2(0.911215, 0.911215)
texture = SubResource("CompressedTexture2D_pd85g")
[node name="ТаблицаЧастот" type="Sprite2D" parent="."]
position = Vector2(794, 569)
texture = ExtResource("8_4em3i")

File diff suppressed because it is too large Load Diff