Доработка. Включение/Выключение помех. Табличка с параметрами помехи. Лог журнала событий по включению/отключению помех.

This commit is contained in:
MaD_CaT
2023-11-29 15:24:35 +03:00
parent c1a5c4cbbc
commit 5dcaef9ea6
16 changed files with 341 additions and 48 deletions

View File

@@ -26,6 +26,7 @@ config/map_image_width=512
config/map_minimum_zoom=5 config/map_minimum_zoom=5
config/map_maximum_zoom=19 config/map_maximum_zoom=19
config/map_server_addr="https://b.tile.openstreetmap.org" config/map_server_addr="https://b.tile.openstreetmap.org"
interfer/resend_timeout=1000.0
[autoload] [autoload]

View File

@@ -1,5 +1,6 @@
extends Control extends Control
var selected: bool
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
@@ -8,8 +9,16 @@ func _ready():
# Функция делает присваивает заданое значение видимости селектору # Функция делает присваивает заданое значение видимости селектору
func set_sel_visible(value: bool): func set_sel_visible(value: bool):
selected = value
$selector.visible = value $selector.visible = value
func _on_bip_pressed(): func _on_bip_gui_input(event):
signaller.emit_signal('rto_threat_sel', self) if event is InputEventMouseButton and event.pressed:
match event.button_index:
MOUSE_BUTTON_LEFT:
signaller.emit_signal('rto_threat_sel', name.to_int())
MOUSE_BUTTON_RIGHT:
if selected:
signaller.emit_signal('rto_threat_unsel', name.to_int())

View File

@@ -141,6 +141,7 @@ layout_mode = 0
offset_right = 1.0 offset_right = 1.0
offset_bottom = 1.0 offset_bottom = 1.0
scale = Vector2(20, 20) scale = Vector2(20, 20)
button_mask = 3
texture_normal = SubResource("PlaceholderTexture2D_w5pye") texture_normal = SubResource("PlaceholderTexture2D_w5pye")
stretch_mode = 3 stretch_mode = 3
@@ -165,4 +166,4 @@ position = Vector2(10, 10)
scale = Vector2(26, 26) scale = Vector2(26, 26)
texture = SubResource("PlaceholderTexture2D_svd33") texture = SubResource("PlaceholderTexture2D_svd33")
[connection signal="pressed" from="bip" to="." method="_on_bip_pressed"] [connection signal="gui_input" from="bip" to="." method="_on_bip_gui_input"]

View File

@@ -1,7 +1,8 @@
[gd_scene load_steps=3 format=3 uid="uid://b1o10yvgjpb0j"] [gd_scene load_steps=4 format=3 uid="uid://b1o10yvgjpb0j"]
[ext_resource type="Texture2D" uid="uid://cs6i1xwx0pmdk" path="res://data/рамка-панели.png" id="1_q1ow7"] [ext_resource type="Texture2D" uid="uid://cs6i1xwx0pmdk" path="res://data/рамка-панели.png" id="1_q1ow7"]
[ext_resource type="Script" path="res://table/table.gd" id="2_82yax"] [ext_resource type="Script" path="res://table/table.gd" id="2_82yax"]
[ext_resource type="Script" path="res://scenes/scroll-ecm-params.gd" id="2_sm6tk"]
[node name="frm_ecm_params" type="NinePatchRect"] [node name="frm_ecm_params" type="NinePatchRect"]
size_flags_horizontal = 3 size_flags_horizontal = 3
@@ -27,9 +28,10 @@ vertical_alignment = 1
[node name="scroll" type="ScrollContainer" parent="."] [node name="scroll" type="ScrollContainer" parent="."]
layout_mode = 0 layout_mode = 0
offset_left = 4.0 offset_left = 4.0
offset_top = 51.0 offset_top = 25.0
offset_right = 476.0 offset_right = 476.0
offset_bottom = 282.0 offset_bottom = 256.0
script = ExtResource("2_sm6tk")
[node name="table" type="GridContainer" parent="scroll"] [node name="table" type="GridContainer" parent="scroll"]
layout_mode = 2 layout_mode = 2

View File

