Merge remote-tracking branch 'sasha/master'

# Conflicts:
#	scenes/button-flat.tscn
#	scenes/tab_switch.tscn
#	scenes/ЭМС.tscn
#	scenes/работа.tscn
This commit is contained in:
MaD_CaT
2023-09-05 14:26:28 +03:00
26 changed files with 618 additions and 733 deletions

View File

@@ -11,7 +11,7 @@ config_version=5
[application]
config/name="uarep-ctl"
run/main_scene="res://scenes/tab_switch.tscn"
run/main_scene="res://scenes/tab-switch.tscn"
config/features=PackedStringArray("4.1")
run/low_processor_mode=true
run/delta_smoothing=false
@@ -22,6 +22,7 @@ config/icon="res://data/icon.png"
[autoload]
signaller="*res://scripts/signaller.gd"
Log="*res://addons/godot-logger/scripts/logger.gd"
Tools="*res://scripts/tools.gd"
REPSettings="*res://scripts/repsettings.gd"

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=9 format=3 uid="uid://da7w3vkhadfwe"]
[ext_resource type="Script" path="res://scenes/nine-patch-button.gd" id="1_u2beb"]
[ext_resource type="Texture2D" uid="uid://ct0ajcwno03h7" path="res://data/кнопка-квадрат-0.png" id="2_7amqa"]
[ext_resource type="Script" path="res://scenes/nine-patch-button.gd" id="1_uqldr"]
[ext_resource type="Texture2D" uid="uid://ct0ajcwno03h7" path="res://data/кнопка-квадрат-0.png" id="2_0loew"]
[sub_resource type="StyleBoxEmpty" id="1"]
@@ -19,13 +19,13 @@
offset_right = 30.0
offset_bottom = 30.0
theme_override_styles/panel = SubResource("1")
script = ExtResource("1_u2beb")
script = ExtResource("1_uqldr")
toggle_mode = true
[node name="state" type="NinePatchRect" parent="."]
show_behind_parent = true
layout_mode = 2
texture = ExtResource("2_7amqa")
texture = ExtResource("2_0loew")
patch_margin_left = 10
patch_margin_top = 10
patch_margin_right = 10

View File

@@ -8,7 +8,7 @@
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_2bft1"]
size = Vector2(1600, 1200)
[sub_resource type="ShaderMaterial" id="ShaderMaterial_dklk6"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_wl0b8"]
resource_local_to_scene = true
shader = ExtResource("4_gb4a1")
shader_parameter/color = Color(1, 1, 1, 0.168627)
@@ -26,6 +26,6 @@ centered = false
script = ExtResource("2_vkwmy")
[node name="строб" parent="." instance=ExtResource("3_uhdvc")]
material = SubResource("ShaderMaterial_dklk6")
material = SubResource("ShaderMaterial_wl0b8")
position = Vector2(560, 560)
scale = Vector2(1100, 1100)

View File

@@ -3,13 +3,3 @@ extends Control
@export var text: String = '':
set(val): $label.set_text(val)
get: return $label.get_text()
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

View File

@@ -12,6 +12,7 @@ patch_margin_top = 30
patch_margin_right = 15
patch_margin_bottom = 10
script = ExtResource("2_7mns1")
text = ""
[node name="header" type="Label" parent="."]
clip_contents = true

View File

@@ -1,61 +0,0 @@
extends ScrollContainer
const CellLineEdit = preload('res://scenes/ячейка-2.tscn')
const TableHeader = preload('res://table/header.tscn')
const TableNode = preload('res://table/node.tscn')
const TABLE_ROW = [CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit]
const TABLE_COLUMN_PARAM = ['id', 'aoa', 'freq', 'proto'] ## Параметры цели отображаемые в таблице.
const TABLE_HEADERS_TEXT = ['Номер', 'Пеленг', 'Частота, МГц', 'Протокол'] ##
func on_row_pressed(i_row: int):
var selected = $tbl_threats.is_row_selected(i_row)
$tbl_threats.set_row_selected(i_row, not selected)
func init_table():
$tbl_threats.set_header([TableHeader, TableHeader, TableHeader, TableHeader])
$tbl_threats.set_header_text(TABLE_HEADERS_TEXT)
$tbl_threats.set_columns_min_size([50, 140, 140, 100])
$tbl_threats.pin_header(self, get_parent())
$tbl_threats.connect('row_pressed', Callable(self, 'on_row_pressed'))
func _ready() -> void:
var th_table_id: = Dictionary()
Threats.connect('threat_new', Callable(self, 'on_threat_new').bind(th_table_id))
Threats.connect('threat_lost', Callable(self, 'on_threat_lost').bind(th_table_id))
call_deferred('init_table')
func rehash(th_table_id: Dictionary):
var rows_count = $tbl_threats.get_rows_count()
for i_row in rows_count:
var item = $tbl_threats.get_node2(0, i_row)
th_table_id[int(item.text)] = i_row
func on_threat_lost(_threats, th, th_table_id: Dictionary):
$tbl_threats.remove_row(th_table_id[th.id])
th_table_id.clear()
rehash(th_table_id)
func on_threat_new(_threats, th, th_table_id):
var i_row = $tbl_threats.get_rows_count()
$tbl_threats.add_row(TABLE_ROW)
var row = map_th_to_row(th)
$tbl_threats.set_row_text(i_row, row)
th_table_id[th.id] = i_row
func map_th_to_row(th):
var row: = Array()
row.resize(TABLE_COLUMN_PARAM.size())
var i_col: int = 0
for param_name in TABLE_COLUMN_PARAM:
row[i_col] = '%s' % th.get(param_name)
i_col += 1
return row

62
scenes/scroll-params.gd Normal file
View File

@@ -0,0 +1,62 @@
extends ScrollContainer
## Отображение параметров цели
const CellLineEdit = preload('res://scenes/ячейка-2.tscn') ## Ячейка таблицы.
const TableHeader = preload('res://table/header.tscn') ## Ячейка заголовок таблицы.
const TABLE_HEADER = [ TableHeader, TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit ] ## Описание ряда.
const TABLE_HEADERS_TEXT = ['Параметр', 'Значение' ] ## Назания колонок.
const TABLE_COLUMN_SIZE = [ 370, 85 ] ## Ширины колонок.
## Параметры цели для отображения в таблице.[br]
## [b]val[0][/b] - Индекс строки.[br][b]val[1][/b] - Содержание.
const TABLE_PARAMS = {
'baud': [0, 'Модуляционная скорость, бод'],
'freqm': [1, 'Режим смены частоты.'],
'power': [2, 'Уровень сигнала, дБм.'],
'tmod': [3, 'Тип модуляции'],
'width': [4, 'Занимая полоса частот, МГц.'],
'rkrp': [5, 'Рекомендуемая помеха'] }
## Обрабатывает сигнал [signal Threats.threat_selected]
func on_threat_selected(th):
$table.set_meta('id', th.id)
on_threat_update(th)
func init_table():
$table.set_header(TABLE_HEADER)
$table.set_header_text(TABLE_HEADERS_TEXT)
$table.set_columns_min_size(TABLE_COLUMN_SIZE)
$table.pin_header(self, get_parent())
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
for i in TABLE_PARAMS.size(): $table.add_row(TABLE_ROW)
for p in TABLE_PARAMS.values():
$table.set_node_text(0, p[0], p[1])
$table.set_node_alligment(0, p[0], HORIZONTAL_ALIGNMENT_LEFT)
$table.set_node_editable(0, p[0], false)
$table.set_node_editable(1, p[0], false)
$table.set_meta('id', 0)
func _ready() -> void:
signaller.connect('threat_selected', Callable(self, 'on_threat_selected'))
Threats.connect('threat_update', Callable(self, 'on_threat_update'))
call_deferred('init_table')
## Обрабатывает сигнал [signal Threats.threat_update].
## Обновляет отображение только для выбранной цели.
func on_threat_update(th):
if th.id != $table.get_meta('id'): return
var mnms = Tools.get_members_names(th)
for member_name in mnms:
if not TABLE_PARAMS.has(member_name): continue
var p = TABLE_PARAMS[member_name]
var val = th.get(member_name)
$table.set_node_text(1, p[0], '%s' % val)

82
scenes/scroll-threats.gd Normal file
View File

@@ -0,0 +1,82 @@
extends ScrollContainer
## Отображает список целей в таблице.
const CellLineEdit = preload('res://scenes/ячейка-2.tscn') ## Ячейка таблицы.
const TableHeader = preload('res://table/header.tscn') ## Ячейка заголовок таблицы.
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader, TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit ] ## Описание ряда.
const TABLE_COLUMN_PARAM = ['id', 'aoa', 'freq', 'proto' ] ## Параметры цели отображаемые в таблице.
const TABLE_HEADERS_TEXT = ['Номер', 'Пеленг', 'Частота, МГц', 'Протокол' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 145, 145, 90 ] ## Ширины колонок.
## Вызывается при нажатии указателем мыши на выбранный ряд.
func on_row_pressed(i_row: int):
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
var threat = $table.get_node_user_data(0, i_row)
signaller.emit_signal('threat_selected', threat)
func init_table():
$table.set_header(TABLE_HEADER)
$table.set_header_text(TABLE_HEADERS_TEXT)
$table.set_columns_min_size(TABLE_COLUMN_SIZE)
$table.pin_header(self, get_parent())
func _ready() -> void:
var table_index: = Dictionary()
Threats.connect('threat_new', Callable(self, 'on_threat_new').bind(table_index))
Threats.connect('threat_lost', Callable(self, 'on_threat_lost').bind(table_index))
Threats.connect('threat_update', Callable(self, 'on_threat_update').bind(table_index))
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
call_deferred('init_table')
## Перестраивает индекс таблицы. Вызывать при удалении строки
func rehash(table_index: Dictionary):
var rows_count = $table.get_rows_count()
for i_row in rows_count:
var item = $table.get_node2(0, i_row)
table_index[int(item.text)] = i_row
## Обрабатывает сигнал [b]threat_update[/b]
func on_threat_update(th, table_index: Dictionary):
var row = map_th_to_row(th)
var i_row = table_index[th.id]
$table.set_row_text(i_row, row)
## Обрабатывает сигнал [b]threat_lost[/b]
func on_threat_lost(th, table_index: Dictionary):
$table.remove_row(table_index[th.id])
table_index.clear()
rehash(table_index)
## Обрабатывает сигнал [b]threat_new[/b]
func on_threat_new(th, table_index):
var i_row = $table.get_rows_count()
$table.add_row(TABLE_ROW)
var row = map_th_to_row(th)
$table.set_row_text(i_row, row)
$table.set_row_editable(i_row, false)
$table.set_node_user_data(0, i_row, th)
table_index[th.id] = i_row
## Преобразует цель в строку таблицы
func map_th_to_row(th) -> Array:
var row: = Array()
row.resize(TABLE_COLUMN_PARAM.size())
var i_col: int = 0
for param_name in TABLE_COLUMN_PARAM:
row[i_col] = '%s' % th.get(param_name)
i_col += 1
return row

