diff --git a/project.godot b/project.godot index 2bf04e0e..f6bec3a7 100644 --- a/project.godot +++ b/project.godot @@ -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" diff --git a/scenes/button_flat.tscn b/scenes/button-flat.tscn similarity index 90% rename from scenes/button_flat.tscn rename to scenes/button-flat.tscn index bafec131..997f3141 100644 --- a/scenes/button_flat.tscn +++ b/scenes/button-flat.tscn @@ -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 diff --git a/scenes/canvas.tscn b/scenes/canvas.tscn index 862fd598..ce18bb38 100644 --- a/scenes/canvas.tscn +++ b/scenes/canvas.tscn @@ -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) diff --git a/scenes/cell-front.gd b/scenes/cell-front.gd index 1da989c0..0623b7a9 100644 --- a/scenes/cell-front.gd +++ b/scenes/cell-front.gd @@ -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 diff --git a/scenes/file_table.gd b/scenes/file-table.gd similarity index 100% rename from scenes/file_table.gd rename to scenes/file-table.gd diff --git a/scenes/frame.tscn b/scenes/frame.tscn index 0c12613f..273a7ed7 100644 --- a/scenes/frame.tscn +++ b/scenes/frame.tscn @@ -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 diff --git a/scenes/scrl_threats.gd b/scenes/scrl_threats.gd deleted file mode 100644 index bb28aad9..00000000 --- a/scenes/scrl_threats.gd +++ /dev/null @@ -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 diff --git a/scenes/scroll-params.gd b/scenes/scroll-params.gd new file mode 100644 index 00000000..48bf8717 --- /dev/null +++ b/scenes/scroll-params.gd @@ -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) diff --git a/scenes/scroll-threats.gd b/scenes/scroll-threats.gd new file mode 100644 index 00000000..dbb1b2a0 --- /dev/null +++ b/scenes/scroll-threats.gd @@ -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 diff --git a/scenes/tab_switch.gd b/scenes/tab-switch.gd similarity index 100% rename from scenes/tab_switch.gd rename to scenes/tab-switch.gd diff --git a/scenes/tab-switch.tscn b/scenes/tab-switch.tscn new file mode 100644 index 00000000..2c3ccdbc --- /dev/null +++ b/scenes/tab-switch.tscn @@ -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 diff --git a/scenes/tab_switch.tscn b/scenes/tab_switch.tscn deleted file mode 100644 index 5bcb3599..00000000 --- a/scenes/tab_switch.tscn +++ /dev/null @@ -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"] diff --git a/scenes/ЭМС.tscn b/scenes/ЭМС.tscn index ebc1a909..36a7a757 100644 --- a/scenes/ЭМС.tscn +++ b/scenes/ЭМС.tscn @@ -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") diff --git a/scenes/журнал.gd b/scenes/журнал.gd index 5b9e6250..06f82333 100644 --- a/scenes/журнал.gd +++ b/scenes/журнал.gd @@ -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одержание журнала очищено оператором') diff --git a/scenes/работа.gd b/scenes/работа.gd index 19d8487a..77673878 100644 --- a/scenes/работа.gd +++ b/scenes/работа.gd @@ -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) diff --git a/scenes/работа.tscn b/scenes/работа.tscn index 0438d2e9..58212c2d 100644 --- a/scenes/работа.tscn +++ b/scenes/работа.tscn @@ -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 = "" - -[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 = "" -[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]] diff --git a/scenes/рамка.gd b/scenes/рамка.gd index 0bb06c22..f83e3a38 100644 --- a/scenes/рамка.gd +++ b/scenes/рамка.gd @@ -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 diff --git a/scripts/capsrpb.gd b/scripts/capsrpb.gd index ac3b93ab..aef472a6 100644 --- a/scripts/capsrpb.gd +++ b/scripts/capsrpb.gd @@ -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 ## Тик время последнего обновления, мс diff --git a/scripts/interfer.gd b/scripts/interfer.gd new file mode 100644 index 00000000..3ac2b4de --- /dev/null +++ b/scripts/interfer.gd @@ -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) diff --git a/scripts/repnetwork.gd b/scripts/repnetwork.gd index 4a2510be..5af32394 100644 --- a/scripts/repnetwork.gd +++ b/scripts/repnetwork.gd @@ -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 diff --git a/scripts/repsettings.gd b/scripts/repsettings.gd index c060ef81..6f4cce8c 100644 --- a/scripts/repsettings.gd +++ b/scripts/repsettings.gd @@ -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 ## Наружний радиус диаграммы в пикселях для отображения частота-пеленг. } diff --git a/scripts/signaller.gd b/scripts/signaller.gd new file mode 100644 index 00000000..670057df --- /dev/null +++ b/scripts/signaller.gd @@ -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) diff --git a/scripts/threats.gd b/scripts/threats.gd index 0353ebe1..00ac6c15 100644 --- a/scripts/threats.gd +++ b/scripts/threats.gd @@ -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 ': номер:%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) diff --git a/scripts/tools.gd b/scripts/tools.gd index 72d53f22..2df164b1 100644 --- a/scripts/tools.gd +++ b/scripts/tools.gd @@ -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 diff --git a/scripts/yau07.gd b/scripts/yau07.gd index d1ca8483..aec65d17 100644 --- a/scripts/yau07.gd +++ b/scripts/yau07.gd @@ -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 diff --git a/table/table.gd b/table/table.gd index bc82f035..bfd022db 100644 --- a/table/table.gd +++ b/table/table.gd @@ -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())