@@ -12,7 +12,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "Откл." text = "Откл."
pressed = true disabled = true
metadata/rfi_name = "off" metadata/rfi_name = "off"
[node name="btn_auto_rfi" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_auto_rfi" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -20,6 +20,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "Автомат" text = "Автомат"
disabled = true
metadata/rfi_name = "auto" metadata/rfi_name = "auto"
[node name="btn_p12" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p12" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -27,6 +28,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "МЧМ-1" text = "МЧМ-1"
disabled = true
metadata/rfi_name = "mchm1" metadata/rfi_name = "mchm1"
[node name="btn_p16" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p16" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -34,6 +36,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "СРН-И1" text = "СРН-И1"
disabled = true
metadata/rfi_name = "srni1" metadata/rfi_name = "srni1"
[node name="btn_p15" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p15" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -41,6 +44,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "СРН-М2" text = "СРН-М2"
disabled = true
metadata/rfi_name = "srnm2" metadata/rfi_name = "srnm2"
[node name="btn_p14" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p14" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -48,6 +52,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "ПД-М4" text = "ПД-М4"
disabled = true
metadata/rfi_name = "pdm4" metadata/rfi_name = "pdm4"
[node name="btn_p13" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p13" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -55,6 +60,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "ПД-М2" text = "ПД-М2"
disabled = true
metadata/rfi_name = "pdm2" metadata/rfi_name = "pdm2"
[node name="btn_p11" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p11" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -62,6 +68,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "ЛЧМ-1" text = "ЛЧМ-1"
disabled = true
metadata/rfi_name = "lchm1" metadata/rfi_name = "lchm1"
[node name="btn_p10" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p10" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -69,6 +76,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "ПД-М4С" text = "ПД-М4С"
disabled = true
metadata/rfi_name = "pdm4s" metadata/rfi_name = "pdm4s"
[node name="btn_p9" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p9" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -76,6 +84,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "ПД-ЧМ" text = "ПД-ЧМ"
disabled = true
metadata/rfi_name = "pdchm" metadata/rfi_name = "pdchm"
[node name="btn_p8" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p8" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -83,6 +92,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "СВ-И1" text = "СВ-И1"
disabled = true
metadata/rfi_name = "svi1" metadata/rfi_name = "svi1"
[node name="btn_p7" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p7" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -90,6 +100,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "K1" text = "K1"
disabled = true
metadata/rfi_name = "k1" metadata/rfi_name = "k1"
[node name="btn_p6" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p6" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -97,6 +108,7 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "СВ-М2" text = "СВ-М2"
disabled = true
metadata/rfi_name = "svm2" metadata/rfi_name = "svm2"
[node name="btn_p5" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")] [node name="btn_p5" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -104,4 +116,5 @@ layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
text = "ОЗП-1" text = "ОЗП-1"
disabled = true
metadata/rfi_name = "ozp1" metadata/rfi_name = "ozp1"

View File

@@ -18,8 +18,13 @@ extends PanelContainer
get: return $button.get_text() get: return $button.get_text()
@export var disabled: bool = false:
set(val): $button.set_disabled(val)
get: return $button.disabled
@export var pressed: bool = false: @export var pressed: bool = false:
set(val): $button.set_pressed(val) set(val): $button.set_pressed(val)
get: return $button.is_pressed() get: return $button.is_pressed()
@@ -32,6 +37,7 @@ extends PanelContainer
func set_text(val: String): $button.set_text(val) func set_text(val: String): $button.set_text(val)
func set_pressed(val: bool): $button.set_pressed(val) func set_pressed(val: bool): $button.set_pressed(val)
func set_disabled(val: bool): $button.set_disabled(val)
func button_connect(button_signal: String, proc: Callable): $button.connect(button_signal, proc) func button_connect(button_signal: String, proc: Callable): $button.connect(button_signal, proc)
func get_text(): return $button.get_text() func get_text(): return $button.get_text()
func is_pressed(): return $button.is_pressed() func is_pressed(): return $button.is_pressed()

View File

@@ -8,7 +8,7 @@ const TableHeader = preload('res://table/header.tscn') ## Ячейка за
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader, TableHeader , TableHeader ] ## Описание ряда заголовка. const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader, TableHeader , TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit , CellLineEdit ] ## Описание ряда. const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit , CellLineEdit ] ## Описание ряда.
const TABLE_HEADERS_TEXT = ['Номер', 'Название', 'Частота, МГц', 'Пеленг', 'Состояние' ] ## Заголовки таблицы. const TABLE_HEADERS_TEXT = ['Номер', 'Название', 'Частота, МГц', 'Пеленг', 'Состояние' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 80, 120, 80, 90 ] ## Ширины колонок. const TABLE_COLUMN_SIZE = [ 65, 80, 120, 70, 100 ] ## Ширины колонок.
## Состояние выполнения сеанса помехи ## Состояние выполнения сеанса помехи
const INTERFER_STATE = { const INTERFER_STATE = {
@@ -44,10 +44,41 @@ const COLUMN_FREQ = 2
const COLUMN_AOA = 3 const COLUMN_AOA = 3
const COLUMN_STATE = 4 const COLUMN_STATE = 4
## Вызывается при нажатии указателем мыши на выбранный ряд.
func on_row_pressed(i_row: int):
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
var ecm = $table.get_node_user_data(0, i_row)
if interfer.thrs.has(ecm.ispp):
signaller.emit_signal('rto_threat_sel', interfer.thrs[ecm.ispp])
else:
signaller.emit_signal('interfer_selected', ecm)
## Вызывается при выборе цели
func on_rto_threat_sel(th_id: int, table_index):
var ecm_ispp = interfer.thrs.find_key(th_id)
var ecm = null
if ecm_ispp != null:
var i_row = table_index[int(ecm_ispp)]
ecm = $table.get_node_user_data(0, i_row)
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
else:
$table.clear_rows_selected()
signaller.emit_signal('interfer_selected', ecm)
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready(): func _ready():
var table_index: = Dictionary() var table_index: = Dictionary()
signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind(table_index)) signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind(table_index))
signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind(table_index))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(table_index))
interfer.connect('interfer_update', Callable(self, 'on_interfer_update').bind(table_index))
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
call_deferred('init_table') call_deferred('init_table')
@@ -58,6 +89,13 @@ func init_table():
$table.pin_header(self, get_parent()) $table.pin_header(self, get_parent())
func on_interfer_update(ecm, table_index):
var row = map_th_to_row(ecm)
if table_index.has(ecm.ispp):
var i_row = table_index[ecm.ispp]
$table.set_row_text(i_row, row)
func on_interfer_new(ecm, table_index): func on_interfer_new(ecm, table_index):
var row = map_th_to_row(ecm) var row = map_th_to_row(ecm)
if table_index.has(ecm.ispp): if table_index.has(ecm.ispp):
@@ -70,6 +108,25 @@ func on_interfer_new(ecm, table_index):
$table.set_row_editable(i_row, false) $table.set_row_editable(i_row, false)
$table.set_node_user_data(0, i_row, ecm) $table.set_node_user_data(0, i_row, ecm)
table_index[ecm.ispp] = i_row table_index[ecm.ispp] = i_row
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
signaller.emit_signal('interfer_selected', ecm)
func on_interfer_off(ecm, ecms, thrs, table_index):
$table.remove_row(table_index[ecm.ispp])
table_index.clear()
rehash(table_index)
ecms.erase(ecm.ispp)
thrs.erase(ecm.ispp)
## Перестраивает индекс таблицы. Вызывать при удалении строки
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
## Преобразует цель в строку таблицы ## Преобразует цель в строку таблицы
@@ -79,7 +136,7 @@ func map_th_to_row(ecm) -> Array:
row[COLUMN_NUMBER] = '%s' % ecm.ispp row[COLUMN_NUMBER] = '%s' % ecm.ispp
row[COLUMN_NAME] = '' row[COLUMN_NAME] = ''
if INTERFER_NAMES.has(ecm.krp): if INTERFER_NAMES.has(ecm.krp):
row[COLUMN_NAME] = '%s' % ecm.krp row[COLUMN_NAME] = '%s' % INTERFER_NAMES[ecm.krp]
row[COLUMN_FREQ] = '%s' % ecm.params['freq'] row[COLUMN_FREQ] = '%s' % ecm.params['freq']
row[COLUMN_AOA] = '%s' % ecm.kni row[COLUMN_AOA] = '%s' % ecm.kni
row[COLUMN_STATE] = '' row[COLUMN_STATE] = ''
@@ -87,3 +144,5 @@ func map_th_to_row(ecm) -> Array:
row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk] row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk]
return row return row
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()

View File

@@ -0,0 +1,97 @@
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 ] ## Ширины колонок.
const TABLE_PARAMS = {
'kni': [0, 'Курсовой улог, гр.', false, 0.0, 360.0],
'powp': [1, 'Мощность, %', true, 0.0, 100.0],
'freq': [2, 'Частота, МГц', true, 400.0, 6000.0],
'width': [3, 'Занимая полоса частот, МГц', true, 0.0, 120.0],
'dur': [4, 'Длительность импульса, мкс', true, 0.0, 1000000.0],
'period': [5, 'Период повтора, мкс', true, 0.0, 1000000.0] }
func init_table():
for i in TABLE_PARAMS.size(): $table.add_row(TABLE_ROW)
for key in TABLE_PARAMS.keys():
var p = TABLE_PARAMS[key]
$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_node_user_data(1, p[0], key)
$table.connect_columns(self, 'text_submitted', 'on_edit_entry', [1], [])
$table.set_columns_min_size(TABLE_COLUMN_SIZE)
$table.set_meta('id', 0)
# Called when the node enters the scene tree for the first time.
func _ready():
signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected'))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
call_deferred('init_table')
func on_edit_entry(text : String, entry):
var ecm = $table.get_meta('ecm')
if $table.has_meta('ecm') == false: return
var indexis = $table.get_key_indexes(entry[0].name)
var row_i = indexis[1]
var param = $table.get_node_user_data(1, row_i)
var p = TABLE_PARAMS[param]
var old_val = ecm.get_value(param)
var val = check_value(text, p[3], p[4], old_val)
ecm.set_value(val, param)
signaller.emit_signal('interfer_new', ecm)
func check_value(val, min_val, max_val, old_val):
if val.is_valid_float():
if float(val) < min_val: return min_val
if float(val) > max_val: return max_val
return float(val)
else: return old_val
func on_interfer_selected(ecm):
if ecm != null:
$table.set_meta('ecm', ecm)
else:
$table.set_meta('ecm', null)
on_ecm_update()
func on_ecm_update():
for item in range(len(TABLE_PARAMS)):
$table.set_node_text(1, item, '')
$table.set_node_editable(1, item, false)
if $table.has_meta('ecm') == false: return
var ecm: interfer.Interfer = $table.get_meta('ecm')
var mnms = tools.get_members_names(ecm)
for item in ecm['params'].keys():
mnms.append(item)
for member_name in mnms:
if not TABLE_PARAMS.has(member_name): continue
var p = TABLE_PARAMS[member_name]
var val = ecm.get_value(member_name)
$table.set_node_text(1, p[0], '%s' % val)
$table.set_node_editable(1, p[0], p[2])
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
func on_rto_threat_unsel(_th_id):
for item in range(len(TABLE_PARAMS)):
$table.set_node_text(1, item, '')
$table.set_node_editable(1, item, false)

View File

@@ -42,6 +42,7 @@ func init_table():
func _ready() -> void: func _ready() -> void:
signaller.connect('threat_selected', Callable(self, 'on_threat_selected')) signaller.connect('threat_selected', Callable(self, 'on_threat_selected'))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
threats.connect('threat_update', Callable(self, 'on_threat_update')) threats.connect('threat_update', Callable(self, 'on_threat_update'))
call_deferred('init_table') call_deferred('init_table')
@@ -49,6 +50,7 @@ func _ready() -> void:
## Обрабатывает сигнал [signal threats.threat_update]. ## Обрабатывает сигнал [signal threats.threat_update].
## Обновляет отображение только для выбранной цели. ## Обновляет отображение только для выбранной цели.
func on_threat_update(th): func on_threat_update(th):
if th.selected == false: return
if th.id != $table.get_meta('id'): return if th.id != $table.get_meta('id'): return
var mnms = tools.get_members_names(th) var mnms = tools.get_members_names(th)
for member_name in mnms: for member_name in mnms:
@@ -56,3 +58,8 @@ func on_threat_update(th):
var p = TABLE_PARAMS[member_name] var p = TABLE_PARAMS[member_name]
var val = th.get(member_name) var val = th.get(member_name)
$table.set_node_text(1, p[0], '%s' % val) $table.set_node_text(1, p[0], '%s' % val)
func on_rto_threat_unsel(_th_id):
for item in range(len(TABLE_PARAMS)):
$table.set_node_text(1, item, '')

View File

@@ -16,13 +16,17 @@ const TABLE_COLUMN_SIZE = [ 65, 145, 145, 90 ]
## Вызывается при нажатии указателем мыши на выбранный ряд. ## Вызывается при нажатии указателем мыши на выбранный ряд.
func on_row_pressed(i_row: int): func on_row_pressed(i_row: int):
row_pressed(i_row)
signaller.emit_signal('rto_threat_sel', $table.get_node_user_data(0, i_row).id)
func row_pressed(i_row: int):
$table.clear_rows_selected() $table.clear_rows_selected()
$table.set_row_selected(i_row, true) $table.set_row_selected(i_row, true)
var threat = $table.get_node_user_data(0, i_row) var threat = $table.get_node_user_data(0, i_row)
signaller.emit_signal('threat_selected', threat) signaller.emit_signal('threat_selected', threat)
func init_table(): func init_table():
$table.set_header(TABLE_HEADER) $table.set_header(TABLE_HEADER)
$table.set_header_text(TABLE_HEADERS_TEXT) $table.set_header_text(TABLE_HEADERS_TEXT)
@@ -36,6 +40,7 @@ func _ready() -> void:
threats.connect('threat_lost', Callable(self, 'on_threat_lost').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)) threats.connect('threat_update', Callable(self, 'on_threat_update').bind(table_index))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind($table)) signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind($table))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
$table.connect('row_pressed', Callable(self, 'on_row_pressed')) $table.connect('row_pressed', Callable(self, 'on_row_pressed'))
call_deferred('init_table') call_deferred('init_table')
@@ -85,10 +90,14 @@ func map_th_to_row(th) -> Array:
## Выделяет выбранную цель в таблице ## Выделяет выбранную цель в таблице
func on_rto_threat_sel(bip, tbl): func on_rto_threat_sel(th_id, tbl):
for i in tbl.get_rows_count(): for i in tbl.get_rows_count():
var node = tbl.get_node2(0, i) var node = tbl.get_node2(0, i)
if node.text.to_int() == bip.name.to_int(): if node.text.to_int() == th_id:
on_row_pressed(i) row_pressed(i)
break break
## Снимает выделение цели
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()

View File

@@ -5,6 +5,11 @@ func on_line_changed(unit, addr): log.message(Logger.INFO, 'Состояние
func on_command_fail(unit, addr): log.message(Logger.ERROR, 'Ошибка: команда не выполнена: %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_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 on_parse_error(unit, msg: String): log.message(Logger.ERROR, '%s: %s' % [unit.to_string(), msg])
func on_interfer_off(ecm, _ecms, _thrs,msg: String): log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()])
func on_interfer_new(ecm, msg: String):
if ecm.krp != interfer.INTERFER_OFF:
log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()])
func _enter_tree(): func _enter_tree():
@@ -20,7 +25,8 @@ func _ready() -> void:
log.info('Операционная система: %s' % [OS.get_distribution_name()]) log.info('Операционная система: %s' % [OS.get_distribution_name()])
threats.connect('threat_new', Callable(self, 'on_threats_changed').bind('Цель обнаружена')) threats.connect('threat_new', Callable(self, 'on_threats_changed').bind('Цель обнаружена'))
threats.connect('threat_lost', Callable(self, 'on_threats_changed').bind('Цель потеряна')) threats.connect('threat_lost', Callable(self, 'on_threats_changed').bind('Цель потеряна'))
signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind('Создан сеанс помехи'))
signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind('Сеанс помехи отключен'))
func _on_clear_button_down() -> void: func _on_clear_button_down() -> void:
$content.clear() $content.clear()