27
scenes/tab-switch.tscn Normal file
View File

@@ -0,0 +1,27 @@
[gd_scene load_steps=6 format=3 uid="uid://3slb0i3pvowc"]
[ext_resource type="Script" path="res://scenes/tab-switch.gd" id="1_qroqt"]
[ext_resource type="PackedScene" uid="uid://b276iygic5itk" path="res://scenes/работа.tscn" id="2_pdbvn"]
[ext_resource type="PackedScene" uid="uid://lwmw4egynmd1" path="res://scenes/контроль.tscn" id="3_2apbp"]
[ext_resource type="PackedScene" uid="uid://trt0q8th3bn2" path="res://scenes/журнал.tscn" id="4_yq6c0"]
[ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/ЭМС.tscn" id="5_tlyql"]
[node name="tab_switch" type="TabContainer"]
offset_right = 1600.0
offset_bottom = 1200.0
script = ExtResource("1_qroqt")
[node name="работа" parent="." instance=ExtResource("2_pdbvn")]
layout_mode = 2
[node name="контроль" parent="." instance=ExtResource("3_2apbp")]
visible = false
layout_mode = 2
[node name="журнал" parent="." instance=ExtResource("4_yq6c0")]
visible = false
layout_mode = 2
[node name="ЭМС" parent="." instance=ExtResource("5_tlyql")]
visible = false
layout_mode = 2

View File

@@ -1,29 +0,0 @@
[gd_scene load_steps=6 format=3 uid="uid://3slb0i3pvowc"]
[ext_resource type="Script" path="res://scenes/tab_switch.gd" id="1_xfqao"]
[ext_resource type="PackedScene" uid="uid://b276iygic5itk" path="res://scenes/работа.tscn" id="2_2j34i"]
[ext_resource type="PackedScene" uid="uid://lwmw4egynmd1" path="res://scenes/контроль.tscn" id="3_i7haq"]
[ext_resource type="PackedScene" uid="uid://trt0q8th3bn2" path="res://scenes/журнал.tscn" id="4_0sgfc"]
[ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/ЭМС.tscn" id="5_vpory"]
[node name="tab_switch" type="TabContainer"]
offset_right = 1600.0
offset_bottom = 1200.0
script = ExtResource("1_xfqao")
[node name="работа" parent="." instance=ExtResource("2_2j34i")]
layout_mode = 2
[node name="контроль" parent="." instance=ExtResource("3_i7haq")]
visible = false
layout_mode = 2
[node name="журнал" parent="." instance=ExtResource("4_0sgfc")]
visible = false
layout_mode = 2
[node name="ЭМС" parent="." instance=ExtResource("5_vpory")]
visible = false
layout_mode = 2
[connection signal="gui_input" from="работа" to="работа" method="_on_gui_input"]

View File

@@ -1,18 +1,18 @@
[gd_scene load_steps=9 format=3 uid="uid://dab6loryocc73"]
[ext_resource type="Script" path="res://scenes/ЭМС.gd" id="1_15kuw"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button_flat.tscn" id="2_3l661"]
[ext_resource type="Texture2D" uid="uid://dd60btbqnpiqw" path="res://data/document-new-0.png" id="3_5nv4v"]
[ext_resource type="Texture2D" uid="uid://coqg6wsftvtxr" path="res://data/document-save-0.png" id="4_nphwc"]
[ext_resource type="Texture2D" uid="uid://cywuevvpkxl7v" path="res://data/edit-copy-0.png" id="5_ulr1g"]
[ext_resource type="Texture2D" uid="uid://7h55yvh84cve" path="res://data/connect.png" id="6_kxtbd"]
[ext_resource type="Texture2D" uid="uid://cjsr544qccftu" path="res://data/disconnect.png" id="7_m7l04"]
[ext_resource type="Script" path="res://table/table.gd" id="8_dd5nu"]
[ext_resource type="Script" path="res://scenes/ЭМС.gd" id="1_7ip0t"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button-flat.tscn" id="2_85cl8"]
[ext_resource type="Texture2D" uid="uid://dd60btbqnpiqw" path="res://data/document-new-0.png" id="3_mtj4x"]
[ext_resource type="Texture2D" uid="uid://coqg6wsftvtxr" path="res://data/document-save-0.png" id="4_m4ucm"]
[ext_resource type="Texture2D" uid="uid://cywuevvpkxl7v" path="res://data/edit-copy-0.png" id="5_eeb4o"]
[ext_resource type="Texture2D" uid="uid://7h55yvh84cve" path="res://data/connect.png" id="6_kacis"]
[ext_resource type="Texture2D" uid="uid://cjsr544qccftu" path="res://data/disconnect.png" id="7_2f7bd"]
[ext_resource type="Script" path="res://table/table.gd" id="8_1mtjm"]
[node name="ЭМС" type="Panel"]
offset_right = 1598.0
offset_bottom = 1201.0
script = ExtResource("1_15kuw")
script = ExtResource("1_7ip0t")
[node name="lbl_online" type="Label" parent="."]
layout_mode = 0
@@ -23,7 +23,7 @@ offset_bottom = 30.0
theme_override_colors/font_color = Color(0, 0.647059, 0.184314, 1)
text = "Ячейка на связи"
[node name="btn_flash_read" parent="." instance=ExtResource("2_3l661")]
[node name="btn_flash_read" parent="." instance=ExtResource("2_85cl8")]
layout_mode = 0
offset_left = 1446.0
offset_top = 55.0
@@ -31,7 +31,7 @@ offset_right = 1583.0
offset_bottom = 85.0
text = "Прочитать"
[node name="btn_flash_write" parent="." instance=ExtResource("2_3l661")]
[node name="btn_flash_write" parent="." instance=ExtResource("2_85cl8")]
layout_mode = 0
offset_left = 1446.0
offset_top = 99.0
@@ -48,7 +48,7 @@ offset_bottom = 1016.0
focus_mode = 0
shortcut_feedback = false
shortcut_in_tooltip = false
icon = ExtResource("3_5nv4v")
icon = ExtResource("3_mtj4x")
[node name="btn_save" type="Button" parent="."]
layout_mode = 0
@@ -57,7 +57,7 @@ offset_top = 1017.0
offset_right = 1509.0
offset_bottom = 1073.0
focus_mode = 0
icon = ExtResource("4_nphwc")
icon = ExtResource("4_m4ucm")
[node name="btn_copy" type="Button" parent="."]
layout_mode = 0
@@ -66,7 +66,7 @@ offset_top = 1074.0
offset_right = 1510.0
offset_bottom = 1130.0
focus_mode = 0
icon = ExtResource("5_ulr1g")
icon = ExtResource("5_eeb4o")
[node name="btn_connect" type="Button" parent="."]
layout_mode = 0
@@ -76,7 +76,7 @@ offset_right = 683.0
offset_bottom = 111.0
focus_mode = 0
theme_override_colors/icon_normal_color = Color(1, 1, 1, 1)
icon = ExtResource("6_kxtbd")
icon = ExtResource("6_kacis")
[node name="btn_disconnect" type="Button" parent="."]
layout_mode = 0
@@ -86,7 +86,7 @@ offset_right = 770.0
offset_bottom = 815.0
focus_mode = 0
theme_override_colors/icon_normal_color = Color(1, 1, 1, 1)
icon = ExtResource("7_m7l04")
icon = ExtResource("7_2f7bd")
[node name="scrollin" type="ScrollContainer" parent="."]
layout_mode = 0
@@ -97,7 +97,7 @@ offset_bottom = 679.0
[node name="tbl_in" type="GridContainer" parent="scrollin"]
layout_mode = 2
script = ExtResource("8_dd5nu")
script = ExtResource("8_1mtjm")
[node name="scrl_files" type="ScrollContainer" parent="."]
layout_mode = 0
@@ -108,7 +108,7 @@ offset_bottom = 1166.0
[node name="tbl_files" type="GridContainer" parent="scrl_files"]
layout_mode = 2
script = ExtResource("8_dd5nu")
script = ExtResource("8_1mtjm")
[node name="scrollout" type="ScrollContainer" parent="."]
layout_mode = 0
@@ -119,7 +119,7 @@ offset_bottom = 679.0
[node name="tbl_out" type="GridContainer" parent="scrollout"]
layout_mode = 2
script = ExtResource("8_dd5nu")
script = ExtResource("8_1mtjm")
[node name="scrl_in_set" type="ScrollContainer" parent="."]
layout_mode = 0
@@ -130,7 +130,7 @@ offset_bottom = 942.0
[node name="tbl_in_set" type="GridContainer" parent="scrl_in_set"]
layout_mode = 2
script = ExtResource("8_dd5nu")
script = ExtResource("8_1mtjm")
[node name="scrl_out_set" type="ScrollContainer" parent="."]
layout_mode = 0
@@ -141,4 +141,4 @@ offset_bottom = 924.0
[node name="tbl_out_set" type="GridContainer" parent="scrl_out_set"]
layout_mode = 2
script = ExtResource("8_dd5nu")
script = ExtResource("8_1mtjm")

View File

@@ -3,6 +3,8 @@ extends Control
func on_line_changed(unit, addr): Log.message(Logger.INFO, 'Состояние связи: %s %s' % [unit, addr])
func on_command_fail(unit, addr): Log.message(Logger.ERROR, 'Ошибка: команда не выполнена: %s %s' % [unit, addr])
func on_threats_changed(th: Object, msg: String): Log.message(Logger.INFO, '%s: %s' % [msg, th.to_string()])
func on_parse_error(unit, msg: String): Log.message(Logger.ERROR, '%s: %s' % [unit.to_string(), msg])
func _ready() -> void:
@@ -12,10 +14,6 @@ func _ready() -> void:
Threats.connect('threat_lost', Callable(self, 'on_threats_changed').bind('Цель потеряна'))
func on_threats_changed(_threats: Dictionary, th: Object, msg: String):
Log.message(Logger.INFO, '%s: %s' % [msg, th.to_string()])
func _on_clear_button_down() -> void:
$content.clear()
Log.info('Cодержание журнала очищено оператором')

View File

@@ -26,10 +26,10 @@ var strob_dir_begin: float ## Направление антенны
var strob_width_begin: float ## Ширина строба по углу в момент начала перетаскивания
signal drag_begin ## Вызывается в момент начала перетаскивания
signal drag_continue ## Вызывается во время продолжения перетаскивания
signal drag_end ## Вызывается в момент завершения перетаскивания
signal full_screen ## Вызывается при смене режима окна полный экран - оконный
signal drag_begin ## Вызывается в момент начала перетаскивания
signal drag_continue ## Вызывается во время продолжения перетаскивания
signal drag_end ## Вызывается в момент завершения перетаскивания
signal full_screen ## Вызывается при смене режима окна полный экран - оконный
## Состояние перетаскивания
@@ -42,11 +42,10 @@ enum DragFSM {
## Переключант режим окна программы полный экран - обычный
func _on_full_screen(): toggle_full_screen(window_0_id)
func _unhandled_key_input(event: InputEvent) -> void: _on_gui_input(event)
## Обработчик сигнала изменения списка целей
func on_threats_changed(threats: Dictionary, _th): $count_all_pad/count_all.text = '%02d' % threats.size()
func on_threats_resized(threats: Dictionary): $count_all_pad/count_all.text = '%02d' % threats.size()
## Производит инициализацию
@@ -58,11 +57,10 @@ func _ready():
drag_fsm = DragFSM.OFF
var nodes: = get_tree().get_nodes_in_group('группа-режим-помехи')
nodes.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_pressed').bind(btn, nodes)))
Threats.connect('threat_lost', Callable(self, 'on_threat_lost'))
Threats.connect('threat_lost', Callable(self, 'on_threats_changed'))
Threats.connect('threat_new', Callable(self, 'on_threat_new'))
Threats.connect('threat_new', Callable(self, 'on_threats_changed'))
Threats.connect('threat_update', Callable(self, 'on_threat_update'))
Threats.connect('threat_new', Callable(self, 'on_threat_new'))
Threats.connect('threat_lost', Callable(self, 'on_threat_lost'))
Threats.connect('threats_resized', Callable(self, 'on_threats_resized'))
Threats.connect('threat_update', Callable(self, 'on_threat_update'))
## Производит отображение цели на диаграмму
@@ -78,13 +76,13 @@ func map_threat_to_bip(th: Threats.Threat, bip: Sprite2D):
## Обработчик сигнала обновления цели
func on_threat_update(_threats: Dictionary, th):
func on_threat_update(th):
var bip = get_node('%d' % th.id)
map_threat_to_bip(th, bip)
## Обработчик сигнала обнаружения цели
func on_threat_new(_threats: Dictionary, th) -> void:
func on_threat_new(th) -> void:
var bip = Bip.instantiate()
bip.name = '%d' % th.id
map_threat_to_bip(th, bip)
@@ -92,7 +90,7 @@ func on_threat_new(_threats: Dictionary, th) -> void:
## Обработчик сигнала потери цели
func on_threat_lost(_threats: Dictionary, th) -> void:
func on_threat_lost(th) -> void:
var bip = get_node('%d' % th.id)
remove_child(bip)
bip.free()
@@ -159,7 +157,8 @@ func _on_drag_begin(event) -> void:
## Обработчик событий вввода. Вызывается godot
func _on_gui_input(event):
func _input(event) -> void:
if not is_visible_in_tree(): return
if event is InputEventMouseMotion:
if drag_fsm == DragFSM.DRAG:
emit_signal('drag_continue', event)
@@ -182,8 +181,7 @@ func _on_gui_input(event):
## Переключает режим окна программы полный - обычный экран
func toggle_full_screen(id: int) -> void:
var mode = DisplayServer.window_get_mode(id)
if mode == DisplayServer.WINDOW_MODE_FULLSCREEN:
mode = DisplayServer.WINDOW_MODE_WINDOWED
else:
mode = DisplayServer.WINDOW_MODE_FULLSCREEN
mode = DisplayServer.WINDOW_MODE_WINDOWED \
if mode == DisplayServer.WINDOW_MODE_FULLSCREEN \
else DisplayServer.WINDOW_MODE_FULLSCREEN
DisplayServer.window_set_mode(mode, id)

View File

@@ -1,19 +1,18 @@
[gd_scene load_steps=10 format=3 uid="uid://b276iygic5itk"]
[ext_resource type="Script" path="res://scenes/работа.gd" id="1_6mcin"]
[ext_resource type="PackedScene" uid="uid://nl1vklubr5kr" path="res://scenes/bip.tscn" id="2_g7x8f"]
[ext_resource type="PackedScene" uid="uid://b5kjdyxuwsot5" path="res://scenes/canvas.tscn" id="3_t5hvp"]
[ext_resource type="PackedScene" uid="uid://bq7haw1ypiv48" path="res://scenes/frame.tscn" id="4_yqsbx"]
[ext_resource type="Script" path="res://scenes/scrl_threats.gd" id="5_37h17"]
[ext_resource type="Script" path="res://table/table.gd" id="6_oewxs"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button_flat.tscn" id="7_t8d0u"]
[ext_resource type="FontFile" uid="uid://befva8r034a4v" path="res://data/DSEG7Classic-Regular.ttf" id="8_j3u1o"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5ugj8"]
[ext_resource type="Script" path="res://scenes/работа.gd" id="1_g2xk6"]
[ext_resource type="PackedScene" uid="uid://nl1vklubr5kr" path="res://scenes/bip.tscn" id="2_ijbv2"]
[ext_resource type="PackedScene" uid="uid://b5kjdyxuwsot5" path="res://scenes/canvas.tscn" id="3_fppu7"]
[ext_resource type="Texture2D" uid="uid://cs6i1xwx0pmdk" path="res://data/рамка-панели.png" id="3_usoq4"]
[ext_resource type="Script" path="res://scenes/scroll-threats.gd" id="5_tr3hj"]
[ext_resource type="Script" path="res://table/table.gd" id="6_fpdpm"]
[ext_resource type="Script" path="res://scenes/scroll-params.gd" id="6_tict0"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button-flat.tscn" id="7_2sxkw"]
[ext_resource type="FontFile" uid="uid://befva8r034a4v" path="res://data/DSEG7Classic-Regular.ttf" id="8_68ssn"]
[node name="Работа" type="Panel"]
script = ExtResource("1_6mcin")
Bip = ExtResource("2_g7x8f")
script = ExtResource("1_g2xk6")
Bip = ExtResource("2_ijbv2")
col_grey = Color(0.34902, 0.643137, 0.772549, 0.168627)
col_red = Color(1, 0.568627, 0.431373, 0.239216)
drag_scale_band = 0.05
@@ -25,445 +24,152 @@ strob_min_width = 5.0
metadata/_edit_vertical_guides_ = []
metadata/_edit_lock_ = true
[node name="canvas" parent="." instance=ExtResource("3_t5hvp")]
metadata/_edit_lock_ = true
[node name="frm_threats" parent="." instance=ExtResource("4_yqsbx")]
layout_mode = 0
offset_left = 1121.0
offset_top = 6.0
offset_right = 1594.0
offset_bottom = 642.0
script = null
metadata/_edit_lock_ = true
[node name="рамка-параметры-цели" parent="frm_threats" instance=ExtResource("4_yqsbx")]
layout_mode = 0
offset_left = 5.0
offset_top = 313.0
offset_right = 465.0
offset_bottom = 632.0
text = "Параметры цели"
[node name="tbl_celi" type="GridContainer" parent="frm_threats/рамка-параметры-цели"]
[node name="grd_side" type="GridContainer" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.012
anchor_top = 0.065
anchor_right = 0.99
anchor_bottom = 0.985
offset_left = 0.212
offset_top = 5.265
offset_right = -0.0100098
offset_bottom = -0.214996
columns = 2
offset_left = 1112.0
offset_top = 6.0
offset_right = 1592.0
offset_bottom = 1169.0
[node name="hdr_col0" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
[node name="frm_threats" type="NinePatchRect" parent="grd_side"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("3_usoq4")
patch_margin_left = 15
patch_margin_top = 30
patch_margin_right = 15
patch_margin_bottom = 10
[node name="header" type="Label" parent="grd_side/frm_threats"]
clip_contents = true
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 22.0
grow_horizontal = 2
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_5ugj8")
text = "Параметр"
text = "Список целей"
horizontal_alignment = 1
vertical_alignment = 1
[node name="hdr_col1" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_5ugj8")
text = "Значение"
horizontal_alignment = 1
[node name="node_02_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Тип модуляции"
[node name="node_02_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "qam256"
horizontal_alignment = 1
[node name="node_03_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Ширина диапазона, МГц"
[node name="node_03_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "2.5"
horizontal_alignment = 1
[node name="node_04_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Мощность, дБ"
[node name="node_04_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "43"
horizontal_alignment = 1
[node name="node_05_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Время обновления"
[node name="node_05_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "20:23:04"
horizontal_alignment = 1
[node name="node_06_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Режим перестройки"
[node name="node_06_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "ЛЧМ"
horizontal_alignment = 1
[node name="node_07_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Скорость данных, бит/с"
[node name="node_07_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "1.8М"
horizontal_alignment = 1
[node name="node_08_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Протокол"
[node name="node_08_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "solo7"
horizontal_alignment = 1
[node name="node_09_00" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Высота, м"
[node name="node_09_01" type="Label" parent="frm_threats/рамка-параметры-цели/tbl_celi"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "128"
horizontal_alignment = 1
[node name="scrl_threats" type="ScrollContainer" parent="frm_threats"]
[node name="scroll" type="ScrollContainer" parent="grd_side/frm_threats"]
layout_mode = 0
offset_left = 8.0
offset_top = 57.0
offset_right = 464.0
offset_bottom = 306.0
horizontal_scroll_mode = 0
script = ExtResource("5_37h17")
offset_left = 4.0
offset_top = 51.0
offset_right = 476.0
offset_bottom = 282.0
script = ExtResource("5_tr3hj")
[node name="tbl_threats" type="GridContainer" parent="frm_threats/scrl_threats"]
[node name="table" type="GridContainer" parent="grd_side/frm_threats/scroll"]
layout_mode = 2
columns = 4
script = ExtResource("6_oewxs")
script = ExtResource("6_fpdpm")
[node name="рамка-сеансы-помех" parent="." instance=ExtResource("4_yqsbx")]
[node name="frm_params" type="NinePatchRect" parent="grd_side"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("3_usoq4")
patch_margin_left = 15
patch_margin_top = 30
patch_margin_right = 15
patch_margin_bottom = 10
[node name="header" type="Label" parent="grd_side/frm_params"]
clip_contents = true
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 22.0
grow_horizontal = 2
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "Параметры цели"
horizontal_alignment = 1
vertical_alignment = 1
[node name="scroll" type="ScrollContainer" parent="grd_side/frm_params"]
layout_mode = 0
offset_left = 1121.0
offset_top = 648.0
offset_right = 1594.0
offset_bottom = 1168.0
offset_left = 4.0
offset_top = 54.0
offset_right = 476.0
offset_bottom = 282.0
script = ExtResource("6_tict0")
[node name="table" type="GridContainer" parent="grd_side/frm_params/scroll"]
layout_mode = 2
script = ExtResource("6_fpdpm")
[node name="frm_ecm_list" type="NinePatchRect" parent="grd_side"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("3_usoq4")
patch_margin_left = 15
patch_margin_top = 30
patch_margin_right = 15
patch_margin_bottom = 10
[node name="header" type="Label" parent="grd_side/frm_ecm_list"]
clip_contents = true
layout_mode = 1
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 22.0
grow_horizontal = 2
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "Сеансы помех"
[node name="tbl_seansy" type="GridContainer" parent="рамка-сеансы-помех"]
layout_mode = 1
anchors_preset = -1
anchor_top = 0.115
anchor_bottom = 0.115
offset_left = 5.0
offset_top = -34.8
offset_right = 453.0
offset_bottom = 185.2
columns = 3
[node name="hdr_col0" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_5ugj8")
text = "Индекс сеанса"
horizontal_alignment = 1
vertical_alignment = 1
[node name="hdr_col1" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_5ugj8")
text = "Номер цели"
horizontal_alignment = 1
[node name="hdr_col2" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_5ugj8")
text = "Режим помехи"
horizontal_alignment = 1
[node name="node_00_00" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "1"
horizontal_alignment = 1
[node name="node_00_01" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "3"
horizontal_alignment = 1
[node name="node_00_02" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "СРН-И1"
horizontal_alignment = 1
[node name="node_01_00" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "2"
horizontal_alignment = 1
[node name="node_01_01" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "1"
horizontal_alignment = 1
[node name="node_01_02" type="Label" parent="рамка-сеансы-помех/tbl_seansy"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "ПД-М4С"
horizontal_alignment = 1
[node name="рамка-помеха" parent="рамка-сеансы-помех" instance=ExtResource("4_yqsbx")]
[node name="scroll" type="ScrollContainer" parent="grd_side/frm_ecm_list"]
layout_mode = 0
offset_left = 5.0
offset_top = 250.0
offset_right = 467.0
offset_bottom = 514.0
text = "Параметры помехи"
offset_left = 4.0
offset_top = 57.0
offset_right = 472.0
offset_bottom = 285.0
[node name="tbl_pomeha" type="GridContainer" parent="рамка-сеансы-помех/рамка-помеха"]
[node name="table" type="GridContainer" parent="grd_side/frm_ecm_list/scroll"]
layout_mode = 2
script = ExtResource("6_fpdpm")
[node name="frm_ecm_params" type="NinePatchRect" parent="grd_side"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("3_usoq4")
patch_margin_left = 15
patch_margin_top = 30
patch_margin_right = 15
patch_margin_bottom = 10
[node name="header" type="Label" parent="grd_side/frm_ecm_params"]
clip_contents = true
layout_mode = 1
anchors_preset = -1
anchor_left = 0.012
anchor_top = 0.065
anchor_right = 0.99
anchor_bottom = 0.985
offset_left = 0.212
offset_top = 7.775
offset_right = -0.0100098
offset_bottom = -0.0249939
columns = 2
[node name="hdr_col0" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 22.0
grow_horizontal = 2
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_5ugj8")
text = "Параметр"
text = "Параметры помехи"
horizontal_alignment = 1
vertical_alignment = 1
[node name="hdr_col1" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
[node name="scroll" type="ScrollContainer" parent="grd_side/frm_ecm_params"]
layout_mode = 0
offset_left = 4.0
offset_top = 51.0
offset_right = 476.0
offset_bottom = 282.0
[node name="table" type="GridContainer" parent="grd_side/frm_ecm_params/scroll"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_styles/normal = SubResource("StyleBoxFlat_5ugj8")
text = "Значение"
horizontal_alignment = 1
script = ExtResource("6_fpdpm")
[node name="node_00_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Индекс сеанса"
[node name="canvas" parent="." instance=ExtResource("3_fppu7")]
metadata/_edit_lock_ = true
[node name="node_00_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "1"
horizontal_alignment = 1
[node name="node_01_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Курсовой угол"
[node name="node_01_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "43"
horizontal_alignment = 1
[node name="node_02_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Частота, МГЦ"
[node name="node_02_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "2600"
horizontal_alignment = 1
[node name="node_03_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Диапазон, МГЦ"
[node name="node_03_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "80"
horizontal_alignment = 1
[node name="node_04_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Режим"
[node name="node_04_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "СРН-М2"
horizontal_alignment = 1
[node name="node_05_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Мощность"
[node name="node_05_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "2.5"
horizontal_alignment = 1
[node name="node_06_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Угол места"
[node name="node_06_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "5"
horizontal_alignment = 1
[node name="node_07_00" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "Режим перестройки"
[node name="node_07_01" type="Label" parent="рамка-сеансы-помех/рамка-помеха/tbl_pomeha"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
size_flags_horizontal = 3
theme_override_colors/font_color = Color(0.729412, 0.729412, 0.729412, 1)
text = "ЛЧМ"
horizontal_alignment = 1
[node name="btn_auto_threat" parent="." instance=ExtResource("7_t8d0u")]
[node name="btn_auto_threat" parent="." instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 912.0
offset_top = 67.0
@@ -471,7 +177,7 @@ offset_right = 1102.0
offset_bottom = 117.0
text = "Автоматически"
[node name="btn_strobe" parent="." instance=ExtResource("7_t8d0u")]
[node name="btn_strobe" parent="." instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 912.0
offset_top = 6.0
@@ -479,7 +185,7 @@ offset_right = 1102.0
offset_bottom = 56.0
text = "Строб"
[node name="btn_p5" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p5" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 1
anchors_preset = -1
offset_left = 980.0
@@ -491,20 +197,7 @@ grow_vertical = 2
text = "ОЗП-1"
metadata/rfi_name = "ozp1"
[node name="btn_p4" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
layout_mode = 1
anchors_preset = -1
offset_left = 1052.0
offset_top = 1118.0
offset_right = 1117.0
offset_bottom = 1168.0
grow_horizontal = 2
grow_vertical = 2
tooltip_text = "Выбор цели или сектора"
text = "<-"
metadata/rfi_name = "<pick>"
[node name="btn_p6" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p6" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 840.0
offset_top = 1118.0
@@ -513,7 +206,7 @@ offset_bottom = 1168.0
text = "СВ-М2"
metadata/rfi_name = "svm2"
[node name="btn_p7" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p7" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 910.0
offset_top = 1118.0
@@ -522,7 +215,7 @@ offset_bottom = 1168.0
text = "K1"
metadata/rfi_name = "k1"
[node name="btn_p8" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p8" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 770.0
offset_top = 1118.0
@@ -531,7 +224,7 @@ offset_bottom = 1168.0
text = "СВ-И1"
metadata/rfi_name = "svi1"
[node name="btn_p9" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p9" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 700.0
offset_top = 1118.0
@@ -540,7 +233,7 @@ offset_bottom = 1168.0
text = "ПД-ЧМ"
metadata/rfi_name = "pdchm"
[node name="btn_p10" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p10" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 1
anchors_preset = -1
offset_left = 630.0
@@ -552,7 +245,7 @@ grow_vertical = 2
text = "ПД-М4С"
metadata/rfi_name = "pdm4s"
[node name="btn_p11" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p11" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 350.0
offset_top = 1118.0
@@ -561,7 +254,7 @@ offset_bottom = 1168.0
text = "ЛЧМ-1"
metadata/rfi_name = "lchm1"
[node name="btn_p12" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p12" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 1
anchors_preset = -1
offset_left = 420.0
@@ -573,7 +266,7 @@ grow_vertical = 2
text = "МЧМ-1"
metadata/rfi_name = "mchm1"
[node name="btn_p13" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p13" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 1
anchors_preset = -1
offset_left = 490.0
@@ -585,7 +278,7 @@ grow_vertical = 2
text = "ПД-М2"
metadata/rfi_name = "pdm2"
[node name="btn_p14" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p14" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 1
anchors_preset = -1
offset_left = 560.0
@@ -597,7 +290,7 @@ grow_vertical = 2
text = "ПД-М4"
metadata/rfi_name = "pdm4"
[node name="btn_p15" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p15" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 1
anchors_preset = -1
offset_left = 280.0
@@ -609,7 +302,7 @@ grow_vertical = 2
text = "СРН-М2"
metadata/rfi_name = "srnm2"
[node name="btn_p16" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_p16" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 210.0
offset_top = 1118.0
@@ -618,7 +311,7 @@ offset_bottom = 1168.0
text = "СРН-И1"
metadata/rfi_name = "srni1"
[node name="btn_off" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_off" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 140.0
offset_top = 1118.0
@@ -627,7 +320,7 @@ offset_bottom = 1168.0
text = "Откл."
metadata/rfi_name = "<off>"
[node name="btn_auto_rfi" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_t8d0u")]
[node name="btn_auto_rfi" parent="." groups=["группа-режим-помехи"] instance=ExtResource("7_2sxkw")]
layout_mode = 0
offset_left = 10.0
offset_top = 1118.0
@@ -643,7 +336,7 @@ offset_left = 96.0
offset_top = 109.0
offset_right = 164.0
offset_bottom = 142.0
theme_override_fonts/font = ExtResource("8_j3u1o")
theme_override_fonts/font = ExtResource("8_68ssn")
theme_override_font_sizes/font_size = 20
text = "88"
vertical_alignment = 1
@@ -652,7 +345,7 @@ vertical_alignment = 1
layout_mode = 0
offset_right = 68.0
offset_bottom = 33.0
theme_override_fonts/font = ExtResource("8_j3u1o")
theme_override_fonts/font = ExtResource("8_68ssn")
theme_override_font_sizes/font_size = 20
text = "00"
vertical_alignment = 1
@@ -664,7 +357,7 @@ offset_left = 96.0
offset_top = 29.0
offset_right = 188.0
offset_bottom = 88.0
theme_override_fonts/font = ExtResource("8_j3u1o")
theme_override_fonts/font = ExtResource("8_68ssn")
theme_override_font_sizes/font_size = 56
text = "88"
@@ -672,7 +365,7 @@ text = "88"
layout_mode = 0
offset_right = 92.0
offset_bottom = 59.0
theme_override_fonts/font = ExtResource("8_j3u1o")
theme_override_fonts/font = ExtResource("8_68ssn")
theme_override_font_sizes/font_size = 56
text = "00"
@@ -704,4 +397,4 @@ text = "Опасных:"
[connection signal="drag_begin" from="." to="." method="_on_drag_begin"]
[connection signal="drag_continue" from="." to="." method="_on_drag_continue"]
[connection signal="full_screen" from="." to="." method="_on_full_screen" flags=3]
[connection signal="full_screen" from="." to="." method="toggle_full_screen" binds= [0]]

View File

@@ -4,15 +4,15 @@ extends NinePatchRect
@export var horizontal_alignment: HorizontalAlignment = HorizontalAlignment.HORIZONTAL_ALIGNMENT_CENTER:
get: return $header.horizontal_alignment
set(val): $header.horizontal_alignment = val
get: return $header.horizontal_alignment if is_inside_tree() else HorizontalAlignment.HORIZONTAL_ALIGNMENT_CENTER
set(val): if is_inside_tree(): $header.horizontal_alignment = val
@export var vertical_alignment: VerticalAlignment = VerticalAlignment.VERTICAL_ALIGNMENT_CENTER:
get: return $header.vertical_alignment
set(val): $header.vertical_alignment = val
get: return $header.vertical_alignment if is_inside_tree() else VerticalAlignment.VERTICAL_ALIGNMENT_CENTER
set(val): if is_inside_tree(): $header.vertical_alignment = val
@export var text: String = 'caption text':
get: return $header.text
set(val): $header.text = val
get: return $header.text if is_inside_tree() else ''
set(val): if is_inside_tree(): $header.text = val

View File

@@ -9,13 +9,13 @@ const BUFFER_SIZE = 2048 ## Размер приёмного буфера д
class CapsRpb:
signal line_changed(unit: CapsRpb) ## Сигнал состояние связи изменилось
signal data_received(unit: CapsRpb) ## Сигнал данные приняты
signal command_fail(unit: CapsRpb) ## Сигнал при не выполнении команды
signal parse_error(unit: CapsRpb, msg: String) ## Сигнал ошибки разбора сообщения
signal line_changed(unit: CapsRpb) ## Сигнал состояние связи изменилось
signal data_received(unit: CapsRpb) ## Сигнал данные приняты
signal command_fail(unit: CapsRpb) ## Сигнал при не выполнении команды
signal parse_error(unit: CapsRpb, msg: String) ## Сигнал ошибки разбора сообщения
static var json_conv: = JSON.new()
var online: = false ## Состояние на связи
var online: = false ## Состояние связи с источником сообщений
var name: String ## Имя экземпляра
var json_dic: Dictionary ## Аппарат для разбора сообщений
var tick: = 0 ## Тик время последнего обновления, мс

82
scripts/interfer.gd Normal file
View File

@@ -0,0 +1,82 @@
extends Node
## Представление помехи
## Состояние выполнения сеанса помехи
const INTERFER_STATE = {
0: 'идёт подготовка к выполнению',
1: 'выполняется',
2: 'не выполнена по причине ошибки в команде',
3: 'не выполнена по причине занятости',
4: 'не выполнена по причинееисправности' }
## Режимы помехи
const ITERFER_MODE = {
'srni1': ['СРН-И1', ['freq', 'width']],
'srnm2': ['СРН-М2', ['freq', 'width']],
'lchm1': ['ЛЧМ-1', ['freq', 'width']],
'mchm1': ['МЧМ-1', ['freq', 'width']],
'pdm2': ['ПД-М2', ['freq', 'width']],
'pdm4': ['ПД-М4', ['freq', 'width']],
'pdm4s': ['ПД-М4С', ['freq', 'width']],
'pdchm': ['ПД-ЧМ', ['freq', 'width']],
'svi1': ['СВ-И1', ['freq', 'width']],
'svm2': ['СВ-М2', ['freq', 'width']],
'k1': ['K1', ['freq', 'width', 'dur', 'period']],
'ozp1': ['ОЗП-1', ['freq', 'width']] }
## Сеанс помехи
class Interfer:
var ss: int = 0 ## Счётчик сообщений.
var ispp: int = 0 ## Индекс сеанса.
var state: = 0 ## Состояние сеанса. Ответ КАПСРПБ. Возможные значения в [param ITERFER_STATE].
var krp: String = '' ## Тип помехи. Возможные значения в [param INTERFER_MODE].
var powp: float = 0.0 ## Мощность излучения выраженная в процентах.
var kni: = 0.0 ## Курсовой угол направления излучения.
var params: = {} ## Параметры помехи.
var get: Array[String] ## Запрос массива параметров (список запрошенных параметров).
var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров.
func set_from_dic(dic: Dictionary):
var names: = Tools.get_members_names(self)
names.any(func(vn): if dic.has(vn): set(vn, dic[vn]); return false)
signal interfer_preparing(ecm: Interfer) ## Вызывается при запуске помехи
signal interfer_run(ecm: Interfer) ## Вызывается в момент начала работы помехи
signal interfer_error(ecm: Interfer, msg: String) ## Вызывается при ошибке
signal interfer_update(ecm: Interfer) ## Вызывается при обновлении помехи
signal interfer_new(ecm: Interfer) ## Вызывается при новой помехе
signal interfer_resized(ecms: Dictionary) ## Вызывается при изменении количества сеансов помех
## Производит приём состояния помех. [param unit] -> [param ecms]
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
if not unit.json_dic.has('ts'): return
if not (unit.json_dic['ts'] is int): return
if unit.json_dic['ts'] != 5: return
if not unit.json_dic.has('msvk'): return
if not (unit.json_dic['msvk'] is Array): return
var msvk = unit.json_dic['msvk']
var sz: = ecms.size()
for dic_msvk in msvk:
if not (dic_msvk is Dictionary): continue
if dic_msvk.has('ispp'):
var ispp = int(dic_msvk['ispp'])
if ecms.has(ispp):
var ecm = ecms[ispp]
ecm.set_from_dic(dic_msvk)
ecm.tick_rx = unit.tick
call_deferred('emit_signal', 'interfer_update', ecm)
else:
var ecm = Interfer.new()
ecm.set_from_dic(dic_msvk)
ecms[ispp] = ecm
ecm.tick_rx = unit.tick
call_deferred('emit_signal', 'interfer_new', ecm)
if sz != ecms.size():
call_deferred('emit_signal', 'interfer_resized', ecms)

View File

@@ -1,13 +1,15 @@
extends Node
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'jsontx': capsrpb.CapsRpb}
class Socket extends PacketPeerUDP:
func send_to(addr, data):
self.set_dest_address(addr[0], addr[1])
self.put_packet(data)
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'jsontx': capsrpb.CapsRpb}
var poll_sockets: Array[Socket]
var units: Dictionary
var sock_unicast: Socket

View File

@@ -2,9 +2,15 @@ extends Node
## Параметры
## Профили внешних устройств
## Профили внешних устройств.[br]
## [param key] - Название.[br]
## [param val[0]] - Протокол.[br]
## [param val[1]] - Адрес.[br]
## [param val[2]] - Порт.[br]
## [param val[3]] - Широковещательное.[br]
## [param val[4]] - Привязывать к адресу.[br]
## [param val[5]] - Комментарий.[br]
@export var UnitProfiles: = { \
# Название Протокол Адрес Порт Широков. Привяз. Комментарий
'уарэп-яу07-частный': ['yau07rx', '127.0.0.1', 50079, false, true, 'IP-адрес на котором принимают частные сообщения от ЯУ-07'],
'уарэп-яу07-общий': ['yau07rx', '127.0.0.255', 50000, true, true, 'IP-адрес на котором принимают широковещательные сообщения от ЯУ-07'],
'уарэп-капсрпб-пол': ['jsonrx', '127.0.0.1', 42023, false, true, 'IP-адрес на котором принимают сообщения от КАПС РПБ'],
@@ -27,12 +33,12 @@ extends Node
## Параметры цели
@export var ThreatParams = {
'radius_center': Vector2(560, 560), ## Координаты центра диаграммы в пикселях для отображения частота-пеленг
'time_lost': 5000, ## Время после последнего обновления в мс, через которое цель считается потерянной
'freq_low': 200.0, ## Нижняя рабочая частота, МГЦ
'freq_high': 6000.0, ## Нижняя рабочая частота, МГЦ
'radius_inner': 200, ## Внутренний радиус диаграммы в пикселях для отображения частота-пеленг
'radius_outter': 550 ## Наружний радиус диаграммы в пикселях для отображения частота-пеленг
'radius_center': Vector2(560, 560), ## Координаты центра диаграммы в пикселях для отображения частота-пеленг.
'time_lost': 5000, ## Время после последнего обновления в мс, через которое цель считается потерянной.
'freq_low': 200.0, ## Нижняя рабочая частота, МГЦ.
'freq_high': 6000.0, ## Верхняя рабочая частота, МГЦ.
'radius_inner': 200, ## Внутренний радиус диаграммы в пикселях для отображения частота-пеленг.
'radius_outter': 550 ## Наружний радиус диаграммы в пикселях для отображения частота-пеленг.
}

16
scripts/signaller.gd Normal file
View File

@@ -0,0 +1,16 @@
class_name Signaller extends Node
## Обмен сигналами между узлами
## Вызывается, когда оператор выбирает цель.
## [param threats] - Словарь. Ключ - идентификатор (номер) цели. Значение - цель
## [param th] - Выбранная цель [br]
signal threat_selected(threats: Dictionary, th)
## Вызывается, когда оператор снимает выбор цели.
## [param threats] - Словарь. Ключ - идентификатор (номер) цели. Значение - цель
## [param th] - Ранее выбранная цель [br]
signal threat_unselected(threats: Dictionary, th)

View File

@@ -1,6 +1,6 @@
extends Node
##
## Работа с целями
## Цель
@@ -12,6 +12,7 @@ class Threat:
var fflags: Dictionary ## Флаги достоверности полей.
var freq: float ## Частота несущей или центральная частота, МГц.
var freqm: String ## Режим смены частоты.
var id: int ## Идентификатор цели.
var lat: float ## Текущие координаты, долгота в градусах.
var lon: float ## Текущие координаты, широта в градусах.
var power: float ## Уровень принимаемого сигнала, дБм.
@@ -22,63 +23,71 @@ class Threat:
var slat: float ## Координаты старта, широта в градусах.
var slon: float ## Координаты старта, долгота в градусах.
var tick: int ## Тик время приёма сигнала, мс.
var tick_rx: int ## Тик время обновления цели, мс.
var tmod: String ## Тип модуляции.
var width: float ## Ширина занимаемого диапазона частот, МГц.
var id: int ## Идентификатор цели.
func _init(): Tools.get_members_names(self).any(func(vn): fflags[vn] = false)
func _to_string() -> String: return 'номер:%d пеленг:%0.1f частота:%0.1f МГц' % [id, aoa, freq]
func _init(): clear_fflags()
func _to_string() -> String: return '<Threat>: номер:%d пеленг:%0.1f частота:%0.1f МГц' % [id, aoa, freq]
func clear_fflags(): Tools.get_members_names(self).any(func(vn): fflags[vn] = false)
func set_from_dic(dic_vals: Dictionary):
var items: = fflags.keys().filter(func(vn): return dic_vals.has(vn))
items.any(func(vn): set(vn, dic_vals[vn]); fflags[vn] = true; return false)
func set_from_dic(dic: Dictionary):
var items: = fflags.keys().filter(func(vn): return dic.has(vn))
items.any(func(vn): set(vn, dic[vn]); fflags[vn] = true; return false)
signal threat_new(threats: Dictionary, th: Threat)
signal threat_lost(threats: Dictionary, th: Threat)
signal threat_update(threats: Dictionary, th: Threat)
var threats = {} ## Список целей. Индекс - <источник цели>:<номер цели> Источник цели может быть: 'RPB', 'SIGMA', 'RLKS', 'MP405'
signal threat_new(th: Threat)
signal threat_lost(th: Threat)
signal threat_update(th: Threat)
signal threats_resized(th: Dictionary)
func _ready() -> void:
Log.info('Модуль обработки целей готов')
var threats = {} ## Список целей. Индекс - <номер цели>
var unit_key = REPSettings.get_unit_key('уарэп-капсрпб-отп')
var unit = REPNetwork.units[unit_key]
var timer_check_lost: = Timer.new()
add_child(timer_check_lost)
unit.connect('data_received', Callable(self, 'on_data_capsrpb_received'))
timer_check_lost.connect('timeout', Callable(self, 'on_timer_check_lost').bind(REPSettings.ThreatParams.time_lost))
unit.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(threats))
timer_check_lost.connect('timeout', Callable(self, 'on_timer_check_lost').bind(REPSettings.ThreatParams.time_lost, threats))
timer_check_lost.start(REPSettings.ThreatParams.time_lost / 1000.0)
## Периодически проверяет приборы на связи
func on_timer_check_lost(time_lost: int):
## Периодически удаляет устаревшие цели
func on_timer_check_lost(time_lost: int, threats: Dictionary):
var tick = Time.get_ticks_msec()
var sz: = threats.size()
for th in threats.values():
if (tick - th.tick) >= time_lost:
if (tick - th.tick_rx) >= time_lost:
threats.erase(th.id)
emit_signal('threat_lost', threats, th)
call_deferred('emit_signal', 'threat_lost', th)
if sz != threats.size():
call_deferred('emit_signal', 'threats_resized', threats)
## Производит приём целей
func on_data_capsrpb_received(unit: capsrpb.CapsRpb):
if 'mis' not in unit.json_dic:
return
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, threats: Dictionary):
if not unit.json_dic.has('ts'): return
if unit.json_dic['ts'] != 5: return
if not unit.json_dic.has('mis'): return
var mis = unit.json_dic['mis']
var sz: = threats.size()
for dic_th in mis:
if dic_th.has('id'):
var id = int(dic_th['id'])
if threats.has(id):
var th = threats[id]
th.clear_fflags()
th.set_from_dic(dic_th)
th.tick = unit.tick
call_deferred('emit_signal', 'threat_update', threats, th)
th.tick_rx = unit.tick
call_deferred('emit_signal', 'threat_update', th)
else:
var th = Threat.new()
th.set_from_dic(dic_th)
th.tick = unit.tick
th.fflags['tick'] = true
threats[id] = th
call_deferred('emit_signal', 'threat_new', threats, th)
th.tick_rx = unit.tick
call_deferred('emit_signal', 'threat_new', th)
if sz != threats.size():
call_deferred('emit_signal', 'threats_resized', threats)

View File

@@ -73,10 +73,11 @@ func map_range(val: float, a0: float, a1: float, b0: float, b1: float) -> float:
## Возвращает true, если точка внутри заданного полигона
func is_point_in_polygon(pos: Vector2, p: PackedVector2Array) -> bool:
assert(len(p))
var j: int = len(p) - 1
var sz: = p.size()
assert(sz)
var j: int = sz - 1
var odd_nodes: int = 0
for i in len(p):
for i in sz:
if ((p[i].y < pos.y and p[j].y >= pos.y or p[j].y < pos.y and p[i].y >= pos.y) and (p[i].x <= pos.x or p[j].x <= pos.x)):
odd_nodes ^= int((p[i].x + (pos.y - p[i].y) / (p[j].y - p[i].y) * (p[j].x - p[i].x) < pos.x))
j = i
@@ -85,6 +86,6 @@ func is_point_in_polygon(pos: Vector2, p: PackedVector2Array) -> bool:
## Записывает слово [param val] в элемент байтовго массива [param buf]
## расположенный по индексу [param index]. Младшее слово
func set_wordi(buf: Array, index: int, val: int) -> void:
func set_wordi(buf: PackedByteArray, index: int, val: int) -> void:
buf[index] = val & 0xff
buf[index + 1] = (val >> 8) & 0xff

View File

@@ -2,10 +2,10 @@ extends Node
## Протокол ячейки ЯУ-07
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от ячейки, секунды
const RESEND_TIMEOUT = 0.3 ## Задержка для повторной отправки команды, секунды
const BUFFER_SIZE = 2048 ## Размер буфера для приёма датаграмм, байты
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от ячейки, мс
const RESEND_TIMEOUT = 300 ## Задержка для повторной отправки команды, мс
const RETRY_COUNT = 5 ## Количество повторных отправок
const BUFFER_SIZE = 2048 ## Размер буфера для приёма датаграмм
## Ячейка ЯУ-07
@@ -19,32 +19,32 @@ class YaU07:
## Состояние автомата выполнения команды
enum CmdState {
UNCK, ## Номер команды не ининциирован
SEND, ## Буфер готов для отправки
WAIT, ## Ожидание выполнения
DONE, ## Команда выполнена
FAIL ## Команда не выполнена
FAIL, ## Команда не выполнена
SEND, ## Буфер готов для отправки
UNCK, ## Номер команды не ининциирован
WAIT ## Ожидание выполнения
}
signal line_changed(unit: YaU07) ## Вызывается когда меняется состояние связи с ячейкой
signal command_done(unit: YaU07) ## Вызывается после выполнения команды
signal command_fail(unit: YaU07) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена
var name: = String()
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07
var cmd_num_rx: = 0 ## Номер команды принятый
var cmd_num_tx: = 0 ## Номер команды переданный
var cmd_state = CmdState.UNCK ## Состояние выполнения команды
var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07
var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду
var tick = 0.0 ## Текущее тик-время в мс
var cmd_tick_tx = 0.0 ## Время последней отправки команды
var cmd_state = CmdState.UNCK ## Состояние выполнения команды
var cmd_tick_rx = 0.0 ## Время последнего приёма команды
var status: = PackedByteArray() ## Поле "состояние прибора"
var tx_data: = [] ## Буфер отправленный
var tx_len = 0 ## Длина последнего отправленного пакета
var cmd_tick_tx = 0.0 ## Время последней отправки команды
var isa_ports = {} ## Результат выполнения команды "читать порт"
var name: = String() ## Имя
var online = false ## Состояние связи с ячейкой
var status: = PackedByteArray() ## Поле "состояние прибора"
var tick = 0.0 ## Текущее тик-время в мс
var tx_data: = PackedByteArray() ## Буфер отправленный
var tx_len = 0 ## Длина последнего отправленного пакета
func _to_string() -> String: return String('яу07: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
@@ -56,8 +56,8 @@ class YaU07:
tick = 0.0
func process(delta: float):
tick += delta
func process(t: int):
tick = t
if online and ((tick - cmd_tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
@@ -93,7 +93,7 @@ class YaU07:
var ports_count = ports_data.size()
tx_len = ports_count * 2 + 8
Tools.set_wordi(tx_data, 2, cmd_num_tx)
tx_data.encode_u16(2, cmd_num_tx)
if cmd_code == CmdCode.WRITE_ISA:
ports_count /= 2
@@ -102,21 +102,22 @@ class YaU07:
var i: = 0
for word in ports_data:
Tools.set_wordi(tx_data, 8 + i, word)
tx_data.encode_u16(8 + i, word)
i += 2
cmd_state = CmdState.SEND
return true
## Возвращает код команды ЯУ-07
## rx_data - Принятые данные
## Возвращает - Код команды не найден, 0...255 - код команды
func get_cmd_code(rx_data):
## [param rx_data] - Принятые данные[br]
## Возвращает [b]null[/b] - Если код команды не найден[br]
## Возвращает [b]0...255[/b] - Код команды
func get_cmd_code(rx_data: PackedByteArray):
var rx_data_len = rx_data.size()
if rx_data_len < 7:
return null
var status_len = Tools.ibytes_to_word(rx_data, 6) # Длина массива байтового "состояние прибора"
var status_len = rx_data.decode_u16(6) # Длина массива байтового "состояние прибора"
if rx_data_len <= (status_len + 6): # Нет поля "ответ на команду", разбор пакета завершить
return null
var cmd_code_pos = status_len + 8 # Положение в приёмном буфере "кода команды"
@@ -125,7 +126,7 @@ class YaU07:
return rx_data[cmd_code_pos] # "код команды"
func parse_isa(rx_data, status_len) -> bool:
func parse_isa(rx_data: PackedByteArray, status_len) -> bool:
var ports_count_pos = status_len + 10 # Положение в приёмном буфере количества портов
if rx_data.size() < ports_count_pos:
return false
@@ -138,11 +139,11 @@ class YaU07:
var i: = 0
while i < ports_count:
var shift: = i * 4
var isa_addr = Tools.ibytes_to_word(rx_data, addr_pos + shift) # Адрес порта ISA яу-07
var isa_data = Tools.ibytes_to_word(rx_data, data_pos + shift) # Данные порта ISA яу-07
var isa_addr = rx_data.decode_u16(addr_pos + shift) # Адрес порта ISA яу-07
var isa_data = rx_data.decode_u16(data_pos + shift) # Данные порта ISA яу-07
isa_ports[isa_addr] = isa_data
i += 1
cmd_data = rx_data.subarray(addr_pos, (addr_pos + ports_count * 4) - 1)
cmd_data = rx_data.slice(addr_pos, (addr_pos + ports_count * 4) - 1)
return i > 0
@@ -161,11 +162,11 @@ class YaU07:
if rx_data_len < 11:
return false
cmd_num_rx = Tools.ibytes_to_word(rx_data, 2)
cmd_num_rx = rx_data.decode_u16(2)
if cmd_state == CmdState.UNCK:
cmd_state = CmdState.DONE
var status_len = Tools.ibytes_to_word(rx_data, 6) # Длина массива байтового "состояние прибора"
var status_len = rx_data.decode_u16(6) # Длина массива байтового "состояние прибора"
if rx_data_len < (status_len + 6):
return false
var i: = 0

View File

@@ -1,13 +1,13 @@
extends GridContainer
class_name GDTable extends GridContainer
## Виджет "Таблица"
@export var node_gap: = Vector2(0.0, 0.0) ## Зазор между ячейками, который не возможно вычислить или получить
@export var selector_color: = Color(1.0, 1.0, 1.0, 1.0) ## Окрашивающий цвет для индикатора выбранного ряда
@export var node_gap: = Vector2(0.0, 0.0) ## Зазор между ячейками, который невозможно вычислить или получить
@export var selector_color: = Color(1.0, 1.0, 1.0, 1.0) ## Окрашивающий цвет для селектора выбранного ряда
@export var selector_key_down: Key = KEY_DOWN ## Клавиша увеличения индекса выбранного ряда
@export var selector_key_up: Key = KEY_UP ## Клавиша уменьшения индекса выбранного ряда
@export_file var node_type_file: = 'res://table/node.tscn': get = get_node_scene, set = load_node_scene ## Сцена ячейки устанавливаемая по умолчанию
@export_file var selector_type_file: = 'res://table/selector.tscn': set = load_selector_scene ## Сцена индикатора для выбранного ряда
@export_file var selector_type_file: = 'res://table/selector.tscn': set = load_selector_scene ## Сцена селектора для выбранного ряда
const HEAD_PREFIX = 'HEAD_' ## Префикс ключа заголовка таблицы
const INDEX_FORMAT = '%02d_%02d' ## Формат индекса ключа
@@ -17,7 +17,7 @@ const SLCT_PREFIX = 'SLCT_' ## Префикс ключа индикато
const HEAD_KEY_FORMAT = HEAD_PREFIX + INDEX_FORMAT ## Формат ключа заголовка
const NODE_KEY_FORMAT = NODE_PREFIX + INDEX_FORMAT ## Формат ключа ячейки
const ROW_SELECTOR_KEY_FORMAT = SLCT_PREFIX + INDEX_FORMAT ## Формат ключа индикаторов выбранного ряда
const SELECTOR_KEY_FORMAT = SLCT_PREFIX + INDEX_FORMAT ## Формат ключа индикаторов выбранного ряда
const META_USER_DATA = 'user_data' ## Имя свойства для сохранения данных пользователя
const META_CALLABLE = 'callable' ## Имя свойства для сохранения вызываемого
const META_EVENT_NAME = 'event_name' ## Имя свойства для сохранения названия события
@@ -28,7 +28,7 @@ var nodes: = {} ## Все ячейки таблицы и до
var ScnNode: PackedScene ## Прототип ячейки таблицы
var ScnSelector: PackedScene ## Прототип индикатора выбранного ряда
var selector_color_proc: Callable ## Ссылка на процедуру генератора цвета индикатора выбранного ряда
var selector_size_proc: Callable ## Ссылка на процедуру генератора размера индикатора выбранного ряда
var selector_size_proc: Callable ## Ссылка на процедуру генератора размера индикатора выбранного ряда
signal row_pressed(i_row: int) ## Вызывается при нажатии кнопкой мыши на строку
signal selected_changed(i_row: int) ## Вызывается при изменении выбранного ряда. i_row - текущий выбранный ряд
@@ -38,17 +38,17 @@ var scroll_adj: = Vector2(0, 0)
func get_node_scene(): return node_type_file
func _assert_meta(i_col: int, i_row: int, pname: String, node): assert(node.has_meta(pname), 'ошибка: нет мета-свойства \"%s\" у ячейки колонка:%d ряд:%d' % [pname, i_col, i_row])
func assert_meta(i_col: int, i_row: int, pname: String, node): assert(node.has_meta(pname), 'ошибка: нет мета-свойства \"%s\" у ячейки колонка:%d ряд:%d' % [pname, i_col, i_row])
func get_node_user_data(i_col: int, i_row: int): return get_node_meta(i_col, i_row, META_USER_DATA)
func set_node_user_data(i_col: int, i_row: int, val) -> void: set_node_meta(i_col, i_row, META_USER_DATA, val)
func defaultselector_color_proc(_i_row: int): return selector_color
## Закрепляет заголовок таблицы. [param scrl] - Прокрутка,
## [param prnt] - Родитель прокрутки заданный в редакторе
## Закрепляет заголовок таблицы. [param scrl] - Прокрутка родитель таблицы.
## [param prnt] - Родитель прокрутки.
func pin_header(scrl: ScrollContainer, prnt: Control):
scrl.remove_child(header)
prnt.add_child(header)
## TODO: Это значение следует получить из темы
var v_separation = get_theme_constant('v_separation')
header.position = scrl.position - Vector2(0, header.size.y + v_separation)
scroll = scrl
@@ -129,43 +129,45 @@ func align_to_left_bottompos(hdr: Control, gap: = Vector2(0, 0)):
position.y = hdr.position.y + hdr.size.y + gap.y
## [param i_col] - индекс колонки. [param i_row] - индекс ряда.
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func set_node_meta(i_col: int, i_row: int, pname: String, val) -> void:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
var node = nodes[key]
node.set_meta(pname, val)
## [param i_col] - индекс колонки. [param i_row] - индекс ряда.
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func get_node_meta(i_col: int, i_row: int, pname: String):
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
var node = nodes[key]
_assert_meta(i_col, i_row, pname, node)
assert_meta(i_col, i_row, pname, node)
return node.get_meta(pname)
## [param i_col] - индекс колонки. [param i_row] - индекс ряда.
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func set_node_property(i_col: int, i_row: int, pname: String, val) -> void:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
var node = nodes[key]
node.set(pname, val)
## [param i_col] - индекс колонки. [param i_row] - индекс ряда.
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func get_node_property(i_col: int, i_row: int, pname: String):
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
var node = nodes[key]
return node.get(pname)
## [param i_col] - индекс колонки. [param i_row] - индекс ряда
## Возвращает ключ для существующей ячеки. Если ячейки с заданными индексами нет,
## вызывает исключение. [param i_col] - Индекс колонки. [param i_row] - Индекс ряда
func get_node_key(format: String, i_col: int, i_row: int) -> String:
var key: String = format % [i_row, i_col]
assert(nodes.has(key), 'ошибка: нет такой ячейки - колонка:%d ряд:%d' % [i_col, i_row])
return key
##
## Возвращает массив с индексом ячейки.
## [b][0][/b] - индекс колонки, [b][1][/b] - индекс строки
func get_key_indexes(key: String) -> Array:
var tokens: = key.split('_')
assert(tokens.size() == 3, 'ошибка: неверный ключ: \"%s\"' % key)
@@ -190,6 +192,7 @@ func set_columns_aligment(alignments: Array) -> void:
##
func _input(event) -> void:
if not is_visible_in_tree(): return
if event is InputEventKey:
if event.pressed and in_focus:
if event.keycode == selector_key_up:
@@ -227,11 +230,6 @@ func check_event_pos(event_pos: Vector2, obj: Control):
and (event_pos.y < (obj.position.y + obj.size.y))
##
func defaultselector_color_proc(_i_row: int):
return selector_color
##
func setselector_color_proc(instance: Object, function: String) -> void:
selector_color_proc = Callable(instance, function)
@@ -262,7 +260,7 @@ func clear_rows_selected():
## [param i_row] - Индекс ряда.
func set_row_selected(i_row: int, selected: bool = true) -> void:
var key: = ROW_SELECTOR_KEY_FORMAT % [i_row, 0]
var key: = SELECTOR_KEY_FORMAT % [i_row, 0]
var node = nodes[NODE_KEY_FORMAT % [i_row, 0]]
if nodes.has(key) and (not selected):
var selector = nodes[key]
@@ -283,7 +281,7 @@ func set_row_selected(i_row: int, selected: bool = true) -> void:
## [param i_row] - Индекс ряда.
func is_row_selected(i_row: int) -> bool:
var key: = ROW_SELECTOR_KEY_FORMAT % [i_row, 0]
var key: = SELECTOR_KEY_FORMAT % [i_row, 0]
return nodes.has(key)
@@ -303,13 +301,13 @@ func get_rows_count() -> int:
return nodes_count / columns
##
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func get_node2(i_col: int, i_row: int) -> Node:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
return nodes[key]
##
## Добавляет ряд. [param row_types] - Массив типов ячеек ряда
func add_row(row_types: Array) -> void:
assert(row_types.size() < MAX_INDEX, 'ошибка: слишком много колонок, больше %d' % (MAX_INDEX + 1))
if columns == 1:
@@ -323,11 +321,11 @@ func add_row(row_types: Array) -> void:
var node = node_type.instantiate()
assert(node.name == node.name, 'ошибка: экземпляр не имеет поля \"name\"')
var head = nodes[HEAD_KEY_FORMAT % [0, i_col]]
node.custom_minimum_size.x = head.custom_minimum_size.x
node.set_deferred('size.x', head.size.x)
var node_key: String = NODE_KEY_FORMAT % [i_row, i_col]
node.name = node_key
add_child(node)
node.custom_minimum_size.x = head.custom_minimum_size.x
node.set_deferred('size.x', head.size.x)
nodes[node_key] = node
var conn = Callable(self, '_on_focus_entered').bind(node)
node.connect('focus_entered', conn)
@@ -350,11 +348,10 @@ func set_header(header_types: Array):
var do_adj: = false
if not header:
header = GridContainer.new()
header.position = position
header.columns = header_types.size()
header.size.x = size.x
var parent = scroll.get_parent()
parent.add_child(header)
header.position = position
header.columns = header_types.size()
do_adj = true
else:
var childrens = header.get_children()
@@ -380,9 +377,9 @@ func set_header_text(headers: Array):
set_row_text(0, headers, 0, HEAD_KEY_FORMAT)
##
## [param i_row] - индекс ряда.
func remove_row(i_row: int):
var sel_key: String = ROW_SELECTOR_KEY_FORMAT % [i_row, 0]
var sel_key: String = SELECTOR_KEY_FORMAT % [i_row, 0]
if nodes.has(sel_key):
var selector = nodes[sel_key]
@@ -442,7 +439,7 @@ func rehash():
swap_nodes(nodes_copy, NODE_KEY_FORMAT, i0, i_node[0])
next_index(i_node)
elif SLCT_PREFIX in key:
swap_nodes(nodes_copy, ROW_SELECTOR_KEY_FORMAT, i0, i_slct[0])
swap_nodes(nodes_copy, SELECTOR_KEY_FORMAT, i0, i_slct[0])
next_index(i_slct)
nodes.clear()
nodes.merge(nodes_copy)
@@ -485,7 +482,7 @@ func set_rows_text(rows: Array) -> void:
node.text = rows[i_row][i_col]
##
## [param i_row] - Индекс ряда.
func set_nodes_min_size(i_row: int, sizes: Array, key_format: String = NODE_KEY_FORMAT) -> void:
for i_col in columns:
var key: = get_node_key(key_format, i_col, i_row)
@@ -494,7 +491,7 @@ func set_nodes_min_size(i_row: int, sizes: Array, key_format: String = NODE_KEY_
node.set_deferred('size.x', sizes[i_col])
##
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func set_node_text(i_col: int, i_row: int, val: String) -> void:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
nodes[key].text = val
@@ -508,13 +505,13 @@ func set_rows_state(rows: Array) -> void:
nodes[key].button_pressed = rows[i_row][i_col]
##
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func set_node_state(i_col: int, i_row: int, val: bool) -> void:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
nodes[key].button_pressed = val
## [param i_col] - индекс колонки. [param i_row] - индекс ряда.
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func set_node_frame(i_col: int, i_row: int, node_name: String, val: int) -> void:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
var node = nodes[key]
@@ -522,13 +519,22 @@ func set_node_frame(i_col: int, i_row: int, node_name: String, val: int) -> void
sprite.frame = val
## [param i_col] - индекс колонки. [param i_row] - индекс ряда.
## Разрешает редактирование ячейки. Ячейка должна иметь свойство [param editable].
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func set_node_editable(i_col: int, i_row: int, val: bool) -> void:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
nodes[key].editable = val
## [param i_col] - индекс колонки. [param i_row] - индекс ряда.
## Разрешает редактирование ряда. Ячейки ряда должны иметь свойство [param editable].
## [param i_row] - Индекс ряда.
func set_row_editable(i_row: int, val: bool) -> void:
for i_col in columns:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
nodes[key].editable = val
## [param i_col] - Индекс колонки. [param i_row] - Индекс ряда.
func set_node_alligment(i_col: int, i_row: int, val: int) -> void:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
if 'horizontal_alignment' in nodes[key]:
@@ -537,14 +543,14 @@ func set_node_alligment(i_col: int, i_row: int, val: int) -> void:
nodes[key].alignment = val
## [param i_row] - индекс ряда.
## [param i_row] - Индекс ряда.
func set_row_alligments(i_row: int, aligns: Array) -> void:
for i_col in columns:
var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row)
nodes[key].align = aligns[i_col]
## [param i_row] - индекс ряда.
## [param i_row] - Индекс ряда.
func get_row_text(i_row: int) -> Array:
var row: = []
for i_col in columns:
@@ -553,7 +559,7 @@ func get_row_text(i_row: int) -> Array:
return row
##
## [param i_row] - Индекс ряда.
func set_row_text(i_row: int, row: Array, i_begin: int = 0, key_format: String = NODE_KEY_FORMAT) -> void:
assert(i_begin >= 0)
assert((columns - i_begin) <= row.size())