View File

@@ -75,7 +75,6 @@ func _ready():
$btn_zoom.set_meta('zoom', min_zoom - 1) $btn_zoom.set_meta('zoom', min_zoom - 1)
$btn_strob.button_connect('pressed', Callable(self, 'on_button_strobe_pressed')) $btn_strob.button_connect('pressed', Callable(self, 'on_button_strobe_pressed'))
$btn_view.button_connect('toggled', Callable(self, 'on_button_view_toggled')) $btn_view.button_connect('toggled', Callable(self, 'on_button_view_toggled'))
$grd_btns/btn_off.set_pressed(true)
drag_fsm = DragFSM.OFF drag_fsm = DragFSM.OFF
var nodes: Array = get_tree().get_nodes_in_group('группа-режим-помехи') var nodes: Array = get_tree().get_nodes_in_group('группа-режим-помехи')
nodes.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_pressed').bind(btn, nodes))) nodes.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_pressed').bind(btn, nodes)))
@@ -84,9 +83,10 @@ func _ready():
threats.connect('threats_resized', Callable(self, 'on_threats_resized')) threats.connect('threats_resized', Callable(self, 'on_threats_resized'))
threats.connect('threat_update', Callable(self, 'on_threat_update')) threats.connect('threat_update', Callable(self, 'on_threat_update'))
signaller.connect('zoom_complete', Callable(self, '_on_zoom_complete')) signaller.connect('zoom_complete', Callable(self, '_on_zoom_complete'))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel')) signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(nodes))
signaller.connect('threat_selected', Callable(self, 'on_threat_selected')) signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel').bind(nodes))
signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(nodes))
signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected').bind(nodes))
func on_enter_tree() -> void: func on_enter_tree() -> void:
call_deferred('_on_btn_scale_pressed') call_deferred('_on_btn_scale_pressed')
@@ -128,20 +128,31 @@ func on_threat_lost(th) -> void:
## Обработчик выбора РТО цели ## Обработчик выбора РТО цели
func on_rto_threat_sel(bip): func on_rto_threat_sel(th_id, ecm_btns):
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int()) var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for item in bips: for item in bips:
item.set_sel_visible(false) if th_id == item.name.to_int():
bip.set_sel_visible(true)
func on_threat_selected(th):
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for item in bips:
if th.id == item.name.to_int():
item.set_sel_visible(true) item.set_sel_visible(true)
else: else:
item.set_sel_visible(false) item.set_sel_visible(false)
for btn in ecm_btns:
btn.set_disabled(false)
## Обработчик снятия выбора РТО цели
func on_rto_threat_unsel(th_id, ecm_btns):
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for item in bips:
if th_id == item.name.to_int():
item.set_sel_visible(false)
break
for btn in ecm_btns:
btn.set_pressed(false)
btn.set_disabled(true)
func on_threat_selected(th, ecm_btns):
on_rto_threat_sel(th.id, ecm_btns)
## Обработчик нажатия кнопки "Строб". Управляет отображением строба ## Обработчик нажатия кнопки "Строб". Управляет отображением строба
@@ -156,6 +167,22 @@ func on_button_pressed(btn_this, btn_others) -> void:
signaller.emit_signal('interfer_init', btn_this) signaller.emit_signal('interfer_init', btn_this)
## Управляет состоянием кнопок в радиогруппе при выборе помехи
func on_interfer_selected(ecm, btns) -> void:
var ecm_name: String
if ecm != null:
ecm_name = ecm.krp
else:
ecm_name = interfer.INTERFER_OFF
for btn in btns:
btn.set_disabled(false)
btn.get_meta('rfi_name')
if ecm_name == btn.get_meta('rfi_name'):
btn.set_pressed(true)
else:
btn.set_pressed(false)
## Возвращает ширину строба по направлению ## Возвращает ширину строба по направлению
func get_strob_width(pos: Vector2, prev: float) -> float: func get_strob_width(pos: Vector2, prev: float) -> float:
var strob_dir_width: float = prev + (drag_pos_begin.y - pos.y) * drag_scale_width var strob_dir_width: float = prev + (drag_pos_begin.y - pos.y) * drag_scale_width

View File

@@ -354,6 +354,3 @@ func on_row_pressed(i_row: int, tbl):
var is_row_selected = tbl.is_row_selected(i_row) var is_row_selected = tbl.is_row_selected(i_row)
tbl.set_row_selected(i_row, not is_row_selected) tbl.set_row_selected(i_row, not is_row_selected)
func _process(_delta):
pass

View File

@@ -5,6 +5,8 @@ extends Node
## Режимы помехи ## Режимы помехи
const ITERFER_MODE = { const ITERFER_MODE = {
'off': ['Откл', ['freq', 'width']],
'auto': ['АВТО', ['freq', 'width']],
'srni1': ['СРН-И1', ['freq', 'width']], 'srni1': ['СРН-И1', ['freq', 'width']],
'srnm2': ['СРН-М2', ['freq', 'width']], 'srnm2': ['СРН-М2', ['freq', 'width']],
'lchm1': ['ЛЧМ-1', ['freq', 'width']], 'lchm1': ['ЛЧМ-1', ['freq', 'width']],
@@ -20,6 +22,7 @@ const ITERFER_MODE = {
const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей
const INTERFER_OFF = 'off' const INTERFER_OFF = 'off'
const STATE_TSMT = 5 ## Значение svk для цели, когда ответ ещё не получен
var msg_ss: int = 0 ## счётчик сообщений var msg_ss: int = 0 ## счётчик сообщений
var id_array: Array ## Массив id воздействий var id_array: Array ## Массив id воздействий
var thrs: Dictionary ## Словарь воздействия для целей, ключ - id воздействия var thrs: Dictionary ## Словарь воздействия для целей, ключ - id воздействия
@@ -36,8 +39,11 @@ class Interfer:
var params: = {} ## Параметры помехи. var params: = {} ## Параметры помехи.
var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров). var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров).
var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров. var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров.
var tick_rx: int ## Тик время обновления цели, мс. var tick_tx: int ## Тик время обновления цели, мс.
func _to_string() -> String:
return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni]
func get_msg6_data(): func get_msg6_data():
var data_to_json : Dictionary = {} var data_to_json : Dictionary = {}
data_to_json['ts'] = 6 data_to_json['ts'] = 6
@@ -57,7 +63,20 @@ class Interfer:
var names: = tools.get_members_names(self) var names: = tools.get_members_names(self)
names.any(func(vn): if dic.has(vn): set(vn, dic[vn]); return false) names.any(func(vn): if dic.has(vn): set(vn, dic[vn]); return false)
func get_value(value_key):
var param = self.get(value_key)
if param == null:
if params.has(value_key): param = params[value_key]
return param
func set_value(value, value_key):
var param = self.get(value_key)
if param == null:
params[value_key] = value
else:
self.set(value_key, value)
signal interfer_preparing(ecm: Interfer) ## Вызывается в момент запуска помехи. signal interfer_preparing(ecm: Interfer) ## Вызывается в момент запуска помехи.
signal interfer_run(ecm: Interfer) ## Вызывается в момент начала работы помехи. signal interfer_run(ecm: Interfer) ## Вызывается в момент начала работы помехи.
signal interfer_error(ecm: Interfer, msg: String) ## Вызывается при ошибке. signal interfer_error(ecm: Interfer, msg: String) ## Вызывается при ошибке.
@@ -71,9 +90,24 @@ func _ready():
id_array.append(i+1) id_array.append(i+1)
var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп') var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп')
var unit = repnetwork.units[unit_key] var unit = repnetwork.units[unit_key]
var timer_check_state: = Timer.new()
add_child(timer_check_state)
var resend_timeout = ProjectSettings.get_setting('application/interfer/resend_timeout', 1000.0)
timer_check_state.connect('timeout', Callable(self, 'on_timer_check_state').bind(unit, ecms, resend_timeout))
timer_check_state.start(resend_timeout / 1000.0)
unit.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(ecms)) unit.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(ecms))
signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit, ecms)) signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit, ecms))
signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(unit))
# Проверяет состояние отправки пакета и если не доставлен, повторяет отправку
func on_timer_check_state(unit, ecms, resend_timeout):
var tick = Time.get_ticks_msec()
for ecm in ecms.values():
if ecm.svk == STATE_TSMT:
if (tick - ecm.tick_tx) >= resend_timeout:
send_ecm(ecm, unit)
ecm.tick_tx = tick
## Производит приём состояния помех. [param unit] -> [param ecms] ## Производит приём состояния помех. [param unit] -> [param ecms]
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary): func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
@@ -91,15 +125,12 @@ func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
if ecms.has(ispp): if ecms.has(ispp):
var ecm = ecms[ispp] var ecm = ecms[ispp]
ecm.set_from_dic(dic_msvk) ecm.set_from_dic(dic_msvk)
ecm.tick_rx = unit.tick
call_deferred('emit_signal', 'interfer_update', ecm) call_deferred('emit_signal', 'interfer_update', ecm)
else: else:
var ecm = Interfer.new() var ecm = Interfer.new()
ecm.set_from_dic(dic_msvk) ecm.set_from_dic(dic_msvk)
ecm.krp = INTERFER_OFF ecm.krp = INTERFER_OFF
var json_data = ecm.get_msg6_data() send_ecm(ecm, unit)
unit.tx_stack.append(json_data)
ecm.tick_rx = unit.tick
if sz != ecms.size(): if sz != ecms.size():
call_deferred('emit_signal', 'interfer_resized', ecms) call_deferred('emit_signal', 'interfer_resized', ecms)
@@ -120,6 +151,8 @@ func on_interfer_create(btn, sel_threats, unit, ecms):
if key != null: if key != null:
ispp = key ispp = key
else: else:
if interfer_name == 'off':
return
ispp = pop_id() ispp = pop_id()
if ispp == 0: return if ispp == 0: return
msg_ss += 1 msg_ss += 1
@@ -128,18 +161,25 @@ func on_interfer_create(btn, sel_threats, unit, ecms):
ecm = ecms[ispp] ecm = ecms[ispp]
else: else:
ecm = Interfer.new() ecm = Interfer.new()
ecm.svk = 5 # Подготовка к передаче сообщения
ecm.ispp = ispp ecm.ispp = ispp
ecms[ispp] = ecm ecms[ispp] = ecm
ecm.svk = STATE_TSMT # Подготовка к передаче сообщения
ecm.ss = msg_ss ecm.ss = msg_ss
ecm.kni = kni ecm.kni = kni
ecm.krp = interfer_name ecm.krp = interfer_name
ecm.params = param ecm.params = param
ecm.powp = 100.0 # Необходимо добавить управление мощностью ecm.powp = 100.0 # Необходимо добавить управление мощностью
thrs[ispp] = item.id thrs[ispp] = item.id
var json_data = ecm.get_msg6_data()
unit.tx_stack.append(json_data)
signaller.emit_signal('interfer_new', ecm) signaller.emit_signal('interfer_new', ecm)
if interfer_name == 'off':
signaller.emit_signal('interfer_off', ecm, ecms, thrs)
push_id(ecm.ispp)
ecm.tick_tx = Time.get_ticks_msec()
func send_ecm(ecm, unit):
var json_data = ecm.get_msg6_data()
unit.tx_stack.append(json_data)
func pop_id(): func pop_id():
@@ -152,3 +192,4 @@ func pop_id():
func push_id(id : int): func push_id(id : int):
id_array.append(id) id_array.append(id)
id_array.sort()

View File

@@ -23,8 +23,13 @@ signal full_screen(id: int)
## Вызывается, когда пользователь выбирает цель ## Вызывается, когда пользователь выбирает цель
## [param bip] - Отметка цели на экране ## [param th_id] - Отметка цели на экране
signal rto_threat_sel (bip: Control) signal rto_threat_sel (th_id: int)
## Вызывается, когда пользователь снимает выделение с цели
## [param th_id] - Отметка цели на экране
signal rto_threat_unsel (th_id: int)
## Вызывается, когда пользователь выбирает помеху ## Вызывается, когда пользователь выбирает помеху
@@ -42,6 +47,17 @@ signal interfer_create (btn: PanelContainer, sel_threats: Array)
signal interfer_new (ecm: interfer.Interfer) signal interfer_new (ecm: interfer.Interfer)
## Вызывается, когда отключается действующая помеха
## [param ecm] - Новая помеха, [param ecms] - словарь помех
## [param ecms] - словарь id помех и связанных с ними целей
signal interfer_off (ecm: interfer.Interfer, ecms: Dictionary, thrs: Dictionary)
## Вызывается, когда отключается действующая помеха
## [param ecm] - Выбранная помеха
signal interfer_selected (ecm: interfer.Interfer)
## Вызывается при запросе изменения уровня детализации карты ## Вызывается при запросе изменения уровня детализации карты
## [param zoom] - Вновь установленный уровень детализации ## [param zoom] - Вновь установленный уровень детализации
signal zoom_changed(zoom: int) signal zoom_changed(zoom: int)

View File

@@ -29,7 +29,7 @@ class Threat:
var selected: bool ## Флаг, что цель выбрана var selected: bool ## Флаг, что цель выбрана
func _init(): clear_fflags() func _init(): clear_fflags()
func _to_string() -> String: return '<Threat>: номер:%d пеленг:%0.1f частота:%0.1f МГц' % [id, aoa, freq] func _to_string() -> String: return 'номер: %d пеленг: %0.1f частота: %0.1f МГц' % [id, aoa, freq]
func clear_fflags(): tools.get_members_names(self).any(func(vn): fflags[vn] = false) func clear_fflags(): tools.get_members_names(self).any(func(vn): fflags[vn] = false)
func set_from_dic(dic: Dictionary): func set_from_dic(dic: Dictionary):
@@ -54,6 +54,7 @@ func _ready() -> void:
timer_check_lost.connect('timeout', Callable(self, 'on_timer_check_lost').bind(repsettings.ThreatParams.time_lost, 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) timer_check_lost.start(repsettings.ThreatParams.time_lost / 1000.0)
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(threats)) signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(threats))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel').bind(threats))
signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(threats)) signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(threats))
signaller.connect('interfer_init', Callable(self, 'on_interfer_init').bind(threats)) signaller.connect('interfer_init', Callable(self, 'on_interfer_init').bind(threats))
@@ -69,11 +70,12 @@ func on_timer_check_lost(time_lost: int, threats: Dictionary):
call_deferred('emit_signal', 'threats_resized', threats) call_deferred('emit_signal', 'threats_resized', threats)
## Снимает выделение с цели, если нажать по отметке цели.
func on_rto_threat_unsel(th_id, threats): threats[th_id].selected = false
## Выбирает цель, если нажать по отметке цели. ## Выбирает цель, если нажать по отметке цели.
func on_rto_threat_sel(bip, threats): func on_rto_threat_sel(th_id, threats): on_threat_selected(threats[th_id], threats)
for threat in threats.values():
threat.selected = false
threats[bip.name.to_int()].selected = true
## Выбирает цель, если выбрать в таблице ## Выбирает цель, если выбрать в таблице