From 9ba277a84ed8e0f22443103513966e3f5af98b6c Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 11 Sep 2025 16:25:35 +0300 Subject: [PATCH 001/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20"=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C".=20=D0=9E=D1=82?= =?UTF-8?q?=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D1=8F=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D1=81=D0=B2=D1=8F=D0=B7=D0=B8=20=D0=B4=D0=BB=D1=8F=20TCP=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp-1.tscn | 1 + scenes/pribor-afsp/pribor-afsp-2.tscn | 1 + scenes/pribor-afsp/pribor-afsp.gd | 18 ++++++++++++++++++ scenes/контроль/контроль.tscn | 7 ++++++- scripts/network.gd | 5 +++++ scripts/settings.gd | 5 +++++ 6 files changed, 36 insertions(+), 1 deletion(-) diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn index 4ae55a58..81a5e01b 100644 --- a/scenes/pribor-afsp/pribor-afsp-1.tscn +++ b/scenes/pribor-afsp/pribor-afsp-1.tscn @@ -19,6 +19,7 @@ offset_right = 70.0 offset_bottom = 30.0 scale = Vector2(1, 0.9) script = ExtResource("1_151rh") +unit_name = &"уарэп-афсп-левый" metadata/DeviceName = &"Устройство РР левого борта" [node name="request" type="HTTPRequest" parent="."] diff --git a/scenes/pribor-afsp/pribor-afsp-2.tscn b/scenes/pribor-afsp/pribor-afsp-2.tscn index 9d8b4cc7..2f252167 100644 --- a/scenes/pribor-afsp/pribor-afsp-2.tscn +++ b/scenes/pribor-afsp/pribor-afsp-2.tscn @@ -19,6 +19,7 @@ offset_right = 81.0 offset_bottom = 108.0 scale = Vector2(1, 0.9) script = ExtResource("1_tfses") +unit_name = &"уарэп-афсп-правый" metadata/DeviceName = &"Устройство РР правого борта" [node name="request" type="HTTPRequest" parent="."] diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index 319ed927..046059bd 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -2,25 +2,39 @@ class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd' @export var prefix_path: String = 'DeviceDescripton[DeviceName]' +@export var unit_name: StringName= '' static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') + func _on_request_completed(result, _response_code, headers, body: PackedByteArray): + + var unit_instance = network.get_unit_instance(unit_name) + if result != 0: var rs = $request.get_result_string(result) log.error('\"%s\"' % rs) + if unit_instance.online: + unit_instance.online = false + unit_instance.emit_signal('line_changed', unit_instance) return var json_str: String = body.get_string_from_utf8() if not json_str: push_error('не удаётся получить строку utf8 из данных (%s)' % headers) + if unit_instance.online: + unit_instance.online = false + unit_instance.emit_signal('line_changed', unit_instance) return var rc = json_conv.parse(json_str) if rc != Error.OK: var err = json_conv.get_error_message() push_error('разбор json прерван - \"%s\" (%s)' % [err, headers]) + if unit_instance.online: + unit_instance.online = false + unit_instance.emit_signal('line_changed', unit_instance) return var pp = [] @@ -38,6 +52,10 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra if this_afsp_name != received_afsp_name: return + if not unit_instance.online: + unit_instance.online = true + unit_instance.emit_signal('line_changed', unit_instance) + for child in $bort.get_node('konverter/grid').get_children(): node_maper.map_value_to_item(json_conv.data, child, 'value0') node_maper.map_value_to_item(json_conv.data, child, 'value1') diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index b62b8584..b646187e 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -45,6 +45,9 @@ const PRIBORS_RES = \\ } +const null_units_names = ['уарэп-афсп-левый', 'уарэп-афсп-правый'] + + func on_line_changed(u, conn_node, _pribor_meta): conn_node.set_val(u.online) @@ -65,7 +68,9 @@ func _ready(): for i in pribor_meta.size(): var unit_pribor = network.get_unit_instance(pribor_meta[i]) unit_pribor.connect('line_changed', Callable(self, pribor_proc).bind(conn_node, pribor_meta)) - + for unit_name in null_units_names: + var unit_instance = network.get_unit_instance(unit_name) + unit_instance.connect('line_changed', on_line_changed) func online_change_arr(_u, conn_node, pribor_meta): var state_online = true diff --git a/scripts/network.gd b/scripts/network.gd index 31f19575..ad04ee30 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -6,6 +6,7 @@ const TCP_PROTO: = {'5p28': tcp5p28.TCP5P28} const SERIAL_PROTO: = {'spt25': spt25.SPT25} const MODBUS_PROTO: = {'mbcs': sch3.Sch3} const NAVI_PROTO: = {'navi': navi.NaviSource} +const NULL_PROTO: = {null: unit.Unit} var tick: int = 0 @@ -272,6 +273,10 @@ func _ready() -> void: serials[unit_name] = serial bind_serials.append([serial, unit_serial, unit_name]) + if proto in NULL_PROTO: + var unit_null = NULL_PROTO[proto].new(unit_name) + units[unit_name] = unit_null + ProjectSettings.connect('settings_changed', Callable(self, '_on_settings_changed_serial').bind(bind_serials)) tcp_sockets.append([create_socket_tcp('уарэп-5п28'), units_tcp['уарэп-5п28']]) diff --git a/scripts/settings.gd b/scripts/settings.gd index 2ac22b72..1c47f91a 100644 --- a/scripts/settings.gd +++ b/scripts/settings.gd @@ -35,6 +35,11 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ # < Название: Протокол, < Имя порта, Адрес СПТ-25, Скорость, Чётность, Бит на символ, Стоп битов >, Комментарий > 'уарэп-спт25-1': ['spt25', ['/dev/ttyUSB1', 0, 19200, 'N', 8, 1], 'Прибор СПТ-25 (G1)'], 'уарэп-спт25-2': ['spt25', ['/dev/ttyUSB2', 0, 19200, 'N', 8, 1], 'Прибор СПТ-25 (G2)'], + 'уарэп-афсп-левый': [null, [], 'Прибор АФСП левого борта'], + 'уарэп-афсп-правый': [null, [], 'Прибор АФСП правого борта'], + 'уарэп-бпо-1': [null, [], 'Прибор БПО 1'], + 'уарэп-бпо-2': [null, [], 'Прибор БПО 2'], + 'уарэп-карта': [null, [], 'Сервер карты'], } ## Параметры цели. From aca8eb7ee4e28a7588015faf5e42e340c990b529 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 11 Sep 2025 16:26:12 +0300 Subject: [PATCH 002/117] =?UTF-8?q?=D0=A7=D0=B8=D1=81=D1=82=D0=BA=D0=B0.?= =?UTF-8?q?=20=D0=9F=D0=BE=D0=BA=D0=B0=20=D0=BD=D0=B5=20=D0=BD=D1=83=D0=B6?= =?UTF-8?q?=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 4 ++-- scripts/spt25.gd | 28 +--------------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/scripts/network.gd b/scripts/network.gd index ad04ee30..3f1f11f2 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -27,7 +27,7 @@ class SocketSerial extends SerialPort: tx_buffer.resize(256) func send_to(data: PackedByteArray): - tx_buffer[0] = 0x7e + """tx_buffer[0] = 0x7e var i: = 1 for v in data: if v != 0x7e: @@ -42,7 +42,7 @@ class SocketSerial extends SerialPort: tx_buffer.encode_u16(i, v_sum) i += 2 tx_buffer[i] = FLAG - i += 1 + i += 1""" # Эта последовательность для запроса состояния, получена от разработчиков СПТ-25 const tx_tula = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] write_raw(tx_tula) diff --git a/scripts/spt25.gd b/scripts/spt25.gd index 5e826f29..06639a6c 100644 --- a/scripts/spt25.gd +++ b/scripts/spt25.gd @@ -13,35 +13,9 @@ class SPT25 extends unit.Unit: func _to_string() -> String: return String('СПТ-25 %s %s' % [self.name, ['отключен', 'на связи'][int(online)]]) - ##Вычисление контрольной суммы - func sciCalcFCS(src: PackedByteArray) -> int: - var P_DIV = 0 - var ln = src[0] - var FCS = ~((src[2]<<8) + src[1]) - for i in range(3, ln): - var C = src[i] - for j in 8: - if C & 1: - if FCS & 1: - FCS = ((FCS >> 1) | 0x8000)^P_DIV - else: - FCS = ((FCS >> 1) | 0x8000) - else: - if FCS & 1: - FCS = (FCS >> 1) ^ P_DIV - else: - FCS = FCS >> 1 - C >>= 1 - for j in 16: - if FCS & 1: - FCS = (FCS >> 1) ^ P_DIV - else: - FCS = FCS >> 1 - return ~FCS - func _init(nm) -> void: self.name = nm - tx_data.resize(5) + tx_data.resize(6) tx_data[0] = 0 # Адрес абонента, которому предназначен пакет tx_data[1] = CmdCode.INFO # Тип пакета, КОД КОМАНДЫ - Получить информацию о состоянии преобразователя tx_data[2] = 0 # Данные From b2633d80634cf0a6ffd5ecdb0b5ae08c045ee1c3 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 11 Sep 2025 16:26:39 +0300 Subject: [PATCH 003/117] Godot4.4 --- scenes/работа/работа.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 64b1bbd5..6d645182 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -305,6 +305,6 @@ text = "Масштаб:" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] From 3203f9cd20bdd4859be069cce8e7a05b4010dbae Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 18 Sep 2025 23:24:42 +0300 Subject: [PATCH 004/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 40 ++++++++++++------------- scripts/capsrpb.gd | 2 +- scripts/interfer.gd | 65 +++++++++++++++++++++++++---------------- 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 242edf4b..1871639e 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -120,26 +120,26 @@ func _ready(): btns_select.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_select').bind(btn, btns_select))) 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))) - 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')) - signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(nodes)) - signaller.connect('bip_pressed', Callable(self, 'on_bip_pressed').bind(nodes)) - 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)) - signaller.connect('interfer_new', Callable(self, 'on_interfer_new')) - signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all')) - signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno').bind(nodes)) - signaller.connect('fs_selected', Callable(self, 'on_fs_selected')) - signaller.connect('fs_update_color', Callable(self, 'on_fs_update_color')) - interfer.connect('interfer_update', Callable(self, 'on_interfer_new')) - signaller.connect('interfer_prinuditelno', Callable(self, 'on_chk_interfer_prinuditelno')) - signaller.connect('fs_update_state', Callable(self, 'on_fs_update_state')) - signaller.connect('map_user_panning', Callable(self, 'on_user_panning')) + 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')) + signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(nodes)) + signaller.connect('bip_pressed', Callable(self, 'on_bip_pressed').bind(nodes)) + 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)) + signaller.connect('interfer_new', Callable(self, 'on_interfer_new')) + signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all')) + signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno').bind(nodes)) + signaller.connect('fs_selected', Callable(self, 'on_fs_selected')) + signaller.connect('fs_update_color', Callable(self, 'on_fs_update_color')) + interfer.connect('interfer_update', Callable(self, 'on_interfer_new')) + signaller.connect('interfer_prinuditelno', Callable(self, 'on_chk_interfer_prinuditelno')) + signaller.connect('fs_update_state', Callable(self, 'on_fs_update_state')) + signaller.connect('map_user_panning', Callable(self, 'on_user_panning')) signaller.connect('update_coordinates_map', Callable(self, 'on_update_coordinates_label')) - signaller.connect('update_scale_map', Callable(self, 'on_update_scale_label')) + signaller.connect('update_scale_map', Callable(self, 'on_update_scale_label')) on_btn_center_toggled(true) on_btn_activate_toggled(true) @@ -176,7 +176,7 @@ func map_threat_to_bip(th: threats.Threat, bip: Control): if freq_range[0] <= freq and freq <= freq_range[1]: sector_key = key break - if sector_key!= null: + if sector_key != null: radius_internal = fs_band[sector_key][0] radius_outter = fs_band[sector_key][1] freq_low = prd.FS_FREQ[sector_key][0] diff --git a/scripts/capsrpb.gd b/scripts/capsrpb.gd index d889997d..6a56699e 100644 --- a/scripts/capsrpb.gd +++ b/scripts/capsrpb.gd @@ -17,7 +17,7 @@ class CapsRpb extends unit.Unit: var source_addr: Array ## Адрес отправителя данных func _to_string() -> String: return String('CapsRpb(\"%s\")' % self.name) - func _init(nm): self.name = nm + func _init(unit_name): self.name = unit_name func parse(data: PackedByteArray, now_tick: int): tick = now_tick diff --git a/scripts/interfer.gd b/scripts/interfer.gd index b7d68810..8bcb6369 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -207,15 +207,15 @@ func on_nav_data_received(coords: Dictionary, unit_caps): ## Проверяет состояние отправки пакета и если не доставлен, повторяет отправку. -func on_timer_check_state(unit, ecms, resend_timeout) -> void: +func on_timer_check_state(unit_instance, ecms, resend_timeout) -> void: var tick = Time.get_ticks_msec() for ecm in ecms.values(): if (tick - ecm.tick_tx) >= resend_timeout: - send_ecm(ecm, unit) + send_ecm(ecm, unit_instance) ecm.tick_tx = tick -func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit) -> void: +func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit_instance) -> void: for thr in threats.values(): var th_id = thr.id for ecm_i in thrs.keys(): @@ -223,7 +223,7 @@ func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit) -> void: var ecm = ecms[ecm_i] ecm.params['freq'] = thr.freq ecm.kni = thr.aoa - send_ecm(ecm, unit) + send_ecm(ecm, unit_instance) signaller.emit_signal('fs_update_color', ecms) prd.update_fs_state(ecms) @@ -238,29 +238,44 @@ func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit) -> void: ## Производит приём состояния помех. [param unit] -> [param ecms]. -func on_data_capsrpb_received(unit0: capsrpb.CapsRpb, ecms: Dictionary) -> void: - if not unit0.json_dic.has('ts'): return - if not (unit0.json_dic['ts'] is float): return - if unit0.json_dic['ts'] != 5: return - if not unit0.json_dic.has('msvk'): return - if not (unit0.json_dic['msvk'] is Array): return - var msvk = unit0.json_dic['msvk'] +func on_data_capsrpb_received(unit_instance: capsrpb.CapsRpb, ecms: Dictionary) -> void: + if not unit_instance.json_dic.has('ts'): return + if not (unit_instance.json_dic['ts'] is float): return + if unit_instance.json_dic['ts'] != 5: return + map_msvk_to_ecms(unit_instance, ecms) + map_mpchf_to_view(unit_instance) + + +## Извлекает массив состояний выполнения команды +func map_msvk_to_ecms(unit_instance: unit.Unit, ecms: Dictionary): + var json_dic = unit_instance.json_dic + if not json_dic.has('msvk'): return + var msvk = unit_instance.json_dic['msvk'] + if msvk is not Array: return for dic_msvk in msvk: if not (dic_msvk is Dictionary): continue - if dic_msvk.has('ispp'): - var ispp = int(dic_msvk['ispp']) - var errmsg = dic_msvk.get('errmsg', '') - if errmsg: - log.error('сеанс %d: \"%s\"' % [ispp, errmsg]) - if ecms.has(ispp): - var ecm = ecms[ispp] - ecm.set_from_dic(dic_msvk) - call_deferred('emit_signal', 'interfer_update', ecm) - else: - var ecm = Interfer.new() - ecm.set_from_dic(dic_msvk) - ecm.krp = INTERFER_OFF - send_ecm(ecm, unit0) + if not dic_msvk.has('ispp'): continue + var ispp = int(dic_msvk['ispp']) + var errmsg = dic_msvk.get('errmsg', '') + if errmsg: + log.error('сеанс %d: \"%s\"' % [ispp, errmsg]) + if ecms.has(ispp): + var ecm = ecms[ispp] + ecm.set_from_dic(dic_msvk) + call_deferred('emit_signal', 'interfer_update', ecm) + else: + var ecm = Interfer.new() + ecm.set_from_dic(dic_msvk) + ecm.krp = INTERFER_OFF + send_ecm(ecm, unit_instance) + + +## Извлекает массив пространственно-частотных фильтров +func map_mpchf_to_view(unit_instance: unit.Unit): + var json_dic = unit_instance.json_dic + if not json_dic.has('mpchf'): return + var mpchf = json_dic['mpchf'] + if mpchf is not Array: return ## Вызыватся, когда пользователь выбрал помеху и выбраны цели. From 9ddb0c5c32b2cbc15857d589b24275b4221467f7 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 18 Sep 2025 23:28:20 +0300 Subject: [PATCH 005/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=A1=D0=9F=D0=A2-25?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 77 +++++++++++++++++++++++----------------------- scripts/spt25.gd | 13 +++----- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/scripts/network.gd b/scripts/network.gd index 3f1f11f2..9e4d8fdf 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -20,31 +20,43 @@ class SocketSerial extends SerialPort: 'N': SerialPort.PARITY_NONE, 'E': SerialPort.PARITY_EVEN, 'O': SerialPort.PARITY_ODD } + static var tick: int - var tx_buffer: PackedByteArray + func on_serial_data(data: PackedByteArray, unit_instance: unit.Unit): + unit_instance.parse(data, tick) - func _init() -> void: - tx_buffer.resize(256) + func on_settings_changed(unit_instance: unit.Unit): + var external_ctl = ProjectSettings.get_setting('application/config/Внешнее управление', false) + try_close() + if external_ctl: + return + var rc = try_open(on_serial_data.bind(unit_instance)) + if rc != Error.OK: + log.message(log.ERROR, 'невозможно открыть %s для \"%s\"' % [self, unit_instance.name]) + else: + log.message(log.INFO, '%s для \"%s\"' % [self, unit_instance.name]) - func send_to(data: PackedByteArray): - """tx_buffer[0] = 0x7e + func format_buffer(data: PackedByteArray): + var buffer: PackedByteArray + buffer.resize(64) var i: = 1 for v in data: if v != 0x7e: - tx_buffer[i] = v - i += 1 + buffer[i] = v; i += 1 else: - tx_buffer[i] = FLAG - i += 1 - tx_buffer[i] = FLAG ^ FLAG_MASK - i += 1 + buffer[i] = FLAG; i += 1 + buffer[i] = FLAG ^ FLAG_MASK; i += 1 var v_sum: = get_check_sum(data) - tx_buffer.encode_u16(i, v_sum) - i += 2 - tx_buffer[i] = FLAG - i += 1""" + buffer.encode_u16(i, v_sum); i += 2 + buffer[i] = FLAG; i += 1 + buffer.resize(i) + return buffer + + func send_to(data: PackedByteArray): + if not is_open(): return + # var buffer = format_buffer(data) # Не проверено, но должно работать # Эта последовательность для запроса состояния, получена от разработчиков СПТ-25 - const tx_tula = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] + const tx_tula: = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] write_raw(tx_tula) func _to_string() -> String: return 'последовательный порт \"%s\" @ %d (%s)' % [self.port, self.baudrate, 'открыт' if is_open() else 'закрыт'] @@ -129,9 +141,6 @@ var send_sockets: Dictionary[StringName, SocketUDP] ## Таблица <имя var addr_port_to_unit_name: Dictionary[StringName, StringName] ## Преобразование адрес:порт в имя устройства -func on_serial_data(data, unit): unit.parse(data, tick) - - ## [param unit_name] - Уникальное имя устройства[br] func create_socket_udp(unit_name: StringName) -> SocketUDP: var st = settings.UnitProfiles[unit_name][1] @@ -192,6 +201,10 @@ func create_serial(unit_name: StringName) -> SocketSerial: return serial +func on_serial_got_error(where: String, what: String, serial: SocketSerial, unit_instance: unit.Unit): + push_error([where, what, serial]) + + ## [param unit_name] - Уникальное имя устройства[br] func create_modbus(unit_name: StringName) -> sch_3.Sch3: var unit_modbus: = sch_3.Sch3.new(unit_name) @@ -266,18 +279,19 @@ func _ready() -> void: bind_modbuses.append([unit_modbus, unit_name]) if proto in SERIAL_PROTO: - var unit_serial = SERIAL_PROTO[proto].new(unit_name) + var unit_instance = SERIAL_PROTO[proto].new(unit_name) var serial: = create_serial(unit_name) - units_serial[unit_name] = unit_serial - units[unit_name] = unit_serial + serial.connect('got_error', on_serial_got_error.bind(serial, unit_instance)) + ProjectSettings.connect('settings_changed', serial.on_settings_changed.bind(unit_instance)) + units_serial[unit_name] = unit_instance + units[unit_name] = unit_instance serials[unit_name] = serial - bind_serials.append([serial, unit_serial, unit_name]) + bind_serials.append([serial, unit_instance, unit_name]) if proto in NULL_PROTO: var unit_null = NULL_PROTO[proto].new(unit_name) units[unit_name] = unit_null - ProjectSettings.connect('settings_changed', Callable(self, '_on_settings_changed_serial').bind(bind_serials)) tcp_sockets.append([create_socket_tcp('уарэп-5п28'), units_tcp['уарэп-5п28']]) for key: StringName in dst_ports: @@ -296,21 +310,6 @@ func _on_settings_changed_modbus(bind_modbuses: Array): var _unit_name = bm[1] -func _on_settings_changed_serial(bind_serials: Array): - var external_ctl = ProjectSettings.get_setting('application/config/Внешнее управление', false) - for bs in bind_serials: - var serial = bs[0] - var unit_serial = bs[1] - var unit_name = bs[2] - serial.try_close() - if not external_ctl: - var rc = serial.try_open(on_serial_data.bind(unit_serial)) - if rc != Error.OK: - log.message(log.ERROR, 'невозможно открыть %s для \"%s\"' % [serial, unit_name]) - else: - log.message(log.INFO, '%s для \"%s\"' % [serial, unit_name]) - - func poll_receive_udp(sock: SocketUDP) -> bool: while sock.get_available_packet_count() > 0: var data: = sock.get_packet() diff --git a/scripts/spt25.gd b/scripts/spt25.gd index 06639a6c..9bc9f601 100644 --- a/scripts/spt25.gd +++ b/scripts/spt25.gd @@ -13,14 +13,11 @@ class SPT25 extends unit.Unit: func _to_string() -> String: return String('СПТ-25 %s %s' % [self.name, ['отключен', 'на связи'][int(online)]]) - func _init(nm) -> void: - self.name = nm - tx_data.resize(6) - tx_data[0] = 0 # Адрес абонента, которому предназначен пакет - tx_data[1] = CmdCode.INFO # Тип пакета, КОД КОМАНДЫ - Получить информацию о состоянии преобразователя - tx_data[2] = 0 # Данные - tx_data[3] = 0 # Данные - tx_data[4] = 0 # Данные + func _init(unit_name) -> void: + self.name = unit_name + tx_data.resize(2) + tx_data[0] = 0 # Адрес абонента, которому предназначен пакет + tx_data[1] = CmdCode.INFO # Тип пакета, КОД КОМАНДЫ - Получить информацию о состоянии преобразователя func parse(rx_data: PackedByteArray, tick: int): From 854e2e8f46e4379edd351edfa48e32ef3a505939 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 18 Sep 2025 23:31:20 +0300 Subject: [PATCH 006/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9E=D1=82=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BA=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B3=D1=80=D0=B0=D0=BC=D0=BC=D1=8B=20=D0=B2?= =?UTF-8?q?=D0=BE=20=D0=B2=D1=80=D0=B5=D0=BC=D1=8F=20=D0=BE=D1=82=D0=BB?= =?UTF-8?q?=D0=B0=D0=B4=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.godot | 1 + 1 file changed, 1 insertion(+) diff --git a/project.godot b/project.godot index 5a6acf44..fdb5e122 100644 --- a/project.godot +++ b/project.godot @@ -84,6 +84,7 @@ window/size/viewport_height=1200 window/size/window_width_override=1024 window/size/window_height_override=768 window/subwindows/embed_subwindows=false +window/frame_pacing/android/enable_frame_pacing=false window/stretch/mode="canvas_items" window/dpi/allow_hidpi=false From 938b4d663a4e5af03068a904893feab4b0561047 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 18 Sep 2025 23:32:08 +0300 Subject: [PATCH 007/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=B7=D0=B0=D0=B3=D0=BB=D1=83=D1=88=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20"=D0=A2=D1=80=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D0=B0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/trassa.gd | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/trassa.gd b/scripts/trassa.gd index faee6834..b203716e 100644 --- a/scripts/trassa.gd +++ b/scripts/trassa.gd @@ -1,13 +1,21 @@ class_name trassa_unit extends Node +const ONLINE_TIMEOUT: = 5000 class Trassa extends unit.Unit: var source_addr: = [] func process(tick: int): + if (tick - rx_tick) > ONLINE_TIMEOUT: + if online: + online = false + emit_signal('line_changed', self) return Error.ERR_BUSY func _init(unit_name: StringName): self.name = unit_name - func parse(data: PackedByteArray, now_tick: int): - pass + func parse(data: PackedByteArray, tick: int): + rx_tick = tick + if not online: + online = true + emit_signal('line_changed', self) From 2992ed7d6fd6c69ab6e090201025a675573befcb Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 18 Sep 2025 23:32:52 +0300 Subject: [PATCH 008/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9D=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=B6=D0=B0=D1=82=D1=8C=20=D0=BE=D1=82=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D0=B8=D0=B7=D0=BB=D1=83=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=B7=D0=B0=20=D1=80=D0=B0=D0=B1=D0=BE=D1=87?= =?UTF-8?q?=D0=B8=D0=BC=D0=B8=20=D0=B4=D0=B8=D0=B0=D0=BF=D0=B0=D0=B7=D0=BE?= =?UTF-8?q?=D0=BD=D0=B0=D0=BC=D0=B8=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9=20=D0=A4=D0=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 1871639e..cfd1a16c 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -166,7 +166,7 @@ func get_all_nodes(root): ## Производит отображение цели на диаграмму. -func map_threat_to_bip(th: threats.Threat, bip: Control): +func map_threat_to_bip(th: threats.Threat, bip: Control) -> bool: var freq = th.freq var sector_key = null var sector_width = 50.0 @@ -189,13 +189,15 @@ func map_threat_to_bip(th: threats.Threat, bip: Control): radius_outter, freq_low, freq_high) - bip.size / 2 + return sector_key != null ## Обработчик сигнала обновления цели. func on_threat_update(th): var bip = get_node('%d' % th.id) bip.update(th.tick_rx) - map_threat_to_bip(th, bip) + var rc = map_threat_to_bip(th, bip) + bip.visible = rc ## Обработчик выбора помехи для цели. From eda22c22b251fb744d729e0b30a234cad8374b16 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Fri, 19 Sep 2025 00:27:23 +0300 Subject: [PATCH 009/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/bip/bip.gd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scenes/bip/bip.gd b/scenes/bip/bip.gd index 20affa3a..34497868 100644 --- a/scenes/bip/bip.gd +++ b/scenes/bip/bip.gd @@ -2,11 +2,11 @@ class_name bip_ extends Control var selected: bool -## Присваивает заданое значение видимости селектору. +## Присваивает заданное значение видимости селектору. func set_track_visible(value: bool): $track.visible = value -## Присваивает заданое значение видимости индикатору выполнения. +## Присваивает заданное значение видимости индикатору выполнения. func set_ecm_visible(value: bool): $ecm_done.visible = value @@ -14,7 +14,7 @@ func update(tick_rx: int): $bip.set_instance_shader_parameter('tick_update', tick_rx) -## Функция присваивает заданое значение видимости селектору. +## Присваивает заданое значение видимости селектору. func set_sel_visible(value: bool): selected = value $selector.visible = value From fb0b771e9870576932e37b61b609ab693c843a74 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Fri, 19 Sep 2025 00:27:58 +0300 Subject: [PATCH 010/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=91=D0=BE=D0=BB=D0=B5=D0=B5=20=D1=88?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=BA=D0=B8=D0=B5=20=D0=B8=D0=BD=D0=B4=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=D1=82=D0=BE=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/bip/bip.tscn | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/scenes/bip/bip.tscn b/scenes/bip/bip.tscn index bf19a9d3..b469d3a1 100644 --- a/scenes/bip/bip.tscn +++ b/scenes/bip/bip.tscn @@ -15,17 +15,17 @@ code = "shader_type canvas_item; uniform vec4 color: source_color = vec4(1, 1, 1, 1); uniform vec4 color_up: source_color = vec4(1, 1, 1, 1); /* Цвет вспышки при обновлении */ -const float ds = 0.00725; /* Относительное расстояние на котором выполняется сглаживание краёв */ -const float dsr = 6.125; +const float ds = 0.01; /* Относительное расстояние на котором выполняется сглаживание краёв */ +const float dsr = 10.0; const vec2 center = vec2(0.5, 0.5); /* Центр должен быть в (0.5, 0.5), но это не так */ const float radius = 0.075 - ds * 2.0; /* Радиус должен быть 0.5, но это не так */ uniform float speed: hint_range(-1024.0, 1024.0) = 0.0; /* Время вспышки при обновлении, c */ uniform int ant_band_count_0 = 3; -const float ant_band_r0_0 = 0.3; +const float ant_band_r0_0 = 0.32; -const float ant_band_r1_0 = 0.4; +const float ant_band_r1_0 = 0.47; float smooth_px(float r, float R, float dss) { @@ -189,19 +189,19 @@ void fragment() shader = SubResource("Shader_81bae") shader_parameter/color = Color(0.0862745, 0.560784, 0.72549, 0.886275) shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = -73.0 +shader_parameter/speed = 23.0 shader_parameter/ant_band_count_0 = 9 -shader_parameter/ant_band_r0_0 = 0.45 -shader_parameter/ant_band_r1_0 = 0.5 +shader_parameter/ant_band_r0_0 = 0.38 +shader_parameter/ant_band_r1_0 = 0.47 [sub_resource type="ShaderMaterial" id="ShaderMaterial_h3oo7"] shader = SubResource("Shader_81bae") shader_parameter/color = Color(1, 0, 0, 1) shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = 66.064 -shader_parameter/ant_band_count_0 = 3 -shader_parameter/ant_band_r0_0 = 0.47 -shader_parameter/ant_band_r1_0 = 0.5 +shader_parameter/speed = 135.76 +shader_parameter/ant_band_count_0 = 4 +shader_parameter/ant_band_r0_0 = 0.3 +shader_parameter/ant_band_r1_0 = 0.45 [sub_resource type="ShaderMaterial" id="ShaderMaterial_lkrha"] shader = ExtResource("3_2a1qb") @@ -214,7 +214,7 @@ shader_parameter/point_6 = Vector2(0.25, 0.125) shader_parameter/point_7 = Vector2(0.125, 0.214) shader_parameter/point_8 = Vector2(0.125, 0.25) shader_parameter/len = 0.264 -shader_parameter/speed = 71.0 +shader_parameter/speed = 63.0 [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_svd33"] @@ -227,37 +227,36 @@ script = ExtResource("1_h7l70") [node name="bip" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_qq6yq") -position = Vector2(10, 10) -scale = Vector2(20, 20) +position = Vector2(14, 14) +scale = Vector2(28, 28) texture = SubResource("PlaceholderTexture2D_xbpqf") [node name="selector" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_fkqwb") -scale = Vector2(20, 20) +scale = Vector2(28, 28) texture = SubResource("PlaceholderTexture2D_hqs6j") centered = false [node name="recomendation" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_lpmq6") -scale = Vector2(20, 20) +scale = Vector2(28, 28) texture = SubResource("PlaceholderTexture2D_hqs6j") centered = false [node name="ecm_done" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_h3oo7") -position = Vector2(-5, -5) -scale = Vector2(30, 30) +scale = Vector2(28, 28) texture = SubResource("PlaceholderTexture2D_hqs6j") centered = false [node name="track" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_lkrha") -position = Vector2(10, 10) -scale = Vector2(26, 26) +position = Vector2(14, 14) +scale = Vector2(28, 28) texture = SubResource("PlaceholderTexture2D_svd33") [connection signal="gui_input" from="." to="." method="_on_bip_gui_input"] From 647f1cf24396018349c51ebeb742662b96a733a2 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 12:09:19 +0300 Subject: [PATCH 011/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/godot-logger/scripts/logger_output.gd | 22 ++++++------- project.godot | 2 +- scenes/работа/работа.gd | 33 ++++++++++---------- scripts/threats.gd | 2 +- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/addons/godot-logger/scripts/logger_output.gd b/addons/godot-logger/scripts/logger_output.gd index ae31ad2b..10d187a1 100644 --- a/addons/godot-logger/scripts/logger_output.gd +++ b/addons/godot-logger/scripts/logger_output.gd @@ -38,7 +38,7 @@ func get_color(level: int) -> Color: ## Установить журнал событий. func set_logger(logger: Logger) -> void: - assert(is_instance_valid(logger), "Invalid Logger.") + tools.allways(is_instance_valid(logger), 'Invalid Logger.') if not is_instance_valid(logger) or is_same(_logger, logger): return @@ -58,20 +58,20 @@ func get_logger() -> Logger: func format(message: Dictionary) -> String: return format_text.format( { - "year": "%02d" % message["year"], - "month": "%02d" % message["month"], - "day": "%02d" % message["day"], - "hour": "%02d" % message["hour"], - "minute": "%02d" % message["minute"], - "second": "%02d" % message["second"], - "level": message["level_name"], - "text": message["text"], + 'year': '%04d' % message['year'], + 'month': '%02d' % message['month'], + 'day': '%02d' % message['day'], + 'hour': '%02d' % message['hour'], + 'minute': '%02d' % message['minute'], + 'second': '%02d' % message['second'], + 'level': message['level_name'], + 'text': message['text'], } ) ## Обработать сообщение. func handle_message(message: Dictionary) -> void: - push_color(get_color(message["level"])) - append_text(format(message) + "\n") + push_color(get_color(message['level'])) + append_text(format(message) + '\n') pop() handled.emit() diff --git a/project.godot b/project.godot index fdb5e122..b50f5542 100644 --- a/project.godot +++ b/project.godot @@ -39,9 +39,9 @@ config/settings_path="user://settings.json" [autoload] commit="*res://scripts/commit.gd" +tools="*res://scripts/tools.gd" log="*res://addons/godot-logger/scripts/logger.gd" unit="*res://scripts/unit.gd" -tools="*res://scripts/tools.gd" signaller="*res://scripts/signaller.gd" settings="*res://scripts/settings.gd" network="*res://scripts/network.gd" diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index cfd1a16c..2b082234 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -196,28 +196,27 @@ func map_threat_to_bip(th: threats.Threat, bip: Control) -> bool: func on_threat_update(th): var bip = get_node('%d' % th.id) bip.update(th.tick_rx) - var rc = map_threat_to_bip(th, bip) - bip.visible = rc + bip.visible = map_threat_to_bip(th, bip) ## Обработчик выбора помехи для цели. func on_interfer_new(ecm): - if interfer.thrs.has(ecm.ispp): - var th_id = interfer.thrs[ecm.ispp] - var bip = get_node('%d' % th_id) - if bip != null: - if ecm.krp!= interfer.INTERFER_OFF: - bip.set_track_visible(true) - if ecm.svk == 1: - bip.set_ecm_visible(true) - else: bip.set_ecm_visible(false) - else: - bip.set_ecm_visible(false) - bip.set_track_visible(false) + if not interfer.thrs.has(ecm.ispp): return + var th_id = interfer.thrs[ecm.ispp] + var bip = get_node('%d' % th_id) + if bip != null: + if ecm.krp!= interfer.INTERFER_OFF: + bip.set_track_visible(true) + if ecm.svk == 1: + bip.set_ecm_visible(true) + else: bip.set_ecm_visible(false) else: - interfer.thrs.erase(ecm.ispp) - set_fs_color(ecm) - update_fs_colors() + bip.set_ecm_visible(false) + bip.set_track_visible(false) + else: + interfer.thrs.erase(ecm.ispp) + set_fs_color(ecm) + update_fs_colors() set_fs_color(ecm) diff --git a/scripts/threats.gd b/scripts/threats.gd index 93d34b33..da7be893 100644 --- a/scripts/threats.gd +++ b/scripts/threats.gd @@ -84,7 +84,7 @@ func on_timer_aoa_update(threats:Dictionary, tmr): tmr.start(1.0) ## отправляет словарь целей в юнит, для запаковки и отправки в 5П28. -func on_get_threats(unit, threats): unit.pack_threats(threats) +func on_get_threats(unit_instance, threats): unit_instance.pack_threats(threats) ## Снимает выделение с цели, если нажать по отметке цели. func on_rto_threat_unsel(th_id, threats): threats[th_id].selected = false From 0ad7cc6b3cd80ee93634a2f7059b6ddcc29298e5 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 13:23:05 +0300 Subject: [PATCH 012/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=A1=D0=BD=D0=B8=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20=D0=BF=D1=80=D0=B8=20=D0=B1=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D1=88=D0=BE=D0=BC=20=D0=BA=D0=BE=D0=BB=D0=B8=D1=87=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D0=B5=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B5=D0=B9?= =?UTF-8?q?=20=D0=B2=20=D0=B6=D1=83=D1=80=D0=BD=D0=B0=D0=BB=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/godot-logger/scripts/logger_output.gd | 7 ++++++- scenes/журнал/журнал.tscn | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/addons/godot-logger/scripts/logger_output.gd b/addons/godot-logger/scripts/logger_output.gd index 10d187a1..ee7e62dc 100644 --- a/addons/godot-logger/scripts/logger_output.gd +++ b/addons/godot-logger/scripts/logger_output.gd @@ -17,7 +17,7 @@ signal handled() Logger.ERROR: Color.RED, Logger.FATAL: Color.RED, } - +@export var max_lines_count: int = 512 var _logger : Logger @@ -75,3 +75,8 @@ func handle_message(message: Dictionary) -> void: append_text(format(message) + '\n') pop() handled.emit() + var pc: = get_paragraph_count() + if pc < max_lines_count: + return + for i in pc - max_lines_count: + remove_paragraph(i) diff --git a/scenes/журнал/журнал.tscn b/scenes/журнал/журнал.tscn index 61ae1eba..75df2f63 100644 --- a/scenes/журнал/журнал.tscn +++ b/scenes/журнал/журнал.tscn @@ -36,6 +36,7 @@ colors = { 8: Color(0.91, 0, 0, 1), 16: Color(0.868077, 0.247988, 0.62812, 1) } +max_lines_count = 256 [node name="btn_save" type="Button" parent="."] layout_mode = 0 From 85ea0557a7002bf83bf8e4579701b4914f3e5efa Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 13:24:48 +0300 Subject: [PATCH 013/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=92=D0=BA=D0=BB=D1=8E=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5/=D0=BE=D1=82=D0=BA=D0=BB=D1=8E=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=D0=BA=D1=80=D1=83=D1=82?= =?UTF-8?q?=D0=BA=D0=B8=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=B2=20=D0=B6=D1=83=D1=80=D0=BD=D0=B0=D0=BB=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addons/godot-logger/scripts/logger_output.gd | 3 +++ scenes/журнал/журнал.tscn | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/addons/godot-logger/scripts/logger_output.gd b/addons/godot-logger/scripts/logger_output.gd index ee7e62dc..dde49396 100644 --- a/addons/godot-logger/scripts/logger_output.gd +++ b/addons/godot-logger/scripts/logger_output.gd @@ -22,6 +22,9 @@ signal handled() var _logger : Logger +func _on_check_box_scroll_toggled(toggled_on: bool) -> void: scroll_following = toggled_on + + func _enter_tree() -> void: var logger := get_node_or_null("/root/log") as Logger if is_instance_valid(logger): diff --git a/scenes/журнал/журнал.tscn b/scenes/журнал/журнал.tscn index 75df2f63..b29cb183 100644 --- a/scenes/журнал/журнал.tscn +++ b/scenes/журнал/журнал.tscn @@ -113,6 +113,12 @@ button_pressed = true text = "Контроль" metadata/filter = "Контроль" +[node name="CheckBox_SCROLL" type="CheckBox" parent="filtrs"] +layout_mode = 2 +button_pressed = true +text = "Прокручивать до конца" +metadata/filter = "Контроль" + [connection signal="button_down" from="btn_save" to="." method="_on_btn_save_button_down"] [connection signal="button_down" from="btn_clear" to="." method="_on_clear_button_down" flags=3] [connection signal="canceled" from="dlg_file" to="." method="_on_dlg_file_confirmed"] @@ -125,3 +131,4 @@ metadata/filter = "Контроль" [connection signal="pressed" from="filtrs/CheckBox_FATAL" to="." method="_on_check_box_pressed"] [connection signal="pressed" from="filtrs/CheckBox_THREAT" to="." method="_on_check_box_pressed"] [connection signal="pressed" from="filtrs/CheckBox_CONTROL" to="." method="_on_check_box_pressed"] +[connection signal="toggled" from="filtrs/CheckBox_SCROLL" to="content" method="_on_check_box_scroll_toggled"] From 94e9d654b65e3b149c178a44393f8e8070189d20 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 15:00:11 +0300 Subject: [PATCH 014/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=A0=D0=B5=D0=B6=D0=B8?= =?UTF-8?q?=D0=BC=20=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0.=20=D0=A1=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B1=20=D0=BC=D0=BE=D0=B6=D0=B5=D1=82=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B0=D1=82=D1=8C=D1=81?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=B8=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B8=20=D0=BE=D0=B1=D0=B7=D0=BE?= =?UTF-8?q?=D1=80=D0=BD=D0=BE=D0=B9=20=D0=BA=D0=B0=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 2b082234..2861e34e 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -284,7 +284,7 @@ func on_rto_threat_unsel(th_id, _ecm_btns): ## Обработчик нажатия кнопки "Строб". Управляет отображением строба. func on_button_strobe_pressed() -> void: drag_fsm = DragFSM.IDLE if $btns_select/btn_strob.is_pressed() else DragFSM.OFF - $canvas.set_strob_visible(drag_fsm == DragFSM.IDLE) + $canvas.set_strob_visible((drag_fsm == DragFSM.IDLE) and (view_mode == MapViewMode.RTO)) ## Поведение радиокнопок в группе. Управляет состоянием кнопок выбора целей. From f50d1a9a9870dcd2f87c635ded669b3ceacfa19e Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 15:00:56 +0300 Subject: [PATCH 015/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=A0=D0=B5=D0=B6=D0=B8?= =?UTF-8?q?=D0=BC=20=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0.=20=D0=A1=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B1=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5,=20=D0=BA=D0=BE=D0=B3=D0=B4=D0=B0=20=D0=BE=D0=BD=20?= =?UTF-8?q?=D1=81=D0=BA=D1=80=D1=8B=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 2861e34e..c5629843 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -349,6 +349,7 @@ func set_strob(pos: Vector2) -> void: ## Обработка движения мыши для управления стробом. Вызывается во время движения мыши. func _on_drag_continue(event) -> void: + if not $canvas.get_strob_visible(): return if drag_button == MOUSE_BUTTON_RIGHT: if shift_pressed: var strob_width: float = get_strob_width(event.position, strob_width_begin) @@ -362,6 +363,7 @@ func _on_drag_continue(event) -> void: ## Обработка движения мыши для управления стробом. Вызывается при нажатии мыши. func _on_drag_begin(event) -> void: + if not $canvas.get_strob_visible(): return drag_pos_begin = event.position if drag_button == MOUSE_BUTTON_LEFT: set_strob(event.position) From 57a6d21fbaf03ae40e13afbbc6f243dcd1cd95f1 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 16:44:52 +0300 Subject: [PATCH 016/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=91=D0=BE=D0=BB=D0=B5=D0=B5=20=D1=88?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=BA=D0=B8=D0=B5=20=D0=B8=D0=BD=D0=B4=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=D1=82=D0=BE=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/bip/bip.tscn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scenes/bip/bip.tscn b/scenes/bip/bip.tscn index b469d3a1..7bfe5028 100644 --- a/scenes/bip/bip.tscn +++ b/scenes/bip/bip.tscn @@ -221,8 +221,8 @@ shader_parameter/speed = 63.0 [node name="threat" type="Control"] layout_mode = 3 anchors_preset = 0 -offset_right = 20.0 -offset_bottom = 20.0 +offset_right = 28.0 +offset_bottom = 28.0 script = ExtResource("1_h7l70") [node name="bip" type="Sprite2D" parent="."] From 05f49778d522a375d071247373168ed546fc3b06 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 16:47:40 +0300 Subject: [PATCH 017/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D1=8B=20=D1=81?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=BE=D1=80=D0=B0=20=D1=83=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=B6=D0=B4=D0=BE=D0=B3=D0=BE=20=D1=8D=D0=BA=D0=B7=D0=B5=D0=BC?= =?UTF-8?q?=D0=BF=D0=BB=D1=8F=D1=80=D0=B0=20=D0=B1=D1=83=D0=B4=D1=83=D1=82?= =?UTF-8?q?=20=D1=81=D0=B2=D0=BE=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 16 ++++++++-------- scenes/diagram/diagram.tscn | 7 ------- scenes/diagram/sector.tscn | 12 +++++------- shaders/sector.gdshader | 14 +++++++------- 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index 008dcd31..0116c167 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -13,17 +13,17 @@ func sv(val: float) -> float: return val / ($строб.scale.x / 2.0) * 0.125 func set_strob_visible(val: bool): $строб.visible = val func set_strob_center(val: Vector2): $строб.position = val -func set_strob_dir(val: float): $строб.material.set('shader_parameter/dir', val) -func set_strob_color(val: Color): $строб.material.set('shader_parameter/color', val) -func set_strob_width(val: float): $строб.material.set('shader_parameter/width', val) -func set_strob_band(val: float): $строб.material.set('shader_parameter/band', val / 125.0) -func set_strob_radius(val: float): $строб.material.set('shader_parameter/radius', sv(val)) +func set_strob_dir(val: float): $строб.set_instance_shader_parameter('dir', val) +func set_strob_color(val: Color): $строб.set_instance_shader_parameter('color', val) +func set_strob_width(val: float): $строб.set_instance_shader_parameter('width', val) +func set_strob_band(val: float): $строб.set_instance_shader_parameter('band', val / 125.0) +func set_strob_radius(val: float): $строб.set_instance_shader_parameter('radius', sv(val)) func get_strob_center() -> Vector2: return $строб.position func get_strob_visible() -> bool: return $строб.visible -func get_strob_width() -> float: return $строб.material.get('shader_parameter/width') -func get_strob_band() -> float: return $строб.material.get('shader_parameter/band') * 125.0 -func get_strob_radius() -> float: return $строб.material.get('shader_parameter/radius') * 125.0 +func get_strob_width() -> float: return $строб.get_instance_shader_parameter('width') +func get_strob_band() -> float: return $строб.get_instance_shader_parameter('band') * 125.0 +func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0 func get_radius_outter() -> float: return material.get('shader_parameter/radius_outter') func get_radius_inner_0() -> float: return material.get('shader_parameter/radius_inner_0') diff --git a/scenes/diagram/diagram.tscn b/scenes/diagram/diagram.tscn index 5e8dffd5..e48a68b4 100644 --- a/scenes/diagram/diagram.tscn +++ b/scenes/diagram/diagram.tscn @@ -11,13 +11,6 @@ size = Vector2(1600, 1200) [sub_resource type="ShaderMaterial" id="ShaderMaterial_lniyv"] resource_local_to_scene = true shader = ExtResource("4_obn6s") -shader_parameter/color = Color(1, 1, 1, 0.168627) -shader_parameter/clip_color = Color(1, 0.5, 0.5, 1) -shader_parameter/width = 45.0 -shader_parameter/band = 0.02 -shader_parameter/radius = 0.08 -shader_parameter/dir = 0.0 -shader_parameter/inner_clip = 0.045 [node name="canvas" type="Sprite2D"] material = ExtResource("1_newdt") diff --git a/scenes/diagram/sector.tscn b/scenes/diagram/sector.tscn index 07b8a30c..4edb09b8 100644 --- a/scenes/diagram/sector.tscn +++ b/scenes/diagram/sector.tscn @@ -5,18 +5,16 @@ [sub_resource type="ShaderMaterial" id="ShaderMaterial_xo5or"] resource_local_to_scene = true shader = ExtResource("1_e0gfn") -shader_parameter/color = Color(1, 1, 1, 0.168627) -shader_parameter/clip_color = Color(1, 0.5, 0.5, 1) -shader_parameter/width = 45.0 -shader_parameter/band = 0.02 -shader_parameter/radius = 0.08 -shader_parameter/dir = 0.0 -shader_parameter/inner_clip = 0.045 [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_2lkm8"] [node name="sector" type="Sprite2D"] material = SubResource("ShaderMaterial_xo5or") +instance_shader_parameters/band = 0.02 +instance_shader_parameters/color = Color(1, 1, 1, 0.188235) +instance_shader_parameters/inner_clip = 0.045 +instance_shader_parameters/radius = 0.08 +instance_shader_parameters/width = 45.0 position = Vector2(610, 600) scale = Vector2(1108, 1108) texture = SubResource("PlaceholderTexture2D_2lkm8") diff --git a/shaders/sector.gdshader b/shaders/sector.gdshader index 1fd8d166..08e31432 100644 --- a/shaders/sector.gdshader +++ b/shaders/sector.gdshader @@ -4,13 +4,13 @@ shader_type canvas_item; /* Закрашенный сектор окружности ограниченный угловым сектором и радиусами */ -uniform vec4 color: source_color = vec4(1, 1, 1, 1); -uniform vec4 clip_color: source_color = vec4(1.0, 0.5, 0.5, 1.0); -uniform float width: hint_range(0.0, 360.0, 0.1) = 45.0; -uniform float band: hint_range(0.0, 0.125) = 0.02; -uniform float radius: hint_range(0.0, 0.125) = 0.08; -uniform float dir: hint_range(0.0, 360.0) = 0.0; -uniform float inner_clip: hint_range(0.0, 0.125) = 0.045; +instance uniform vec4 color: source_color = vec4(1, 1, 1, 1); +instance uniform vec4 clip_color: source_color = vec4(1.0, 0.5, 0.5, 1.0); +instance uniform float width: hint_range(0.0, 360.0, 0.1) = 45.0; +instance uniform float band: hint_range(0.0, 0.125) = 0.02; +instance uniform float radius: hint_range(0.0, 0.125) = 0.08; +instance uniform float dir: hint_range(0.0, 360.0) = 0.0; +instance uniform float inner_clip: hint_range(0.0, 0.125) = 0.045; const vec2 center = vec2(0.125, 0.125); /* Центр. Должен быть в (0.5, 0.5), но это не так */ From be4beb561859a3ddc599833bdac0ea664ea0e337 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 16:49:48 +0300 Subject: [PATCH 018/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1=D0=BE=D0=B0?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D0=B5=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BE=D1=82=20=D0=9A=D0=90=D0=9F=D0=A1=D0=A0=D0=9F=D0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 13 +++++++++++++ scenes/diagram/diagram.tscn | 1 + 2 files changed, 14 insertions(+) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index 0116c167..e0cd7b23 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -4,6 +4,8 @@ const NUM_OF_RANGE = 7 const NUM_OF_DIRECTIONS = 4 var fs_default_colors: Array ## Цвета по умолчанию для блоков ФС. +@export var SecZap: PackedScene + func _ready() -> void: signaller.connect('map_mode_changed', Callable(self, 'set_view_mode')) set_def_colors() @@ -32,6 +34,17 @@ func get_radius_inner_1() -> float: return material.get('shader_parameter/radius func set_band_colors(val: Array): material.set('shader_parameter/ant_band_c', val) +## Добавляет сектор запрета[br] +## [param fc] - Центральная частота[br] +## [param fw] - Ширина диапазона[br] +## [param ac] - Угол центра[br] +## [param aw] - Ширина по углу[br] +func add_seczap(id: int, fc: float, fw: float, ac: float, aw: float): + var sec_zap = SecZap.instantiate() + sec_zap.name = 'SECZAP%d' % id + add_child(sec_zap) + + func set_view_mode(val: int): if val == 1: $строб.hide() diff --git a/scenes/diagram/diagram.tscn b/scenes/diagram/diagram.tscn index e48a68b4..bc00d0ab 100644 --- a/scenes/diagram/diagram.tscn +++ b/scenes/diagram/diagram.tscn @@ -17,6 +17,7 @@ material = ExtResource("1_newdt") texture = SubResource("PlaceholderTexture2D_2bft1") centered = false script = ExtResource("2_8xjuy") +SecZap = ExtResource("3_tgnog") [node name="строб" parent="." instance=ExtResource("3_tgnog")] material = SubResource("ShaderMaterial_lniyv") From 2bfb566578c5ebd80a8df7699b46c6bdd4ef4104 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 17:05:55 +0300 Subject: [PATCH 019/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index e0cd7b23..e916e4bc 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -16,10 +16,10 @@ func sv(val: float) -> float: return val / ($строб.scale.x / 2.0) * 0.125 func set_strob_visible(val: bool): $строб.visible = val func set_strob_center(val: Vector2): $строб.position = val func set_strob_dir(val: float): $строб.set_instance_shader_parameter('dir', val) -func set_strob_color(val: Color): $строб.set_instance_shader_parameter('color', val) func set_strob_width(val: float): $строб.set_instance_shader_parameter('width', val) func set_strob_band(val: float): $строб.set_instance_shader_parameter('band', val / 125.0) func set_strob_radius(val: float): $строб.set_instance_shader_parameter('radius', sv(val)) +func set_strob_color(val: Color): $строб.set_instance_shader_parameter('color', val) func get_strob_center() -> Vector2: return $строб.position func get_strob_visible() -> bool: return $строб.visible From 293ca59936439df3cad5eb370caa923d6dc894b5 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 20 Sep 2025 17:07:47 +0300 Subject: [PATCH 020/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=94=D0=BB=D1=8F=20=D0=B2?= =?UTF-8?q?=D1=81=D0=B5=D1=85=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B2,=20=D0=B4=D0=BE=D0=BB=D0=B6=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B1=D1=8B=D1=82=D1=8C=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6?= =?UTF-8?q?=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index e916e4bc..d8cbd722 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -23,9 +23,11 @@ func set_strob_color(val: Color): $строб.set_instance_shader_parameter(' func get_strob_center() -> Vector2: return $строб.position func get_strob_visible() -> bool: return $строб.visible +func get_strob_dir() -> float: return $строб.get_instance_shader_parameter('dir') func get_strob_width() -> float: return $строб.get_instance_shader_parameter('width') func get_strob_band() -> float: return $строб.get_instance_shader_parameter('band') * 125.0 func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0 +func get_strob_color() -> float: return $строб.get_instance_shader_parameter('color') func get_radius_outter() -> float: return material.get('shader_parameter/radius_outter') func get_radius_inner_0() -> float: return material.get('shader_parameter/radius_inner_0') From 39bb436407b264a8100a35889f351e33726b9102 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 11:57:21 +0300 Subject: [PATCH 021/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 14 ++++++------ scenes/pribor-afsp/pribor-bpo.gd | 4 ++-- scenes/контроль/request.gd | 2 +- scripts/interfer.gd | 9 ++++---- scripts/threats.gd | 38 +++++++++++++++++--------------- scripts/tools.gd | 2 +- settings.json | 2 +- 7 files changed, 36 insertions(+), 35 deletions(-) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index d8cbd722..1ba8af5f 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -21,13 +21,13 @@ func set_strob_band(val: float): $строб.set_instance_shader_parameter(' func set_strob_radius(val: float): $строб.set_instance_shader_parameter('radius', sv(val)) func set_strob_color(val: Color): $строб.set_instance_shader_parameter('color', val) -func get_strob_center() -> Vector2: return $строб.position -func get_strob_visible() -> bool: return $строб.visible -func get_strob_dir() -> float: return $строб.get_instance_shader_parameter('dir') -func get_strob_width() -> float: return $строб.get_instance_shader_parameter('width') -func get_strob_band() -> float: return $строб.get_instance_shader_parameter('band') * 125.0 -func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0 -func get_strob_color() -> float: return $строб.get_instance_shader_parameter('color') +func get_strob_center() -> Vector2: return $строб.position +func get_strob_visible() -> bool: return $строб.visible +func get_strob_dir() -> float: return $строб.get_instance_shader_parameter('dir') +func get_strob_width() -> float: return $строб.get_instance_shader_parameter('width') +func get_strob_band() -> float: return $строб.get_instance_shader_parameter('band') * 125.0 +func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0 +func get_strob_color() -> float: return $строб.get_instance_shader_parameter('color') func get_radius_outter() -> float: return material.get('shader_parameter/radius_outter') func get_radius_inner_0() -> float: return material.get('shader_parameter/radius_inner_0') diff --git a/scenes/pribor-afsp/pribor-bpo.gd b/scenes/pribor-afsp/pribor-bpo.gd index 941bde1a..677bb5d9 100644 --- a/scenes/pribor-afsp/pribor-bpo.gd +++ b/scenes/pribor-afsp/pribor-bpo.gd @@ -18,12 +18,12 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra log.error('\"%s\"' % rs) return - var json_str: String = body.get_string_from_utf8() + var json_str: = body.get_string_from_utf8() if not json_str: push_error('не удаётся получить строку из utf8-данных (%s)' % headers) return - var rc = json_conv.parse(json_str) + var rc: = json_conv.parse(json_str) if rc != Error.OK: var err = json_conv.get_error_message() push_error('разбор json прерван - \"%s\" (%s)' % [err, headers]) diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd index e52d0a47..e138987e 100644 --- a/scenes/контроль/request.gd +++ b/scenes/контроль/request.gd @@ -46,5 +46,5 @@ func _on_request_timer(): var rc = request(addr) if rc != Error.OK: var s: String = '%s: %s' % [error_string(rc), addr] - log.error('ошибка: %s' % s) + log.error('%s' % s) i_bort = (i_bort + 1) % 2 diff --git a/scripts/interfer.gd b/scripts/interfer.gd index 8bcb6369..eae4f65a 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -177,10 +177,10 @@ func _ready() -> void: signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno')) signaller.connect('emit_changed', Callable(self, 'on_emit_changed').bind(ecms)) threats.connect('threat_lost', Callable(self, 'on_threats_lost').bind(ecms, unit_caps)) - var unit_nav = network.get_unit_instance('навигация') - unit_nav.connect('data_received', on_nav_data_received.bind(unit_caps)) threats.connect('threats_resized', Callable(self, 'on_threats_resized')) threats.connect('threat_update', Callable(self, 'on_threats_update').bind(ecms, unit_caps)) + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_nav_data_received.bind(unit_caps)) func on_nav_data_received(coords: Dictionary, unit_caps): @@ -250,10 +250,9 @@ func on_data_capsrpb_received(unit_instance: capsrpb.CapsRpb, ecms: Dictionary) func map_msvk_to_ecms(unit_instance: unit.Unit, ecms: Dictionary): var json_dic = unit_instance.json_dic if not json_dic.has('msvk'): return - var msvk = unit_instance.json_dic['msvk'] - if msvk is not Array: return + var msvk = unit_instance.json_dic.get('msvk', []) for dic_msvk in msvk: - if not (dic_msvk is Dictionary): continue + if dic_msvk is not Dictionary: continue if not dic_msvk.has('ispp'): continue var ispp = int(dic_msvk['ispp']) var errmsg = dic_msvk.get('errmsg', '') diff --git a/scripts/threats.gd b/scripts/threats.gd index da7be893..80c62e69 100644 --- a/scripts/threats.gd +++ b/scripts/threats.gd @@ -45,13 +45,13 @@ signal threats_resized(th: Dictionary) func _ready() -> void: - var threats = {} ## Список целей. Индекс - <номер цели> var unit_caps = network.get_unit_instance('уарэп-капсрпб') var unit_5p28 = network.get_unit_instance('уарэп-5п28') var timer_check_lost: = Timer.new() var timer_aoa_update: = Timer.new() add_child(timer_check_lost) add_child(timer_aoa_update) + var threats = {} ## Список целей. Индекс - <номер цели> unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(threats)) unit_5p28.connect('get_threats', Callable(self, 'on_get_threats').bind(unit_5p28, threats)) timer_check_lost.connect('timeout', Callable(self, 'on_timer_check_lost').bind(settings.ThreatParams.time_lost, threats)) @@ -69,7 +69,7 @@ func _ready() -> void: ## Периодически удаляет устаревшие цели. func on_timer_check_lost(time_lost: int, threats: Dictionary): - var tick = Time.get_ticks_msec() + var tick: = Time.get_ticks_msec() var sz: = threats.size() for th in threats.values(): if (tick - th.tick_rx) >= time_lost: @@ -115,7 +115,7 @@ func on_interfer_init(interfer_name, fs_arr, power, threats): sel_threats.append(threat) if threat.auto_selected: sel_threats.append(threat) - if len(sel_threats) or (len(fs_arr)): + if len(sel_threats) or len(fs_arr): signaller.emit_signal('interfer_create', interfer_name, sel_threats, fs_arr, power) @@ -128,20 +128,22 @@ func on_data_capsrpb_received(unit: capsrpb.CapsRpb, threats: Dictionary): var mis = unit.json_dic['mis'] var sz: = threats.size() for dic_th in mis: - if dic_th is Dictionary: - 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_rx = unit.tick - call_deferred('emit_signal', 'threat_update', th) - else: - var th = Threat.new() - th.set_from_dic(dic_th) - threats[id] = th - th.tick_rx = unit.tick - call_deferred('emit_signal', 'threat_new', th) + if dic_th is not Dictionary: + continue + if not dic_th.has('id'): + continue + 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_rx = unit.tick + call_deferred('emit_signal', 'threat_update', th) + else: + var th: = Threat.new() + th.set_from_dic(dic_th) + threats[id] = 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 6b061c6a..c11dea62 100644 --- a/scripts/tools.gd +++ b/scripts/tools.gd @@ -33,7 +33,7 @@ func is_overlap(x1, x2, y1, y2) -> bool: return max(x1, y1) <= min(x2, y2) ## [param msg] - сообщение об ошибке func allways(val: bool, msg: String = '<не указано>'): if val: return - push_error('ошибка: %s\n' % msg) + push_error('%s\n' % msg) get_tree().quit(Error.FAILED) diff --git a/settings.json b/settings.json index f3eee9db..7ad413ee 100644 --- a/settings.json +++ b/settings.json @@ -157,4 +157,4 @@ false, true ] -} \ No newline at end of file +} From 336ae30eaf98614eaf0943d05c622710ddf602b1 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:13:44 +0300 Subject: [PATCH 022/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D0=B5=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BE=D1=82=20=D0=9A=D0=90=D0=9F=D0=A1=D0=A0=D0=9F=D0=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 50 ++++++++++++++++++++++++++++++++------- scripts/interfer.gd | 28 +++++++++++++--------- 2 files changed, 59 insertions(+), 19 deletions(-) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index 1ba8af5f..e8280394 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -37,14 +37,48 @@ func set_band_colors(val: Array): material.set('shader_parameter/ant_band_c', va ## Добавляет сектор запрета[br] -## [param fc] - Центральная частота[br] -## [param fw] - Ширина диапазона[br] -## [param ac] - Угол центра[br] -## [param aw] - Ширина по углу[br] -func add_seczap(id: int, fc: float, fw: float, ac: float, aw: float): - var sec_zap = SecZap.instantiate() - sec_zap.name = 'SECZAP%d' % id - add_child(sec_zap) +## [param id] - Индекс сектора запрета.[br] +## [param szv.x] - Центральная частота (198...546).[br] +## [param szv.w] - Ширина диапазона (198...546).[br] +## [param szv.y] - Угол центра (0...360).[br] +## [param szv.z] - Ширина по углу (0...360).[br] +func add_seczap(id: int, szv: Vector4): + var seczap: = SecZap.instantiate() + seczap.name = StringName('SECZAP%d' % id) + seczap.position = $строб.position + seczap.set_instance_shader_parameter('dir', szv.y - 90.0) + seczap.set_instance_shader_parameter('width', szv.z) + seczap.set_instance_shader_parameter('band', sv(szv.w)) + seczap.set_instance_shader_parameter('radius', sv(szv.x)) + add_child(seczap) + + +## Удаляет сектор запрета[br] +## [param id] - Индекс сектора запрета[br] +func remove_seczap(id: int): + var seczap: = get_node_or_null('SECZAP%d' % id) + if not seczap: return + remove_child(seczap) + seczap.queue_free() + + +## Изменяет сектор запрета[br] +## [param id] - Индекс сектора запрета[br] +## [param szv.x] - Центральная частота[br] +## [param szv.w] - Ширина диапазона[br] +## [param szv.y] - Угол центра[br] +## [param szv.z] - Ширина по углу[br] +func set_seczap(id: int, szv: Vector4): + var seczap: = get_node('SECZAP%d' % id) + seczap.set_instance_shader_parameter('dir', szv.y) + seczap.set_instance_shader_parameter('width', szv.z) + seczap.set_instance_shader_parameter('band', sv(szv.w)) + seczap.set_instance_shader_parameter('radius', sv(szv.x)) + + +func set_seczap_color(id: int, color: Color): + var seczap: = get_node('SECZAP%d' % id) + seczap.set_instance_shader_parameter('color', color) func set_view_mode(val: int): diff --git a/scripts/interfer.gd b/scripts/interfer.gd index eae4f65a..f32db08f 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -154,7 +154,6 @@ func on_full_auto() -> void: auto_enabled = true func _ready() -> void: - var ecms: Dictionary = {} ## Словарь помех. for i in ID_INTERFERS_LEN: # Заполняет массив ID целей id_array.append(i + 1) var unit_caps = network.get_unit_instance('уарэп-капсрпб') @@ -162,9 +161,11 @@ func _ready() -> void: var timer_check_state: = Timer.new() add_child(timer_check_state) var resend_timeout = ProjectSettings.get_setting('application/interfer/resend_timeout', 1000.0) + var ecms: Dictionary = {} ## Словарь помех. + var seczaps: Dictionary = {} ## Словарь секторов запрета timer_check_state.connect('timeout', Callable(self, 'on_timer_check_state').bind(unit_caps, ecms, resend_timeout)) timer_check_state.start(resend_timeout / 1000.0) - unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(ecms)) + unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(ecms, seczaps)) unit_5p28.connect('get_interfers', Callable(self, 'on_get_interfers').bind(unit_5p28, ecms)) signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit_caps, ecms)) signaller.connect('interfer_rcv', Callable(self, 'on_interfer_rcv').bind(unit_5p28, ecms)) @@ -238,12 +239,12 @@ func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit_instance) -> v ## Производит приём состояния помех. [param unit] -> [param ecms]. -func on_data_capsrpb_received(unit_instance: capsrpb.CapsRpb, ecms: Dictionary) -> void: - if not unit_instance.json_dic.has('ts'): return - if not (unit_instance.json_dic['ts'] is float): return - if unit_instance.json_dic['ts'] != 5: return +func on_data_capsrpb_received(unit_instance: capsrpb.CapsRpb, ecms: Dictionary, seczaps: Dictionary) -> void: + if not unit_instance.json_dic.has('ts'): return + if not tools.type_is_num(unit_instance.json_dic['ts']): return + if unit_instance.json_dic['ts'] != 5: return map_msvk_to_ecms(unit_instance, ecms) - map_mpchf_to_view(unit_instance) + map_mpchf_to_seczaps(unit_instance, seczaps) ## Извлекает массив состояний выполнения команды @@ -270,11 +271,16 @@ func map_msvk_to_ecms(unit_instance: unit.Unit, ecms: Dictionary): ## Извлекает массив пространственно-частотных фильтров -func map_mpchf_to_view(unit_instance: unit.Unit): - var json_dic = unit_instance.json_dic - if not json_dic.has('mpchf'): return - var mpchf = json_dic['mpchf'] +func map_mpchf_to_seczaps(unit_instance: unit.Unit, seczaps: Dictionary): + var json_dic: = unit_instance.json_dic as Dictionary + var mpchf = json_dic.get('mpchf', []) if mpchf is not Array: return + for item in mpchf: + if item is not Dictionary: continue + var id = item.get('index', -1) + if id < 0: continue + var freq = item.get('freq', 0) + if freq == 0: continue ## Вызыватся, когда пользователь выбрал помеху и выбраны цели. From 5c17f1f237e9e6d6b0415885cdfbfec8746346ab Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:27:09 +0300 Subject: [PATCH 023/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B4=D1=83=D0=B5=D0=BC=D1=8B=D0=B5=20=D0=BF=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D1=85=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/frame-ecm-list/scroll-ecm-list.gd | 10 +++++ scripts/interfer.gd | 54 ++++++++++++++++++++++++ scripts/threats.gd | 2 +- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index 7acaa671..95fe1072 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -84,6 +84,7 @@ func _ready(): signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel')) signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(table_index)) interfer.connect('interfer_update', Callable(self, 'on_interfer_update').bind(table_index)) + interfer.connect('interfer_recommendate', Callable(self, 'on_interfer_recommendate')) $table.connect('row_pressed', Callable(self, 'on_row_pressed')) call_deferred('init_table') @@ -159,3 +160,12 @@ func map_th_to_row(ecm) -> Array: if INTERFER_STATE.has(ecm.svk): row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk] return row + + +func on_interfer_recommendate(ecm): + var sel_rows: Array + $table.get_selected_rows(sel_rows) + if not len(sel_rows): return + var sel_ecm = $table.get_node_user_data(0, sel_rows[0]) + if ecm == sel_ecm: + signaller.emit_signal('interfer_selected', ecm) diff --git a/scripts/interfer.gd b/scripts/interfer.gd index f32db08f..0669a1bd 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -20,6 +20,11 @@ const ITERFER_MODE = { 'k1': [INTERFER_IQFILE, K1_PARAMS, 50], 'ozp1': [INTERFER_IQFILE, OZP1_PARAMS, 51] } +const RECOMMEND_INTERFER = { + 'ПСП + ФМ-2': 'srni1', + 'Линейная ЧМ': 'lchm1' +} + const SRNI1_PARAMS = {'par_names' : ['freq', 'width']} const SRNM2_PARAMS = {'par_names' : ['freq', 'width', 'period']} const SRNGPS_PARAMS = {'par_names' : ['freq', 'filename'], @@ -139,6 +144,7 @@ signal interfer_run(ecm: Interfer) ## Вызывается в м signal interfer_error(ecm: Interfer, msg: String) ## Вызывается при ошибке. signal interfer_update(ecm: Interfer) ## Вызывается при обновлении помехи. signal interfer_resized(ecms: Dictionary) ## Вызывается при изменении количества сеансов помех. +signal interfer_recommendate(ecm: Interfer) ## Вызывается когда назначается рекомендуемая для цели помеха ## Отправляет словарь помех в юнит, для запаковки и отправки в 5П28. @@ -291,6 +297,11 @@ func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> v var id = item.id param['freq'] = item.freq param['width'] = item.width + if (item.rkrp != '') and item.fflags.rkrp: + var krp = get_krp(item) + if krp != '': + interfer_name = krp + set_rparams(item, param) if (param['width'] < settings.WIDTH_MIN): param['width'] = settings.WIDTH_MIN elif (param['width'] > settings.WIDTH_MAX): @@ -307,6 +318,11 @@ func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> v if th != null: param['freq'] = th.freq param['width'] = th.width + if (th.rkrp != '') and th.fflags.rkrp: + var krp = get_krp(th) + if krp != '': + interfer_name = krp + set_rparams(th, param) else: param['freq'] = item[1] param['width'] = item[2] @@ -490,6 +506,13 @@ func on_threats_update(threat, ecms, unit_caps): if thrs[ecm_i] == th_id: ecm = ecms[ecm_i] ecm.params['freq'] = threat.freq + ecm.params['width'] = threat.width + if (threat.rkrp != '') and threat.fflags.rkrp: + var krp = get_krp(threat) + if krp != '': + ecm.krp = krp + set_rparams(threat, ecm.params) + emit_signal('interfer_recommendate', ecm) ecm.kni = threat.aoa set_nmfs(ecm) if threat.tmod != 'fm': @@ -558,3 +581,34 @@ func find_threat(freq: int, aoa: float): if fs_index_arr[0] == fs_index: return th return null + + +func set_rparams(threat: threats.Threat, params: Dictionary): + if threat.rparams.has('freq'): + params['freq'] = threat.rparams['freq'] + else: + params['freq'] = threat.freq + if threat.rparams.has('period'): + params['period'] = threat.rparams['period'] + if threat.rparams.has('width'): + params['width'] = threat.rparams['width'] + else: + params['width'] = threat.width + if threat.rparams.has('filename'): + params['filename'] = threat.rparams['filename'] + + +func get_krp(threat: threats.Threat): + var krp = '' + if RECOMMEND_INTERFER.has(threat.rkrp): + krp = RECOMMEND_INTERFER[threat.rkrp] + return krp + elif threat.rkrp == INTERFER_IQFILE: + if not threat.rparams.has('filename'): return krp + for key in ITERFER_MODE.keys(): + var ecm_params = ITERFER_MODE[key][1] + if not ecm_params.has('files'): continue + if ecm_params['files'] == threat.rparams['filename']: + krp = key + return krp + return krp diff --git a/scripts/threats.gd b/scripts/threats.gd index 80c62e69..83de85c5 100644 --- a/scripts/threats.gd +++ b/scripts/threats.gd @@ -18,7 +18,7 @@ class Threat: var power: float ## Уровень принимаемого сигнала, дБм. var proto: String ## Тип протокола источника сигнала. var rkrp: String ## Рекомендуемый режим помехи. - var rparams: String ## Рекомендуемые параметры помехи. + var rparams: Dictionary ## Рекомендуемые параметры помехи. var salt: float ## Координаты старта, высота от уровня моря, м. var slat: float ## Координаты старта, широта в градусах. var slon: float ## Координаты старта, долгота в градусах. From c50a9caa05dc6e9a68851521d6907046c875d69a Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:40:33 +0300 Subject: [PATCH 024/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=91=D0=9F=D0=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.godot | 4 ++- scenes/pribor-afsp/pribor-afsp-1.tscn | 1 + scenes/pribor-afsp/pribor-afsp.gd | 2 +- scenes/pribor-afsp/pribor-bpo.gd | 25 +++++++++++--- scenes/pribor-afsp/pribor-bpo.tscn | 48 ++++++++++++++++----------- scenes/контроль/request.gd | 28 ++++++++++++++-- scenes/настройки/настройки.tscn | 3 +- shaders/sector.gdshader | 2 +- 8 files changed, 83 insertions(+), 30 deletions(-) diff --git a/project.godot b/project.godot index b50f5542..1fa004a5 100644 --- a/project.godot +++ b/project.godot @@ -31,10 +31,11 @@ interfer/select_color=Vector3(1, 1, 1) interfer/interfer_color=Vector3(0.58, 0.47, 0.51) interfer/resend_timeout=1000.0 config/external_cu=false -config/unit_rr_request_period=5.0 +config/unit_rr_request_period=20.0 config/kems_files_path="user://kems/" config/emsg_files_path="user://emsg/" config/settings_path="user://settings.json" +config/unit_bpo_request_period=20.0 [autoload] @@ -143,6 +144,7 @@ folder_colors={ map_server_addr=false center_offset=Vector2(0, 0) external_cu=false +unit_bpo_request_period=0.0 [global_group] diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn index 81a5e01b..3081df5c 100644 --- a/scenes/pribor-afsp/pribor-afsp-1.tscn +++ b/scenes/pribor-afsp/pribor-afsp-1.tscn @@ -29,6 +29,7 @@ projsettings_path_left = "application/config/Адрес АФСП левого б projsettings_path_right = "application/config/Адрес АФСП правого борта" [node name="timer" type="Timer" parent="request"] +wait_time = 20.0 autostart = true script = SubResource("GDScript_yhnwg") diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index 046059bd..be349a64 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -1,7 +1,7 @@ @tool class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd' -@export var prefix_path: String = 'DeviceDescripton[DeviceName]' +@export var prefix_path: String = 'DeviceDescription[DeviceName]' @export var unit_name: StringName= '' static var json_conv: JSON = JSON.new() diff --git a/scenes/pribor-afsp/pribor-bpo.gd b/scenes/pribor-afsp/pribor-bpo.gd index 677bb5d9..e1799a4c 100644 --- a/scenes/pribor-afsp/pribor-bpo.gd +++ b/scenes/pribor-afsp/pribor-bpo.gd @@ -1,21 +1,21 @@ @tool class_name pribor_rtr extends 'res://scenes/контроль/прибор.gd' -@export var prefix_path: String = 'DeviceDescripton[DeviceName]' +@export var prefix_path: String = 'DeviceDescription[DeviceName]' static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') const bort_to_node_name = { - 'Устройство РР левого борта': 'grid_bpo_a1', - 'Устройство РР правого борта': 'grid_bpo_a2'} + 'Устройство БПО левого борта': 'grid_bpo_a1', + 'Устройство БПО правого борта': 'grid_bpo_a2'} func _on_request_completed(result, _response_code, headers, body: PackedByteArray): if result != 0: var rs = $request.get_result_string(result) - log.error('\"%s\"' % rs) + push_error('\"%s\"' % rs) return var json_str: = body.get_string_from_utf8() @@ -39,6 +39,7 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra return if not bort_to_node_name.has(ret_val[0]): + push_error('не известное устройство: \"%s\"' % ret_val[0]) return var node_name = bort_to_node_name[ret_val[0]] @@ -46,3 +47,19 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra for item in bort_node.get_children(): node_maper.map_value_to_item(json_conv.data, item, 'state') + + var items = get_tree().get_nodes_in_group('управляется-по-шине-1') + for node in items: + if node.state == 1: + $yas_bpo_a1.state = 1 + break + items = get_tree().get_nodes_in_group('управляется-по-шине-2') + for node in items: + if node.state == 1: + $yas_bpo_a2.state = 1 + break + items = get_tree().get_nodes_in_group('потребитель-питания') + for node in items: + if node.state == 1: + $mod_pit_g1.state = 1 + break diff --git a/scenes/pribor-afsp/pribor-bpo.tscn b/scenes/pribor-afsp/pribor-bpo.tscn index 71ae79cd..0dc97f30 100644 --- a/scenes/pribor-afsp/pribor-bpo.tscn +++ b/scenes/pribor-afsp/pribor-bpo.tscn @@ -1,10 +1,16 @@ -[gd_scene load_steps=5 format=3 uid="uid://5uv1idl3lqea"] +[gd_scene load_steps=6 format=3 uid="uid://5uv1idl3lqea"] [ext_resource type="Script" uid="uid://d0jwv5opi3mrk" path="res://scenes/pribor-afsp/pribor-bpo.gd" id="1_bhc4e"] [ext_resource type="PackedScene" uid="uid://d3iqb5e4g81m5" path="res://scenes/контроль/элемент-г.tscn" id="2_jp6m0"] [ext_resource type="PackedScene" uid="uid://p2suppildvq0" path="res://scenes/контроль/элемент-в.tscn" id="3_jcpjs"] [ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="4_crej3"] +[sub_resource type="GDScript" id="GDScript_bhc4e"] +script/source = "extends Timer + +func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_bpo_request_period') +" + [node name="pribor_bpo" type="Control"] layout_mode = 3 anchors_preset = 0 @@ -43,63 +49,63 @@ offset_right = 498.0 offset_bottom = 320.0 columns = 4 -[node name="kanal1" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal1" parent="grid_bpo_a1" groups=["потребитель-питания"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 1" metadata/state = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']" -[node name="kanal2" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal2" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 2" metadata/state = "SelfTest[0].SystemList[0].DevList[1]['TestPassed']" -[node name="kanal3" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal3" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 3" metadata/state = "SelfTest[0].SystemList[0].DevList[2]['TestPassed']" -[node name="kanal4" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal4" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 4" metadata/state = "SelfTest[0].SystemList[0].DevList[3]['TestPassed']" -[node name="kanal5" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal5" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 5" metadata/state = "SelfTest[0].SystemList[0].DevList[4]['TestPassed']" -[node name="kanal6" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal6" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 6" metadata/state = "SelfTest[0].SystemList[0].DevList[5]['TestPassed']" -[node name="kanal7" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal7" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 7" metadata/state = "SelfTest[0].SystemList[0].DevList[6]['TestPassed']" -[node name="kanal8" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal8" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 8" metadata/state = "SelfTest[0].SystemList[0].DevList[7]['TestPassed']" -[node name="yas_bpo_a1" parent="." instance=ExtResource("3_jcpjs")] +[node name="yas_bpo_a1" parent="." groups=["потребитель-питания"] instance=ExtResource("3_jcpjs")] offset_left = 500.0 offset_top = 175.0 offset_right = 550.0 @@ -126,63 +132,63 @@ offset_right = 498.0 offset_bottom = 520.0 columns = 4 -[node name="kanal1" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal1" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 1" metadata/state = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']" -[node name="kanal2" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal2" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 2" metadata/state = "SelfTest[0].SystemList[0].DevList[1]['TestPassed']" -[node name="kanal3" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal3" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 3" metadata/state = "SelfTest[0].SystemList[0].DevList[2]['TestPassed']" -[node name="kanal4" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal4" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 4" metadata/state = "SelfTest[0].SystemList[0].DevList[3]['TestPassed']" -[node name="kanal5" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal5" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 5" metadata/state = "SelfTest[0].SystemList[0].DevList[4]['TestPassed']" -[node name="kanal6" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal6" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 6" metadata/state = "SelfTest[0].SystemList[0].DevList[5]['TestPassed']" -[node name="kanal7" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal7" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 7" metadata/state = "SelfTest[0].SystemList[0].DevList[6]['TestPassed']" -[node name="kanal8" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal8" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 8" metadata/state = "SelfTest[0].SystemList[0].DevList[7]['TestPassed']" -[node name="yas_bpo_a2" parent="." instance=ExtResource("3_jcpjs")] +[node name="yas_bpo_a2" parent="." groups=["потребитель-питания"] instance=ExtResource("3_jcpjs")] offset_left = 500.0 offset_top = 375.0 offset_right = 550.0 @@ -192,13 +198,15 @@ self_size = Vector2i(50, 145) fname = "Яч. связи" [node name="request" type="HTTPRequest" parent="."] -use_threads = true script = ExtResource("4_crej3") projsettings_path_left = "application/config/Адрес БПО левого борта" projsettings_path_right = "application/config/Адрес БПО правого борта" +projsettings_path_wait_time = "application/config/Период опроса состояния БПО, секунды" [node name="timer" type="Timer" parent="request"] +wait_time = 5.0 autostart = true +script = SubResource("GDScript_bhc4e") [connection signal="request_completed" from="request" to="." method="_on_request_completed"] [connection signal="timeout" from="request/timer" to="request" method="_on_request_timer"] diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd index e138987e..94815447 100644 --- a/scenes/контроль/request.gd +++ b/scenes/контроль/request.gd @@ -18,9 +18,30 @@ const RESULT_STRINGS = { RESULT_REDIRECT_LIMIT_REACHED: 'Запрос достиг максимального предела перенаправления, см. `max_redirects`', RESULT_TIMEOUT: 'Время истекло' } +const headers_left = [ + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Encoding: gzip, deflate', + 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', + 'Connection: keep-alive', + 'Host: 172.22.246.12:8081', + 'Priority: u=0,i', + 'Upgrade-Insecure-Requests: 1', + 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0' ] + +const headers_right = [ + 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Encoding: gzip, deflate', + 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', + 'Connection: keep-alive', + 'Host: 172.22.246.14:8082', + 'Priority: u=0,i', + 'Upgrade-Insecure-Requests: 1', + 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0' ] @export var projsettings_path_left: String = '' @export var projsettings_path_right: String = '' +@export var projsettings_path_wait_time: String = '' + var i_bort: int = 0 var addr_left: String @@ -30,6 +51,7 @@ var addr_right: String func on_settings_changed(): addr_left = ProjectSettings.get_setting(projsettings_path_left) addr_right = ProjectSettings.get_setting(projsettings_path_right) + $timer.wait_time = int(ProjectSettings.get_setting(projsettings_path_wait_time, 5)) func get_result_string(result: Result): @@ -42,8 +64,10 @@ func _ready(): func _on_request_timer(): - var addr = [addr_left, addr_right][i_bort] - var rc = request(addr) + cancel_request() + var addr = [addr_right, addr_left][i_bort] + var hdrs = [headers_right, headers_left][i_bort] + var rc: = request(addr, hdrs) if rc != Error.OK: var s: String = '%s: %s' % [error_string(rc), addr] log.error('%s' % s) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index b69067fc..c21899b6 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -60,7 +60,8 @@ const SETTING_TABLE = [ ['Адрес АФСП левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'], ['Адрес АФСП правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'], ['Адрес БПО левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], - ['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'] ] + ['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], + ['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ] ] const EXTERNAL_CU = 16 ## Внешнее целеуказание const SUPPRESS = 17 ## Строка - Подавление diff --git a/shaders/sector.gdshader b/shaders/sector.gdshader index 08e31432..f3783bf5 100644 --- a/shaders/sector.gdshader +++ b/shaders/sector.gdshader @@ -9,7 +9,7 @@ instance uniform vec4 clip_color: source_color = vec4(1.0, 0.5, 0.5, 1.0); instance uniform float width: hint_range(0.0, 360.0, 0.1) = 45.0; instance uniform float band: hint_range(0.0, 0.125) = 0.02; instance uniform float radius: hint_range(0.0, 0.125) = 0.08; -instance uniform float dir: hint_range(0.0, 360.0) = 0.0; +instance uniform float dir: hint_range(0.0, 360.0) = 0.0; instance uniform float inner_clip: hint_range(0.0, 0.125) = 0.045; From 5f8fd976494c4f046cb4837c4b5e1d80dff19833 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:44:01 +0300 Subject: [PATCH 025/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A1=D0=BE=D0=BE=D0=B1=D1=89=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=B1=20=D0=BD=D0=B5=D0=B8=D0=B7?= =?UTF-8?q?=D0=B2=D0=B5=D1=81=D1=82=D0=BD=D0=BE=D0=BC=20=D1=83=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=B5=20=D0=B2=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index be349a64..d7d5ca14 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -50,6 +50,7 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra var received_afsp_name: StringName = ret_val[0] if this_afsp_name != received_afsp_name: + push_error('не известное устройство: \"%s\"' % received_afsp_name) return if not unit_instance.online: From a963d84c45fefbf0aeaadaf70acd4cfdb986b4e2 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:45:04 +0300 Subject: [PATCH 026/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9F=D1=80=D0=B8=D1=81?= =?UTF-8?q?=D0=B2=D0=BE=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B5=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=82=D0=B8=D0=BF?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-v/pribor-prd-v.gd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index ff1e90f9..e2c6bb9f 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -207,12 +207,12 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: $kasseta_FS_VD/ref_A2.state = STATE_VAL.GOOD if result_dic.dkm_5 else STATE_VAL.ERROR $dou5_A6.state = STATE_VAL.GOOD if result_dic.dou_5 else STATE_VAL.ERROR else: - result_dic.fs_5 = false + result_dic.fs_5 = 0 if result_dic.fs_4 == 1: $kasseta_FS_VD/ref_A6.state = STATE_VAL.GOOD if result_dic.dkm_4 else STATE_VAL.ERROR $dou4_A5.state = STATE_VAL.GOOD if result_dic.dou_4 else STATE_VAL.ERROR else: - result_dic.fs_4 = false + result_dic.fs_4 = 0 power_fill(power_dic) var result = true From 443d4aa40f5adaba51932c19e459772f6c05549a Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:45:39 +0300 Subject: [PATCH 027/117] =?UTF-8?q?=D0=A7=D0=B8=D1=81=D1=82=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-v/pribor-prd-v.gd | 2 -- 1 file changed, 2 deletions(-) diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index e2c6bb9f..572035a6 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -160,8 +160,6 @@ func on_mode_changed(in_tree: bool) -> void: func power_fill(pow_dic: Dictionary) -> void: - #if not control_prd_v.block_kasseta_y5_config.yau07 or not control_prd_v.block_kasseta_y5_config.ukp1 or not control_prd_v.block_kasseta_y5_config.ukp2: - #return var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier') for i_powapm in power_amplifier: var powamp_meta: String = i_powapm.get_meta('um') From 8f877b6d6fe4e5baa48cbc5d427c063c87427f5d Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:46:46 +0300 Subject: [PATCH 028/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9F=D1=80=D0=B8=D1=81?= =?UTF-8?q?=D0=B2=D0=BE=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B5=D1=83=D0=BC?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=82=D0=B8=D0=BF?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-n/pribor-prd-n.gd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index 6e177be2..04c9e60d 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -207,12 +207,12 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: $kasseta_FS_ND/ref_A4.state = STATE_VAL.GOOD if result_dic.dkm_2 else STATE_VAL.ERROR $dou2_A5.state = STATE_VAL.GOOD if result_dic.dou_2 else STATE_VAL.ERROR else: - result_dic.fs_2 = false + result_dic.fs_2 = 0 if result_dic.fs_3 == 1: $kasseta_FS_ND/ref_A3.state = STATE_VAL.GOOD if result_dic.dkm_3 else STATE_VAL.ERROR $dou3_A6.state = STATE_VAL.GOOD if result_dic.dou_3 else STATE_VAL.ERROR else: - result_dic.fs_3 = false + result_dic.fs_3 = 0 power_fill(power_dic) From 70ee588574700aeffa5972d40acf290dcc557772 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:47:16 +0300 Subject: [PATCH 029/117] =?UTF-8?q?=D0=9F=D1=80=D0=BE=D0=B8=D0=B7=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/tools.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tools.gd b/scripts/tools.gd index c11dea62..de9232ca 100644 --- a/scripts/tools.gd +++ b/scripts/tools.gd @@ -9,7 +9,7 @@ func round_to(v: float, a: float) -> float: return snappedf(v, -a if v < 0 else ## Возвращает [b]true[/b], если [param val] число, [b]false[/b] - если иначе. -func type_is_num(val) -> bool: return (typeof(val) == TYPE_INT) or (typeof(val) == TYPE_FLOAT) +func type_is_num(val) -> bool: return (val is int) or (val is float) ## Возвращает значение в радианах для угла в градусах [param val]. From 8cbbdacf5ec36121ec5a2f4bbf766a52c7919615 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:47:34 +0300 Subject: [PATCH 030/117] Godot4.4 --- scenes/работа/работа.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 6d645182..64b1bbd5 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -305,6 +305,6 @@ text = "Масштаб:" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] From 0b3f28d4380790e3b37b488a8a26991e979b30e6 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 12:48:38 +0300 Subject: [PATCH 031/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9F=D1=80=D0=B8=D0=BC=D0=B5=D1=80=20?= =?UTF-8?q?=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D1=81=D0=B5=D0=BA=D1=82=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index c5629843..1f150bc9 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -142,6 +142,13 @@ func _ready(): signaller.connect('update_scale_map', Callable(self, 'on_update_scale_label')) on_btn_center_toggled(true) on_btn_activate_toggled(true) + #$canvas.add_seczap(0, Vector4(372, 0, 30, 348)) + #$canvas.add_seczap(1, Vector4(372, 90, 30, 348)) + #$canvas.add_seczap(2, Vector4(198 + 348, 180, 30, 5)) + #$canvas.add_seczap(3, Vector4(203, 270, 30, 5)) + + #$canvas.set_seczap_color(2, Color.MAGENTA) + #$canvas.set_seczap_color(3, Color.CHARTREUSE) func on_user_panning(): From 4c65fd92ac8fd7f02b721e3f56471bfe5f0942d5 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 1 Oct 2025 14:09:02 +0300 Subject: [PATCH 032/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20=D0=9D=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=B0=D0=B5=D1=82=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=BF=D1=80=D0=B8=D0=B1=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?=D0=A3=D0=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-uf/pribor-uf.gd | 4 ++-- scenes/pribor-uf/pribor-uf.tscn | 3 +++ scenes/контроль/контроль.tscn | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scenes/pribor-uf/pribor-uf.gd b/scenes/pribor-uf/pribor-uf.gd index 1c38a802..31f3ed95 100644 --- a/scenes/pribor-uf/pribor-uf.gd +++ b/scenes/pribor-uf/pribor-uf.gd @@ -12,11 +12,11 @@ func _ready() -> void: return var unit_uf = network.get_unit_instance('уарэп-эмс') unit_uf.connect('line_changed', on_line_changed) - on_timer.bind(unit_uf) control_vk() -func on_timer(unit_uf: unit.Unit): +func on_timer(unit_name: StringName): + var unit_uf = network.get_unit_instance(unit_name) status_uf() # отслеживание состояния прибора if unit_uf.online: # проверка ЯУ, внутреннего коммутатора и ИП-5Б control_ems(unit_uf.status) # проверка ЭМС ячеек diff --git a/scenes/pribor-uf/pribor-uf.tscn b/scenes/pribor-uf/pribor-uf.tscn index 9b63dc86..998ace6e 100644 --- a/scenes/pribor-uf/pribor-uf.tscn +++ b/scenes/pribor-uf/pribor-uf.tscn @@ -155,3 +155,6 @@ horizontal_alignment = 1 vertical_alignment = 1 [node name="timer" type="Timer" parent="."] +autostart = true + +[connection signal="timeout" from="timer" to="." method="on_timer" binds= [&"уарэп-эмс"]] diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index b646187e..48caf186 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -326,6 +326,7 @@ vertical_alignment = 1 [node name="frame" type="NinePatchRect" parent="pribor_uf"] visible = false +self_modulate = Color(0.890196, 0.486275, 0.196078, 1) layout_mode = 0 offset_left = -14.0 offset_top = -30.0 From 7ccedcd913693d1003c2a7b5aba4b32bc906707c Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Oct 2025 12:03:22 +0300 Subject: [PATCH 033/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20UDP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 6 +++--- scripts/settings.gd | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/network.gd b/scripts/network.gd index 9e4d8fdf..0b4c58a7 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -161,8 +161,8 @@ func create_socket_udp(unit_name: StringName) -> SocketUDP: func create_socket_caps(unit_name: StringName) -> SocketUDP: var st = settings.UnitProfiles[unit_name][1] - var addr = st[0] - var port = st[1] + var addr = st[1] + var port = st[2] var sock: = SocketUDP.new() var rc: = sock.bind(port, addr) if rc == Error.OK: @@ -263,7 +263,7 @@ func _ready() -> void: units[unit_name] = new_unit units_udptx[unit_name] = new_unit dst_addrs[unit_name] = unit_profile[0] - dst_ports[unit_name] = unit_profile[2] + dst_ports[unit_name] = unit_profile[3] if proto in TCP_PROTO: var unit_tcp = TCP_PROTO[proto].new(unit_name) diff --git a/scripts/settings.gd b/scripts/settings.gd index 1c47f91a..2635a46d 100644 --- a/scripts/settings.gd +++ b/scripts/settings.gd @@ -9,8 +9,8 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ # < Название: Протокол, Адрес, <Порт>|[, Порт], Широковещательное, Привязывать, Комментарий > 'уарэп-яу07-частный': ['yau07rx', ['10.1.1.2', 50002, false, true], 'IP-адрес для приёма частных сообщений от ЯУ-07'], 'уарэп-яу07-общий': ['yau07rx', ['*', 50000, true, true], 'IP-адрес для приёма широковещательных сообщений от ЯУ-07'], - 'уарэп-капсрпб': ['capsrpb', ['127.0.0.1', 42023, 42022, false, true], 'IP-адрес для обмена сообщениями со службой \"МП550\" (СТЦ)'], - 'уарэп-трасса': ['trassa', ['127.0.0.1', 50200, 50200, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], + 'уарэп-капсрпб': ['capsrpb', ['127.0.0.1', '127.0.0.1', 42023, 42022, false, true], 'IP-адрес для обмена сообщениями со службой \"МП550\" (СТЦ)'], + 'уарэп-трасса': ['trassa', ['127.0.0.1', '127.0.0.1', 50200, 50200, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], 'уарэп-эмс': ['yau07tx', ['10.1.1.52', 50052, false, false], 'IP-адрес прибора УФ'], 'уарэп-яу07-2в': ['yau07tx', ['10.1.1.22', 50022, false, false], 'IP-адрес прибора ПРД-В2'], 'уарэп-яу07-2н': ['yau07tx', ['10.1.1.21', 50021, false, false], 'IP-адрес прибора ПРД-Н2'], From cdd59138cccf2a5bb37a2671977566dd4651e1e3 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Oct 2025 12:03:44 +0300 Subject: [PATCH 034/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-uf/pribor-uf.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/pribor-uf/pribor-uf.gd b/scenes/pribor-uf/pribor-uf.gd index 31f3ed95..958279c4 100644 --- a/scenes/pribor-uf/pribor-uf.gd +++ b/scenes/pribor-uf/pribor-uf.gd @@ -10,7 +10,7 @@ const REVFF = '(rev ff)' func _ready() -> void: if Engine.is_editor_hint(): return - var unit_uf = network.get_unit_instance('уарэп-эмс') + var unit_uf: = network.get_unit_instance('уарэп-эмс') unit_uf.connect('line_changed', on_line_changed) control_vk() From 3456eada95de2cecde198f3d00bca9a3a65f5c42 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Oct 2025 12:04:02 +0300 Subject: [PATCH 035/117] Godot4.4 --- scenes/работа/работа.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 64b1bbd5..6d645182 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -305,6 +305,6 @@ text = "Масштаб:" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] From 3f5178689d4cd13fafd5305ccc2df7e2e2dd5ec3 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Oct 2025 12:58:19 +0300 Subject: [PATCH 036/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20=D0=9D=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=B0=D0=B5=D1=82=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=BF=D1=80=D0=B8=D0=B1=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?=D0=A3=D0=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-uf/pribor-uf.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/scenes/pribor-uf/pribor-uf.gd b/scenes/pribor-uf/pribor-uf.gd index 958279c4..159c6d64 100644 --- a/scenes/pribor-uf/pribor-uf.gd +++ b/scenes/pribor-uf/pribor-uf.gd @@ -13,6 +13,7 @@ func _ready() -> void: var unit_uf: = network.get_unit_instance('уарэп-эмс') unit_uf.connect('line_changed', on_line_changed) control_vk() + on_line_changed(unit_uf) func on_timer(unit_name: StringName): From a903dae55d8f737d18af82a634e6d9f52b0026ea Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Oct 2025 16:11:39 +0300 Subject: [PATCH 037/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=97=D0=B0=D0=BF=D1=83=D1=81=D0=BA=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8=20=D0=B8=D0=B7=20=D1=84?= =?UTF-8?q?=D0=B0=D0=B9=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/interfer.gd | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/interfer.gd b/scripts/interfer.gd index 0669a1bd..7a1d7c49 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -5,7 +5,7 @@ class_name Iterfer extends Node ## Режимы помехи. const ITERFER_MODE = { INTERFER_OFF: [INTERFER_OFF, {}, 0], - 'srni1': ['ПСП + ФМ-2', SRNI1_PARAMS, 1], + 'srni1': [INTERFER_IQFILE, SRNI1_PARAMS, 1], 'srnm2': ['Линейная ЧМ', SRNM2_PARAMS, 2], 'srngps': [INTERFER_IQFILE, SRNGPS_PARAMS, 3], 'lchm1': ['Линейная ЧМ', LCHM1_PARAMS, 10], @@ -25,7 +25,10 @@ const RECOMMEND_INTERFER = { 'Линейная ЧМ': 'lchm1' } -const SRNI1_PARAMS = {'par_names' : ['freq', 'width']} +const SRNI1_PARAMS = {'files': {3: ['SRNI1_LIT4.pcm', 1220], + 4: ['SRNI1_LIT5.pcm', 1555]}, + 'call_proc': 'call_diap', + 'par_names' : ['freq', 'filename']} const SRNM2_PARAMS = {'par_names' : ['freq', 'width', 'period']} const SRNGPS_PARAMS = {'par_names' : ['freq', 'filename'], 'files': 'SRNGPS.pcm', @@ -74,7 +77,7 @@ const EXCLUDE_INTERFER = ['srni1', 'srnm2', 'srngps', 'svi1', 'svm2'] const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей. const INTERFER_OFF = 'off' const INTERFER_IQFILE = 'IQ-файл' -const POW_DEFAULT: float = 100.0 +const POW_DEFAULT: float = 50.0 var msg6_num: int = 0 ## Счётчик сообщений "тип 6" var msg8_num: int = 0 ## Счётчик сообщений "тип 8" var id_array: Array ## Массив id воздействий. @@ -419,8 +422,6 @@ func send_ecm(ecm, unit0) -> void: if ecm.krp != INTERFER_OFF: if not emit_enable: return - elif not ecm.modulation: - return msg6_num += 1 var json_data = ecm.get_msg6_data(msg6_num) unit0.tx_stack.append(json_data) From a76ec7f1b06c470498dd4e6aec050b8f7e8ff355 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Oct 2025 16:16:33 +0300 Subject: [PATCH 038/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C.=20=D0=91=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D1=88=D0=B5=20=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=B0?= =?UTF-8?q?=20=D0=BE=D1=82=20=D0=90=D0=A4=D0=A1=D0=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.godot | 4 ++-- scenes/pribor-afsp/pribor-afsp-1.tscn | 4 ++-- scenes/pribor-afsp/pribor-afsp-2.tscn | 1 + scenes/pribor-afsp/pribor-afsp.gd | 3 ++- scenes/pribor-afsp/pribor-bpo.tscn | 3 ++- scenes/контроль/request.gd | 3 +-- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/project.godot b/project.godot index 1fa004a5..de2e4e59 100644 --- a/project.godot +++ b/project.godot @@ -31,11 +31,11 @@ interfer/select_color=Vector3(1, 1, 1) interfer/interfer_color=Vector3(0.58, 0.47, 0.51) interfer/resend_timeout=1000.0 config/external_cu=false -config/unit_rr_request_period=20.0 +config/unit_rr_request_period=30.0 config/kems_files_path="user://kems/" config/emsg_files_path="user://emsg/" config/settings_path="user://settings.json" -config/unit_bpo_request_period=20.0 +config/unit_bpo_request_period=30.0 [autoload] diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn index 3081df5c..58cb3de7 100644 --- a/scenes/pribor-afsp/pribor-afsp-1.tscn +++ b/scenes/pribor-afsp/pribor-afsp-1.tscn @@ -7,7 +7,7 @@ [sub_resource type="GDScript" id="GDScript_yhnwg"] script/source = "extends Timer -func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_rr_request_period') +func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_bpo_request_period') " [node name="pribor_afsp" type="Control"] @@ -29,7 +29,7 @@ projsettings_path_left = "application/config/Адрес АФСП левого б projsettings_path_right = "application/config/Адрес АФСП правого борта" [node name="timer" type="Timer" parent="request"] -wait_time = 20.0 +wait_time = 30.0 autostart = true script = SubResource("GDScript_yhnwg") diff --git a/scenes/pribor-afsp/pribor-afsp-2.tscn b/scenes/pribor-afsp/pribor-afsp-2.tscn index 2f252167..1bbfa3d4 100644 --- a/scenes/pribor-afsp/pribor-afsp-2.tscn +++ b/scenes/pribor-afsp/pribor-afsp-2.tscn @@ -29,6 +29,7 @@ projsettings_path_left = "application/config/Адрес АФСП левого б projsettings_path_right = "application/config/Адрес АФСП правого борта" [node name="timer" type="Timer" parent="request"] +wait_time = 30.0 autostart = true script = SubResource("GDScript_yhnwg") diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index d7d5ca14..cc24c2bb 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -7,6 +7,7 @@ class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd' static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') +# SystemName: "gen" DevList - там состояние связи с генератором по кан шине func _on_request_completed(result, _response_code, headers, body: PackedByteArray): @@ -50,7 +51,7 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra var received_afsp_name: StringName = ret_val[0] if this_afsp_name != received_afsp_name: - push_error('не известное устройство: \"%s\"' % received_afsp_name) + push_error('не известное устройство: \"%s\", ожидадось: \"%s\"' % [received_afsp_name, this_afsp_name]) return if not unit_instance.online: diff --git a/scenes/pribor-afsp/pribor-bpo.tscn b/scenes/pribor-afsp/pribor-bpo.tscn index 0dc97f30..c1951261 100644 --- a/scenes/pribor-afsp/pribor-bpo.tscn +++ b/scenes/pribor-afsp/pribor-bpo.tscn @@ -198,13 +198,14 @@ self_size = Vector2i(50, 145) fname = "Яч. связи" [node name="request" type="HTTPRequest" parent="."] +use_threads = true script = ExtResource("4_crej3") projsettings_path_left = "application/config/Адрес БПО левого борта" projsettings_path_right = "application/config/Адрес БПО правого борта" projsettings_path_wait_time = "application/config/Период опроса состояния БПО, секунды" [node name="timer" type="Timer" parent="request"] -wait_time = 5.0 +wait_time = 30.0 autostart = true script = SubResource("GDScript_bhc4e") diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd index 94815447..92cbd33f 100644 --- a/scenes/контроль/request.gd +++ b/scenes/контроль/request.gd @@ -64,11 +64,10 @@ func _ready(): func _on_request_timer(): - cancel_request() var addr = [addr_right, addr_left][i_bort] var hdrs = [headers_right, headers_left][i_bort] var rc: = request(addr, hdrs) if rc != Error.OK: var s: String = '%s: %s' % [error_string(rc), addr] log.error('%s' % s) - i_bort = (i_bort + 1) % 2 + i_bort = (i_bort + 1) % 2 From 667f4f052ffdb67c769ac338791a80a778f59cf6 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 2 Oct 2025 16:18:00 +0300 Subject: [PATCH 039/117] Godot4.4 --- scenes/работа/работа.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 6d645182..64b1bbd5 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -305,6 +305,6 @@ text = "Масштаб:" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] From bf2c24b1a57580fc929db39f612c2ca03acec283 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 5 Oct 2025 14:47:00 +0300 Subject: [PATCH 040/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=20=D0=A1=D0=9A=D0=92.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 41d1abca..a3b149bc 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ override.cfg # контроль версий scripts/commit.gd +*.bak + # python специфичное modbus/pymodbus/__pycache__ modbus/serial/__pycache__ From b634a607ace31f14102e367731972d2b05aac449 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 5 Oct 2025 14:54:31 +0300 Subject: [PATCH 041/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20?= =?UTF-8?q?=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B3=D0=BE=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D0=B0=20=D0=90=D0=A4=D0=A1=D0=9F=20=D0=B8=20=D0=91=D0=9F=D0=9E?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D0=B8=D1=82?= =?UTF-8?q?=D1=81=D1=8F=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B5=D0=B4=D1=8B=D0=B4=D1=83=D1=89=D0=B5=D0=B3=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.godot | 4 ++-- scenes/контроль/request.gd | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/project.godot b/project.godot index de2e4e59..3345a9ef 100644 --- a/project.godot +++ b/project.godot @@ -31,11 +31,11 @@ interfer/select_color=Vector3(1, 1, 1) interfer/interfer_color=Vector3(0.58, 0.47, 0.51) interfer/resend_timeout=1000.0 config/external_cu=false -config/unit_rr_request_period=30.0 +config/unit_rr_request_period=5.0 config/kems_files_path="user://kems/" config/emsg_files_path="user://emsg/" config/settings_path="user://settings.json" -config/unit_bpo_request_period=30.0 +config/unit_bpo_request_period=5.0 [autoload] diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd index 92cbd33f..9987069f 100644 --- a/scenes/контроль/request.gd +++ b/scenes/контроль/request.gd @@ -64,10 +64,11 @@ func _ready(): func _on_request_timer(): + if HTTPClient.Status.STATUS_REQUESTING == get_http_client_status(): + return var addr = [addr_right, addr_left][i_bort] var hdrs = [headers_right, headers_left][i_bort] var rc: = request(addr, hdrs) if rc != Error.OK: - var s: String = '%s: %s' % [error_string(rc), addr] - log.error('%s' % s) + push_error('%s: \"%s\"' % [error_string(rc), addr]) i_bort = (i_bort + 1) % 2 From 22620ddc95dbf6f326fec635b9f668a93bb2c6dc Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 5 Oct 2025 18:33:07 +0300 Subject: [PATCH 042/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B0=20?= =?UTF-8?q?=D0=95=D0=9F=D0=A0=D0=9B=D0=A1.=20=D0=92=D1=8B=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B5=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B4=D1=83=D0=B5=D0=BC=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D0=B0=20=D0=BF=D0=BE=D0=BC=D0=B5?= =?UTF-8?q?=D1=85=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/button-flat/button-flat.tscn | 1 + scenes/button-flat/nine-patch-button.gd | 5 ++++ scenes/frame-ecm-list/scroll-ecm-list.gd | 13 ++------- scenes/grid-buttons-ecm/grid-buttons-ecm.tscn | 12 +++++++- scenes/журнал/журнал.gd | 2 +- scenes/работа/работа.gd | 7 ----- scripts/interfer.gd | 28 +++++++++++++++---- 7 files changed, 43 insertions(+), 25 deletions(-) diff --git a/scenes/button-flat/button-flat.tscn b/scenes/button-flat/button-flat.tscn index 6fe161c8..a35c4c31 100644 --- a/scenes/button-flat/button-flat.tscn +++ b/scenes/button-flat/button-flat.tscn @@ -79,6 +79,7 @@ axis_stretch_vertical = 2 layout_mode = 2 theme_override_colors/font_outline_color = Color(0, 0, 0, 1) theme_override_constants/outline_size = 4 +theme_override_font_sizes/font_size = 15 theme_override_styles/focus = SubResource("4") theme_override_styles/disabled = SubResource("5") theme_override_styles/hover = SubResource("2") diff --git a/scenes/button-flat/nine-patch-button.gd b/scenes/button-flat/nine-patch-button.gd index 7e2e61d0..10a93a27 100644 --- a/scenes/button-flat/nine-patch-button.gd +++ b/scenes/button-flat/nine-patch-button.gd @@ -59,6 +59,11 @@ var _pressed: = false $button.set_toggle_mode(val) +@export var font_size: int = 15: + set(val): + $button.add_theme_font_size_override('theme_override_font_sizes/font_size', val) + + func set_pressed(val: bool): pressed = val diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index 95fe1072..cfd7603b 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -36,7 +36,8 @@ const INTERFER_NAMES = { 'svi1': 'СВ-И1', 'k1': 'K1', 'svm2': 'СВ-М2', - 'ozp1': 'ОЗП-1'} + 'ozp1': 'ОЗП-1', + 'eprls': 'ЕПРЛС',} ## Индексы колонок @@ -121,21 +122,13 @@ func on_interfer_new(ecm, table_index): signaller.emit_signal('interfer_selected', ecm) -func on_interfer_off(ecm, ecms, thrs, table_index): - var sz = ecms.size() +func on_interfer_off(ecm, table_index): $table.remove_row(table_index[ecm.ispp]) rehash(table_index) - ecms.erase(ecm.ispp) - thrs.erase(ecm.ispp) - interfer.cu.erase(ecm.ispp) - interfer.fs.erase(ecm.ispp) - interfer.push_id(ecm.ispp) var sel_rows: Array $table.get_selected_rows(sel_rows) if not len(sel_rows): signaller.emit_signal('interfer_selected', null) - if sz != ecms.size(): - interfer.call_deferred('emit_signal', 'interfer_resized', ecms) ## Перестраивает индекс таблицы. Вызывать при удалении строки diff --git a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn index 3c28e215..b9efbe39 100644 --- a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn +++ b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn @@ -5,7 +5,7 @@ [node name="grd_btns" type="GridContainer"] offset_right = 1096.0 offset_bottom = 54.0 -columns = 15 +columns = 16 [node name="btn_off" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] layout_mode = 2 @@ -141,3 +141,13 @@ strips_rotation = 30.0 text = "ОЗП-1" disabled = true metadata/rfi_name = "ozp1" + +[node name="btn_p19" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +strips_rotation = 30.0 +text = "ЕПРЛС" +disabled = true +font_size = 1 +metadata/rfi_name = "eprls" diff --git a/scenes/журнал/журнал.gd b/scenes/журнал/журнал.gd index dc5ab850..401ad0d8 100644 --- a/scenes/журнал/журнал.gd +++ b/scenes/журнал/журнал.gd @@ -5,7 +5,7 @@ func on_line_changed(unit_inst): log.message(Logger.INFO, '\"%s\" изменен func on_command_fail(unit_inst): log.message(Logger.ERROR, '\"%s\" команда не выполнена' % unit_inst.name) func on_threats_changed(th: Object, msg: String): log.message(Logger.INFO, '%s: %s' % [msg, th.to_string()]) func on_parse_error(unit_inst, msg: String): log.message(Logger.ERROR, '%s: %s' % [unit_inst.name, msg]) -func on_interfer_off(ecm, _ecms, _thrs,msg: String): log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()]) +func on_interfer_off(ecm, msg: String): log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()]) func on_set_program_mode(msg: String): log.message(Logger.INFO, msg) func on_interfer_new(ecm, msg: String): diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 1f150bc9..130a1f91 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -237,13 +237,6 @@ func on_interfer_off_all(): update_fs_colors() -func on_interfer_off(ecm_id): - fs_active.erase(ecm_id) - fs_selected.erase(ecm_id) - fs_active.clear() - update_fs_colors() - - ## Обработчик сигнала обнаружения цели. func on_threat_new(th) -> void: var bip = Bip.instantiate() diff --git a/scripts/interfer.gd b/scripts/interfer.gd index 7a1d7c49..514b9d7b 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -18,7 +18,8 @@ const ITERFER_MODE = { 'svi1': [INTERFER_IQFILE, SVI1_PARAMS, 20], 'svm2': [INTERFER_IQFILE, SVM2_PARAMS, 21], 'k1': [INTERFER_IQFILE, K1_PARAMS, 50], - 'ozp1': [INTERFER_IQFILE, OZP1_PARAMS, 51] } + 'ozp1': [INTERFER_IQFILE, OZP1_PARAMS, 51], + 'eprls': [INTERFER_IQFILE, EPRLS_PARAMS, 52] } const RECOMMEND_INTERFER = { 'ПСП + ФМ-2': 'srni1', @@ -62,7 +63,9 @@ const SVM2_PARAMS = {'files': {1: ['SVM2_LIT2.pcm', 1017], 2: ['SVM2_LIT3.pcm', 1156]}, 'call_proc': 'call_diap', 'par_names' : ['freq', 'filename']} - +const EPRLS_PARAMS = {'files' : 'ERLS.pcm', + 'call_proc' : 'call_all_diap', + 'par_names' : ['freq', 'filename']} # Файл : Ключ (ширина): ['имя файла'] const PDCHM_PARAMS = {'files': { 5 : 'pdchm_5.pcm', @@ -181,7 +184,7 @@ func _ready() -> void: signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(unit_caps)) signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all').bind(unit_caps, ecms)) signaller.connect('th_aoa_update', Callable(self, 'on_th_aoa_update').bind(ecms, unit_caps)) - signaller.connect('interfer_off', Callable(self, 'on_interfer_off')) + signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind(ecms)) signaller.connect('manual_control', Callable(self, 'on_manual_control')) signaller.connect('full_auto', Callable(self, 'on_full_auto')) signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno')) @@ -410,7 +413,7 @@ func interfer_create(u, interfer_name, ecms, param, kni, id, dict, source_interf log.error('Ошибка выбора модуля ФС для помехи: %s' %[ecm.ispp]) signaller.emit_signal('interfer_new', ecm) if interfer_name == 'off': - signaller.emit_signal('interfer_off', ecm, ecms, thrs) + signaller.emit_signal('interfer_off', ecm) thrs.erase(ispp) ecm.tick_tx = Time.get_ticks_msec() send_ecm(ecm, u) @@ -421,6 +424,8 @@ func interfer_create(u, interfer_name, ecms, param, kni, id, dict, source_interf func send_ecm(ecm, unit0) -> void: if ecm.krp != INTERFER_OFF: if not emit_enable: + ecm.svk = 0 + call_deferred('emit_signal', 'interfer_update', ecm) return msg6_num += 1 var json_data = ecm.get_msg6_data(msg6_num) @@ -431,7 +436,7 @@ func on_interfer_off_all(unit0, ecms: Dictionary) -> void: for ecm in ecms.values(): ecm.krp = INTERFER_OFF send_ecm(ecm, unit0) - signaller.emit_signal('interfer_off', ecm, ecms, thrs) + signaller.emit_signal('interfer_off', ecm) func on_threats_lost(th, ecms, unit0) -> void: @@ -441,7 +446,7 @@ func on_threats_lost(th, ecms, unit0) -> void: var ecm = ecms[ecm_id] ecm.krp = INTERFER_OFF send_ecm(ecm, unit0) - signaller.emit_signal('interfer_off', ecm, ecms, thrs) + signaller.emit_signal('interfer_off', ecm) func pop_id() -> int: @@ -613,3 +618,14 @@ func get_krp(threat: threats.Threat): krp = key return krp return krp + + +func on_interfer_off(ecm: Interfer, ecms): + var sz = ecms.size() + ecms.erase(ecm.ispp) + thrs.erase(ecm.ispp) + interfer.cu.erase(ecm.ispp) + interfer.fs.erase(ecm.ispp) + interfer.push_id(ecm.ispp) + if sz != ecms.size(): + interfer.call_deferred('emit_signal', 'interfer_resized', ecms) From dfafd9861bea7c11cfb0286a5ca7ae138f4c9327 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 5 Oct 2025 18:33:20 +0300 Subject: [PATCH 043/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/frame-ecm-list/scroll-ecm-list.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index cfd7603b..b1a72d9a 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -20,7 +20,7 @@ const INTERFER_STATE = { 5: '' } -## Состояние выполнения сеанса помехи +## Названия помех const INTERFER_NAMES = { 'off': 'Откл', 'mchm1': 'МЧМ-1', From 91209a96566cc23e710bfe3396c64ac7737fbc6e Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 6 Oct 2025 00:16:30 +0300 Subject: [PATCH 044/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9D=D0=B5=D0=BC=D0=BD=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=B4=D1=80=D1=83=D0=B3=D0=BE=D0=B9=20=D0=B2=D0=B8?= =?UTF-8?q?=D0=B4=20=D0=BE=D1=82=D0=BC=D0=B5=D1=82=D0=BE=D0=BA=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/bip/bip.tscn | 64 +++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/scenes/bip/bip.tscn b/scenes/bip/bip.tscn index 7bfe5028..1cb79e0b 100644 --- a/scenes/bip/bip.tscn +++ b/scenes/bip/bip.tscn @@ -23,7 +23,9 @@ const float radius = 0.075 - ds * 2.0; /* Радиус долж uniform float speed: hint_range(-1024.0, 1024.0) = 0.0; /* Время вспышки при обновлении, c */ uniform int ant_band_count_0 = 3; -const float ant_band_r0_0 = 0.32; +const float ant_band_r0_0 = 0.27 + +; const float ant_band_r1_0 = 0.47; @@ -97,7 +99,7 @@ void fragment() shader = SubResource("Shader_60ho7") shader_parameter/color = Color(1, 1, 1, 0.968627) shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = 73.0 +shader_parameter/speed = -118.48 shader_parameter/ant_band_count_0 = 3 [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_hqs6j"] @@ -185,20 +187,11 @@ void fragment() } " -[sub_resource type="ShaderMaterial" id="ShaderMaterial_lpmq6"] -shader = SubResource("Shader_81bae") -shader_parameter/color = Color(0.0862745, 0.560784, 0.72549, 0.886275) -shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = 23.0 -shader_parameter/ant_band_count_0 = 9 -shader_parameter/ant_band_r0_0 = 0.38 -shader_parameter/ant_band_r1_0 = 0.47 - [sub_resource type="ShaderMaterial" id="ShaderMaterial_h3oo7"] shader = SubResource("Shader_81bae") shader_parameter/color = Color(1, 0, 0, 1) shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = 135.76 +shader_parameter/speed = 85.808 shader_parameter/ant_band_count_0 = 4 shader_parameter/ant_band_r0_0 = 0.3 shader_parameter/ant_band_r1_0 = 0.45 @@ -213,50 +206,63 @@ shader_parameter/point_5 = Vector2(0.214, 0.125) shader_parameter/point_6 = Vector2(0.25, 0.125) shader_parameter/point_7 = Vector2(0.125, 0.214) shader_parameter/point_8 = Vector2(0.125, 0.25) -shader_parameter/len = 0.264 +shader_parameter/len = 0.179 shader_parameter/speed = 63.0 [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_svd33"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_lpmq6"] +shader = SubResource("Shader_81bae") +shader_parameter/color = Color(0.0784314, 0.501961, 0.701961, 0.917647) +shader_parameter/color_up = Color(1, 1, 1, 0) +shader_parameter/speed = 158.179 +shader_parameter/ant_band_count_0 = 9 +shader_parameter/ant_band_r0_0 = 0.27 +shader_parameter/ant_band_r1_0 = 0.45 + [node name="threat" type="Control"] layout_mode = 3 anchors_preset = 0 -offset_right = 28.0 -offset_bottom = 28.0 +offset_left = -12.0 +offset_top = -12.0 +offset_right = 12.0 +offset_bottom = 12.0 script = ExtResource("1_h7l70") [node name="bip" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_qq6yq") -position = Vector2(14, 14) -scale = Vector2(28, 28) +position = Vector2(12, 12) +scale = Vector2(14, 14) texture = SubResource("PlaceholderTexture2D_xbpqf") [node name="selector" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_fkqwb") -scale = Vector2(28, 28) +position = Vector2(-1, -1) +scale = Vector2(26, 26) texture = SubResource("PlaceholderTexture2D_hqs6j") -centered = false - -[node name="recomendation" type="Sprite2D" parent="."] -visible = false -material = SubResource("ShaderMaterial_lpmq6") -scale = Vector2(28, 28) -texture = SubResource("PlaceholderTexture2D_hqs6j") -centered = false +offset = Vector2(0.5, 0.5) [node name="ecm_done" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_h3oo7") +position = Vector2(-2, -2) scale = Vector2(28, 28) texture = SubResource("PlaceholderTexture2D_hqs6j") -centered = false +offset = Vector2(0.5, 0.5) [node name="track" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_lkrha") -position = Vector2(14, 14) -scale = Vector2(28, 28) +position = Vector2(12, 12) +scale = Vector2(34, 34) texture = SubResource("PlaceholderTexture2D_svd33") +[node name="recomendation" type="Sprite2D" parent="."] +visible = false +material = SubResource("ShaderMaterial_lpmq6") +scale = Vector2(24, 24) +texture = SubResource("PlaceholderTexture2D_hqs6j") +offset = Vector2(0.5, 0.5) + [connection signal="gui_input" from="." to="." method="_on_bip_gui_input"] From f212aea7bf13a38052408cb64047e5dcfb50e9ae Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 6 Oct 2025 00:18:52 +0300 Subject: [PATCH 045/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9A=D0=BE=D0=BB=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=BE=20=D0=BE=D0=BF=D0=B0=D1=81=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D1=86=D0=B5=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 130a1f91..02bd4ac0 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -72,10 +72,6 @@ const VAL_TO_EVENT = { true: 'full_auto' } ## Выбор целей и установка помех автоматически. -## Обработчик сигнала изменения списка целей. -func on_threats_resized(threats: Dictionary): $count_all_pad/count_all.text = '%02d' % threats.size() - - ## Обработчик выбора цели. func on_threat_selected(th, ecm_btns): on_rto_threat_sel(th.id, ecm_btns) @@ -84,6 +80,13 @@ func on_threat_selected(th, ecm_btns): on_rto_threat_sel(th.id, ecm_btns) func on_enter_tree() -> void: call_deferred('on_button_strobe_pressed') +## Обработчик сигнала изменения списка целей. +func on_threats_resized(ths: Dictionary): + $count_all_pad/count_all.text = '%02d' % ths.size() + var c: int = ths.values().filter(func(th: threats.Threat): return th.proto != '').size() + $count_danger_pad/count_danger.text = '%02d' % c + + ## Обработчик нажатия на кнопку вид. func on_button_view_toggled(toggled: bool): signaller.emit_signal('map_mode_changed', int(toggled)) From a7d5f081a3c0236ea14a234452cf98bed4bda8ca Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 6 Oct 2025 00:20:04 +0300 Subject: [PATCH 046/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20=D0=91=D1=8B=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5.=20=D0=92=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=20=D0=BE=D0=B1=D1=80=D0=B0=D1=89=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=BA=20=D0=BD=D0=B5=D1=81=D1=83=D1=89=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D1=83=D1=8E=D1=89=D0=B5=D0=BC=D1=83=20=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 02bd4ac0..583da524 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -431,6 +431,9 @@ func sel_fs_sector(event): func set_fs_color(ecm): + if prd.fs_caps_id.has(ecm.nmfs): + push_warning('нет такого модуля ФС: %d, но имеется: %s' % [ecm.nmfs, prd.fs_caps_id.keys()]) + return if ecm.krp != interfer.INTERFER_OFF: fs_active[prd.fs_caps_id[ecm.nmfs]] = null else: From 60d9640a5cce1f0e2fa7be14f0f1294ab31db557 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 6 Oct 2025 00:20:55 +0300 Subject: [PATCH 047/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D0=BF=D0=BE=D0=B4=D1=81=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B0=D1=82=D0=BE=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.tscn | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 64b1bbd5..73bf583a 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -200,6 +200,7 @@ offset_left = 115.0 offset_top = 1085.0 offset_right = 257.0 offset_bottom = 1112.0 +tooltip_text = "Автоматический выбор цели и помехи" action_mode = 0 text = "Автоматически" @@ -256,6 +257,7 @@ offset_top = 995.0 offset_right = 1136.0 offset_bottom = 1127.0 scale = Vector2(0.5, 0.5) +tooltip_text = "Применение выбранного режима помехи" toggle_mode = true button_pressed = true action_mode = 0 @@ -280,11 +282,23 @@ offset_top = 1005.0 offset_right = 1030.0 offset_bottom = 1121.0 scale = Vector2(0.5, 0.5) +tooltip_text = "Устанавливает центр карты на текущие координаты" toggle_mode = true button_pressed = true texture_normal = ExtResource("12_5ffal") texture_pressed = ExtResource("13_ggrwd") +[node name="label" type="Label" parent="btn_center"] +layout_mode = 0 +offset_left = -32.0 +offset_top = 100.0 +offset_right = 65.0 +offset_bottom = 119.0 +scale = Vector2(2, 2) +text = "Центрировать" +horizontal_alignment = 1 +vertical_alignment = 1 + [node name="coordinates_map" type="Label" parent="."] layout_mode = 0 offset_left = 1000.0 From da15b924087b4ba2ebf33d8e3bf10bd8e556a06c Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 6 Oct 2025 17:46:25 +0300 Subject: [PATCH 048/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=92=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5?= =?UTF-8?q?=D1=81=D1=81=D0=B5.=20=D0=92=D1=80=D0=B0=D1=89=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=20=D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5?= =?UTF-8?q?=D1=82=D1=81=D0=B2=D0=B8=D0=B8=20=D1=81=20=D0=BA=D1=83=D1=80?= =?UTF-8?q?=D1=81=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 2 ++ scenes/tilemap/tilemap.gd | 7 ++++--- scenes/работа/работа.gd | 6 ++++++ shaders/antenas.tres | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index e8280394..862f3855 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -13,6 +13,7 @@ func _ready() -> void: func sv(val: float) -> float: return val / ($строб.scale.x / 2.0) * 0.125 +func set_canvas_rotation(val: float) -> void: material.set('shader_parameter/rotation', val) func set_strob_visible(val: bool): $строб.visible = val func set_strob_center(val: Vector2): $строб.position = val func set_strob_dir(val: float): $строб.set_instance_shader_parameter('dir', val) @@ -29,6 +30,7 @@ func get_strob_band() -> float: return $строб.get_instance_shader_param func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0 func get_strob_color() -> float: return $строб.get_instance_shader_parameter('color') +func get_canvas_rotation() -> float: return material.get('shader_parameter/rotation') func get_radius_outter() -> float: return material.get('shader_parameter/radius_outter') func get_radius_inner_0() -> float: return material.get('shader_parameter/radius_inner_0') func get_radius_inner_1() -> float: return material.get('shader_parameter/radius_inner_1') diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index d06c8f06..2cbdfb35 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -152,7 +152,7 @@ func on_data_received(coords: Dictionary) -> void: if not is_centered: return if coords.has_all(['latitude', 'longitude']): - set_coordinates(coords['longitude'], coords['latitude']) + set_coordinates(coords['longitude'], coords['latitude'], coords['k']) func _on_resize() -> void: @@ -677,7 +677,7 @@ func clear() -> void: queue_redraw() -func set_coordinates(lon: float, lat: float) -> void: +func set_coordinates(lon: float, lat: float, course: float) -> void: var anim: Animation = $player.get_animation('goto') var new_pos: Vector2 = lonlat_to_world(lon, lat) anim.track_insert_key(0, 0, _xyz.x) @@ -690,7 +690,8 @@ func set_coordinates(lon: float, lat: float) -> void: ship_instance = ship_mark.instantiate() add_mark_from_lon_lat(ship_id, lon, lat, ship_instance, 0.0) else: - _marks[ship_id].position = lonlat_to_world(lon, lat) + ship_instance.position = lonlat_to_world(lon, lat) + ship_instance.rotation_degrees = course - 90 func blend_mask(val: bool) -> void: diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 583da524..6cb7d8d2 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -143,6 +143,8 @@ func _ready(): signaller.connect('map_user_panning', Callable(self, 'on_user_panning')) signaller.connect('update_coordinates_map', Callable(self, 'on_update_coordinates_label')) signaller.connect('update_scale_map', Callable(self, 'on_update_scale_label')) + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_navi_data_received) on_btn_center_toggled(true) on_btn_activate_toggled(true) #$canvas.add_seczap(0, Vector4(372, 0, 30, 348)) @@ -154,6 +156,10 @@ func _ready(): #$canvas.set_seczap_color(3, Color.CHARTREUSE) +func on_navi_data_received(data: Dictionary): + $canvas.set_canvas_rotation(data.get('k', 0.0)) + + func on_user_panning(): $btn_center.button_pressed = false diff --git a/shaders/antenas.tres b/shaders/antenas.tres index 87248d14..0c40d21f 100644 --- a/shaders/antenas.tres +++ b/shaders/antenas.tres @@ -90,7 +90,7 @@ void antenas(inout vec4 c, vec2 uv, vec2 p0, int cnt, float r0, float r1, inout void vertex() { - rotate_vec2(VERTEX, radians(rotation), pc0); + rotate_vec2(VERTEX, radians(360.0 - rotation), pc0); } From 6c60eeda74d6725dcb69f027649b6e3bd9cef721 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 6 Oct 2025 17:47:02 +0300 Subject: [PATCH 049/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20=D0=9D=D0=B5=D1=82=20=D0=B8=D0=BD=D0=B4?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D0=B8=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D1=8B=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D1=8F=20=D0=A4?= =?UTF-8?q?=D0=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 6cb7d8d2..550efc6f 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -437,7 +437,7 @@ func sel_fs_sector(event): func set_fs_color(ecm): - if prd.fs_caps_id.has(ecm.nmfs): + if not prd.fs_caps_id.has(ecm.nmfs): push_warning('нет такого модуля ФС: %d, но имеется: %s' % [ecm.nmfs, prd.fs_caps_id.keys()]) return if ecm.krp != interfer.INTERFER_OFF: From 482d1f6dda9c463a119bc173786b02f4de81e116 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 7 Oct 2025 12:43:06 +0300 Subject: [PATCH 050/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A6=D0=B2=D0=B5=D1=82=20=D0=B0=D0=BD?= =?UTF-8?q?=D1=82=D0=B5=D0=BD=D0=BD=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C?= =?UTF-8?q?=20Color,=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20Vector3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.godot | 8 ++++---- scenes/diagram/diagram.gd | 6 +++--- scenes/работа/работа.gd | 4 ++-- shaders/antenas.tres | 17 ++++++++--------- shaders/sector.gdshader | 4 ++-- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/project.godot b/project.godot index 3345a9ef..74bb0bbb 100644 --- a/project.godot +++ b/project.godot @@ -25,10 +25,10 @@ config/map_tile_size=256 config/map_minimum_zoom=5 config/map_maximum_zoom=19 interfer/center_offset=Vector2(200, 225) -interfer/default_color0=Vector3(0.38, 0.47, 0.51) -interfer/default_color1=Vector3(0.39, 0.44, 0.5) -interfer/select_color=Vector3(1, 1, 1) -interfer/interfer_color=Vector3(0.58, 0.47, 0.51) +interfer/default_color0=Color(0.38, 0.47, 0.51, 1) +interfer/default_color1=Color(0.39, 0.44, 0.5, 1) +interfer/select_color=Color(1, 1, 1, 1) +interfer/interfer_color=Color(0.58, 0.47, 0.51, 1) interfer/resend_timeout=1000.0 config/external_cu=false config/unit_rr_request_period=5.0 diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index 862f3855..accc1a84 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -2,7 +2,7 @@ class_name Diagram extends Sprite2D const NUM_OF_RANGE = 7 const NUM_OF_DIRECTIONS = 4 -var fs_default_colors: Array ## Цвета по умолчанию для блоков ФС. +var fs_default_colors: Array[Color] ## Цвета по умолчанию для блоков ФС. @export var SecZap: PackedScene @@ -93,8 +93,8 @@ func set_view_mode(val: int): ## Закрашивание по умолчанию блоков ФС цветами из настроек. func set_def_colors(): - var color0: Vector3 = ProjectSettings.get_setting('application/interfer/default_color0', Vector3(0.38, 0.47, 0.51)) - var color1: Vector3 = ProjectSettings.get_setting('application/interfer/default_color1', Vector3(0.39, 0.44, 0.50)) + var color0: Color = ProjectSettings.get_setting('application/interfer/default_color0', Color(0.38, 0.47, 0.51, 1.0)) + var color1: Color = ProjectSettings.get_setting('application/interfer/default_color1', Color(0.39, 0.44, 0.50, 1.0)) var col_arr: Array = [color0, color1] var col = false for i in NUM_OF_RANGE: diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 550efc6f..0fbe42f1 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -449,8 +449,8 @@ func set_fs_color(ecm): func update_fs_colors(): var fs_colors = $canvas.fs_default_colors.duplicate() - var color_ecm: Vector3 = ProjectSettings.get_setting('application/interfer/interfer_color', Vector3(0.58, 0.47, 0.51)) - var color_select: Vector3 = ProjectSettings.get_setting('application/interfer/select_color', Vector3(1.0, 1.0, 1.0)) + var color_ecm: Color = ProjectSettings.get_setting('application/interfer/interfer_color', Color(0.58, 0.47, 0.51, 1.0)) + var color_select: Color = ProjectSettings.get_setting('application/interfer/select_color', Color(1.0, 1.0, 1.0, 1.0)) for key in fs_active.keys(): fs_colors[key] = color_ecm for key in fs_selected.keys(): diff --git a/shaders/antenas.tres b/shaders/antenas.tres index 0c40d21f..74c1d79c 100644 --- a/shaders/antenas.tres +++ b/shaders/antenas.tres @@ -1,4 +1,4 @@ -[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://s6xe8igevnv2"] +[gd_resource type="ShaderMaterial" load_steps=2 format=4 uid="uid://s6xe8igevnv2"] [sub_resource type="Shader" id="1"] code = "shader_type canvas_item; @@ -15,6 +15,7 @@ uniform vec4 color1: source_color = vec4(0.39, 0.44, 0.50, 0.4); uniform float radius_inner_0 = RADIUS_INNER_0; uniform float radius_inner_1 = RADIUS_INNER_1; uniform float radius_outter = 550.0; /* Радиус внешний. Должно быть равно ant_band_r1_6 */ +uniform float alpha: hint_range(0.0, 1.0) = 0.5; uniform int mode = 0; /* Режим отображения. Приоритет РТО - 0, приоритет РЛС - 1 */ const int ant_band_count_0 = 2; @@ -41,8 +42,7 @@ const float ant_band_r1_4[] = {450.0, 530.0}; const float ant_band_r1_5[] = {500.0, 540.0}; const float ant_band_r1_6[] = {550.0, 550.0}; -uniform vec3 ant_band_c[28]; - +uniform vec4 ant_band_c[28]; const float d4 = 90.0; const float ds = 1.0; @@ -76,11 +76,9 @@ void antenas(inout vec4 c, vec2 uv, vec2 p0, int cnt, float r0, float r1, inout index--; j = index - 3; } - col.x = ant_band_c[j].x; - col.y = ant_band_c[j].y; - col.z = ant_band_c[j].z; + col.rgb = ant_band_c[j].rgb; index++; - col.a = 0.5; + col.a = alpha; float v = float(i & 1); vec4 color = v * col + (1.0f - v) * col; sector(c, uv, p0, float(i) * da, da, r0, r1, color); @@ -98,7 +96,7 @@ void fragment() { ivec2 isz = textureSize(TEXTURE, 0); vec2 uv = UV * vec2(float(isz.x), float(isz.y)); // координаты текущей точки в пикселях - COLOR = vec4(0, 0, 0, 0); //texture(TEXTURE, UV); // Цвет текущей точки + COLOR = vec4(0, 0, 0, 0); int index = 0; // Сетка антенн antenas(COLOR, uv, pc0, ant_band_count_0, ant_band_r0_0[mode], ant_band_r1_0[mode], index); @@ -120,5 +118,6 @@ shader_parameter/color1 = Color(0.3315, 0.45645, 0.51, 0.537255) shader_parameter/radius_inner_0 = 200.0 shader_parameter/radius_inner_1 = 480.0 shader_parameter/radius_outter = 550.0 +shader_parameter/alpha = 0.5 shader_parameter/mode = 0 -shader_parameter/ant_band_c = PackedVector3Array(0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5) +shader_parameter/ant_band_c = PackedVector4Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) diff --git a/shaders/sector.gdshader b/shaders/sector.gdshader index f3783bf5..d73ad643 100644 --- a/shaders/sector.gdshader +++ b/shaders/sector.gdshader @@ -14,8 +14,8 @@ instance uniform float inner_clip: hint_range(0.0, 0.125) = 0.045; const vec2 center = vec2(0.125, 0.125); /* Центр. Должен быть в (0.5, 0.5), но это не так */ -const float dsa = 0.0025; /* Относительное расстояние на котором выполняется сглаживание краёв по радиальным линиям */ -const float dsr = 0.00025; /* Относительное расстояние на котором выполняется сглаживание краёв по круговым линиям */ +const float dsa = 0.003; /* Относительное расстояние на котором выполняется сглаживание краёв по радиальным линиям */ +const float dsr = 0.0003; /* Относительное расстояние на котором выполняется сглаживание краёв по круговым линиям */ vec4 sector(vec4 c, vec2 uv_pos, float r0, float r1, float w) From 31602bfa1926f5ac4aa64ff145e33e89d11a9b2f Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 7 Oct 2025 14:36:17 +0300 Subject: [PATCH 051/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9C=D0=B5=D0=BD=D1=8C=D1=88=D0=B5=20?= =?UTF-8?q?=D1=81=D0=B8=D0=BC=D0=B2=D0=BE=D0=BB=D0=BE=D0=B2=20=D0=BF=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B5=20=D0=B7=D0=B0=D0=BF=D1=8F=D1=82=D0=BE=D0=B9?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=B2=20=D1=86=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/frame-threats/scroll-threats.gd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scenes/frame-threats/scroll-threats.gd b/scenes/frame-threats/scroll-threats.gd index a0f2056c..e2ef9d3b 100644 --- a/scenes/frame-threats/scroll-threats.gd +++ b/scenes/frame-threats/scroll-threats.gd @@ -89,7 +89,8 @@ func map_th_to_row(th) -> 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) + var val = th.get(param_name) + row[i_col] = '%0.1f' % val if val is float else '%s' % val i_col += 1 return row From 0af986bd33e80cdd5c493efdd317be69375ffd20 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 7 Oct 2025 14:38:26 +0300 Subject: [PATCH 052/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D0=B0=D1=80=D0=BC=D0=B5=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B8=D0=B7=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/работа/работа.gd | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 0fbe42f1..94ec2636 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -30,7 +30,8 @@ var strob_band_begin: float ## Ширина строба в моме var strob_dir_begin: float ## Направление антенны в момент начала перетаскивания. var strob_width_begin: float ## Ширина строба по углу в момент начала перетаскивания. var view_mode: MapViewMode ## Режим отображения карты - +var color_ecm: Color +var color_select: Color signal drag_begin ## Вызывается в момент начала перетаскивания. signal drag_continue ## Вызывается во время продолжения перетаскивания. @@ -80,6 +81,11 @@ func on_threat_selected(th, ecm_btns): on_rto_threat_sel(th.id, ecm_btns) func on_enter_tree() -> void: call_deferred('on_button_strobe_pressed') +func on_settings_changed(): + color_ecm = ProjectSettings.get_setting('application/interfer/interfer_color', Color(0.58, 0.47, 0.51, 1.0)) + color_select = ProjectSettings.get_setting('application/interfer/select_color', Color(1.0, 1.0, 1.0, 1.0)) + + ## Обработчик сигнала изменения списка целей. func on_threats_resized(ths: Dictionary): $count_all_pad/count_all.text = '%02d' % ths.size() @@ -116,6 +122,8 @@ func _exit_tree() -> void: ## Производит инициализацию. func _ready(): + ProjectSettings.connect('settings_changed', on_settings_changed) + on_settings_changed() min_zoom = ProjectSettings.get_setting('application/config/map_minimum_zoom', 5) max_zoom = ProjectSettings.get_setting('application/config/map_maximum_zoom', 19) drag_fsm = DragFSM.OFF @@ -449,8 +457,6 @@ func set_fs_color(ecm): func update_fs_colors(): var fs_colors = $canvas.fs_default_colors.duplicate() - var color_ecm: Color = ProjectSettings.get_setting('application/interfer/interfer_color', Color(0.58, 0.47, 0.51, 1.0)) - var color_select: Color = ProjectSettings.get_setting('application/interfer/select_color', Color(1.0, 1.0, 1.0, 1.0)) for key in fs_active.keys(): fs_colors[key] = color_ecm for key in fs_selected.keys(): From f1277873351e5e80abadba50d3d12785c25c419a Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 7 Oct 2025 14:40:12 +0300 Subject: [PATCH 053/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9D=D0=B0=D0=B7=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B2=D0=BD=D0=B5=D1=88=D0=BD=D0=B5?= =?UTF-8?q?=D0=B3=D0=BE=20"=D0=BF=D1=80=D0=B8=D0=B1=D0=BE=D1=80=D0=B0"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 48caf186..4724f633 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -241,7 +241,7 @@ size_flags_horizontal = 15 size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") -unit_name = &"навигация" +unit_name = &"уарэп-карта" [node name="label" type="Label" parent="maps"] layout_mode = 0 From f810b462815a921a278afd63e440f9970de21d30 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 7 Oct 2025 14:40:50 +0300 Subject: [PATCH 054/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 1 + 1 file changed, 1 insertion(+) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 4724f633..942b5947 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -72,6 +72,7 @@ func _ready(): var unit_instance = network.get_unit_instance(unit_name) unit_instance.connect('line_changed', on_line_changed) + func online_change_arr(_u, conn_node, pribor_meta): var state_online = true for i in pribor_meta.size(): From 066c6d4ca0971c394176ee1847f139a9e2eb9c14 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 7 Oct 2025 17:09:13 +0300 Subject: [PATCH 055/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=98=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=B2=D0=BD=D0=B5=D1=88=D0=BD=D0=B8=D1=85?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 942b5947..5a420020 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -364,6 +364,7 @@ texture_normal = ExtResource("3_hhadv") stretch_mode = 0 script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +unit_name = &"уарэп-бпо" [node name="label" type="Label" parent="pribor_rtr"] layout_mode = 0 @@ -425,6 +426,7 @@ texture_normal = ExtResource("9_iqgf5") stretch_mode = 0 script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +unit_name = &"уарэп-афсп-левый" [node name="label" type="Label" parent="pribor_afsp_1"] layout_mode = 0 @@ -490,6 +492,7 @@ stretch_mode = 0 flip_h = true script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +unit_name = &"уарэп-афсп-правый" [node name="label" type="Label" parent="pribor_afsp_2"] layout_mode = 0 From b3e641136e68ec9d2ffa0e8e161135e09059b87d Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 11:55:00 +0300 Subject: [PATCH 056/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9A=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BB=D1=8C=20=D0=BF=D1=80=D0=B8=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=90=D0=A4=D0=A1=D0=9F=20=D0=B8=20=D0=91=D0=9F?= =?UTF-8?q?=D0=9E=20=D0=BD=D0=B5=20=D0=BF=D1=80=D0=B5=D0=BA=D1=80=D0=B0?= =?UTF-8?q?=D1=89=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=BF=D0=BE=D1=81=D0=BB?= =?UTF-8?q?=D0=B5=20=D0=B2=D1=8B=D1=85=D0=BE=D0=B4=D0=B0=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D0=B0=20=D0=9A=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp-1.tscn | 2 +- scenes/контроль/контроль.tscn | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn index 58cb3de7..4c027fd8 100644 --- a/scenes/pribor-afsp/pribor-afsp-1.tscn +++ b/scenes/pribor-afsp/pribor-afsp-1.tscn @@ -7,7 +7,7 @@ [sub_resource type="GDScript" id="GDScript_yhnwg"] script/source = "extends Timer -func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_bpo_request_period') +func _enter_tree() -> void: wait_time = ProjectSettings.get_setting('application/config/unit_bpo_request_period') " [node name="pribor_afsp" type="Control"] diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 5a420020..8fb04b7b 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -49,6 +49,7 @@ const null_units_names = ['уарэп-афсп-левый', 'уарэп-афсп func on_line_changed(u, conn_node, _pribor_meta): conn_node.set_val(u.online) +func on_mode_changed(): clean_pribor_items() func _ready(): @@ -71,6 +72,10 @@ func _ready(): for unit_name in null_units_names: var unit_instance = network.get_unit_instance(unit_name) unit_instance.connect('line_changed', on_line_changed) + signaller.conn(signaller.режим_работа, on_mode_changed) + signaller.conn(signaller.режим_журнал, on_mode_changed) + signaller.conn(signaller.режим_настройки, on_mode_changed) + signaller.conn(signaller.режим_эмс, on_mode_changed) func online_change_arr(_u, conn_node, pribor_meta): @@ -83,11 +88,15 @@ func online_change_arr(_u, conn_node, pribor_meta): conn_node.set_val(state_online) -func on_pribor_press(pribor_path, header_text, pribor_node): +func clean_pribor_items(): var items = get_tree().get_nodes_in_group('pribor_items') for item in items: remove_child(item) item.queue_free() + + +func on_pribor_press(pribor_path, header_text, pribor_node): + clean_pribor_items() var pribor_obj = load(pribor_path) if not pribor_obj: push_error('не загружено: \\\"%s\\\" (%s)' % [pribor_path, header_text]) From 7c1a9da02c6b740933379db6b4168be1190404e9 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 11:56:53 +0300 Subject: [PATCH 057/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=92=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5?= =?UTF-8?q?=D1=81=D1=81=D0=B5.=20=D0=98=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D0=B5=D0=B9=20?= =?UTF-8?q?=D1=84=D1=81=20=D0=BD=D0=B0=20=D0=B4=D0=B8=D0=B0=D0=B3=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=BC=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shaders/tools.gdshaderinc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shaders/tools.gdshaderinc b/shaders/tools.gdshaderinc index 8dc0df97..73ba7306 100644 --- a/shaders/tools.gdshaderinc +++ b/shaders/tools.gdshaderinc @@ -1,6 +1,12 @@ const float DS = 0.004; /* Относительное расстояние на котором выполняется сглаживание краёв */ +float random_timed(vec2 uv) +{ + return fract(sin(TIME * dot(uv.xy, vec2(12.9898, 78.233))) * 43758.5453123); +} + + float smooth_px(float r, float R, float ds) { return 1.0 - smoothstep(R - ds, R + ds, r); From 3735600278d779d4da4828079a91b8079895b1b5 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 11:59:19 +0300 Subject: [PATCH 058/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20=D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=90=D0=A4=D0=A1=D0=9F=20=D0=B8=20=D0=91=D0=9F?= =?UTF-8?q?=D0=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/request.gd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd index 9987069f..657efbbd 100644 --- a/scenes/контроль/request.gd +++ b/scenes/контроль/request.gd @@ -65,10 +65,11 @@ func _ready(): func _on_request_timer(): if HTTPClient.Status.STATUS_REQUESTING == get_http_client_status(): + push_warning('HTTPClient.Status.STATUS_REQUESTING') return - var addr = [addr_right, addr_left][i_bort] + var addr = [addr_left, addr_right][i_bort] var hdrs = [headers_right, headers_left][i_bort] var rc: = request(addr, hdrs) if rc != Error.OK: push_error('%s: \"%s\"' % [error_string(rc), addr]) - i_bort = (i_bort + 1) % 2 + i_bort = (i_bort + 1) % 2 From 1f1221cf6f18cf0a7b5790a6471a972a9a1c1441 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 11:59:30 +0300 Subject: [PATCH 059/117] Godot4.4 --- scenes/контроль/контроль.tscn | 3 --- scenes/работа/работа.tscn | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 8fb04b7b..3a92e7ad 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -373,7 +373,6 @@ texture_normal = ExtResource("3_hhadv") stretch_mode = 0 script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] -unit_name = &"уарэп-бпо" [node name="label" type="Label" parent="pribor_rtr"] layout_mode = 0 @@ -435,7 +434,6 @@ texture_normal = ExtResource("9_iqgf5") stretch_mode = 0 script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] -unit_name = &"уарэп-афсп-левый" [node name="label" type="Label" parent="pribor_afsp_1"] layout_mode = 0 @@ -501,7 +499,6 @@ stretch_mode = 0 flip_h = true script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] -unit_name = &"уарэп-афсп-правый" [node name="label" type="Label" parent="pribor_afsp_2"] layout_mode = 0 diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 73bf583a..f31ccf3d 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -319,6 +319,6 @@ text = "Масштаб:" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] From 776ae9ce6c896e9c658cead02af07ceb367986bf Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 12:16:18 +0300 Subject: [PATCH 060/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9D=D0=B0=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=20=D1=83=D1=81=D0=B8=D0=BB=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D0=B5=D0=B9=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5?= =?UTF-8?q?=20=D0=B2=D1=8B=D1=85=D0=BE=D0=B4=D0=B0=20=D0=B8=D0=B7=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B6=D0=B8=D0=BC=D0=B0=20=D0=9A=D0=BE=D0=BD=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-k/pribor-prd-k.gd | 12 ++++++------ scenes/pribor-prd-n/pribor-prd-n.gd | 4 ++-- scenes/pribor-prd-v/pribor-prd-v.gd | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/scenes/pribor-prd-k/pribor-prd-k.gd b/scenes/pribor-prd-k/pribor-prd-k.gd index 18a4a231..5557b0e5 100644 --- a/scenes/pribor-prd-k/pribor-prd-k.gd +++ b/scenes/pribor-prd-k/pribor-prd-k.gd @@ -15,9 +15,9 @@ const constants_k: Dictionary = { 'POWER_THRESHOLD': 40, 'RAY_DOU_NUM': 0x3, 'ATT_UM_1': 0x0, - 'ATT_UM_6': 0x7, - 'ATT_UM_7': 0x7, - 'POWER_UM': 85, + 'ATT_UM_6': 0x3, + 'ATT_UM_7': 0x2, + 'POWER_UM': 90, 'TIMER_DELAY': 5.0, 'STATE_MASHINE_TIMER': 0.3, } @@ -55,9 +55,9 @@ var block_kasseta_y5_prd_config_k: = { } # Основные переменные var start_litera: int = 1 -var ug_work_1: int = 0 -var ug_work_2: int = 0 -var ug_work_3: int = 0 +var ug_work_1: int = 3 ## Аттенюация усилителей мощности +var ug_work_2: int = 2 ## Аттенюация усилителей мощности +var ug_work_3: int = 0 ## Аттенюация усилителей мощности var mashine_timer: Timer = Timer.new() var prd_k_module: Object var unit_prd_k: Object diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index 04c9e60d..92bb5b37 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -50,8 +50,8 @@ var block_kasseta_y5_prd_config_n: = { # Основные переменные var start_litera: int = 2 -var ug_work_1: int = 0 -var ug_work_2: int = 0 +var ug_work_1: int = 3 ## Аттенюация усилителей мощности +var ug_work_2: int = 3 ## Аттенюация усилителей мощности # Флаги и таймеры var mashine_timer: Timer = Timer.new() var prd_n_module: Object diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index 572035a6..36b847e5 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -50,8 +50,8 @@ var block_kasseta_y5_prd_config_v: = { # Основные переменные var start_litera: int = 4 -var ug_work_1: int = 0 -var ug_work_2: int = 0 +var ug_work_1: int = 3 ## Аттенюация усилителей мощности +var ug_work_2: int = 3 ## Аттенюация усилителей мощности # Флаги и таймеры var mashine_timer: Timer = Timer.new() var prd_v_module: Object From 0a48a09a0e4ee073af0eeebb1dc4e98845fc4927 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 12:54:24 +0300 Subject: [PATCH 061/117] =?UTF-8?q?=D0=A7=D0=B8=D1=81=D1=82=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp.gd | 1 - scripts/pribor-prd.gd | 2 -- 2 files changed, 3 deletions(-) diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index cc24c2bb..041184c2 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -83,4 +83,3 @@ func _on_item_pressed(block_a: Control): var metas = block_a.get_meta_list() for n in metas: var v = block_a.get_meta(n) - print_debug('%s:%s' % [n, v]) diff --git a/scripts/pribor-prd.gd b/scripts/pribor-prd.gd index 27c8a651..c5e23b8d 100644 --- a/scripts/pribor-prd.gd +++ b/scripts/pribor-prd.gd @@ -258,7 +258,6 @@ class TestPRD extends Node: func _on_ems_6666_timer() -> void: - print_debug('Write 6666') module_prd.cmd_array.append([unit_prd.CmdCode.WRITE_ISA, [constants.BASE_ADDR_EMS_G, 6666]]) @@ -635,7 +634,6 @@ class TestPRD extends Node: for i_pow_arr in ray_dic.values(): for i_pow in i_pow_arr.size(): if i_pow_arr[i_pow] < cnst.POWER_THRESHOLD: - #print_debug('dou_%s: false' % litera) all_dou_ok = false control_dic[dou] = all_dou_ok From bf1a53f1fe7be968db0fb3904b17d969b33e36c4 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 14:48:04 +0300 Subject: [PATCH 062/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=92=D1=80=D0=B5=D0=BC?= =?UTF-8?q?=D1=8F=20=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D0=B0=20=D0=90=D0=A4?= =?UTF-8?q?=D0=A1=D0=9F=20=D0=BA=D0=BE=D1=80=D0=BE=D1=82=D0=BA=D0=BE=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.godot | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project.godot b/project.godot index 74bb0bbb..fd03a88a 100644 --- a/project.godot +++ b/project.godot @@ -31,11 +31,11 @@ interfer/select_color=Color(1, 1, 1, 1) interfer/interfer_color=Color(0.58, 0.47, 0.51, 1) interfer/resend_timeout=1000.0 config/external_cu=false -config/unit_rr_request_period=5.0 +config/unit_rr_request_period=20.0 config/kems_files_path="user://kems/" config/emsg_files_path="user://emsg/" config/settings_path="user://settings.json" -config/unit_bpo_request_period=5.0 +config/unit_bpo_request_period=20.0 [autoload] From 7677fe43329a1efe7310da22acdb1f8a36be8892 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 14:50:53 +0300 Subject: [PATCH 063/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9A=D0=BE=D0=BD=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BB=D1=8C=20=D0=94=D0=9A=D0=9C=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BA=D0=B0=D0=B7=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=20=D0=BD=D0=B5?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D0=BD=D1=8B=D0=B9=20=D1=80=D0=B5=D0=B7=D1=83?= =?UTF-8?q?=D0=BB=D1=8C=D1=82=D0=B0=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-k/pribor-prd-k.gd | 2 +- scripts/pribor-prd.gd | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/scenes/pribor-prd-k/pribor-prd-k.gd b/scenes/pribor-prd-k/pribor-prd-k.gd index 5557b0e5..3c7b47f7 100644 --- a/scenes/pribor-prd-k/pribor-prd-k.gd +++ b/scenes/pribor-prd-k/pribor-prd-k.gd @@ -17,7 +17,7 @@ const constants_k: Dictionary = { 'ATT_UM_1': 0x0, 'ATT_UM_6': 0x3, 'ATT_UM_7': 0x2, - 'POWER_UM': 90, + 'POWER_UM': 100, 'TIMER_DELAY': 5.0, 'STATE_MASHINE_TIMER': 0.3, } diff --git a/scripts/pribor-prd.gd b/scripts/pribor-prd.gd index c5e23b8d..6031b733 100644 --- a/scripts/pribor-prd.gd +++ b/scripts/pribor-prd.gd @@ -171,7 +171,7 @@ class TestPRD extends Node: STATE_MASHINE.UG_SET_RAY_0: _handle_ug_set_state(0x0) - await get_tree().create_timer(1.0).timeout + await get_tree().create_timer(1.2).timeout state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_1: _handle_ug_set_state(0x1) @@ -248,11 +248,11 @@ class TestPRD extends Node: elif self_name == '1н' or self_name == '2н' or self_name == '3н' or self_name == '4н': dic_att['ATT_UM_1'] = constants.ATT_UM_2 dic_att['ATT_UM_2'] = constants.ATT_UM_3 - control_label.text = 'Выполняется настройка угла (%s) и атт (%s, %s, %s)' % [ + + var log_text = dic_att.ATT_UM_3 if current_litera == 1 else dic_att.ATT_UM_1 if current_litera in [2, 4, 6] else dic_att.ATT_UM_2 + control_label.text = 'Выполняется настройка угла (%s) и атт (0x0%s)' % [ dic_att.RAY_DOU_NUM, - dic_att.ATT_UM_1, - dic_att.ATT_UM_2, - dic_att.ATT_UM_3, + log_text ] on_ug_setting(module_prd, unit_prd, dic_att) @@ -321,7 +321,15 @@ class TestPRD extends Node: var dkm_bit = _get_dkm_bit_for_current_fs(current_litera, constants) if dkm_bit == 0: control_results['dkm_1'] = check_dkm(status, dkm_bit) - elif dkm_bit == 1: + + var addr: int = constants.ADDR_UG_LITERA_1 + if current_litera == 3 or current_litera == 5 or current_litera == 7: + addr = constants.ADDR_UG_LITERA_2 + if not unit_prd.isa_ports.has(addr) or not (unit_prd.cmd_state == unit_prd.CmdState.DONE): + return + if not unit_prd.isa_ports[addr] & 0x07 == 6: return + + if dkm_bit == 1: control_results['dkm_2'] = check_dkm(status, dkm_bit) elif dkm_bit == 2: control_results['dkm_3'] = check_dkm(status, dkm_bit) From 7fc9b96ec404f5a1ac5268dc9b4793c1f62ca05d Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 15:50:51 +0300 Subject: [PATCH 064/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=A2?= =?UTF-8?q?=D1=80=D0=B5=D0=BD=D0=B0=D0=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tabs-switch/tab-switch.gd | 4 ++++ scenes/tabs-switch/tab-switch.tscn | 17 ++++++++++++++++- scenes/журнал/журнал.gd | 4 ++++ scripts/interfer.gd | 7 ++++++- scripts/prd.gd | 5 +++-- scripts/signaller.gd | 3 +++ 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/scenes/tabs-switch/tab-switch.gd b/scenes/tabs-switch/tab-switch.gd index 66f14765..5d8dba77 100644 --- a/scenes/tabs-switch/tab-switch.gd +++ b/scenes/tabs-switch/tab-switch.gd @@ -27,3 +27,7 @@ func _on_tab_changed(tab) -> void: func on_setting_changed(): var ext_cu = ProjectSettings.get_setting('application/config/Внешнее управление', false) get_parent().get_node('remote_control').visible = ext_cu + + +func _on_button_trenaj_toggled(toggled_mode: bool) -> void: + signaller.emit_signal('режим_тренаж', toggled_mode) diff --git a/scenes/tabs-switch/tab-switch.tscn b/scenes/tabs-switch/tab-switch.tscn index 477a9670..d9ab0277 100644 --- a/scenes/tabs-switch/tab-switch.tscn +++ b/scenes/tabs-switch/tab-switch.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=14 format=3 uid="uid://3slb0i3pvowc"] +[gd_scene load_steps=15 format=3 uid="uid://3slb0i3pvowc"] [ext_resource type="Script" uid="uid://bvo6tcreqyuex" path="res://scenes/tabs-switch/tab-switch.gd" id="1_fg0vd"] [ext_resource type="PackedScene" uid="uid://b276iygic5itk" path="res://scenes/работа/работа.tscn" id="2_u7p16"] @@ -20,6 +20,8 @@ [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_o1r22"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_imu1q"] + [node name="panel" type="Panel"] offset_right = 1600.0 offset_bottom = 1200.0 @@ -95,4 +97,17 @@ text = "Внешнее управление" horizontal_alignment = 1 vertical_alignment = 1 +[node name="тренаж_режим" type="Button" parent="."] +layout_mode = 0 +offset_left = 1404.0 +offset_right = 1501.0 +offset_bottom = 27.0 +tooltip_text = "Задействовать режим Тренаж" +focus_mode = 0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_styles/normal = SubResource("StyleBoxFlat_imu1q") +toggle_mode = true +text = "Тренаж" + [connection signal="tab_changed" from="tab_switch" to="tab_switch" method="_on_tab_changed"] +[connection signal="toggled" from="тренаж_режим" to="tab_switch" method="_on_button_trenaj_toggled"] diff --git a/scenes/журнал/журнал.gd b/scenes/журнал/журнал.gd index 401ad0d8..2fcb0369 100644 --- a/scenes/журнал/журнал.gd +++ b/scenes/журнал/журнал.gd @@ -7,6 +7,7 @@ func on_threats_changed(th: Object, msg: String): log.message(Logger.INFO, '%s: func on_parse_error(unit_inst, msg: String): log.message(Logger.ERROR, '%s: %s' % [unit_inst.name, msg]) func on_interfer_off(ecm, msg: String): log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()]) func on_set_program_mode(msg: String): log.message(Logger.INFO, msg) +func on_mode_trenazh(val: bool): log.message(Logger.INFO, 'Режим \"Тренаж\" %s' % ['отменён', 'задейсвован'][int(val)]) func on_interfer_new(ecm, msg: String): if ecm.krp != interfer.INTERFER_OFF: @@ -33,6 +34,9 @@ func _ready() -> void: signaller.conn(signaller.режим_эмс, Callable(log, 'info').bind('Программа в режиме \"ЭМС\"')) signaller.conn(signaller.режим_журнал, Callable(log, 'info').bind('Программа в режиме \"Журнал\"')) signaller.conn(signaller.режим_контроль, Callable(log, 'info').bind('Программа в режиме \"Контроль\"')) + signaller.conn(signaller.режим_тренаж, Callable(self, 'on_mode_trenazh')) + + func _on_clear_button_down() -> void: diff --git a/scripts/interfer.gd b/scripts/interfer.gd index 514b9d7b..988b240d 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -90,6 +90,7 @@ var cu: Dictionary ## Словарь воздействий для 5 var thrs_dict: Dictionary ## Ссылка на словарь целей var auto_enabled: bool = false ## Режим автомата var emit_enable: bool = true ## Разрешить излучение +var trenazh_mode: bool = false ## Переключение режима Тренаж ## Сеанс помехи. class Interfer: @@ -189,6 +190,7 @@ func _ready() -> void: signaller.connect('full_auto', Callable(self, 'on_full_auto')) signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno')) signaller.connect('emit_changed', Callable(self, 'on_emit_changed').bind(ecms)) + signaller.connect('режим_тренаж', on_trenazh_mode) threats.connect('threat_lost', Callable(self, 'on_threats_lost').bind(ecms, unit_caps)) threats.connect('threats_resized', Callable(self, 'on_threats_resized')) threats.connect('threat_update', Callable(self, 'on_threats_update').bind(ecms, unit_caps)) @@ -196,6 +198,9 @@ func _ready() -> void: unit_nav.connect('data_received', on_nav_data_received.bind(unit_caps)) +func on_trenazh_mode(val: bool): trenazh_mode = val + + func on_nav_data_received(coords: Dictionary, unit_caps): var ship_time = Time.get_datetime_dict_from_system() var data_to_json = { @@ -238,7 +243,7 @@ func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit_instance) -> v ecm.kni = thr.aoa send_ecm(ecm, unit_instance) signaller.emit_signal('fs_update_color', ecms) - prd.update_fs_state(ecms) + prd.update_fs_state(ecms, trenazh_mode) if not auto_enabled: return diff --git a/scripts/prd.gd b/scripts/prd.gd index 30cfe54f..0e8e807d 100644 --- a/scripts/prd.gd +++ b/scripts/prd.gd @@ -318,7 +318,7 @@ func find_fs_index(aoa: float, freq: int, fs_index_arr: Array): ## Обновление состояния модулей формирователя сигналов -func update_fs_state(ecms): +func update_fs_state(ecms, trenaz_mode: bool): for fs in fs_dict.values(): ## Запрет модуляции для всех ФС fs.set_modulation(false) for ecm in ecms.values(): ## Выставление состояния помехи в ФС @@ -330,7 +330,8 @@ func update_fs_state(ecms): for prd_module in prd_dict.values(): ## Отправка команды на исполнение в ПРД if prd_module.state != PrdState.WORK: continue if not prd_module.unit_yau07.online: continue - prd_module.cmd_array.append([prd_module.unit_yau07.CmdCode.WRITE_ISA, [prd_module.yemsg_board.base_addr_isa, 6666]]) + if not trenaz_mode: + prd_module.cmd_array.append([prd_module.unit_yau07.CmdCode.WRITE_ISA, [prd_module.yemsg_board.base_addr_isa, 6666]]) var um_data_array: Array = [] for fs in prd_module.fs_dic.values(): if not prd_module.ug_online: continue diff --git a/scripts/signaller.gd b/scripts/signaller.gd index d96201fd..82d8cf19 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -34,6 +34,9 @@ signal режим_эмс() ## Вызывается при переходе в режим [b]Настройка[/b]. signal режим_настройки() +## Вызывается при включении/отключении режима [b]Тренаж[/b].[br] +## [param val] - [b]true[/b] тренаж включён. +signal режим_тренаж(val: bool) ## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора цели и помехи[/b]. signal full_auto() From 4284aa97ce0971f270f8d06b0f495ceaa622a56c Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 23:30:48 +0300 Subject: [PATCH 065/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=20=D0=BF=D1=80=D0=B8=D0=B1=D0=BE=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=9F=D0=A0=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-n/pribor-prd-n.gd | 8 ++++---- scenes/pribor-prd-v/pribor-prd-v.gd | 8 ++++---- scenes/контроль/блок-в.tscn | 19 +++++++++---------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index 92bb5b37..42b39cb4 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -13,9 +13,9 @@ const constants_n = { 'TEMP_THRESHOLD': 70, 'POWER_THRESHOLD': 40, 'RAY_DOU_NUM': 0x3, - 'ATT_UM_2': 0x7, - 'ATT_UM_3': 0x7, - 'POWER_UM': 70, + 'ATT_UM_2': 0x2, + 'ATT_UM_3': 0x3, + 'POWER_UM': 100, 'TIMER_DELAY': 5.0, 'STATE_MASHINE_TIMER': 0.3, } @@ -50,7 +50,7 @@ var block_kasseta_y5_prd_config_n: = { # Основные переменные var start_litera: int = 2 -var ug_work_1: int = 3 ## Аттенюация усилителей мощности +var ug_work_1: int = 2 ## Аттенюация усилителей мощности var ug_work_2: int = 3 ## Аттенюация усилителей мощности # Флаги и таймеры var mashine_timer: Timer = Timer.new() diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index 36b847e5..35e9ff40 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -13,9 +13,9 @@ const constants_v = { 'TEMP_THRESHOLD': 70, 'POWER_THRESHOLD': 40, 'RAY_DOU_NUM': 0x3, - 'ATT_UM_4': 0x7, - 'ATT_UM_5': 0x7, - 'POWER_UM': 75, + 'ATT_UM_4': 0x2, + 'ATT_UM_5': 0x3, + 'POWER_UM': 100, 'TIMER_DELAY': 5.0, 'STATE_MASHINE_TIMER': 0.3, } @@ -50,7 +50,7 @@ var block_kasseta_y5_prd_config_v: = { # Основные переменные var start_litera: int = 4 -var ug_work_1: int = 3 ## Аттенюация усилителей мощности +var ug_work_1: int = 2 ## Аттенюация усилителей мощности var ug_work_2: int = 3 ## Аттенюация усилителей мощности # Флаги и таймеры var mashine_timer: Timer = Timer.new() diff --git a/scenes/контроль/блок-в.tscn b/scenes/контроль/блок-в.tscn index 12673c7b..9f706046 100644 --- a/scenes/контроль/блок-в.tscn +++ b/scenes/контроль/блок-в.tscn @@ -16,6 +16,7 @@ class_name blok_v extends PanelContainer @export var textures: Array @export var animation_duration: float = 1.5 signal pressed(control: PanelContainer) +var tween: Tween ## Значения уровней @@ -36,7 +37,6 @@ signal pressed(control: PanelContainer) return $margin/vbox/grid1/level7.value = v $margin/vbox/grid1/level7.tint_progress = Color.RED if v > 70 else Color.WHITE - @export var min_value0: float: @@ -141,18 +141,21 @@ signal pressed(control: PanelContainer) func _on_button_pressed(): emit_signal('pressed', self) -func _enter_tree() -> void: call_deferred('_enter_tree_defered') func set_value0(value: Array): value0.assign(value) +func _enter_tree() -> void: call_deferred('_enter_tree_defered') func _ready(): - var items: Array= get_level_nodes() + var items: Array = get_level_nodes() for item in items: - item.connect('value_changed', on_level_changed.bind(item, value1_info)) + item.connect('value_changed', on_level_changed.bind(item, value0_info)) on_level_changed(item.value, item, value0_info) - var level7 = $margin/vbox/grid1/level7 + var level7: = $margin/vbox/grid1/level7 level7.connect('value_changed', on_level_changed.bind(level7, value1_info)) on_level_changed(level7.value, level7, value1_info) + tween = create_tween() + tween.set_ease(Tween.EASE_OUT) + tween.set_trans(Tween.TRANS_QUINT) func on_level_changed(_val: float, item: TextureProgressBar, info: String): @@ -225,11 +228,7 @@ func get_name_nodes() -> Array: func set_value0_animated(target_node, target_value: float) -> void: - var tween = create_tween() - tween.set_ease(Tween.EASE_OUT) - tween.set_trans(Tween.TRANS_QUINT) - - tween.tween_property(target_node, \"value\", target_value, animation_duration) + tween.tween_property(target_node, 'value', target_value, animation_duration) " [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_rceim"] From 3b53e2bfaa8c9b4d64da11d440b9201f4f3fd360 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 8 Oct 2025 23:53:16 +0300 Subject: [PATCH 066/117] =?UTF-8?q?=D0=9A=D0=BD=D0=BE=D0=BF=D0=BA=D0=B8=20?= =?UTF-8?q?=D1=83=D0=B2=D0=B5=D0=BB=D0=B8=D1=87=D0=B5=D0=BD=D0=B8=D1=8F/?= =?UTF-8?q?=D1=83=D0=BC=D0=B5=D0=BD=D1=8C=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BC=D0=B0=D1=81=D1=88=D1=82=D0=B0=D0=B1=D0=B0.=20=D0=9A?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D1=86=D0=BE=20=D0=B2=D0=BE=D0=BA=D1=80=D1=83?= =?UTF-8?q?=D0=B3=20=D0=BA=D0=BE=D1=80=D0=B0=D0=B1=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tilemap/tilemap.gd | 95 ++++++++++++++++++++++++++++++++++++++- scenes/работа/работа.tscn | 45 +++++++++++++++---- 2 files changed, 130 insertions(+), 10 deletions(-) diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index 2cbdfb35..d3dc6819 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -23,6 +23,8 @@ const TILE_REQUEST_NAME: = 'tile_request_%d' @export_range(0, 20, 1) var min_zoom_level: int = 0 @export_range(0, 20, 1) var max_zoom_level_server: int = 20 @export_color_no_alpha() var back_color: = Color.BLACK +@export var show_ship_radius: bool = true +@export var ship_radius_km: float = 8.0 @onready var scale_label: String @onready var coordinates_label: String @onready var threat_mark: PackedScene = load("res://scenes/tilemap/threat.tscn") @@ -34,6 +36,8 @@ var is_centered: = false var is_out_border1: = true var is_out_border2: = true var threat_markers := {} +var zoom_timer: Timer +var zoom_action: String @export var animation_time: float = 0.1: set(val): @@ -129,6 +133,12 @@ func _ready() -> void: img.set_pixel(0, 1, Color.CORAL) border2 = ImageTexture.create_from_image(img) + zoom_timer = Timer.new() + add_child(zoom_timer) + zoom_timer.one_shot = false + zoom_timer.wait_time = 0.1 + zoom_timer.timeout.connect(_on_zoom_timeout) + _xyz.z = min_zoom_level image_type = 'png' $canvas.connect('mouse_entered', func(): _rollover = true) @@ -252,6 +262,7 @@ func multiply_zoom(multiplier: float, pivot: Vector2) -> void: var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y + update_scale_label() func increment_zoom(increment: float, pivot: Vector2) -> void: @@ -260,6 +271,7 @@ func increment_zoom(increment: float, pivot: Vector2) -> void: var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y + update_scale_label() func set_zoom(zoom: float, pivot: Vector2) -> void: @@ -268,6 +280,7 @@ func set_zoom(zoom: float, pivot: Vector2) -> void: var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y + update_scale_label() func _draw() -> void: @@ -302,6 +315,9 @@ func _draw() -> void: if is_out_border2 and _dragging: draw_texture_rect(border2, Rect2(p1, p2), false, Color.WHITE, false) + if should_draw_ship_radius(): + draw_ship_radius() + func _clean_all() -> void: _queue.clear() @@ -700,7 +716,7 @@ func blend_mask(val: bool) -> void: func update_coordinates_label(lon: float, lat: float) -> void: - coordinates_label = 'Координаты:\nNS:%f\nEW: %f' % [lat, lon] + coordinates_label = 'Координаты:\nNS:%f\nEW:%f' % [lat, lon] signaller.emit_signal('update_coordinates_map', coordinates_label) @@ -732,3 +748,80 @@ func _on_threat_lost(th) -> void: var target = get_parent().get_node(str(th.id)) if target: target.queue_free() + + +func zoom_in() -> void: + if _xyz.z >= max_zoom_level: + return + var center: Vector2 = $canvas.size / 2.0 + increment_zoom(zoom_step, center) + queue_redraw() + + +func zoom_out() -> void: + if _xyz.z <= min_zoom_level: + return + var center: Vector2 = $canvas.size / 2.0 + increment_zoom(-zoom_step, center) + queue_redraw() + + +func _on_zoom_plus_button_down() -> void: + zoom_action = "in" + perform_zoom() + zoom_timer.start(0.3) + + +func _on_zoom_minus_button_down() -> void: + zoom_action = "out" + perform_zoom() + zoom_timer.start(0.3) + + +func _on_zoom_button_up() -> void: + zoom_action = "" + zoom_timer.stop() + + +func _on_zoom_timeout(): + perform_zoom() + zoom_timer.wait_time = 0.1 + + +func perform_zoom(): + if zoom_action != "": + if zoom_action == "in": + zoom_in() + else: + zoom_out() + update_scale_label() + + +# Вычисление для радиуса в мировых координатах +func get_ship_radius_world() -> float: + if not _marks.has(ship_id): + return 0.0 + var ship_world_pos = _marks[ship_id].position + var ship_lonlat = world_to_lonlat(ship_world_pos.x, ship_world_pos.y) + var earth_radius_km = 6371.0 + var distance_deg = (ship_radius_km / earth_radius_km) * (180.0 / PI) / cos(deg_to_rad(ship_lonlat.y)) + var east_lon = ship_lonlat.x + distance_deg + var east_point_world = lonlat_to_world(east_lon, ship_lonlat.y) + return abs(east_point_world.x - ship_world_pos.x) + + +func should_draw_ship_radius() -> bool: + if not show_ship_radius or not _marks.has(ship_id): + return false + return _xyz.z >= 11 + + +func draw_ship_radius() -> void: + var ship_world_pos = _marks[ship_id].position + var ship_screen_pos = world_to_screen(ship_world_pos) + var radius_world = get_ship_radius_world() + var radius_point_world = Vector2(ship_world_pos.x + radius_world, ship_world_pos.y) + var radius_point_screen = world_to_screen(radius_point_world) + var radius_screen = ship_screen_pos.distance_to(radius_point_screen) + #draw_arc(ship_screen_pos, radius_screen, 0, TAU, 64, Color.ORANGE, 2.0) # отрисовка контура + draw_circle(ship_screen_pos, radius_screen, Color.ORANGE_RED * Color(1, 1, 1, 0.1)) # отрисовка заливки diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index f31ccf3d..bbb9f017 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://b276iygic5itk"] +[gd_scene load_steps=18 format=3 uid="uid://b276iygic5itk"] [ext_resource type="Script" uid="uid://daudc0s3oox3i" path="res://scenes/работа/работа.gd" id="1_niok4"] [ext_resource type="PackedScene" uid="uid://nl1vklubr5kr" path="res://scenes/bip/bip.tscn" id="2_br3s6"] @@ -51,6 +51,9 @@ _data = { offsets = PackedFloat32Array(0.181818, 0.751623) colors = PackedColorArray(1, 1, 1, 0.352941, 1, 1, 1, 0) +[sub_resource type="SystemFont" id="SystemFont_5ffal"] +generate_mipmaps = true + [node name="Работа" type="Panel"] script = ExtResource("1_niok4") Bip = ExtResource("2_br3s6") @@ -86,6 +89,7 @@ self_modulate = Color(1, 1, 1, 0.415686) position = Vector2(360, 360) min_zoom_level = 3 max_zoom_level_server = 11 +ship_radius_km = 3.0 az = 3.0 [node name="player" type="AnimationPlayer" parent="tilemap"] @@ -95,11 +99,10 @@ libraries = { [node name="grd_side" parent="." instance=ExtResource("3_s2j0e")] layout_mode = 0 -offset_left = 1114.0 +offset_left = 1116.0 offset_top = 7.0 offset_right = 1594.0 offset_bottom = 1170.0 -metadata/_edit_lock_ = true [node name="grd_btns" parent="." instance=ExtResource("5_2jnbs")] layout_mode = 0 @@ -301,20 +304,39 @@ vertical_alignment = 1 [node name="coordinates_map" type="Label" parent="."] layout_mode = 0 -offset_left = 1000.0 +offset_left = 999.0 offset_top = 128.0 -offset_right = 1112.0 +offset_right = 1111.0 offset_bottom = 147.0 text = "Координаты:" [node name="scale_map" type="Label" parent="."] layout_mode = 0 -offset_left = 1000.0 -offset_top = 192.0 -offset_right = 1110.0 -offset_bottom = 213.0 +offset_left = 999.0 +offset_top = 202.0 +offset_right = 1109.0 +offset_bottom = 223.0 text = "Масштаб:" +[node name="zoom_plus" type="Button" parent="."] +layout_mode = 0 +offset_left = 1056.0 +offset_top = 230.0 +offset_right = 1088.0 +offset_bottom = 262.0 +theme_override_fonts/font = SubResource("SystemFont_5ffal") +theme_override_font_sizes/font_size = 20 +text = "+" + +[node name="zoom_minus" type="Button" parent="."] +layout_mode = 0 +offset_left = 1056.0 +offset_top = 270.0 +offset_right = 1088.0 +offset_bottom = 302.0 +theme_override_font_sizes/font_size = 20 +text = "−" + [connection signal="drag_begin" from="." to="." method="_on_drag_begin"] [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] @@ -322,3 +344,8 @@ text = "Масштаб:" [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] +[connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"] +[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"] +[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"] +[connection signal="button_down" from="zoom_minus" to="tilemap" method="_on_zoom_minus_button_down"] +[connection signal="button_up" from="zoom_minus" to="tilemap" method="_on_zoom_button_up"] From db668d4b49621434a7010480c97f73c321d14ce2 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 9 Oct 2025 13:46:35 +0300 Subject: [PATCH 067/117] =?UTF-8?q?=D0=92=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5?= =?UTF-8?q?=D1=81=D1=81=D0=B5.=20Subject:=20[PATCH]=20Merge=20remote-track?= =?UTF-8?q?ing=20branch=20'lepshiy/master'=20=D0=A2=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D0=B0.=20=D0=9D=D0=B0=D0=B6=D0=B0=D1=82=D0=B8=D0=B5/?= =?UTF-8?q?=D0=BE=D1=82=D0=B6=D0=B0=D1=82=D0=B8=D0=B5=20=D0=BA=D0=BD=D0=BE?= =?UTF-8?q?=D0=BF=D0=BE=D0=BA=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=8B=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=BD=D1=83=D0=B4=D0=B8=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=BE.=20=D1=82=D1=80=D0=B0=D1=81=D1=81=D0=B0.=20?= =?UTF-8?q?=D0=BF=D0=B0=D1=80=D1=81=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BA=D0=B5=D1=82=D0=B0=20=D0=BE=D1=82=20=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D1=8B,=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0=20?= =?UTF-8?q?=D1=82=D1=80=D0=B0=D1=81=D1=81=D1=8B=20=D0=B2=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=D1=85,=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B0/=D1=81?= =?UTF-8?q?=D0=BD=D1=8F=D1=82=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85?= =?UTF-8?q?,=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B0=20=D0=B8=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=BA=D0=B5=D1=82=D0=B0=20=D0=B2=20=D1=82=D1=80?= =?UTF-8?q?=D0=B0=D1=81=D1=81=D1=83=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F.=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D1=8B=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?=D1=83=D0=B3=D0=BB=D0=B0=20=D0=BC=D0=B5=D1=81=D1=82=D0=B0.=20?= =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F.=20=D0=9B=D0=B8=D1=88=D0=BD=D1=8F=D1=8F=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B6=D0=B0=D1=82=D0=BE=D0=B9=20=D0=BA=D0=BD=D0=BE?= =?UTF-8?q?=D0=BF=D0=BA=D0=B5=20=D0=9F=D0=BE=D0=B4=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F.=20Merge=20remote-tracking=20branch=20'refs/?= =?UTF-8?q?remotes/Cat/master'=20=D1=82=D1=80=D0=B0=D1=81=D1=81=D0=B0.=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0.=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D0=BD=20=D0=BC=D0=B5=D1=85=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=20=D0=BE=D1=82=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8,=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B5=D1=91=20=D0=BE=D1=82=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BD=D0=B0=D0=B4=D0=BE=20?= =?UTF-8?q?=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D1=82=D1=8C=20=D1=82?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=81=D0=B0=D0=BC=D1=83=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D1=83.=20=D0=94=D0=BE=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=B9=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8=20=D0=95?= =?UTF-8?q?=D0=9F=D0=A0=D0=9B=D0=A1=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9F=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D0=BA=D0=B0=20=D1=84=D0=BB=D0=B0=D0=B3=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B4=D0=BE=D1=81=D1=82=D0=BE=D0=B2=D0=B5=D1=80=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D1=83=D0=B5=D0=BC=D0=BE=D0=B9=20=D0=BF=D0=BE=D0=BC=D0=B5?= =?UTF-8?q?=D1=85=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D1=86=D0=B5=D0=BB=D0=B8.?= =?UTF-8?q?=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20?= =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=D1=8B=D0=B1=D1=80=D0=B0=D0=BD=D0=BD=D0=BE?= =?UTF-8?q?=D0=B9=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B2=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B8?= =?UTF-8?q?=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD=D0=B4=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D0=BE=D0=B9=20=D0=BE=D1=82=20=D1=86=D0=B5?= =?UTF-8?q?=D0=BB=D0=B8.=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0.=20=D0=92=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD=D0=B4?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D0=BE=D0=B9=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D1=86=D0=B5=D0=BB=D0=B8=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85?= =?UTF-8?q?=D0=B8.=20Merge=20remote-tracking=20branch=20'sasha/master'=20G?= =?UTF-8?q?odot4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/настройки/настройки.tscn | 10 ++ scripts/signaller.gd | 2 +- scripts/trassa.gd | 160 +++++++++++++++++++++++++++++++- 3 files changed, 166 insertions(+), 6 deletions(-) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index c21899b6..87b1403e 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -31,6 +31,7 @@ const SETTING_TABLE = [ ['Кнопка «JTIDS»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], ['Кнопка «КУПД»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], ['Внешнее управление', TableEdit, TableToggle, 'Передать управление в 5П28'], + ['Внешнее указание Трасса', TableEdit, TableToggle, 'Разрешить постановку помех от Трасса'], ['Кнопка «Подавление»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], ['Виртуальная клавиатура', TableEdit, TableToggle, 'Включить отображение экранной клавиатуры'], ['Скрыть вкладку ЭМС 2', TableEdit, TableToggle, 'Отображать вкладку \\\"ЭМС-2\\\"'], @@ -68,6 +69,7 @@ const SUPPRESS = 17 ## Строка - Подавление const KEYBOARD = 18 ## Строка - Виртуальная клавиатура const HIDE_EMS2 = 19 ## Строка - Скрыть вкладку ЭМС 2 const COMMIT = 20 ## Строка - Версия УАРЭП +const TRASSA = 21 var name_to_line_index: = {} ## Для преобразования названия параметра в номер строки @@ -91,6 +93,11 @@ func on_external_cu_btn_pressed(btn) -> void: signaller.emit_signal('interfer_off_all') +func on_trassa_btn_pressed(btn) -> void: + var state = btn.button_pressed + ProjectSettings.set_setting('application/config/Внешнее указание Трасса', state) + + func on_vk_pressed(btn) -> void: var state = btn.button_pressed signaller.emit_signal('kb_pressed', state) @@ -207,6 +214,9 @@ func button_settings(): var extern_cu_node = $scroll_set/table.get_node2(1, EXTERNAL_CU).get_children()[0] extern_cu_node.connect('pressed', on_external_cu_btn_pressed.bind(extern_cu_node)) on_external_cu_btn_pressed(extern_cu_node) + var trassa_node = $scroll_set/table.get_node2(1, TRASSA).get_children()[0] + trassa_node.connect('pressed', on_trassa_btn_pressed.bind(trassa_node)) + on_trassa_btn_pressed(trassa_node) var vk_node = $scroll_set/table.get_node2(1, KEYBOARD).get_children()[0] vk_node.connect('pressed', on_vk_pressed.bind(vk_node)) var ems2_hide_node = $scroll_set/table.get_node2(1, HIDE_EMS2).get_children()[0] diff --git a/scripts/signaller.gd b/scripts/signaller.gd index 82d8cf19..561ed7de 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -110,7 +110,7 @@ signal interfer_new(ecm: interfer.Interfer) ## [param ecm] - Новая помеха.[br] ## [param ecms] - словарь помех.[br] ## [param thrs] - словарь id помех и связанных с ними целей.[br] -signal interfer_off(ecm: interfer.Interfer, ecms: Dictionary, thrs: Dictionary) +signal interfer_off(ecm: interfer.Interfer) ## Вызывается при нажатии отключить. diff --git a/scripts/trassa.gd b/scripts/trassa.gd index b203716e..3cb5b526 100644 --- a/scripts/trassa.gd +++ b/scripts/trassa.gd @@ -1,6 +1,9 @@ class_name trassa_unit extends Node -const ONLINE_TIMEOUT: = 5000 +const ONLINE_TIMEOUT: int = 5000 # Время ожидания данных +const REQUEST_PERIOD: int = 3000 # Период отправки, мс +const WORDS_TOTAL: int = 75 +const NOINFO: int = 0x80000000 class Trassa extends unit.Unit: var source_addr: = [] @@ -11,11 +14,158 @@ class Trassa extends unit.Unit: emit_signal('line_changed', self) return Error.ERR_BUSY - func _init(unit_name: StringName): - self.name = unit_name + var unit_caps = network.get_unit_instance('уарэп-капсрпб') + var source_addr: Array + var tx_stack: Array[int] = [] + var msg_counter: int = 0 + var ecms: Dictionary = {} # Словарь всех активных помех + var srn = 0 + var jtids = 0 + var prinud_but: Array = [] + var forced_buttons: Array = [] # Храним ссылки на кнопки + + # Инициализация + func _init(nm: StringName, buttons: Array = []) -> void: + self.name = nm + self.forced_buttons = buttons + tx_stack.resize(WORDS_TOTAL) + tx_stack.fill(NOINFO) + interfer.connect("interfer_resized", Callable(self, "on_interfer_resized")) - func parse(data: PackedByteArray, tick: int): + + # Обработка полученного пакета + func parse(rx_data: PackedByteArray, tick: int): rx_tick = tick if not online: online = true - emit_signal('line_changed', self) + emit_signal("line_changed", self) + var words: Array[int] = [] + var offset: int = 0 + while offset < rx_data.size(): + if offset + 4 <= rx_data.size(): + var word = rx_data.decode_u32(offset) + words.append(word) + offset += 4 + else: + break + if words.size() < 10: + emit_signal('parse_failed', self) + tx_stack.fill(NOINFO) + tx_stack[0] = words[0] # ID + tx_stack[1] = msg_counter # Nc + tx_stack[2] = 0x01 # Nб + tx_stack[3] = 0x00 # Ск + tx_stack[4] = 0x0194 # НТС + tx_stack[5] = (0x0001 << 16) | 0x0080 # Ии + tx_stack[6] = 0x01 # РКС + srn = words[7] # SRN + jtids = words[8] # JTIDS + btn_trassa_pressed() + interfer_data() + tx_stack[74] = _calc_crc(tx_stack) + emit_signal("data_received", self) + + + func interfer_data() -> void: + for i in range(67, 74): + tx_stack[i] = 0 + for ecm in ecms.values(): + if ecm.svk == 1: + var nmfs_value = ecm.nmfs + var fs_key = get_fs_key(nmfs_value) + if fs_key != NOINFO: + var string_index = fs_key / 4 + var bit_position = fs_key % 4 + if string_index >= 0 and string_index < 7: + var target_string = 67 + string_index + tx_stack[target_string] |= (1 << bit_position) + + + func get_fs_key(nmfs_value: int) -> int: + if prd.fs_caps_id.has(nmfs_value): + return prd.fs_caps_id[nmfs_value] + return NOINFO + + + # Отправка пакета от uarep-ctl + func process(now_tick: int) -> int: + if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT): + online = false + emit_signal("line_changed", self) + if (now_tick - tx_tick) > REQUEST_PERIOD: + tx_tick = now_tick + msg_counter += 1 + interfer_uarep() + interfer_data() + var data = PackedByteArray() + data.resize(WORDS_TOTAL * 4) + for i in range(WORDS_TOTAL): + data.encode_u32(i * 4, tx_stack[i]) + tx_data = data + tx_len = WORDS_TOTAL * 4 + return Error.OK + return Error.ERR_BUSY + + + # CRC вычисление + func _calc_crc(data: Array) -> int: + var acc: int = 0 + for i in range(data.size() - 1): # кроме CRC + if i in [0, 1]: + continue + acc = (acc + (data[i] & 0xFFFFFFFF)) & 0xFFFFFFFF + return acc + + + # Обновление всех активных помех + func on_interfer_resized(ecms_dic: Dictionary) -> void: ecms = ecms_dic + + + func interfer_uarep() -> void: + tx_stack[65] = 0 + tx_stack[66] = 0 + for ecm in ecms.values(): + if ecm.krp == "srni1" and ecm.svk == 1: + tx_stack[65] = 1 + if ecm.krp == "svi1" and ecm.svk == 1: + tx_stack[66] = 1 + tx_stack[1] = msg_counter + + + # Обработка указаний от Трассы по кнопке + func btn_trassa_pressed() -> void: + var state = ProjectSettings.get_setting('application/config/Внешнее указание Трасса', false) + if state == true: + var tree: SceneTree = Engine.get_main_loop() + if tree is SceneTree: + var nodes: Array = tree.get_nodes_in_group('группа-принудительно') + for btn in nodes: + if btn.name == 'btn_srn': + btn.pressed = (srn == 1) + elif btn.name == 'btn_jtids': + btn.pressed = (jtids == 1) + if srn == 1: + tx_stack[65] = 1 + signaller.emit_signal('interfer_prinuditelno', frm_ecm_list.srn_sectors) + else: + tx_stack[65] = 0 + for ecm in ecms.values(): + if ecm.krp == "srni1" and ecm.svk == 1: + ecm.krp = interfer.INTERFER_OFF + interfer.send_ecm(ecm, unit_caps) + signaller.emit_signal('interfer_off', ecm) + if jtids == 1: + tx_stack[66] = 1 + signaller.emit_signal('interfer_prinuditelno', frm_ecm_list.jtids_sectors) + else: + tx_stack[66] = 0 + for ecm in ecms.values(): + if ecm.krp == "svi1" and ecm.svk == 1: + ecm.krp = interfer.INTERFER_OFF + interfer.send_ecm(ecm, unit_caps) + signaller.emit_signal('interfer_off', ecm) + for ecm in ecms.values(): + if ecm.krp == "svi1" and ecm.svk == 1: + ecm.krp = interfer.INTERFER_OFF + interfer.send_ecm(ecm, unit_caps) + signaller.emit_signal('interfer_off', ecm) From 87b4e83c314f25b3a6d603d5871304ce20efc17a Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 9 Oct 2025 14:08:18 +0300 Subject: [PATCH 068/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C.=20=D0=9F=D1=80?= =?UTF-8?q?=D0=B8=D0=B1=D0=BE=D1=80=D1=8B=20=D0=9F=D0=A0=D0=94.=20=D0=9F?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=BD=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D1=87=D0=B8=D1=8F=20=D0=94=D0=9A=D0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-k/pribor-prd-k.gd | 7 +++++-- scripts/pribor-prd.gd | 9 +++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/scenes/pribor-prd-k/pribor-prd-k.gd b/scenes/pribor-prd-k/pribor-prd-k.gd index 3c7b47f7..b392fac7 100644 --- a/scenes/pribor-prd-k/pribor-prd-k.gd +++ b/scenes/pribor-prd-k/pribor-prd-k.gd @@ -166,7 +166,7 @@ func on_mode_changed(in_tree: bool) -> void: mashine_timer.start() -func power_fill(pow_dic: Dictionary) -> void: +func power_fill(pow_dic: Dictionary, fs_result: Dictionary) -> void: #if not control_prd_k.block_kasseta_y5_config.yau07 or not control_prd_k.block_kasseta_y5_config.ukp1 or not control_prd_k.block_kasseta_y5_config.ukp2: #return var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier') @@ -179,6 +179,9 @@ func power_fill(pow_dic: Dictionary) -> void: if pow_dic[powamp_meta].size() < 6: status = STATE_VAL.ERROR else: + if powamp_meta == 'um_7' and not fs_result.fs_1: return + if powamp_meta in ['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'] and not fs_result.fs_6: return + if powamp_meta in ['um_8', 'um_9', 'um_10', 'um_11', 'um_12', 'um_13'] and not fs_result.fs_7: return i_powapm.value0 = pow_dic[powamp_meta] for i_p in pow_dic[powamp_meta]: if i_p < constants_k.POWER_THRESHOLD: @@ -228,7 +231,7 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: result_dic.fs_7 = false - power_fill(power_dic) + power_fill(power_dic, result_dic) var result = true for device in result_dic.values(): diff --git a/scripts/pribor-prd.gd b/scripts/pribor-prd.gd index 6031b733..121c2830 100644 --- a/scripts/pribor-prd.gd +++ b/scripts/pribor-prd.gd @@ -61,6 +61,7 @@ class TestPRD extends Node: var state: int = STATE_MASHINE.INIT var current_litera: int var flag_timer_started: bool = false + var flag_fs_status_ok: bool = false var unit_prd: Object var module_prd: Object var power_amplify: Array @@ -123,6 +124,7 @@ class TestPRD extends Node: var fs_result := {fs_key: 0} fs_result = on_fs_state(packet_type_7, fs_mapping, fs_result) control_results[fs_key] = fs_result[fs_key] + flag_fs_status_ok = control_results[fs_key] == 1 ## @@ -134,13 +136,14 @@ class TestPRD extends Node: _handle_fs_turn_on_state() state = STATE_MASHINE.FS_WORK STATE_MASHINE.FS_WORK: - if ecms.size(): + if ecms.size() and flag_fs_status_ok: _handle_fs_work_state() STATE_MASHINE.CHEK_KASSETA_Y5: if block_kasseta_y5_config['yau07']: state = STATE_MASHINE.WRITE_ISA STATE_MASHINE.WRITE_ISA: _handle_ug_set_state(0x6) + await get_tree().create_timer(1.5).timeout state = STATE_MASHINE.READ_ISA STATE_MASHINE.READ_ISA: if (unit_prd.cmd_state == unit_prd.CmdState.DONE) or (unit_prd.cmd_state == unit_prd.CmdState.FAIL): @@ -171,7 +174,7 @@ class TestPRD extends Node: STATE_MASHINE.UG_SET_RAY_0: _handle_ug_set_state(0x0) - await get_tree().create_timer(1.2).timeout + await get_tree().create_timer(0.5).timeout state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_1: _handle_ug_set_state(0x1) @@ -263,6 +266,7 @@ class TestPRD extends Node: func _handle_fs_turn_off_state() -> void: control_label.text = 'Выполняется отключение ФС-%s' % current_litera + flag_fs_status_ok = false manage_fs(false, self_name, pribor_config, fs_parameters, current_litera, constants.POWER_UM) @@ -421,6 +425,7 @@ class TestPRD extends Node: params.width, sectors[litera - 1] if litera == 1 else sectors[litera - 5] if litera > 5 else sectors[litera - 4] if litera > 3 else sectors[litera - 2] ]) + signaller.emit_signal('emit_changed', mode) signaller.emit_signal('interfer_init', interfer_name, fs_arr, power_um) From 2077673cdeee769a45ad9cd9bea58511f5026560 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 9 Oct 2025 14:29:49 +0300 Subject: [PATCH 069/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9D=D0=B5=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BF=D1=83=D1=81=D0=BA=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D0=BB=D0=B5=20=D1=81=D0=BB=D0=B8=D1=8F=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/настройки/настройки.tscn | 13 +++++++------ scripts/trassa.gd | 16 ++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index 87b1403e..1a79eb01 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -65,11 +65,11 @@ const SETTING_TABLE = [ ['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ] ] const EXTERNAL_CU = 16 ## Внешнее целеуказание -const SUPPRESS = 17 ## Строка - Подавление -const KEYBOARD = 18 ## Строка - Виртуальная клавиатура -const HIDE_EMS2 = 19 ## Строка - Скрыть вкладку ЭМС 2 -const COMMIT = 20 ## Строка - Версия УАРЭП -const TRASSA = 21 +const TRASSA = 17 +const SUPPRESS = 18 ## Строка - Подавление +const KEYBOARD = 19 ## Строка - Виртуальная клавиатура +const HIDE_EMS2 = 20 ## Строка - Скрыть вкладку ЭМС 2 +const COMMIT = 21 ## Строка - Версия УАРЭП var name_to_line_index: = {} ## Для преобразования названия параметра в номер строки @@ -214,7 +214,8 @@ func button_settings(): var extern_cu_node = $scroll_set/table.get_node2(1, EXTERNAL_CU).get_children()[0] extern_cu_node.connect('pressed', on_external_cu_btn_pressed.bind(extern_cu_node)) on_external_cu_btn_pressed(extern_cu_node) - var trassa_node = $scroll_set/table.get_node2(1, TRASSA).get_children()[0] + var trassa_node = $scroll_set/table.get_node2(1, TRASSA).get_children() + trassa_node = trassa_node[0] trassa_node.connect('pressed', on_trassa_btn_pressed.bind(trassa_node)) on_trassa_btn_pressed(trassa_node) var vk_node = $scroll_set/table.get_node2(1, KEYBOARD).get_children()[0] diff --git a/scripts/trassa.gd b/scripts/trassa.gd index 3cb5b526..e31f7dec 100644 --- a/scripts/trassa.gd +++ b/scripts/trassa.gd @@ -7,27 +7,19 @@ const NOINFO: int = 0x80000000 class Trassa extends unit.Unit: var source_addr: = [] - func process(tick: int): - if (tick - rx_tick) > ONLINE_TIMEOUT: - if online: - online = false - emit_signal('line_changed', self) - return Error.ERR_BUSY - var unit_caps = network.get_unit_instance('уарэп-капсрпб') - var source_addr: Array var tx_stack: Array[int] = [] var msg_counter: int = 0 var ecms: Dictionary = {} # Словарь всех активных помех - var srn = 0 + var srn = 0 var jtids = 0 var prinud_but: Array = [] var forced_buttons: Array = [] # Храним ссылки на кнопки - + # Инициализация func _init(nm: StringName, buttons: Array = []) -> void: self.name = nm - self.forced_buttons = buttons + self.forced_buttons = buttons tx_stack.resize(WORDS_TOTAL) tx_stack.fill(NOINFO) interfer.connect("interfer_resized", Callable(self, "on_interfer_resized")) @@ -133,7 +125,7 @@ class Trassa extends unit.Unit: # Обработка указаний от Трассы по кнопке - func btn_trassa_pressed() -> void: + func btn_trassa_pressed() -> void: var state = ProjectSettings.get_setting('application/config/Внешнее указание Трасса', false) if state == true: var tree: SceneTree = Engine.get_main_loop() From 148e705af199bcf2a4766fb7e77f7e3c12411744 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 9 Oct 2025 14:41:33 +0300 Subject: [PATCH 070/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F.=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D1=8B=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20?= =?UTF-8?q?=D1=83=D0=B3=D0=BB=D0=B0=20=D0=BC=D0=B5=D1=81=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/prd.gd | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/prd.gd b/scripts/prd.gd index 0e8e807d..567156a8 100644 --- a/scripts/prd.gd +++ b/scripts/prd.gd @@ -93,11 +93,11 @@ var fs_caps_id: Dictionary ## Словарь соответствия номе class Fs: const UM_PORTS: Dictionary = { 1 : 0x106, - 2 : 0x10A, + 2 : 0x108, 3 : 0x106, - 4 : 0x10A, + 4 : 0x108, 5 : 0x106, - 6 : 0x10A } + 6 : 0x108 } const CODE_UM: Array = [ [-5, 0], @@ -145,7 +145,7 @@ class Fs: if UM_PORTS.has(index/4): var val = um_code_tx if u.isa_ports.has(um_port): - val = tools.set_bits(u.isa_ports[um_port], um_code_tx, 0x0003) + val = tools.set_bits(u.isa_ports[um_port], um_code_tx, 0x0007) data_arr.append(um_port) data_arr.append(val) @@ -225,6 +225,7 @@ class PRD: func execute_cmd(): if not len(cmd_array): return + if unit_yau07.cmd_state != unit_yau07.CmdState.DONE: return var cmd: Array = cmd_array.pop_front() unit_yau07.send_isa(cmd[0], cmd[1]) From 71178ced2d36b185dd5b035cadbf609448b54bd1 Mon Sep 17 00:00:00 2001 From: MaD_CaT Date: Thu, 9 Oct 2025 15:38:55 +0300 Subject: [PATCH 071/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D1=83=D1=80=D1=81?= =?UTF-8?q?=D0=B0=20=D0=BA=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D1=83=20=D1=81?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=BE=D1=80=D0=BE=D0=B2.=20=D0=98=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B0=D0=B9=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B2?= =?UTF-8?q?=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=B2?= =?UTF-8?q?=D1=83=D1=85=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B5=20=D0=A1=D0=A0?= =?UTF-8?q?=D0=9D.=20=D0=90=D0=B2=D1=82=D0=BE=D0=B2=D1=8B=D0=B1=D0=BE?= =?UTF-8?q?=D1=80=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D1=86=D0=B5=D0=BB=D0=B8=20=D1=82=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D0=BA=D0=BE=20=D0=B2=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=BE=D0=BC=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B6=D0=B8=D0=BC=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/frame-ecm-list/scroll-ecm-list.gd | 9 ++++++++- scenes/работа/работа.gd | 7 +++++-- scenes/работа/работа.tscn | 3 ++- scripts/interfer.gd | 17 ++++++++++------- scripts/prd.gd | 9 ++++++++- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index b1a72d9a..733550e9 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -46,6 +46,7 @@ const COLUMN_NAME = 1 const COLUMN_AOA = 2 const COLUMN_STATE = 3 +var course = 0.0 ## Курс корабля func on_rto_threat_unsel(_th_id): $table.clear_rows_selected() @@ -88,6 +89,8 @@ func _ready(): interfer.connect('interfer_recommendate', Callable(self, 'on_interfer_recommendate')) $table.connect('row_pressed', Callable(self, 'on_row_pressed')) call_deferred('init_table') + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_navi_data_received) func init_table(): @@ -148,7 +151,7 @@ func map_th_to_row(ecm) -> Array: row[COLUMN_NAME] = '' if INTERFER_NAMES.has(ecm.krp): row[COLUMN_NAME] = '%s' % INTERFER_NAMES[ecm.krp] - row[COLUMN_AOA] = '%s' % ecm.kni + row[COLUMN_AOA] = '%s' % (ecm.kni + course) row[COLUMN_STATE] = '' if INTERFER_STATE.has(ecm.svk): row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk] @@ -162,3 +165,7 @@ func on_interfer_recommendate(ecm): var sel_ecm = $table.get_node_user_data(0, sel_rows[0]) if ecm == sel_ecm: signaller.emit_signal('interfer_selected', ecm) + + +func on_navi_data_received(data: Dictionary): + course = data.get('k', 0.0) diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 94ec2636..86c3cdbc 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -33,6 +33,8 @@ var view_mode: MapViewMode ## Режим отображения к var color_ecm: Color var color_select: Color +var course = 0.0 ## Курс корабля + signal drag_begin ## Вызывается в момент начала перетаскивания. signal drag_continue ## Вызывается во время продолжения перетаскивания. signal drag_end ## Вызывается в момент завершения перетаскивания. @@ -165,7 +167,8 @@ func _ready(): func on_navi_data_received(data: Dictionary): - $canvas.set_canvas_rotation(data.get('k', 0.0)) + $canvas.set_canvas_rotation(data.get('k', 0.0)) + course = data.get('k', 0.0) func on_user_panning(): @@ -417,7 +420,7 @@ func sel_fs_sector(event): if (event.button_index == MOUSE_BUTTON_LEFT) or (event.button_index == MOUSE_BUTTON_RIGHT): var center: Vector2 = $tilemap.position var center_offset: Vector2 = ProjectSettings.get_setting('application/interfer/center_offset', Vector2i(0, 25)) - var angle: float = event.position.angle_to_point(center + center_offset) * 180/PI - 45.0 + var angle: float = event.position.angle_to_point(center + center_offset) * 180/PI - 45.0 - course if angle < 0: angle += 360 var distance: float = event.position.distance_to(center + center_offset) diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index bbb9f017..dca53d69 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -53,6 +53,7 @@ colors = PackedColorArray(1, 1, 1, 0.352941, 1, 1, 1, 0) [sub_resource type="SystemFont" id="SystemFont_5ffal"] generate_mipmaps = true +subpixel_positioning = 0 [node name="Работа" type="Panel"] script = ExtResource("1_niok4") @@ -345,7 +346,7 @@ text = "−" [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] [connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"] -[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"] [connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"] +[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"] [connection signal="button_down" from="zoom_minus" to="tilemap" method="_on_zoom_minus_button_down"] [connection signal="button_up" from="zoom_minus" to="tilemap" method="_on_zoom_button_up"] diff --git a/scripts/interfer.gd b/scripts/interfer.gd index 988b240d..e8c08f0a 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -308,7 +308,7 @@ func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> v var id = item.id param['freq'] = item.freq param['width'] = item.width - if (item.rkrp != '') and item.fflags.rkrp: + if (item.rkrp != '') and item.fflags.rkrp and auto_enabled: var krp = get_krp(item) if krp != '': interfer_name = krp @@ -324,12 +324,15 @@ func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> v var kni: float = item[0] var id = item[3] var th = null - if not interfer_name in EXCLUDE_INTERFER: - th = find_threat(item[1], kni) + th = find_threat(item[1], kni) if th != null: - param['freq'] = th.freq - param['width'] = th.width - if (th.rkrp != '') and th.fflags.rkrp: + if not interfer_name in EXCLUDE_INTERFER: + param['freq'] = th.freq + param['width'] = th.width + else: + param['freq'] = item[1] + param['width'] = item[2] + if (th.rkrp != '') and th.fflags.rkrp and auto_enabled: var krp = get_krp(th) if krp != '': interfer_name = krp @@ -518,7 +521,7 @@ func on_threats_update(threat, ecms, unit_caps): ecm = ecms[ecm_i] ecm.params['freq'] = threat.freq ecm.params['width'] = threat.width - if (threat.rkrp != '') and threat.fflags.rkrp: + if (threat.rkrp != '') and threat.fflags.rkrp and auto_enabled: var krp = get_krp(threat) if krp != '': ecm.krp = krp diff --git a/scripts/prd.gd b/scripts/prd.gd index 567156a8..91f78de0 100644 --- a/scripts/prd.gd +++ b/scripts/prd.gd @@ -86,7 +86,7 @@ const FS_PRD: Dictionary = { var fs_dict: Dictionary ## Словарь с модулями ФС var prd_dict: Dictionary ## Словарь с приборами ПРД - +var course = 0.0 ## Курс корабля var fs_caps_id: Dictionary ## Словарь соответствия номеров ФС от КАПС РПБ внутрипрограммной нумерации @@ -185,6 +185,7 @@ class PRD: unit_yau07.connect('command_done', Callable(self, 'on_command_done')) unit_yau07.connect('line_changed', Callable(self, 'on_line_changed')) + func on_command_done(u): if yemsg_board.state_board != yemsg_board.WAIT or yemsg_board.state_cmd != yemsg_board.WAIT: yemsg_board.on_command_done(u) @@ -284,6 +285,8 @@ func _ready() -> void: unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received')) signaller.connect('режим_контроль', Callable(self, 'on_mode_changed').bind(PrdState.CONTROL)) signaller.connect('режим_работа', Callable(self, 'on_mode_changed').bind(PrdState.WORK)) + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_navi_data_received) func get_fs_param(index: int) -> Array: @@ -388,3 +391,7 @@ func on_data_capsrpb_received(unit0: capsrpb.CapsRpb): func on_mode_changed(changed_mode: int) -> void: for pdr in prd.prd_dict.values(): pdr.state = changed_mode + + +func on_navi_data_received(data: Dictionary): + course = data.get('k', 0.0) From dfab026c1113317c1b1c324eee9c113438359579 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 9 Oct 2025 22:51:50 +0300 Subject: [PATCH 072/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/network.gd b/scripts/network.gd index 0b4c58a7..53e152fb 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -78,7 +78,7 @@ class SocketSerial extends SerialPort: fcs = (fcs >> 1) ^ P_DIV if fcs & 1 else fcs >> 1 return (~fcs) & 0xffff - func try_open(parsing_proc: Callable): + func try_open(parsing_proc: Callable) -> Error: if is_open(): return Error.OK var rc: = open(port) From 0fe47eaa22c1ffe26126cdfbc348700d275dc3a8 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 9 Oct 2025 22:52:18 +0300 Subject: [PATCH 073/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20Tween=20=D0=BD=D0=B5=20=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/блок-в.tscn | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scenes/контроль/блок-в.tscn b/scenes/контроль/блок-в.tscn index 9f706046..06dcfa85 100644 --- a/scenes/контроль/блок-в.tscn +++ b/scenes/контроль/блок-в.tscn @@ -16,7 +16,6 @@ class_name blok_v extends PanelContainer @export var textures: Array @export var animation_duration: float = 1.5 signal pressed(control: PanelContainer) -var tween: Tween ## Значения уровней @@ -153,9 +152,6 @@ func _ready(): var level7: = $margin/vbox/grid1/level7 level7.connect('value_changed', on_level_changed.bind(level7, value1_info)) on_level_changed(level7.value, level7, value1_info) - tween = create_tween() - tween.set_ease(Tween.EASE_OUT) - tween.set_trans(Tween.TRANS_QUINT) func on_level_changed(_val: float, item: TextureProgressBar, info: String): @@ -228,6 +224,9 @@ func get_name_nodes() -> Array: func set_value0_animated(target_node, target_value: float) -> void: + var tween: Tween = create_tween() + tween.set_ease(Tween.EASE_OUT) + tween.set_trans(Tween.TRANS_QUINT) tween.tween_property(target_node, 'value', target_value, animation_duration) " From 2d37e240d327e480bcbad75e602bae25b3fc732a Mon Sep 17 00:00:00 2001 From: sasha80 Date: Fri, 10 Oct 2025 00:54:51 +0300 Subject: [PATCH 074/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=A1=D0=9F=D0=A2-25=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=BF=D1=80=D0=B5=D1=80=D1=8B=D0=B2=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B0=D0=B5=D1=82=D1=81=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/network.gd b/scripts/network.gd index 53e152fb..093c1177 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -401,6 +401,7 @@ func _process(_delta: float) -> void: for unit_name: StringName in units_serial: var unit_serial: = units_serial[unit_name] var serial: = serials[unit_name] + serial.tick = tick if Error.OK == unit_serial.process(tick): serial.send_to(unit_serial.tx_data) for unit_name: StringName in units_modbus: From 895da274e7f342d32ca8b6b841bebc22d54571d6 Mon Sep 17 00:00:00 2001 From: lepshiy Date: Fri, 10 Oct 2025 22:13:16 +0300 Subject: [PATCH 075/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9A=D0=BE=D1=80=D0=B0=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D0=BA=20=D1=81=20=D0=B1=D0=BE=D0=BB=D0=B5=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D1=82=D0=BD=D1=8B=D0=BC=20=D0=BD=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tilemap/23900.png | Bin 125286 -> 3194 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/scenes/tilemap/23900.png b/scenes/tilemap/23900.png index b92410e35dba6dad6aa0424dcd8ff856d929f3e2..b7ca1d1b35a14b34b23e70ce0a9521dd76f3ec1e 100644 GIT binary patch literal 3194 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 From 10d560c63ffc1e7f193cf598256989c9a20a78cb Mon Sep 17 00:00:00 2001 From: sasha80 Date: Fri, 10 Oct 2025 22:16:38 +0300 Subject: [PATCH 076/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-uyep/spt25-view.gd | 4 ++-- scenes/tabs-switch/tab-switch.gd | 18 +++++----------- scenes/контроль/кнопка-прибора.gd | 2 +- scenes/контроль/контроль.tscn | 36 +++++++++++++++---------------- scripts/signaller.gd | 1 + 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/scenes/pribor-uyep/spt25-view.gd b/scenes/pribor-uyep/spt25-view.gd index 30066a90..02938f55 100644 --- a/scenes/pribor-uyep/spt25-view.gd +++ b/scenes/pribor-uyep/spt25-view.gd @@ -3,8 +3,8 @@ extends 'res://scenes/контроль/элемент-я.gd' -func on_line_changed(unit0): - if not unit0.online: +func on_line_changed(unit_instance): + if not unit_instance.online: disable_all() diff --git a/scenes/tabs-switch/tab-switch.gd b/scenes/tabs-switch/tab-switch.gd index 5d8dba77..6e510749 100644 --- a/scenes/tabs-switch/tab-switch.gd +++ b/scenes/tabs-switch/tab-switch.gd @@ -9,25 +9,17 @@ const TAB_TOSIGNAL_NAME = { 5: 'режим_настройки' } +func on_ems2_hide_pressed(state): set_tab_hidden(4, state) +func _on_tab_changed(tab) -> void: signaller.emit_signal(TAB_TOSIGNAL_NAME[tab]) +func _on_button_trenazh_toggled(toggled_mode: bool) -> void: signaller.emit_signal('режим_тренаж', toggled_mode) + + func _enter_tree() -> void: network.logger_page = $Журнал signaller.connect('ems2_hide_pressed', on_ems2_hide_pressed) ProjectSettings.connect('settings_changed', on_setting_changed) -func on_ems2_hide_pressed(state): - set_tab_hidden(4, state) - - -func _on_tab_changed(tab) -> void: - if TAB_TOSIGNAL_NAME.has(tab): - signaller.emit_signal(TAB_TOSIGNAL_NAME[tab]) - - func on_setting_changed(): var ext_cu = ProjectSettings.get_setting('application/config/Внешнее управление', false) get_parent().get_node('remote_control').visible = ext_cu - - -func _on_button_trenaj_toggled(toggled_mode: bool) -> void: - signaller.emit_signal('режим_тренаж', toggled_mode) diff --git a/scenes/контроль/кнопка-прибора.gd b/scenes/контроль/кнопка-прибора.gd index 13d337b1..b6adb741 100644 --- a/scenes/контроль/кнопка-прибора.gd +++ b/scenes/контроль/кнопка-прибора.gd @@ -1,6 +1,6 @@ @tool -extends Node +extends TextureButton @export var state_colors: Array diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 3a92e7ad..95ae9bbb 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -25,23 +25,23 @@ script/source = "extends Panel #TODO: рефактор: заменить подчёркивание на тире const PRIBORS_RES = \\ { - 'pribor_prd_k_1': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 1'], - 'pribor_prd_k_2': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 2'], - 'pribor_prd_k_3': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 3'], - 'pribor_prd_k_4': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 4'], - 'pribor_prd_n_1': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 1'], - 'pribor_prd_n_2': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 2'], - 'pribor_prd_n_3': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 3'], - 'pribor_prd_n_4': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 4'], - 'pribor_prd_v_1': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 1'], - 'pribor_prd_v_2': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 2'], - 'pribor_prd_v_3': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 3'], - 'pribor_prd_v_4': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 4'], - 'pribor_rtr': ['res://scenes/pribor-afsp/pribor-bpo.tscn', 'Контроль исправности прибора РТР'], - 'pribor_afsp_1': ['res://scenes/pribor-afsp/pribor-afsp-1.tscn', 'Контроль исправности прибора АФСП 1'], - 'pribor_afsp_2': ['res://scenes/pribor-afsp/pribor-afsp-2.tscn', 'Контроль исправности прибора АФСП 2'], - 'pribor_uf': ['res://scenes/pribor-uf/pribor-uf.tscn', 'Контроль исправности прибора УФ'], - 'pribor_uyep': ['res://scenes/pribor-uyep/pribor-uyep.tscn', 'Контроль исправности устройства У-ЭП'], + 'pribor_prd_k_1': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 1'], + 'pribor_prd_k_2': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 2'], + 'pribor_prd_k_3': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 3'], + 'pribor_prd_k_4': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 4'], + 'pribor_prd_n_1': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 1'], + 'pribor_prd_n_2': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 2'], + 'pribor_prd_n_3': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 3'], + 'pribor_prd_n_4': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 4'], + 'pribor_prd_v_1': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 1'], + 'pribor_prd_v_2': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 2'], + 'pribor_prd_v_3': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 3'], + 'pribor_prd_v_4': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 4'], + 'pribor_rtr': ['res://scenes/pribor-afsp/pribor-bpo.tscn', 'Контроль исправности прибора РТР'], + 'pribor_afsp_1': ['res://scenes/pribor-afsp/pribor-afsp-1.tscn', 'Контроль исправности прибора АФСП 1'], + 'pribor_afsp_2': ['res://scenes/pribor-afsp/pribor-afsp-2.tscn', 'Контроль исправности прибора АФСП 2'], + 'pribor_uf': ['res://scenes/pribor-uf/pribor-uf.tscn', 'Контроль исправности прибора УФ'], + 'pribor_uyep': ['res://scenes/pribor-uyep/pribor-uyep.tscn', 'Контроль исправности устройства У-ЭП'], } @@ -55,7 +55,7 @@ func on_mode_changed(): clean_pribor_items() func _ready(): var group = ButtonGroup.new() for k in PRIBORS_RES: - var pribor_node = get_node(k) + var pribor_node: Node = get_node(k) var pribor_path = PRIBORS_RES[k][0] var header_text = PRIBORS_RES[k][1] pribor_node.set_button_group(group) diff --git a/scripts/signaller.gd b/scripts/signaller.gd index 561ed7de..16cdb39a 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -38,6 +38,7 @@ signal режим_настройки() ## [param val] - [b]true[/b] тренаж включён. signal режим_тренаж(val: bool) + ## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора цели и помехи[/b]. signal full_auto() From 51cf6fa6f759f011848d4e386d08457c52808dad Mon Sep 17 00:00:00 2001 From: sasha80 Date: Fri, 10 Oct 2025 22:21:53 +0300 Subject: [PATCH 077/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C.=20=D0=9E=D1=82?= =?UTF-8?q?=D0=B6=D0=B0=D1=82=D0=B8=D0=B5=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=B1=D0=BE=D1=80=D0=B0=20=D0=BF=D1=80=D0=B8=20=D0=B2?= =?UTF-8?q?=D1=8B=D1=85=D0=BE=D0=B4=D0=B5=20=D0=B8=D0=B7=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B6=D0=BC=D0=B0=20=D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 95ae9bbb..8500da91 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -49,7 +49,13 @@ const null_units_names = ['уарэп-афсп-левый', 'уарэп-афсп func on_line_changed(u, conn_node, _pribor_meta): conn_node.set_val(u.online) -func on_mode_changed(): clean_pribor_items() + + +func on_mode_changed(): + clean_pribor_items() + var pribor_buttons: = get_tree().get_nodes_in_group('pribor_buttons') + for node in pribor_buttons: + node.button_pressed = false func _ready(): From c7f1c44cf7426ad96a5d7c5891210bc3f609c479 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Fri, 10 Oct 2025 22:22:51 +0300 Subject: [PATCH 078/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C.=20=D0=9F=D1=80?= =?UTF-8?q?=D0=B8=D0=B1=D0=BE=D1=80=20=D0=BD=D0=B0=20=D1=81=D0=B2=D1=8F?= =?UTF-8?q?=D0=B7=D0=B8=20=D0=B5=D1=81=D0=BB=D0=B8=20=D1=85=D0=BE=D1=82?= =?UTF-8?q?=D1=8F=20=D0=B1=D1=8B=20=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=B8=D0=B7?= =?UTF-8?q?=20=D0=B5=D0=B3=D0=BE=20=D1=81=D0=BE=D1=81=D1=82=D0=B0=D0=B2?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D0=BD=D0=B0=20=D1=81=D0=B2=D1=8F=D0=B7?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 8500da91..31bf9ec8 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -85,11 +85,11 @@ func _ready(): func online_change_arr(_u, conn_node, pribor_meta): - var state_online = true - for i in pribor_meta.size(): - var unit_pribor = network.get_unit_instance(pribor_meta[i]) - if not unit_pribor.online: - state_online = false + var state_online: = false + for meta in pribor_meta: + var unit_pribor = network.get_unit_instance(meta) + if unit_pribor.online: + state_online = true break conn_node.set_val(state_online) From 2dedea8cfc77275c16b0f69773594c37046c0684 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Fri, 10 Oct 2025 22:24:47 +0300 Subject: [PATCH 079/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C.=20=D0=98=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BF=D1=80=D0=B8=D0=B1=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=B8=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20"=D0=BD=D0=B0=20=D1=81=D0=B2=D1=8F=D0=B7=D0=B8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 31bf9ec8..bcc4331b 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -379,6 +379,7 @@ texture_normal = ExtResource("3_hhadv") stretch_mode = 0 script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +metadata/unit_name = [&"уарэп-бпо-1", &"уарэп-бпо-2"] [node name="label" type="Label" parent="pribor_rtr"] layout_mode = 0 @@ -440,6 +441,8 @@ texture_normal = ExtResource("9_iqgf5") stretch_mode = 0 script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +metadata/unit_name = [&"уарэп-афсп-левый"] +metadata/online_proc = "on_line_changed" [node name="label" type="Label" parent="pribor_afsp_1"] layout_mode = 0 @@ -505,6 +508,8 @@ stretch_mode = 0 flip_h = true script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +metadata/unit_name = [&"уарэп-афсп-правый"] +metadata/online_proc = "on_line_changed" [node name="label" type="Label" parent="pribor_afsp_2"] layout_mode = 0 From ed0c517bd63f33cb8a5b431ebc556686db38c166 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 11 Oct 2025 23:34:50 +0300 Subject: [PATCH 080/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=91=D0=BE=D0=BB=D1=8C=D1=88=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B5=20=D0=BD=D1=83=D0=B6=D0=BD=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/network.gd b/scripts/network.gd index 093c1177..524a2e28 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -26,10 +26,7 @@ class SocketSerial extends SerialPort: unit_instance.parse(data, tick) func on_settings_changed(unit_instance: unit.Unit): - var external_ctl = ProjectSettings.get_setting('application/config/Внешнее управление', false) try_close() - if external_ctl: - return var rc = try_open(on_serial_data.bind(unit_instance)) if rc != Error.OK: log.message(log.ERROR, 'невозможно открыть %s для \"%s\"' % [self, unit_instance.name]) From 8fb0d32e48ada0940c8bd62e1512d7f548ebcb50 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 11 Oct 2025 23:35:53 +0300 Subject: [PATCH 081/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA?= =?UTF-8?q?=20=D0=A1=D0=9F=D0=A2=20=D0=B2=20=D1=81=D0=BB=D1=83=D1=87=D0=B0?= =?UTF-8?q?=D0=B5=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/network.gd b/scripts/network.gd index 524a2e28..27fc1185 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -54,7 +54,9 @@ class SocketSerial extends SerialPort: # var buffer = format_buffer(data) # Не проверено, но должно работать # Эта последовательность для запроса состояния, получена от разработчиков СПТ-25 const tx_tula: = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] - write_raw(tx_tula) + var sz = write_raw(tx_tula) + if sz != tx_tula.size(): # TODO: Не совсем адекватное, но работает + ProjectSettings.emit_signal('settings_changed') func _to_string() -> String: return 'последовательный порт \"%s\" @ %d (%s)' % [self.port, self.baudrate, 'открыт' if is_open() else 'закрыт'] From 42267ffc1e89984f9ec02b4848d1b820c96920a7 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 11 Oct 2025 23:38:23 +0300 Subject: [PATCH 082/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp.gd | 6 +++--- scripts/network.gd | 2 +- scripts/trassa.gd | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index 041184c2..36dadc51 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -11,7 +11,7 @@ static var node_maper = load('res://scenes/контроль/node-maper.gd') func _on_request_completed(result, _response_code, headers, body: PackedByteArray): - var unit_instance = network.get_unit_instance(unit_name) + var unit_instance: = network.get_unit_instance(unit_name) if result != 0: var rs = $request.get_result_string(result) @@ -29,9 +29,9 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra unit_instance.emit_signal('line_changed', unit_instance) return - var rc = json_conv.parse(json_str) + var rc: = json_conv.parse(json_str) if rc != Error.OK: - var err = json_conv.get_error_message() + var err: = json_conv.get_error_message() push_error('разбор json прерван - \"%s\" (%s)' % [err, headers]) if unit_instance.online: unit_instance.online = false diff --git a/scripts/network.gd b/scripts/network.gd index 27fc1185..e6312e16 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -91,7 +91,7 @@ class SocketSerial extends SerialPort: return Error.FAILED stop_monitoring() close() - var connections = data_received.get_connections() + var connections: = data_received.get_connections() for conn in connections: data_received.disconnect(conn.callable) return Error.OK diff --git a/scripts/trassa.gd b/scripts/trassa.gd index e31f7dec..6972ac82 100644 --- a/scripts/trassa.gd +++ b/scripts/trassa.gd @@ -30,7 +30,7 @@ class Trassa extends unit.Unit: rx_tick = tick if not online: online = true - emit_signal("line_changed", self) + emit_signal('line_changed', self) var words: Array[int] = [] var offset: int = 0 while offset < rx_data.size(): From b4ea2ccc88d2b3d2a96e32880962d332b13e6208 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 11 Oct 2025 23:43:14 +0300 Subject: [PATCH 083/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=9A?= =?UTF-8?q?=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C.=20=D0=A2=D0=B5?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D1=8C=20=D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2?= =?UTF-8?q?=D0=BE=D0=B4=D0=B8=D1=82=D1=81=D1=8F=20=D0=BE=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=81=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=B2=D1=8B=D0=B1?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=90=D0=A4=D0=A1?= =?UTF-8?q?=D0=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp-1.tscn | 17 ++++------ scenes/pribor-afsp/pribor-afsp-2.tscn | 17 ++++------ scenes/pribor-afsp/pribor-afsp.gd | 25 +++++++++++--- scenes/pribor-afsp/pribor-bpo.tscn | 3 -- scenes/контроль/request.gd | 49 +++------------------------ scenes/контроль/контроль.tscn | 3 -- scenes/настройки/настройки.tscn | 3 +- 7 files changed, 39 insertions(+), 78 deletions(-) diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn index 4c027fd8..08b5216b 100644 --- a/scenes/pribor-afsp/pribor-afsp-1.tscn +++ b/scenes/pribor-afsp/pribor-afsp-1.tscn @@ -1,15 +1,9 @@ -[gd_scene load_steps=5 format=3 uid="uid://8ll27id5ajq1"] +[gd_scene load_steps=4 format=3 uid="uid://8ll27id5ajq1"] [ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_151rh"] [ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_4vyhj"] [ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/контроль/bort-afsp.tscn" id="3_d7iti"] -[sub_resource type="GDScript" id="GDScript_yhnwg"] -script/source = "extends Timer - -func _enter_tree() -> void: wait_time = ProjectSettings.get_setting('application/config/unit_bpo_request_period') -" - [node name="pribor_afsp" type="Control"] layout_mode = 3 anchors_preset = 0 @@ -19,19 +13,20 @@ offset_right = 70.0 offset_bottom = 30.0 scale = Vector2(1, 0.9) script = ExtResource("1_151rh") +prefix_path = "DeviceDescription[DeviceName]" +this_afsp_name = "Устройство РР левого борта" unit_name = &"уарэп-афсп-левый" +settings_path_to_url = "Адрес АФСП левого борта" +settings_path_to_wait_time = "Период опроса состояния АФСП, секунды" metadata/DeviceName = &"Устройство РР левого борта" [node name="request" type="HTTPRequest" parent="."] use_threads = true script = ExtResource("2_4vyhj") -projsettings_path_left = "application/config/Адрес АФСП левого борта" -projsettings_path_right = "application/config/Адрес АФСП правого борта" +request_url = null [node name="timer" type="Timer" parent="request"] -wait_time = 30.0 autostart = true -script = SubResource("GDScript_yhnwg") [node name="bort" parent="." instance=ExtResource("3_d7iti")] layout_mode = 0 diff --git a/scenes/pribor-afsp/pribor-afsp-2.tscn b/scenes/pribor-afsp/pribor-afsp-2.tscn index 1bbfa3d4..f5a30eb8 100644 --- a/scenes/pribor-afsp/pribor-afsp-2.tscn +++ b/scenes/pribor-afsp/pribor-afsp-2.tscn @@ -1,15 +1,9 @@ -[gd_scene load_steps=5 format=3 uid="uid://5uv1idl3lqet"] +[gd_scene load_steps=4 format=3 uid="uid://5uv1idl3lqet"] [ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_tfses"] [ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_miwrd"] [ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/контроль/bort-afsp.tscn" id="3_xpxb5"] -[sub_resource type="GDScript" id="GDScript_yhnwg"] -script/source = "extends Timer - -func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_rr_request_period') -" - [node name="pribor_afsp" type="Control"] layout_mode = 3 anchors_preset = 0 @@ -19,19 +13,20 @@ offset_right = 81.0 offset_bottom = 108.0 scale = Vector2(1, 0.9) script = ExtResource("1_tfses") +prefix_path = "DeviceDescription[DeviceName]" +this_afsp_name = "Устройство РР правого борта" unit_name = &"уарэп-афсп-правый" +settings_path_to_url = "Адрес АФСП правого борта" +settings_path_to_wait_time = "Период опроса состояния АФСП, секунды" metadata/DeviceName = &"Устройство РР правого борта" [node name="request" type="HTTPRequest" parent="."] use_threads = true script = ExtResource("2_miwrd") -projsettings_path_left = "application/config/Адрес АФСП левого борта" -projsettings_path_right = "application/config/Адрес АФСП правого борта" +request_url = null [node name="timer" type="Timer" parent="request"] -wait_time = 30.0 autostart = true -script = SubResource("GDScript_yhnwg") [node name="bort" parent="." instance=ExtResource("3_xpxb5")] layout_mode = 0 diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index 36dadc51..60fad6a6 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -1,14 +1,29 @@ @tool class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd' -@export var prefix_path: String = 'DeviceDescription[DeviceName]' -@export var unit_name: StringName= '' +@export var prefix_path: String = '' ## Должно быть в JSON +@export var this_afsp_name: String = '' ## Должно быть в JSON +@export var unit_name: StringName= '' ## Должно быть в settings.gd +@export var settings_path_to_url: String = '' ## Должно быть в ProjectSettings +@export var settings_path_to_wait_time: String = '' ## Должно быть в ProjectSettings static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') # SystemName: "gen" DevList - там состояние связи с генератором по кан шине + +func _ready() -> void: + ProjectSettings.connect('settings_changed', on_settings_chaged) + on_settings_chaged() + + +func on_settings_chaged(): + $request.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path_to_url) + $request/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time)) + tools.allways($request.request_url != null) + + func _on_request_completed(result, _response_code, headers, body: PackedByteArray): var unit_instance: = network.get_unit_instance(unit_name) @@ -47,13 +62,15 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra push_error('путь %s не найден (%s)' % [pp_copy, ret_val[2]]) return - var this_afsp_name: StringName = $bort.get_meta('DeviceName', '') var received_afsp_name: StringName = ret_val[0] if this_afsp_name != received_afsp_name: - push_error('не известное устройство: \"%s\", ожидадось: \"%s\"' % [received_afsp_name, this_afsp_name]) + # TODO: Сюда попадаем, когда приходит от другого борта + #push_error('не известное устройство: \"%s\", ожидадось: \"%s\"' % [received_afsp_name, this_afsp_name]) return + unit_instance.rx_tick = Time.get_ticks_msec() + if not unit_instance.online: unit_instance.online = true unit_instance.emit_signal('line_changed', unit_instance) diff --git a/scenes/pribor-afsp/pribor-bpo.tscn b/scenes/pribor-afsp/pribor-bpo.tscn index c1951261..ea8b7b87 100644 --- a/scenes/pribor-afsp/pribor-bpo.tscn +++ b/scenes/pribor-afsp/pribor-bpo.tscn @@ -200,9 +200,6 @@ fname = "Яч. связи" [node name="request" type="HTTPRequest" parent="."] use_threads = true script = ExtResource("4_crej3") -projsettings_path_left = "application/config/Адрес БПО левого борта" -projsettings_path_right = "application/config/Адрес БПО правого борта" -projsettings_path_wait_time = "application/config/Период опроса состояния БПО, секунды" [node name="timer" type="Timer" parent="request"] wait_time = 30.0 diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd index 657efbbd..284a8e1d 100644 --- a/scenes/контроль/request.gd +++ b/scenes/контроль/request.gd @@ -18,58 +18,17 @@ const RESULT_STRINGS = { RESULT_REDIRECT_LIMIT_REACHED: 'Запрос достиг максимального предела перенаправления, см. `max_redirects`', RESULT_TIMEOUT: 'Время истекло' } -const headers_left = [ - 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'Accept-Encoding: gzip, deflate', - 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', - 'Connection: keep-alive', - 'Host: 172.22.246.12:8081', - 'Priority: u=0,i', - 'Upgrade-Insecure-Requests: 1', - 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0' ] -const headers_right = [ - 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'Accept-Encoding: gzip, deflate', - 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3', - 'Connection: keep-alive', - 'Host: 172.22.246.14:8082', - 'Priority: u=0,i', - 'Upgrade-Insecure-Requests: 1', - 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:143.0) Gecko/20100101 Firefox/143.0' ] - -@export var projsettings_path_left: String = '' -@export var projsettings_path_right: String = '' -@export var projsettings_path_wait_time: String = '' - - -var i_bort: int = 0 -var addr_left: String -var addr_right: String - - -func on_settings_changed(): - addr_left = ProjectSettings.get_setting(projsettings_path_left) - addr_right = ProjectSettings.get_setting(projsettings_path_right) - $timer.wait_time = int(ProjectSettings.get_setting(projsettings_path_wait_time, 5)) +@export var request_url: String = '' func get_result_string(result: Result): return RESULT_STRINGS[result] if RESULT_STRINGS.has(result) else '<неизвестный код результата HTTPRequest - %d>' % result -func _ready(): - ProjectSettings.connect('settings_changed', on_settings_changed) - on_settings_changed() - - func _on_request_timer(): - if HTTPClient.Status.STATUS_REQUESTING == get_http_client_status(): - push_warning('HTTPClient.Status.STATUS_REQUESTING') + if HTTPClient.Status.STATUS_DISCONNECTED != get_http_client_status(): return - var addr = [addr_left, addr_right][i_bort] - var hdrs = [headers_right, headers_left][i_bort] - var rc: = request(addr, hdrs) + var rc: = request(request_url) if rc != Error.OK: - push_error('%s: \"%s\"' % [error_string(rc), addr]) - i_bort = (i_bort + 1) % 2 + push_error('%s: \"%s\"' % [error_string(rc), request_url]) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index bcc4331b..6e75b606 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -45,9 +45,6 @@ const PRIBORS_RES = \\ } -const null_units_names = ['уарэп-афсп-левый', 'уарэп-афсп-правый'] - - func on_line_changed(u, conn_node, _pribor_meta): conn_node.set_val(u.online) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index 1a79eb01..44442b39 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -62,7 +62,8 @@ const SETTING_TABLE = [ ['Адрес АФСП правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'], ['Адрес БПО левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], ['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], - ['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ] ] + ['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ], + ['Период опроса состояния АФСП, секунды', TableEdit, TableEdit, 'Время в секундах' ] ] const EXTERNAL_CU = 16 ## Внешнее целеуказание const TRASSA = 17 From 7d38419e4ef26d5f92a7f390992b6cd4db5f7728 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 11 Oct 2025 23:43:32 +0300 Subject: [PATCH 084/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 6e75b606..114376f0 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -50,6 +50,10 @@ func on_line_changed(u, conn_node, _pribor_meta): conn_node.set_val(u.online) func on_mode_changed(): clean_pribor_items() + reset_pribor_buttons() + + +func reset_pribor_buttons(): var pribor_buttons: = get_tree().get_nodes_in_group('pribor_buttons') for node in pribor_buttons: node.button_pressed = false @@ -57,6 +61,7 @@ func on_mode_changed(): func _ready(): var group = ButtonGroup.new() + # Кнопки приборов, по нажатию на которые отображаеся мнемосхема for k in PRIBORS_RES: var pribor_node: Node = get_node(k) var pribor_path = PRIBORS_RES[k][0] From 7666d606ff2f83bad01dec2be1021dae6e06b819 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sat, 11 Oct 2025 23:44:37 +0300 Subject: [PATCH 085/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20"=D0=BD=D0=B0=20=D1=81=D0=B2=D1=8F=D0=B7?= =?UTF-8?q?=D0=B8"=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D0=BD=D0=B5=D1=88=D0=BD?= =?UTF-8?q?=D0=B8=D1=85=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 36 ++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 114376f0..9b4ddf43 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -69,17 +69,22 @@ func _ready(): pribor_node.set_button_group(group) pribor_node.connect('button_down', Callable(self, 'on_pribor_press').bind(pribor_path, header_text, pribor_node)) var conn_node = pribor_node.get_node('connect_pribor') - var pribor_meta = pribor_node.get_meta('unit_name', []) + var unit_names = pribor_node.get_meta('unit_name', []) var pribor_proc = pribor_node.get_meta('online_proc', '') if pribor_proc == '': continue - if pribor_meta.size(): - for i in pribor_meta.size(): - var unit_pribor = network.get_unit_instance(pribor_meta[i]) - unit_pribor.connect('line_changed', Callable(self, pribor_proc).bind(conn_node, pribor_meta)) - for unit_name in null_units_names: - var unit_instance = network.get_unit_instance(unit_name) - unit_instance.connect('line_changed', on_line_changed) + if not unit_names.size(): + continue + for i in unit_names.size(): + var unit_instance: = network.get_unit_instance(unit_names[i]) + unit_instance.connect('line_changed', Callable(self, pribor_proc).bind(conn_node, unit_names)) + # Пиктограммы приборов, которые отображают состояние подключения только + for pribor_node in get_tree().get_nodes_in_group('pribor_pics'): + var unit_name = pribor_node.get_meta('unit_name') + var unit_instance: = network.get_unit_instance(unit_name) + var conn_node: = pribor_node.get_node('connect_pribor') + unit_instance.connect('line_changed', on_line_changed.bind(conn_node)) + signaller.conn(signaller.режим_работа, on_mode_changed) signaller.conn(signaller.режим_журнал, on_mode_changed) signaller.conn(signaller.режим_настройки, on_mode_changed) @@ -145,7 +150,7 @@ grow_vertical = 2 script = SubResource("GDScript_iqgf5") metadata/_edit_lock_ = true -[node name="capsrpb" type="TextureRect" parent="."] +[node name="capsrpb" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -159,6 +164,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"уарэп-капсрпб" +metadata/unit_name = &"уарэп-капсрпб" [node name="label" type="Label" parent="capsrpb"] layout_mode = 0 @@ -178,7 +184,7 @@ scale = Vector2(2.6, 2.6) sprite_frames = SubResource("SpriteFrames_foasq") script = ExtResource("11_u7tym") -[node name="5p28" type="TextureRect" parent="."] +[node name="5p28" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -192,6 +198,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"уарэп-5п28" +metadata/unit_name = &"уарэп-5п28" [node name="label" type="Label" parent="5p28"] layout_mode = 0 @@ -212,7 +219,7 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="akng" type="TextureRect" parent="."] +[node name="akng" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -226,6 +233,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"навигация" +metadata/unit_name = &"навигация" [node name="label" type="Label" parent="akng"] layout_mode = 0 @@ -246,7 +254,7 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="maps" type="TextureRect" parent="."] +[node name="maps" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -260,6 +268,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"уарэп-карта" +metadata/unit_name = &"уарэп-карта" [node name="label" type="Label" parent="maps"] layout_mode = 0 @@ -280,7 +289,7 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="trassa" type="TextureRect" parent="."] +[node name="trassa" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -294,6 +303,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"уарэп-трасса" +metadata/unit_name = &"уарэп-трасса" [node name="label" type="Label" parent="trassa"] layout_mode = 0 From bd7c6be2dcb17f8f818da60202d9240f971d30b4 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 12 Oct 2025 01:54:52 +0300 Subject: [PATCH 086/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/{контроль => pribor-afsp}/bort-afsp.tscn | 0 scenes/pribor-afsp/pribor-afsp-1.tscn | 2 +- scenes/pribor-afsp/pribor-afsp-2.tscn | 2 +- scenes/журнал/журнал.gd | 2 -- 4 files changed, 2 insertions(+), 4 deletions(-) rename scenes/{контроль => pribor-afsp}/bort-afsp.tscn (100%) diff --git a/scenes/контроль/bort-afsp.tscn b/scenes/pribor-afsp/bort-afsp.tscn similarity index 100% rename from scenes/контроль/bort-afsp.tscn rename to scenes/pribor-afsp/bort-afsp.tscn diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn index 08b5216b..867517f0 100644 --- a/scenes/pribor-afsp/pribor-afsp-1.tscn +++ b/scenes/pribor-afsp/pribor-afsp-1.tscn @@ -2,7 +2,7 @@ [ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_151rh"] [ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_4vyhj"] -[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/контроль/bort-afsp.tscn" id="3_d7iti"] +[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_d7iti"] [node name="pribor_afsp" type="Control"] layout_mode = 3 diff --git a/scenes/pribor-afsp/pribor-afsp-2.tscn b/scenes/pribor-afsp/pribor-afsp-2.tscn index f5a30eb8..51ff32da 100644 --- a/scenes/pribor-afsp/pribor-afsp-2.tscn +++ b/scenes/pribor-afsp/pribor-afsp-2.tscn @@ -2,7 +2,7 @@ [ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_tfses"] [ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_miwrd"] -[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/контроль/bort-afsp.tscn" id="3_xpxb5"] +[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_xpxb5"] [node name="pribor_afsp" type="Control"] layout_mode = 3 diff --git a/scenes/журнал/журнал.gd b/scenes/журнал/журнал.gd index 2fcb0369..7bc53059 100644 --- a/scenes/журнал/журнал.gd +++ b/scenes/журнал/журнал.gd @@ -37,8 +37,6 @@ func _ready() -> void: signaller.conn(signaller.режим_тренаж, Callable(self, 'on_mode_trenazh')) - - func _on_clear_button_down() -> void: $content.clear() log.info('Cодержание журнала очищено оператором') From 7daa074cf35f349f8d6067346d0cfb1c6a347fbe Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 12 Oct 2025 01:55:53 +0300 Subject: [PATCH 087/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=A1=D0=B8=D0=B3=D0=BD?= =?UTF-8?q?=D0=B0=D0=BB=20=D0=BD=D0=B5=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=B0=D1=82=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=D1=81=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 9b4ddf43..944c4ee2 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -83,7 +83,7 @@ func _ready(): var unit_name = pribor_node.get_meta('unit_name') var unit_instance: = network.get_unit_instance(unit_name) var conn_node: = pribor_node.get_node('connect_pribor') - unit_instance.connect('line_changed', on_line_changed.bind(conn_node)) + unit_instance.connect('line_changed', on_line_changed.bind(conn_node, unit_name)) signaller.conn(signaller.режим_работа, on_mode_changed) signaller.conn(signaller.режим_журнал, on_mode_changed) From 43540b1ae66587cf3cb80249ca9489452f119d0f Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 12 Oct 2025 18:34:18 +0300 Subject: [PATCH 088/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A3=D1=82=D0=BE=D1=87=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=20=D1=82=D1=80=D0=B0=D1=81=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/настройки/настройки.tscn | 3 ++- scripts/settings.gd | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index 44442b39..43c99312 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -63,7 +63,8 @@ const SETTING_TABLE = [ ['Адрес БПО левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], ['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], ['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ], - ['Период опроса состояния АФСП, секунды', TableEdit, TableEdit, 'Время в секундах' ] ] + ['Период опроса состояния АФСП, секунды', TableEdit, TableEdit, 'Время в секундах' ], + ['уареп-трасса', TableEdit, TableEdit, 'IP-адрес для связи с Трассой [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'] ] const EXTERNAL_CU = 16 ## Внешнее целеуказание const TRASSA = 17 diff --git a/scripts/settings.gd b/scripts/settings.gd index 2635a46d..93270847 100644 --- a/scripts/settings.gd +++ b/scripts/settings.gd @@ -10,7 +10,7 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ 'уарэп-яу07-частный': ['yau07rx', ['10.1.1.2', 50002, false, true], 'IP-адрес для приёма частных сообщений от ЯУ-07'], 'уарэп-яу07-общий': ['yau07rx', ['*', 50000, true, true], 'IP-адрес для приёма широковещательных сообщений от ЯУ-07'], 'уарэп-капсрпб': ['capsrpb', ['127.0.0.1', '127.0.0.1', 42023, 42022, false, true], 'IP-адрес для обмена сообщениями со службой \"МП550\" (СТЦ)'], - 'уарэп-трасса': ['trassa', ['127.0.0.1', '127.0.0.1', 50200, 50200, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], + 'уарэп-трасса': ['trassa', ['127.0.0.1', '127.0.0.1', 50200, 10004, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], 'уарэп-эмс': ['yau07tx', ['10.1.1.52', 50052, false, false], 'IP-адрес прибора УФ'], 'уарэп-яу07-2в': ['yau07tx', ['10.1.1.22', 50022, false, false], 'IP-адрес прибора ПРД-В2'], 'уарэп-яу07-2н': ['yau07tx', ['10.1.1.21', 50021, false, false], 'IP-адрес прибора ПРД-Н2'], From 53e08b9efddeb4d9696cf221e410b997fe7afc70 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 12 Oct 2025 18:34:35 +0300 Subject: [PATCH 089/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A3=D1=82=D0=BE=D1=87=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=BA=D0=B0=D0=BF=D1=81=D1=80=D0=BF=D0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/настройки/настройки.tscn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index 43c99312..f2d66db6 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -38,7 +38,7 @@ const SETTING_TABLE = [ ['Текущая версия ПО УАРЭП', TableEdit, TableEdit, 'Время сборки, версия и номер фиксации'], ['уарэп-яу07-частный', TableEdit, TableEdit, 'IP-адрес для получения частных сообщений от ЯУ-07'], ['уарэп-яу07-общий', TableEdit, TableEdit, 'IP-адрес для получения широковещательных сообщений от ЯУ-07'], - ['уарэп-капсрпб', TableEdit, TableEdit, 'IP-адрес для связи с КАПС-РПБ'], + ['уарэп-капсрпб', TableEdit, TableEdit, 'IP-адрес для связи с КАПС-РПБ [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'], ['уарэп-эмс', TableEdit, TableEdit, 'IP-адрес для связи с ЭМС'], ['уарэп-яу07-2в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 2'], ['уарэп-яу07-2н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 2'], From 16df89e426983b596365d52ee0a341666615182f Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 12 Oct 2025 18:34:42 +0300 Subject: [PATCH 090/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/trassa.gd | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/trassa.gd b/scripts/trassa.gd index 6972ac82..fafcff6a 100644 --- a/scripts/trassa.gd +++ b/scripts/trassa.gd @@ -22,7 +22,7 @@ class Trassa extends unit.Unit: self.forced_buttons = buttons tx_stack.resize(WORDS_TOTAL) tx_stack.fill(NOINFO) - interfer.connect("interfer_resized", Callable(self, "on_interfer_resized")) + interfer.connect('interfer_resized', Callable(self, 'on_interfer_resized')) # Обработка полученного пакета @@ -83,7 +83,7 @@ class Trassa extends unit.Unit: func process(now_tick: int) -> int: if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT): online = false - emit_signal("line_changed", self) + emit_signal('line_changed', self) if (now_tick - tx_tick) > REQUEST_PERIOD: tx_tick = now_tick msg_counter += 1 @@ -117,9 +117,9 @@ class Trassa extends unit.Unit: tx_stack[65] = 0 tx_stack[66] = 0 for ecm in ecms.values(): - if ecm.krp == "srni1" and ecm.svk == 1: + if ecm.krp == 'srni' and ecm.svk == 1: tx_stack[65] = 1 - if ecm.krp == "svi1" and ecm.svk == 1: + if ecm.krp == 'svi1' and ecm.svk == 1: tx_stack[66] = 1 tx_stack[1] = msg_counter @@ -152,12 +152,12 @@ class Trassa extends unit.Unit: else: tx_stack[66] = 0 for ecm in ecms.values(): - if ecm.krp == "svi1" and ecm.svk == 1: + if ecm.krp == 'svi1' and ecm.svk == 1: ecm.krp = interfer.INTERFER_OFF interfer.send_ecm(ecm, unit_caps) signaller.emit_signal('interfer_off', ecm) for ecm in ecms.values(): - if ecm.krp == "svi1" and ecm.svk == 1: + if ecm.krp == 'svi1' and ecm.svk == 1: ecm.krp = interfer.INTERFER_OFF interfer.send_ecm(ecm, unit_caps) signaller.emit_signal('interfer_off', ecm) From 0978a06a3fd13fbc1705039cb06ee615e136138a Mon Sep 17 00:00:00 2001 From: sasha80 Date: Sun, 12 Oct 2025 19:52:40 +0300 Subject: [PATCH 091/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=98=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=20=D0=BA=D0=B0=D1=80=D1=82=20"=D0=BD=D0=B0=20=D1=81=D0=B2?= =?UTF-8?q?=D1=8F=D0=B7=D0=B8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tilemap/tilemap.gd | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index d3dc6819..8a7bad2d 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -90,7 +90,6 @@ var image: = Image.new() var image_load_proc: Callable var now: = 0 var visible_marks_count: = 0 -var map_server_available: = false var border1: ImageTexture var border2: ImageTexture @@ -383,20 +382,22 @@ func _process(delta) -> void: func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: Tile) -> void: + var unit_instance = network.get_unit_instance('уарэп-карта') + _req_count -= 1 remove_child(req) req.queue_free() if result != HTTPRequest.RESULT_SUCCESS: - if map_server_available: - map_server_available = false - emit_signal('map_server_offline') + if unit_instance.online: + unit_instance.online = false + unit_instance.emit_signal('line_changed', unit_instance) _queue[tile.i] = tile return - if not map_server_available: - map_server_available = true - emit_signal('map_server_online') + if not unit_instance.online: + unit_instance.online = true + unit_instance.emit_signal('line_changed', unit_instance) if code == 404: push_error('на сервере нет \"%s\"' % tile.url) From ea359778848267450a6a73db8974b0fc19e5c3e3 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 13 Oct 2025 11:08:07 +0300 Subject: [PATCH 092/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=98=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20"=D0=BD=D0=B0=20=D1=81=D0=B2=D1=8F=D0=B7?= =?UTF-8?q?=D0=B8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp.gd | 1 - scenes/pribor-afsp/pribor-bpo.gd | 41 ++++++++++++++++++++++++++---- scenes/pribor-afsp/pribor-bpo.tscn | 36 ++++++++++++++++---------- scenes/tilemap/tilemap.gd | 8 ++++-- scenes/контроль/контроль.tscn | 1 + scripts/network.gd | 3 ++- 6 files changed, 68 insertions(+), 22 deletions(-) diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index 60fad6a6..3e5d5e2e 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -70,7 +70,6 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra return unit_instance.rx_tick = Time.get_ticks_msec() - if not unit_instance.online: unit_instance.online = true unit_instance.emit_signal('line_changed', unit_instance) diff --git a/scenes/pribor-afsp/pribor-bpo.gd b/scenes/pribor-afsp/pribor-bpo.gd index e1799a4c..e493d0e3 100644 --- a/scenes/pribor-afsp/pribor-bpo.gd +++ b/scenes/pribor-afsp/pribor-bpo.gd @@ -1,20 +1,44 @@ @tool class_name pribor_rtr extends 'res://scenes/контроль/прибор.gd' -@export var prefix_path: String = 'DeviceDescription[DeviceName]' +@export var prefix_path: String = '' ## Должно быть в JSON +@export var this_bpo1_name: String = '' ## Должно быть в JSON +@export var this_bpo2_name: String = '' ## Должно быть в JSON +@export var unit_name1: StringName= '' ## Должно быть в settings.gd +@export var unit_name2: StringName= '' ## Должно быть в settings.gd +@export var settings_path1_to_url: String = '' ## Должно быть в ProjectSettings +@export var settings_path2_to_url: String = '' ## Должно быть в ProjectSettings +@export var settings_path_to_wait_time: String = '' ## Должно быть в ProjectSettings + static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') -const bort_to_node_name = { - 'Устройство БПО левого борта': 'grid_bpo_a1', - 'Устройство БПО правого борта': 'grid_bpo_a2'} +var bort_to_node_name = {} +var bort_to_unit_name = {} + + + +func _ready() -> void: + ProjectSettings.connect('settings_changed', on_settings_changed) + on_settings_changed() + + +func on_settings_changed(): + bort_to_node_name.merge({this_bpo1_name: 'grid_bpo_a1', this_bpo2_name: 'grid_bpo_a2'}, true) + bort_to_unit_name.merge({this_bpo1_name: unit_name1, this_bpo2_name: unit_name2}) + $request1.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path1_to_url) + $request1/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time)) + $request2.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path2_to_url) + $request2/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time)) + assert($request1.request_url != null) + assert($request2.request_url != null) func _on_request_completed(result, _response_code, headers, body: PackedByteArray): if result != 0: - var rs = $request.get_result_string(result) + var rs = $request1.get_result_string(result) push_error('\"%s\"' % rs) return @@ -45,6 +69,13 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra var node_name = bort_to_node_name[ret_val[0]] var bort_node = get_node(node_name) + var unit_name = bort_to_unit_name[ret_val[0]] + var unit_instance = network.get_unit_instance(unit_name) + unit_instance.rx_tick = Time.get_ticks_msec() + if not unit_instance.online: + unit_instance.online = true + unit_instance.emit_signal('line_changed', unit_instance) + for item in bort_node.get_children(): node_maper.map_value_to_item(json_conv.data, item, 'state') diff --git a/scenes/pribor-afsp/pribor-bpo.tscn b/scenes/pribor-afsp/pribor-bpo.tscn index ea8b7b87..36d5db08 100644 --- a/scenes/pribor-afsp/pribor-bpo.tscn +++ b/scenes/pribor-afsp/pribor-bpo.tscn @@ -1,16 +1,10 @@ -[gd_scene load_steps=6 format=3 uid="uid://5uv1idl3lqea"] +[gd_scene load_steps=5 format=3 uid="uid://5uv1idl3lqea"] [ext_resource type="Script" uid="uid://d0jwv5opi3mrk" path="res://scenes/pribor-afsp/pribor-bpo.gd" id="1_bhc4e"] [ext_resource type="PackedScene" uid="uid://d3iqb5e4g81m5" path="res://scenes/контроль/элемент-г.tscn" id="2_jp6m0"] [ext_resource type="PackedScene" uid="uid://p2suppildvq0" path="res://scenes/контроль/элемент-в.tscn" id="3_jcpjs"] [ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="4_crej3"] -[sub_resource type="GDScript" id="GDScript_bhc4e"] -script/source = "extends Timer - -func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_bpo_request_period') -" - [node name="pribor_bpo" type="Control"] layout_mode = 3 anchors_preset = 0 @@ -19,6 +13,14 @@ offset_top = 150.0 offset_right = 115.0 offset_bottom = 150.0 script = ExtResource("1_bhc4e") +prefix_path = "DeviceDescription[DeviceName]" +this_bpo1_name = "Устройство БПО левого борта" +this_bpo2_name = "Устройство БПО правого борта" +unit_name1 = &"уарэп-бпо-1" +unit_name2 = &"уарэп-бпо-2" +settings_path1_to_url = "Адрес БПО левого борта" +settings_path2_to_url = "Адрес БПО правого борта" +settings_path_to_wait_time = "Период опроса состояния БПО, секунды" [node name="mod_pit_g1" parent="." instance=ExtResource("2_jp6m0")] layout_mode = 2 @@ -197,14 +199,22 @@ show_rname = false self_size = Vector2i(50, 145) fname = "Яч. связи" -[node name="request" type="HTTPRequest" parent="."] +[node name="request1" type="HTTPRequest" parent="."] +use_threads = true +script = ExtResource("4_crej3") +request_url = null + +[node name="timer" type="Timer" parent="request1"] +autostart = true + +[node name="request2" type="HTTPRequest" parent="."] use_threads = true script = ExtResource("4_crej3") -[node name="timer" type="Timer" parent="request"] -wait_time = 30.0 +[node name="timer" type="Timer" parent="request2"] autostart = true -script = SubResource("GDScript_bhc4e") -[connection signal="request_completed" from="request" to="." method="_on_request_completed"] -[connection signal="timeout" from="request/timer" to="request" method="_on_request_timer"] +[connection signal="request_completed" from="request1" to="." method="_on_request_completed"] +[connection signal="timeout" from="request1/timer" to="request1" method="_on_request_timer"] +[connection signal="request_completed" from="request2" to="." method="_on_request_completed"] +[connection signal="timeout" from="request2/timer" to="request2" method="_on_request_timer"] diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index 8a7bad2d..a3f4137c 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -382,8 +382,6 @@ func _process(delta) -> void: func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: Tile) -> void: - var unit_instance = network.get_unit_instance('уарэп-карта') - _req_count -= 1 remove_child(req) req.queue_free() @@ -407,6 +405,12 @@ func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: push_error('не удалось получить изображение (неверный формат?) из \"%s\"' % tile.url) return + var unit_instance = network.get_unit_instance('уарэп-карта') + unit_instance.rx_tick = Time.get_ticks_msec() + if not unit_instance.online: + unit_instance.online = true + unit_instance.emit_signal('line_changed', unit_instance) + tile.texture = ImageTexture.create_from_image(image) _cache[tile.i] = tile diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 944c4ee2..5eb62062 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -392,6 +392,7 @@ stretch_mode = 0 script = ExtResource("3_4pt7j") state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] metadata/unit_name = [&"уарэп-бпо-1", &"уарэп-бпо-2"] +metadata/online_proc = "online_change_arr" [node name="label" type="Label" parent="pribor_rtr"] layout_mode = 0 diff --git a/scripts/network.gd b/scripts/network.gd index e6312e16..74d6fa01 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -7,7 +7,6 @@ const SERIAL_PROTO: = {'spt25': spt25.SPT25} const MODBUS_PROTO: = {'mbcs': sch3.Sch3} const NAVI_PROTO: = {'navi': navi.NaviSource} const NULL_PROTO: = {null: unit.Unit} - var tick: int = 0 @@ -131,6 +130,7 @@ var units_udprx: Dictionary[StringName, unit.Unit] ## Экземпляры var units_tcp: Dictionary[StringName, unit.Unit] ## Экземпляры устройств с tcp-соединением var units_serial: Dictionary[StringName, unit.Unit] ## Экземпляры устройств с uart-соединением var units_modbus: Dictionary[StringName, unit.Unit] ## Экземпляры устройств с modbusserial-соединением +var units_nullp: Dictionary[StringName, unit.Unit] ## Экземпляры устройств без протокола var serials: Dictionary[StringName, SocketSerial] ## Последовательные порты (uart) var dst_ports: Dictionary[StringName, int] ## Преобразование имя устройства в порт назначения var dst_addrs: Dictionary[StringName, StringName] ## Преобразование имя устройства в адрес назначения @@ -290,6 +290,7 @@ func _ready() -> void: if proto in NULL_PROTO: var unit_null = NULL_PROTO[proto].new(unit_name) units[unit_name] = unit_null + units_nullp[unit_name] = unit_null tcp_sockets.append([create_socket_tcp('уарэп-5п28'), units_tcp['уарэп-5п28']]) From 308c028038414fdb2761615cbf52eeae0a6fac55 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 13 Oct 2025 11:08:30 +0300 Subject: [PATCH 093/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D1=91=D0=BD=20=D1=84=D0=B0=D0=B9=D0=BB=20=D0=BD=D0=B0=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=B5=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.json | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/settings.json b/settings.json index 7ad413ee..2453de8d 100644 --- a/settings.json +++ b/settings.json @@ -4,6 +4,7 @@ "Адрес БПО левого борта": "http://172.22.246.13:8081/selftest", "Адрес БПО правого борта": "http://172.22.246.11:8082/selftest", "Виртуальная клавиатура": false, + "Внешнее указание Трасса": false, "Внешнее управление": false, "Кнопка «JTIDS»": false, "Кнопка «К1»": false, @@ -22,20 +23,24 @@ "Кнопка «СВ-И1»": false, "Кнопка «СВ-М2»": false, "Ограниченный режим": false, + "Период опроса состояния АФСП, секунды": "30", + "Период опроса состояния БПО, секунды": "30", "Скрыть вкладку ЭМС 2": true, - "Текущая версия ПО УАРЭП": "HEAD 48353cc Fri Sep 5 14:44:15 2025 +0300", - "Шаблон адреса сервера карт": "http://169.254.27.71:8001/osm_tiles/{z}/{x}/{y}.png", + "Текущая версия ПО УАРЭП": "master b2633d8 Thu Sep 11 16:26:39 2025 +0300", + "Шаблон адреса сервера карт": "https://tile.openstreetmap.org/{z}/{x}/{y}.png", "навигация": [ "*", 60000, true, true ], + "уареп-трасса": "127.0.0.1,127.0.0.1,50200,10004", "уарэп-5п28": [ "127.0.0.1", 50000 ], "уарэп-капсрпб": [ + "127.0.0.1", "127.0.0.1", 42023, 42022, @@ -43,7 +48,7 @@ true ], "уарэп-спт25-1": [ - "/dev/ttyUSB1", + "COM4", 0, 19200, "N", @@ -51,7 +56,7 @@ 1 ], "уарэп-спт25-2": [ - "/dev/ttyUSB2", + "CNCA0", 0, 19200, "N", @@ -152,9 +157,9 @@ true ], "уарэп-яу07-частный": [ - "10.1.1.2", - 50002, + "10.1.1.79", + 50079, false, true ] -} +} \ No newline at end of file From fad2e1cd645c5b2fb98a4440b5ff3f0750850d00 Mon Sep 17 00:00:00 2001 From: MaD_CaT Date: Mon, 13 Oct 2025 11:35:41 +0300 Subject: [PATCH 094/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=5F=5F=D0=A3=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=5F=D0=BB=D0=B8=D1=88=D0=BD=D0=B8=D0=B9=5F=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D1=82=5F=5F=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0=5F=5F=D0=A0=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B4=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D0=B0=D1=8F=5F=D0=BF?= =?UTF-8?q?=D0=BE=D0=BC=D0=B5=D1=85=D0=B0=5F=5F=D0=9A=D1=83=D1=80=D1=81=5F?= =?UTF-8?q?=D0=BA=D0=BE=D1=80=D0=B0=D0=B1=D0=BB=D1=8F=5F=D0=BF=D0=BE=5F?= =?UTF-8?q?=D1=86=D0=B5=D0=BB=D0=B8=5F=5F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/frame-ecm-list/scroll-ecm-list.gd | 5 +- scenes/grid-buttons-ecm/grid-buttons-ecm.tscn | 1 - scenes/tilemap/tilemap.gd | 3 +- scenes/работа/работа.gd | 13 ++- scripts/interfer.gd | 92 +++++++++++-------- scripts/prd.gd | 6 +- scripts/settings.gd | 2 +- 7 files changed, 73 insertions(+), 49 deletions(-) diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index 733550e9..e0f42344 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -151,7 +151,10 @@ func map_th_to_row(ecm) -> Array: row[COLUMN_NAME] = '' if INTERFER_NAMES.has(ecm.krp): row[COLUMN_NAME] = '%s' % INTERFER_NAMES[ecm.krp] - row[COLUMN_AOA] = '%s' % (ecm.kni + course) + var aoa = ecm.kni + course + if aoa > 360.0: + aoa -= 360.0 + row[COLUMN_AOA] = '%5.1f' % aoa row[COLUMN_STATE] = '' if INTERFER_STATE.has(ecm.svk): row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk] diff --git a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn index b9efbe39..a1b2522a 100644 --- a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn +++ b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn @@ -149,5 +149,4 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ЕПРЛС" disabled = true -font_size = 1 metadata/rfi_name = "eprls" diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index a3f4137c..d546a2f8 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -381,7 +381,7 @@ func _process(delta) -> void: func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: Tile) -> void: - + var unit_instance = network.get_unit_instance('уарэп-карта') _req_count -= 1 remove_child(req) req.queue_free() @@ -405,7 +405,6 @@ func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: push_error('не удалось получить изображение (неверный формат?) из \"%s\"' % tile.url) return - var unit_instance = network.get_unit_instance('уарэп-карта') unit_instance.rx_tick = Time.get_ticks_msec() if not unit_instance.online: unit_instance.online = true diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 86c3cdbc..fa4950da 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -30,6 +30,7 @@ var strob_band_begin: float ## Ширина строба в моме var strob_dir_begin: float ## Направление антенны в момент начала перетаскивания. var strob_width_begin: float ## Ширина строба по углу в момент начала перетаскивания. var view_mode: MapViewMode ## Режим отображения карты +var thrs_dict: Dictionary ## Ссылка на словарь целей var color_ecm: Color var color_select: Color @@ -93,6 +94,7 @@ func on_threats_resized(ths: Dictionary): $count_all_pad/count_all.text = '%02d' % ths.size() var c: int = ths.values().filter(func(th: threats.Threat): return th.proto != '').size() $count_danger_pad/count_danger.text = '%02d' % c + thrs_dict = ths ## Обработчик нажатия на кнопку вид. @@ -287,18 +289,27 @@ func on_rto_threat_sel(th_id, ecm_btns): unsel_fs_all(false) else: item.set_sel_visible(false) + var th = thrs_dict[th_id] + var krp = interfer.get_krp(th) for btn in ecm_btns: set_btns_disabled(false, btn) + var btn_meta = btn.get_meta('rfi_name') + if krp == btn_meta: + btn.modulate = Color.DEEP_SKY_BLUE + else: + btn.modulate = Color(1.0, 1.0, 1.0, 1.0) ## Обработчик снятия выбора РТО цели. -func on_rto_threat_unsel(th_id, _ecm_btns): +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 set_ecm_btns_state(true) + for btn in ecm_btns: + btn.modulate = Color(1.0, 1.0, 1.0, 1.0) ## Обработчик нажатия кнопки "Строб". Управляет отображением строба. diff --git a/scripts/interfer.gd b/scripts/interfer.gd index e8c08f0a..ee76a19c 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -39,15 +39,27 @@ const LCHM2_PARAMS = {'par_names' : ['freq', 'width', 'period']} const MCHM1_PARAMS = {'par_names' : ['freq', 'filename'], 'files': 'MCHM1.pcm', 'call_proc': 'call_all_diap'} -const PDM2_PARAMS = {'par_names' : ['freq', 'filename'], - 'files': 'PDM2_20.pcm', - 'call_proc': 'call_all_diap'} -const PDM4_PARAMS = {'par_names' : ['freq', 'filename'], - 'files': 'PDM4_20.pcm', - 'call_proc': 'call_all_diap'} -const PDM4S_PARAMS = {'par_names' : ['freq', 'filename'], - 'files': 'PDM4S_5.pcm', - 'call_proc': 'call_all_diap'} +const PDM2_PARAMS = {'files': { + 20 : 'PDM2_20.pcm', + 40: 'PDM2_40.pcm', + 88: 'PDM2_88.pcm', + 112: 'PDM2_112.pcm' }, + 'call_proc': 'call_pdchm', + 'par_names' : ['freq', 'filename'],} +const PDM4_PARAMS = {'files': { + 20 : 'PDM4_20.pcm', + 40: 'PDM4_40.pcm', + 84: 'PDM4_84.pcm', + 108: 'PDM4_108.pcm' }, + 'call_proc': 'call_pdchm', + 'par_names' : ['freq', 'filename'],} +const PDM4S_PARAMS = {'files': { + 5 : 'PDM4S_5.pcm', + 7 : 'PDM4S_10.pcm', + 10: 'PDM4S_2_5.pcm', + 20: 'PDM4S_10.pcm' }, + 'call_proc': 'call_pdchm', + 'par_names' : ['freq', 'filename'],} const K1_PARAMS = {'files' : 'K1.pcm', 'call_proc' : 'call_all_diap', 'par_names' : ['freq', 'filename']} @@ -68,10 +80,10 @@ const EPRLS_PARAMS = {'files' : 'ERLS.pcm', 'par_names' : ['freq', 'filename']} # Файл : Ключ (ширина): ['имя файла'] const PDCHM_PARAMS = {'files': { - 5 : 'pdchm_5.pcm', - 10: 'pdchm__0.pcm', - 20: 'pdchm_20.pcm', - 40: 'pdchm_40.pcm' }, + 5 : 'PDCHM_5.pcm', + 10: 'PDCHM_10.pcm', + 20: 'PDCHM_20.pcm', + 40: 'PDCHM_40.pcm' }, 'call_proc': 'call_pdchm', 'par_names' : ['freq', 'filename'],} @@ -91,6 +103,7 @@ var thrs_dict: Dictionary ## Ссылка на словарь целей var auto_enabled: bool = false ## Режим автомата var emit_enable: bool = true ## Разрешить излучение var trenazh_mode: bool = false ## Переключение режима Тренаж +var course = 0.0 ## Курс корабля ## Сеанс помехи. class Interfer: @@ -182,7 +195,7 @@ func _ready() -> void: unit_5p28.connect('get_interfers', Callable(self, 'on_get_interfers').bind(unit_5p28, ecms)) signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit_caps, ecms)) signaller.connect('interfer_rcv', Callable(self, 'on_interfer_rcv').bind(unit_5p28, ecms)) - signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(unit_caps)) + signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind(unit_caps)) signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all').bind(unit_caps, ecms)) signaller.connect('th_aoa_update', Callable(self, 'on_th_aoa_update').bind(ecms, unit_caps)) signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind(ecms)) @@ -203,6 +216,7 @@ func on_trenazh_mode(val: bool): trenazh_mode = val func on_nav_data_received(coords: Dictionary, unit_caps): var ship_time = Time.get_datetime_dict_from_system() + course = coords.get('k', 0.0) var data_to_json = { 'ts': 8, 'ss': msg8_num, @@ -240,7 +254,9 @@ func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit_instance) -> v if thrs[ecm_i] == th_id: var ecm = ecms[ecm_i] ecm.params['freq'] = thr.freq - ecm.kni = thr.aoa + ecm.kni = thr.aoa - course + if ecm.kni < 0: + ecm.kni += 360 send_ecm(ecm, unit_instance) signaller.emit_signal('fs_update_color', ecms) prd.update_fs_state(ecms, trenazh_mode) @@ -304,7 +320,9 @@ func map_mpchf_to_seczaps(unit_instance: unit.Unit, seczaps: Dictionary): func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> void: for item in sel_threats: var param: Dictionary = {} - var kni: float = item.aoa + var kni: float = item.aoa - course + if kni < 0: + kni += 360.0 var id = item.id param['freq'] = item.freq param['width'] = item.width @@ -323,38 +341,22 @@ func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> v var param: Dictionary = {} var kni: float = item[0] var id = item[3] - var th = null - th = find_threat(item[1], kni) - if th != null: - if not interfer_name in EXCLUDE_INTERFER: - param['freq'] = th.freq - param['width'] = th.width - else: - param['freq'] = item[1] - param['width'] = item[2] - if (th.rkrp != '') and th.fflags.rkrp and auto_enabled: - var krp = get_krp(th) - if krp != '': - interfer_name = krp - set_rparams(th, param) - else: - param['freq'] = item[1] - param['width'] = item[2] + param['freq'] = item[1] + param['width'] = item[2] if (param['width'] < settings.WIDTH_MIN): param['width'] = settings.WIDTH_MIN elif (param['width'] > settings.WIDTH_MAX): param['width'] = settings.WIDTH_MAX - if th == null: - interfer_create(u, interfer_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1], power) - else: - id = th.id - interfer_create(u, interfer_name, ecms, param, kni, id, thrs, SOURCE_INTERFER[0], power) + interfer_create(u, interfer_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1], power) + func on_interfer_rcv(interfer_params: Array, unit0, ecms) -> void: var err: bool = false var mode = interfer_params[0] var id = interfer_params[1] - var aoa = interfer_params[2] + var aoa = interfer_params[2] - course + if aoa < 0: + aoa += 360 var um = interfer_params[3] if (aoa < 0.0) and (aoa > 360.0): err = true @@ -527,7 +529,9 @@ func on_threats_update(threat, ecms, unit_caps): ecm.krp = krp set_rparams(threat, ecm.params) emit_signal('interfer_recommendate', ecm) - ecm.kni = threat.aoa + ecm.kni = threat.aoa - course + if ecm.kni < 0: + ecm.kni += 360 set_nmfs(ecm) if threat.tmod != 'fm': if ecm != null: @@ -637,3 +641,11 @@ func on_interfer_off(ecm: Interfer, ecms): interfer.push_id(ecm.ispp) if sz != ecms.size(): interfer.call_deferred('emit_signal', 'interfer_resized', ecms) + + +func on_interfer_new(ecm, unit_caps): + var ecm_params = ITERFER_MODE[ecm.krp][1] + if ecm_params.has('call_proc'): + var call_set_params = Callable(self, ecm_params['call_proc']).bind(ecm, ecm_params) + call_set_params.call() + send_ecm(ecm, unit_caps) diff --git a/scripts/prd.gd b/scripts/prd.gd index 91f78de0..0ff163e3 100644 --- a/scripts/prd.gd +++ b/scripts/prd.gd @@ -33,8 +33,8 @@ const FS_FREQ: Dictionary = { 0: [390.0, 510.0, 450.0], 1: [800.0, 1065.0, 932.0], 2: [1065.0, 1210.0, 1137.0], - 3: [1150.0, 1280.0, 1215.0], - 4: [1490.0, 2000.0, 1575.0], + 3: [1150.0, 1380.0, 1215.0], + 4: [1380.0, 2000.0, 1575.0], 5: [2000.0, 3500.0, 2750.0], 6: [3500.0, 6000.0, 4750.0] } @@ -86,7 +86,7 @@ const FS_PRD: Dictionary = { var fs_dict: Dictionary ## Словарь с модулями ФС var prd_dict: Dictionary ## Словарь с приборами ПРД -var course = 0.0 ## Курс корабля +var course = 0.0 ## Курс корабля var fs_caps_id: Dictionary ## Словарь соответствия номеров ФС от КАПС РПБ внутрипрограммной нумерации diff --git a/scripts/settings.gd b/scripts/settings.gd index 93270847..0628fcd8 100644 --- a/scripts/settings.gd +++ b/scripts/settings.gd @@ -50,7 +50,7 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ const FREQ_MAX: = 6000.0 const FREQ_MIN: = 400.0 -const WIDTH_MAX: = 100.0 +const WIDTH_MAX: = 120.0 const WIDTH_MIN: = 0.0 const DUR_MAX: = 1000000.0 const PERIOD_MAX: = 1000000.0 From d09a0f3f4caaf0d0392be68f8a0c33efabee6b52 Mon Sep 17 00:00:00 2001 From: Maxim Date: Mon, 13 Oct 2025 11:53:18 +0300 Subject: [PATCH 095/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20[PATCH]=20=D0=BE=D1=82=D0=BB=D0=B0=D0=B4?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8F?= =?UTF-8?q?,=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=B8=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D0=B8=20=D1=80?= =?UTF-8?q?=D0=B5=D0=B6=D0=B8=D0=BC=D0=B0=20=D0=A2=D1=80=D0=B5=D0=BD=D0=B0?= =?UTF-8?q?=D0=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-n/pribor-prd-n.gd | 6 +++-- scenes/pribor-prd-v/pribor-prd-v.gd | 6 +++-- scenes/tabs-switch/lbl_ready.gd | 8 +++++++ scenes/tabs-switch/lbl_ready.gd.uid | 1 + scenes/tabs-switch/tab-switch.tscn | 20 +++++++++++++++- scenes/tabs-switch/тренаж_режим.gd | 11 +++++++++ scenes/tabs-switch/тренаж_режим.gd.uid | 1 + scenes/работа/работа.tscn | 2 +- scripts/pribor-prd.gd | 32 ++++++++++++++++++++++++++ 9 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 scenes/tabs-switch/lbl_ready.gd create mode 100644 scenes/tabs-switch/lbl_ready.gd.uid create mode 100644 scenes/tabs-switch/тренаж_режим.gd create mode 100644 scenes/tabs-switch/тренаж_режим.gd.uid diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index 42b39cb4..cd835968 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -159,7 +159,7 @@ func on_mode_changed(in_tree: bool) -> void: mashine_timer.start() -func power_fill(pow_dic: Dictionary) -> void: +func power_fill(pow_dic: Dictionary, fs_result: Dictionary) -> void: #if not control_prd_n.block_kasseta_y5_config.yau07 or not control_prd_n.block_kasseta_y5_config.ukp1 or not control_prd_n.block_kasseta_y5_config.ukp2: #return var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier') @@ -169,6 +169,8 @@ func power_fill(pow_dic: Dictionary) -> void: if pow_dic[powamp_meta].size() < 6: status = STATE_VAL.ERROR else: + if powamp_meta in ['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'] and not fs_result.fs_2: return + if powamp_meta in ['um_7', 'um_8', 'um_9', 'um_10', 'um_11', 'um_12'] and not fs_result.fs_3: return i_powapm.value0 = pow_dic[powamp_meta] for i_p in pow_dic[powamp_meta]: if i_p < constants_n.POWER_THRESHOLD: @@ -214,7 +216,7 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: result_dic.fs_3 = 0 - power_fill(power_dic) + power_fill(power_dic, result_dic) var result = true for device in result_dic.values(): diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index 35e9ff40..f50352f1 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -159,7 +159,7 @@ func on_mode_changed(in_tree: bool) -> void: mashine_timer.start() -func power_fill(pow_dic: Dictionary) -> void: +func power_fill(pow_dic: Dictionary, fs_result: Dictionary) -> void: var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier') for i_powapm in power_amplifier: var powamp_meta: String = i_powapm.get_meta('um') @@ -167,6 +167,8 @@ func power_fill(pow_dic: Dictionary) -> void: if pow_dic[powamp_meta].size() < 6: status = STATE_VAL.ERROR else: + if powamp_meta in ['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'] and not fs_result.fs_4: return + if powamp_meta in ['um_7', 'um_8', 'um_9', 'um_10', 'um_11', 'um_12'] and not fs_result.fs_5: return i_powapm.value0 = pow_dic[powamp_meta] for i_p in pow_dic[powamp_meta]: if i_p < constants_v.POWER_THRESHOLD: @@ -211,7 +213,7 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: $dou4_A5.state = STATE_VAL.GOOD if result_dic.dou_4 else STATE_VAL.ERROR else: result_dic.fs_4 = 0 - power_fill(power_dic) + power_fill(power_dic, result_dic) var result = true for device in result_dic.values(): diff --git a/scenes/tabs-switch/lbl_ready.gd b/scenes/tabs-switch/lbl_ready.gd new file mode 100644 index 00000000..14fe79fc --- /dev/null +++ b/scenes/tabs-switch/lbl_ready.gd @@ -0,0 +1,8 @@ +extends Label + +func _ready() -> void: + var prd_dict = prd.prd_dict + + for prd_module in prd_dict.values(): ## Отправка команды на исполнение в ПРД + print('prd_module.unit_yau07.online: ', prd_module.unit_yau07.online) + pass diff --git a/scenes/tabs-switch/lbl_ready.gd.uid b/scenes/tabs-switch/lbl_ready.gd.uid new file mode 100644 index 00000000..6476ba86 --- /dev/null +++ b/scenes/tabs-switch/lbl_ready.gd.uid @@ -0,0 +1 @@ +uid://b5ykwyk5vpi6 diff --git a/scenes/tabs-switch/tab-switch.tscn b/scenes/tabs-switch/tab-switch.tscn index d9ab0277..da0800d4 100644 --- a/scenes/tabs-switch/tab-switch.tscn +++ b/scenes/tabs-switch/tab-switch.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=15 format=3 uid="uid://3slb0i3pvowc"] +[gd_scene load_steps=20 format=3 uid="uid://3slb0i3pvowc"] [ext_resource type="Script" uid="uid://bvo6tcreqyuex" path="res://scenes/tabs-switch/tab-switch.gd" id="1_fg0vd"] [ext_resource type="PackedScene" uid="uid://b276iygic5itk" path="res://scenes/работа/работа.tscn" id="2_u7p16"] @@ -7,6 +7,8 @@ [ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/эмс/эмс.tscn" id="5_u71bh"] [ext_resource type="PackedScene" uid="uid://bnptm4rlp60dq" path="res://scenes/настройки/настройки.tscn" id="6_i8iv3"] [ext_resource type="PackedScene" uid="uid://musb21x2u0xs" path="res://scenes/эмс2/эмс2.tscn" id="6_rsg03"] +[ext_resource type="Script" uid="uid://b5ykwyk5vpi6" path="res://scenes/tabs-switch/lbl_ready.gd" id="8_tidwt"] +[ext_resource type="Script" uid="uid://roajn6c6wvc1" path="res://scenes/tabs-switch/тренаж_режим.gd" id="9_41d34"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tidwt"] @@ -20,6 +22,15 @@ [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_o1r22"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nmdfd"] +bg_color = Color(0.061, 100, 0.051, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cw2ss"] +bg_color = Color(0.473976, 0.473976, 0.473976, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_41d34"] +bg_color = Color(0.39, 100, 0.327, 1) + [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_imu1q"] [node name="panel" type="Panel"] @@ -81,6 +92,7 @@ theme_override_styles/normal = SubResource("StyleBoxFlat_o1r22") text = "Исправно" horizontal_alignment = 1 vertical_alignment = 1 +script = ExtResource("8_tidwt") [node name="remote_control" type="Label" parent="."] visible = false @@ -104,10 +116,16 @@ offset_right = 1501.0 offset_bottom = 27.0 tooltip_text = "Задействовать режим Тренаж" focus_mode = 0 +theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1) theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_styles/hover_pressed = SubResource("StyleBoxFlat_nmdfd") +theme_override_styles/hover = SubResource("StyleBoxFlat_cw2ss") +theme_override_styles/pressed = SubResource("StyleBoxFlat_41d34") theme_override_styles/normal = SubResource("StyleBoxFlat_imu1q") toggle_mode = true text = "Тренаж" +script = ExtResource("9_41d34") [connection signal="tab_changed" from="tab_switch" to="tab_switch" method="_on_tab_changed"] [connection signal="toggled" from="тренаж_режим" to="tab_switch" method="_on_button_trenaj_toggled"] diff --git a/scenes/tabs-switch/тренаж_режим.gd b/scenes/tabs-switch/тренаж_режим.gd new file mode 100644 index 00000000..d334ce3c --- /dev/null +++ b/scenes/tabs-switch/тренаж_режим.gd @@ -0,0 +1,11 @@ +extends Button + +func _ready(): + connect("toggled", Callable(self, "_on_button_toggled")) + + +func _on_button_toggled(mode: bool): + if mode: + tooltip_text = "Режим \"Тренаж\" задействован" + else: + tooltip_text = "Задейстовать режим \"Тренаж\"" diff --git a/scenes/tabs-switch/тренаж_режим.gd.uid b/scenes/tabs-switch/тренаж_режим.gd.uid new file mode 100644 index 00000000..89b2121e --- /dev/null +++ b/scenes/tabs-switch/тренаж_режим.gd.uid @@ -0,0 +1 @@ +uid://roajn6c6wvc1 diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index dca53d69..cb6871f1 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -342,8 +342,8 @@ text = "−" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] [connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"] [connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"] diff --git a/scripts/pribor-prd.gd b/scripts/pribor-prd.gd index 121c2830..965d279c 100644 --- a/scripts/pribor-prd.gd +++ b/scripts/pribor-prd.gd @@ -5,6 +5,20 @@ class TestPRD extends Node: const RAY_25:= 'RAY_25' const RAY_35:= 'RAY_35' const RAY_45:= 'RAY_45' + enum DataIndices { + STATUS_BOARD = 0, + IN_BLANK_PRD = 1, + IN_IMPULS_PRD = 7, + OUT_BLANK_PRD = 13, + OUT_IMPULS_PRD = 19, + DRY_CONTACT = 27, + DKM = 28, + POWER_UKP_1 = 31, + TEMPERATURE_UKP_1 = 47, + POWER_UKP_2 = 63, + TEMPERATURE_UKP_2 = 79, + } + enum STATE_MASHINE { INIT, FS_TURN_ON, @@ -62,6 +76,8 @@ class TestPRD extends Node: var current_litera: int var flag_timer_started: bool = false var flag_fs_status_ok: bool = false + var flag_si_fs_input: bool = false + var flag_si_fs_output: bool = false var unit_prd: Object var module_prd: Object var power_amplify: Array @@ -106,6 +122,7 @@ class TestPRD extends Node: block_kasseta_y5_config = check_block_kasseta_y5(status, block_kasseta_y5_config) block_ip_config = check_block_ip(status, block_ip_config) control_results.temperature = check_temperature_um(status, power_amplify) + socket_status_ems_g(status) _process_dkm_status(status) if current_litera != 0: var tek_litera: Dictionary = power_result[current_litera] @@ -115,6 +132,21 @@ class TestPRD extends Node: power_result[current_litera] = tek_litera + func socket_status_ems_g(packet_form_yau_07: PackedByteArray) -> void: + var number_socket_input: int + if current_litera >= 1 and current_litera <= 7: + number_socket_input = current_litera + 7 + + var in_blank: int = packet_form_yau_07.decode_u16(DataIndices.IN_BLANK_PRD) + flag_si_fs_input = (in_blank & (1 << number_socket_input)) != 0 ## Флаг СИ от ФС входа в ЭМС-Г для текущей литеры + + var number_socket_output: int + number_socket_output = 4 if current_litera in [2, 4, 6] else 3 if current_litera == 1 else 5 + + var out_blank: int = packet_form_yau_07.decode_u16(DataIndices.OUT_BLANK_PRD) + flag_si_fs_output = (out_blank & (1 << number_socket_output)) != 0 ## Флаг Модуляции УМ ЭМС-Г для текущей литеры + + ## Пакеты от MP550Service func on_fs_update_state(packet_type_7: Dictionary, fs_mapping: Dictionary) -> void: var fs_key: String = FS_KEYS.get(current_litera, '') From 53667e5ac9e698ac1e25c17fb28b57d5654e20a8 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Mon, 13 Oct 2025 14:04:31 +0300 Subject: [PATCH 096/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9E=D1=82=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8=20=D0=B2=20=D1=81?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=BE=D1=80=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/diagram/diagram.gd | 2 ++ scenes/работа/работа.gd | 2 ++ scenes/работа/работа.tscn | 2 +- shaders/antenas.tres | 10 +++++----- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index accc1a84..d0a346d8 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -95,6 +95,8 @@ func set_view_mode(val: int): func set_def_colors(): var color0: Color = ProjectSettings.get_setting('application/interfer/default_color0', Color(0.38, 0.47, 0.51, 1.0)) var color1: Color = ProjectSettings.get_setting('application/interfer/default_color1', Color(0.39, 0.44, 0.50, 1.0)) + color0 *= Color(1.0, 1.0, 1.0, 0.0) + color1 *= Color(1.0, 1.0, 1.0, 0.0) var col_arr: Array = [color0, color1] var col = false for i in NUM_OF_RANGE: diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index fa4950da..1315666c 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -87,6 +87,8 @@ func on_enter_tree() -> void: call_deferred('on_button_strobe_pressed') func on_settings_changed(): color_ecm = ProjectSettings.get_setting('application/interfer/interfer_color', Color(0.58, 0.47, 0.51, 1.0)) color_select = ProjectSettings.get_setting('application/interfer/select_color', Color(1.0, 1.0, 1.0, 1.0)) + color_select *= Color(1.0, 1.0, 1.0, 0.0) + color_ecm *= Color(1.0, 1.0, 1.0, 0.0) ## Обработчик сигнала изменения списка целей. diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index cb6871f1..dca53d69 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -342,8 +342,8 @@ text = "−" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] [connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"] [connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"] diff --git a/shaders/antenas.tres b/shaders/antenas.tres index 74c1d79c..2c689e09 100644 --- a/shaders/antenas.tres +++ b/shaders/antenas.tres @@ -78,11 +78,11 @@ void antenas(inout vec4 c, vec2 uv, vec2 p0, int cnt, float r0, float r1, inout } col.rgb = ant_band_c[j].rgb; index++; - col.a = alpha; - float v = float(i & 1); - vec4 color = v * col + (1.0f - v) * col; - sector(c, uv, p0, float(i) * da, da, r0, r1, color); - } + col.a = alpha + (random_timed(uv) - 0.5f) * ant_band_c[j].a; + float v = float(i & 1); + vec4 color = v * col + (1.0f - v) * col; + sector(c, uv, p0, float(i) * da, da, r0, r1, color); + } } From 8556725bba6dc56d12c1528ad26aaa7cd72dd214 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 14 Oct 2025 17:02:14 +0300 Subject: [PATCH 097/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9E=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=20=D1=83=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D1=91=D0=BD=D0=BD=D0=BE=D0=BC=D1=83=20=D1=8D=D0=BB=D0=B5?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D1=82=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- table/table.gd | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/table/table.gd b/table/table.gd index 3a623609..f1706f3d 100644 --- a/table/table.gd +++ b/table/table.gd @@ -324,9 +324,12 @@ func _set_row_selected(i_row: int, selected: bool = true) -> void: if nodes.has(selector_key) and (not selected): var node = nodes[node_key] var selector = nodes[selector_key] - node.remove_child(selector) - selector.queue_free() nodes.erase(selector_key) + if is_instance_valid(selector): + node.remove_child(selector) + selector.queue_free() + else: + push_warning('обращение к удалённому элементу \"%s\"' % selector_key) elif (not nodes.has(selector_key)) and selected: var selector = ScnSelector.instantiate() var rect: = [0, 0, 0, 0] From 6a105522e6654935f980ac46b950ff42684b0a07 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 14 Oct 2025 23:12:31 +0300 Subject: [PATCH 098/117] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BD=D0=BE=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tabs-switch/lbl_ready.gd | 16 ++++++++-------- scenes/настройки/настройки.tscn | 11 ++++------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/scenes/tabs-switch/lbl_ready.gd b/scenes/tabs-switch/lbl_ready.gd index 14fe79fc..cecc6a69 100644 --- a/scenes/tabs-switch/lbl_ready.gd +++ b/scenes/tabs-switch/lbl_ready.gd @@ -1,8 +1,8 @@ -extends Label - -func _ready() -> void: - var prd_dict = prd.prd_dict - - for prd_module in prd_dict.values(): ## Отправка команды на исполнение в ПРД - print('prd_module.unit_yau07.online: ', prd_module.unit_yau07.online) - pass +extends Label + +func _ready() -> void: + var prd_dict = prd.prd_dict + + for prd_module in prd_dict.values(): ## Отправка команды на исполнение в ПРД + print('prd_module.unit_yau07.online: ', prd_module.unit_yau07.online) + pass diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index f2d66db6..7384e82c 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -89,20 +89,17 @@ func _ready() -> void: func on_external_cu_btn_pressed(btn) -> void: - var state = btn.button_pressed - ProjectSettings.set_setting('application/config/Внешнее управление', state) - if state: + ProjectSettings.set_setting('application/config/Внешнее управление', btn.button_pressed) + if btn.button_pressed: signaller.emit_signal('interfer_off_all') func on_trassa_btn_pressed(btn) -> void: - var state = btn.button_pressed - ProjectSettings.set_setting('application/config/Внешнее указание Трасса', state) + ProjectSettings.set_setting('application/config/Внешнее указание Трасса', btn.button_pressed) func on_vk_pressed(btn) -> void: - var state = btn.button_pressed - signaller.emit_signal('kb_pressed', state) + signaller.emit_signal('kb_pressed', btn.button_pressed) func on_ems2_pressed(btn) -> void: From 8d3d2958ccc826abbcb324fc8bb19e0b1648cd83 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 14 Oct 2025 23:16:46 +0300 Subject: [PATCH 099/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20=D0=9D=D0=B5=20=D0=B2=D1=81=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B8=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B3=D1=80=D1=83=D0=B6=D0=B0=D1=8E=D1=82=D1=81=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/настройки/настройки.tscn | 3 +-- scripts/settings.gd | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index 7384e82c..e7573903 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -175,7 +175,7 @@ func setting_tab(): var child = node_values[0] if child is CheckButton: child.connect('pressed', Callable(self, 'on_checkbutton_pressed').bind(i)) - var val = settings_data[param_name] if settings_data.has(param_name) else false + var val = ProjectSettings.get_setting('application/config/%s' % param_name) child.set_pressed(val) else: if settings_data.has(param_name): @@ -216,7 +216,6 @@ func button_settings(): var trassa_node = $scroll_set/table.get_node2(1, TRASSA).get_children() trassa_node = trassa_node[0] trassa_node.connect('pressed', on_trassa_btn_pressed.bind(trassa_node)) - on_trassa_btn_pressed(trassa_node) var vk_node = $scroll_set/table.get_node2(1, KEYBOARD).get_children()[0] vk_node.connect('pressed', on_vk_pressed.bind(vk_node)) var ems2_hide_node = $scroll_set/table.get_node2(1, HIDE_EMS2).get_children()[0] diff --git a/scripts/settings.gd b/scripts/settings.gd index 0628fcd8..fe308b99 100644 --- a/scripts/settings.gd +++ b/scripts/settings.gd @@ -79,7 +79,7 @@ func _ready() -> void: log.warning('Будут использованы настройики по умолчанию.') return var json_data = json_conv.get_data() - settings_program.merge(json_data) + settings_program.merge(json_data, true) for key in settings_program: ProjectSettings.set_setting('application/config/%s' % key, settings_program[key]) for key: StringName in UnitProfiles.keys(): From e471df018896d3349fc4a3c4ef8350fb0f513d4e Mon Sep 17 00:00:00 2001 From: lepshiy Date: Wed, 15 Oct 2025 01:00:29 +0300 Subject: [PATCH 100/117] =?UTF-8?q?[PATCH]=20=D0=94=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20=D0=9F=D0=BE=D0=B4=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=97=D0=98=D0=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-afsp/pribor-afsp.gd | 1 + scenes/pribor-afsp/pribor-bpo.gd | 18 ++++++++++++++++++ scenes/pribor-prd-k/pribor-prd-k.gd | 18 ++++++++++++++++++ scenes/pribor-prd-n/pribor-prd-n.gd | 22 +++++++++++++++++++--- scenes/pribor-prd-v/pribor-prd-v.gd | 18 ++++++++++++++++++ scenes/pribor-uf/pribor-uf.gd | 18 ++++++++++++++++++ scenes/pribor-uyep/pribor-uyep.tscn | 2 ++ scenes/pribor-uyep/sch3.tscn | 2 +- scenes/работа/работа.tscn | 2 +- scripts/signaller.gd | 3 +++ 10 files changed, 99 insertions(+), 5 deletions(-) diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index 3e5d5e2e..67a150ba 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -9,6 +9,7 @@ class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd' static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') +var ctrl_pos = 0 # SystemName: "gen" DevList - там состояние связи с генератором по кан шине diff --git a/scenes/pribor-afsp/pribor-bpo.gd b/scenes/pribor-afsp/pribor-bpo.gd index e493d0e3..e68f542c 100644 --- a/scenes/pribor-afsp/pribor-bpo.gd +++ b/scenes/pribor-afsp/pribor-bpo.gd @@ -13,6 +13,7 @@ class_name pribor_rtr extends 'res://scenes/контроль/прибор.gd' static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') +var ctrl_pos = 110 var bort_to_node_name = {} @@ -23,6 +24,7 @@ var bort_to_unit_name = {} func _ready() -> void: ProjectSettings.connect('settings_changed', on_settings_changed) on_settings_changed() + find_labels(self) func on_settings_changed(): @@ -94,3 +96,19 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra if node.state == 1: $mod_pit_g1.state = 1 break + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-prd-k/pribor-prd-k.gd b/scenes/pribor-prd-k/pribor-prd-k.gd index b392fac7..92d616c9 100644 --- a/scenes/pribor-prd-k/pribor-prd-k.gd +++ b/scenes/pribor-prd-k/pribor-prd-k.gd @@ -77,6 +77,7 @@ var control_results_k: Dictionary = { } var test_control_k = preload('res://scripts/pribor-prd.gd') +var ctrl_pos = 30 func _ready() -> void: @@ -86,6 +87,7 @@ func _ready() -> void: initialize_connections() setup_timer() set_default_state() + find_labels(self) func on_state_mashine() -> void: @@ -245,3 +247,19 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: $control_result.text = 'Прибор ПРД-%s неисправен' % name_prd $control_result.add_theme_color_override('font_color', Color.RED) + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index cd835968..8497ec61 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -69,8 +69,7 @@ var control_results_n: Dictionary = { 'fs_3': 2, } var test_control_n = preload('res://scripts/pribor-prd.gd') - - +var ctrl_pos = 0 ################################ func on_state_mashine() -> void: control_prd_n.state_control_machine() @@ -83,7 +82,8 @@ func _ready() -> void: initialize_connections() setup_timer() set_default_state() - + find_labels(self) + func initialize_connections() -> void: var unit_name = get_meta('unit_name')[0] @@ -230,3 +230,19 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: $control_result.text = 'Прибор ПРД-%s неисправен' % name_prd $control_result.add_theme_color_override('font_color', Color.RED) + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index f50352f1..40f55e16 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -69,6 +69,7 @@ var control_results_v: Dictionary = { 'fs_5': 2, } var test_control_v = preload('res://scripts/pribor-prd.gd') +var ctrl_pos = 70 func on_state_mashine() -> void: @@ -82,6 +83,7 @@ func _ready() -> void: initialize_connections() setup_timer() set_default_state() + find_labels(self) func initialize_connections() -> void: @@ -227,3 +229,19 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: $control_result.text = 'Прибор ПРД-%s неисправен' % name_prd $control_result.add_theme_color_override('font_color', Color.RED) + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-uf/pribor-uf.gd b/scenes/pribor-uf/pribor-uf.gd index 159c6d64..3f2ab26e 100644 --- a/scenes/pribor-uf/pribor-uf.gd +++ b/scenes/pribor-uf/pribor-uf.gd @@ -5,6 +5,7 @@ enum STATE_VAL {NONE = 0, GOOD = 1, ERROR = 2} const DEV_LIST = ['00:1f.6', '07:00.0', '08:00.0', '0b:00.0'] const USB_TRACKERBALL = '13ba:0018' const REVFF = '(rev ff)' +var ctrl_pos = 100 func _ready() -> void: @@ -14,6 +15,7 @@ func _ready() -> void: unit_uf.connect('line_changed', on_line_changed) control_vk() on_line_changed(unit_uf) + find_labels(self) func on_timer(unit_name: StringName): @@ -99,3 +101,19 @@ func status_uf() -> void: $lbl_header2.text = 'Прибор не исправен' $lbl_header2.modulate = Color.RED $lbl_header2.visible = true + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-uyep/pribor-uyep.tscn b/scenes/pribor-uyep/pribor-uyep.tscn index 4748443f..e78e7826 100644 --- a/scenes/pribor-uyep/pribor-uyep.tscn +++ b/scenes/pribor-uyep/pribor-uyep.tscn @@ -33,6 +33,7 @@ offset_left = 88.0 offset_top = 319.0 offset_right = 343.0 offset_bottom = 749.0 +tooltip_text = "Ящик - 11, Позиция - 3" script = ExtResource("4_v0lil") unit_name = "уарэп-спт25-1" fname = "СПТ-25-230-400-3" @@ -67,6 +68,7 @@ offset_left = 392.0 offset_top = 320.0 offset_right = 642.0 offset_bottom = 750.0 +tooltip_text = "Ящик - 11, Позиция - 2" script = ExtResource("4_v0lil") unit_name = "уарэп-спт25-2" fname = "СПТ-25-230-400-3" diff --git a/scenes/pribor-uyep/sch3.tscn b/scenes/pribor-uyep/sch3.tscn index a175a03f..296270da 100644 --- a/scenes/pribor-uyep/sch3.tscn +++ b/scenes/pribor-uyep/sch3.tscn @@ -106,7 +106,7 @@ vertical_alignment = 1 layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 6 -tooltip_text = "Позиционное обозначение" +tooltip_text = "Ящик - 11, Позиция - 1" mouse_filter = 0 theme_override_font_sizes/font_size = 22 horizontal_alignment = 2 diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index dca53d69..006c55c8 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -346,7 +346,7 @@ text = "−" [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] [connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"] -[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"] [connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"] +[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"] [connection signal="button_down" from="zoom_minus" to="tilemap" method="_on_zoom_minus_button_down"] [connection signal="button_up" from="zoom_minus" to="tilemap" method="_on_zoom_button_up"] diff --git a/scripts/signaller.gd b/scripts/signaller.gd index 16cdb39a..c77682f3 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -193,3 +193,6 @@ signal update_scale_map(new_scale) ## Вызывается при изменении текущих координат.[br] ## [param new_coordinates] - обновленное значение координат ([b]true[/b] signal update_coordinates_map(new_coordinates) + + +signal tool_tip(new_ctrl_pos) From 979826b3432870067a854c8421ece2f661b46003 Mon Sep 17 00:00:00 2001 From: MaD_CaT Date: Wed, 15 Oct 2025 11:17:15 +0300 Subject: [PATCH 101/117] =?UTF-8?q?[PATCH]=20=D0=94=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20=D0=98=D0=B7=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=91=D0=BD=20ip=20=D1=82=D1=80=D0=B0=D1=81=D1=81=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=BD=D0=B0=D1=81=D1=82=D0=BE=D1=8F=D1=89?= =?UTF-8?q?=D0=B8=D0=B9.=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0.=20=D0=97=D0=B5=D0=BB=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=92=D0=9A-110.=20=D0=94=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20=D0=92=D0=B8=D0=B7=D1=83?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BC=D0=B5=D1=85=D0=B8.=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0.=20=D0=A3=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20=D0=BF=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D1=85=D0=B8.=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B2=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D0=B4=D0=BA=D0=B8=20=D0=AD=D0=9C=D0=A1=202=20?= =?UTF-8?q?=D0=B2=20=D0=AD=D0=9C=D0=A1=20=D0=A2=D0=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.godot | 2 ++ scenes/pribor-uf/pribor-uf.gd | 2 ++ scenes/tabs-switch/tab-switch.tscn | 2 +- scenes/работа/работа.gd | 21 ++++++++++++++++++++- scripts/settings.gd | 2 +- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/project.godot b/project.godot index fd03a88a..43e88265 100644 --- a/project.godot +++ b/project.godot @@ -36,6 +36,8 @@ config/kems_files_path="user://kems/" config/emsg_files_path="user://emsg/" config/settings_path="user://settings.json" config/unit_bpo_request_period=20.0 +interfer/emit_color=Color(0.58, 0.471, 0.51, 0.2) +interfer/emit_sel_color=Color(1, 1, 1, 1) [autoload] diff --git a/scenes/pribor-uf/pribor-uf.gd b/scenes/pribor-uf/pribor-uf.gd index 3f2ab26e..5f6b0380 100644 --- a/scenes/pribor-uf/pribor-uf.gd +++ b/scenes/pribor-uf/pribor-uf.gd @@ -76,6 +76,8 @@ func control_vk() -> void: else: $ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.ERROR + $ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.GOOD ## заглушка для зеленения ВК-110 + func control_ems(status: Array) -> void: $ref_uf/ref_kassetav13/ref_A4_KEMS.state = STATE_VAL.GOOD if ((status[0] >> 0) & 1) and ((status[0] >> 3) & 1) else STATE_VAL.ERROR diff --git a/scenes/tabs-switch/tab-switch.tscn b/scenes/tabs-switch/tab-switch.tscn index da0800d4..19727339 100644 --- a/scenes/tabs-switch/tab-switch.tscn +++ b/scenes/tabs-switch/tab-switch.tscn @@ -69,7 +69,7 @@ visible = false layout_mode = 2 metadata/_tab_index = 3 -[node name="ЭМС2" parent="tab_switch" instance=ExtResource("6_rsg03")] +[node name="ЭМС ТГ" parent="tab_switch" instance=ExtResource("6_rsg03")] visible = false layout_mode = 2 metadata/_tab_index = 4 diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 1315666c..fe9aae39 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -18,6 +18,7 @@ class_name work extends Panel @export var strob_min_width: float ## Минимальная ширина строба по углу. @export var window_0_id: int ## Идетификатор окна. Присваивается godot от 0 до количества созданных окон. +const SVK_EMIT = 1 ## Код состояния выполнения помехи - выполняется var drag_button: MouseButton ## Кнопка мыши нажатая при перетаскивании. var drag_fsm: DragFSM = DragFSM.IDLE ## Текущее состояние перетаскивания. @@ -33,6 +34,8 @@ var view_mode: MapViewMode ## Режим отображения к var thrs_dict: Dictionary ## Ссылка на словарь целей var color_ecm: Color var color_select: Color +var color_emit: Color +var color_emit_sel: Color var course = 0.0 ## Курс корабля @@ -48,6 +51,7 @@ const map_sizes = [ var fs_band = prd.FS_BAND_RTO ## Текущий режим блоков ФС по частоте var fs_selected: Dictionary ## Словарь выбранных секторов var fs_active: Dictionary ## Словарь секторов назначенных на подавление +var fs_emit: Dictionary ## Словарь секторов назначенных на подавление ## Состояние перетаскивания. enum DragFSM { @@ -85,10 +89,14 @@ func on_enter_tree() -> void: call_deferred('on_button_strobe_pressed') func on_settings_changed(): + color_emit_sel = ProjectSettings.get_setting('application/interfer/emit_sel_color', Color(1.0, 1.0, 1.0, 1.0)) + color_emit = ProjectSettings.get_setting('application/interfer/emit_color', Color(0.58, 0.47, 0.51, 1.0)) color_ecm = ProjectSettings.get_setting('application/interfer/interfer_color', Color(0.58, 0.47, 0.51, 1.0)) color_select = ProjectSettings.get_setting('application/interfer/select_color', Color(1.0, 1.0, 1.0, 1.0)) + color_select *= Color(1.0, 1.0, 1.0, 0.0) color_ecm *= Color(1.0, 1.0, 1.0, 0.0) + color_emit_sel *= Color(1.0, 1.0, 1.0, 0.2) ## Обработчик сигнала изменения списка целей. @@ -258,6 +266,7 @@ func on_interfer_off_all(): bip.set_ecm_visible(false) bip.set_track_visible(false) fs_active.clear() + fs_emit.clear() update_fs_colors() @@ -468,6 +477,10 @@ func set_fs_color(ecm): fs_active[prd.fs_caps_id[ecm.nmfs]] = null else: fs_active.erase(prd.fs_caps_id[ecm.nmfs]) + if ecm.svk == SVK_EMIT: + fs_emit[prd.fs_caps_id[ecm.nmfs]] = null + else: + fs_emit.erase(prd.fs_caps_id[ecm.nmfs]) update_fs_colors() @@ -475,8 +488,13 @@ func update_fs_colors(): var fs_colors = $canvas.fs_default_colors.duplicate() for key in fs_active.keys(): fs_colors[key] = color_ecm + for key in fs_emit.keys(): + fs_colors[key] = color_emit for key in fs_selected.keys(): - fs_colors[key] = color_select + if key in fs_emit: + fs_colors[key] = color_emit_sel + else: + fs_colors[key] = color_select $canvas.set_band_colors(fs_colors) @@ -514,6 +532,7 @@ func set_btns_disabled(value: bool, btn): func on_fs_update_color(ecms): fs_active.clear() + fs_emit.clear() for ecm in ecms.values(): set_fs_color(ecm) update_fs_colors() diff --git a/scripts/settings.gd b/scripts/settings.gd index fe308b99..28069108 100644 --- a/scripts/settings.gd +++ b/scripts/settings.gd @@ -10,7 +10,7 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ 'уарэп-яу07-частный': ['yau07rx', ['10.1.1.2', 50002, false, true], 'IP-адрес для приёма частных сообщений от ЯУ-07'], 'уарэп-яу07-общий': ['yau07rx', ['*', 50000, true, true], 'IP-адрес для приёма широковещательных сообщений от ЯУ-07'], 'уарэп-капсрпб': ['capsrpb', ['127.0.0.1', '127.0.0.1', 42023, 42022, false, true], 'IP-адрес для обмена сообщениями со службой \"МП550\" (СТЦ)'], - 'уарэп-трасса': ['trassa', ['127.0.0.1', '127.0.0.1', 50200, 10004, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], + 'уарэп-трасса': ['trassa', ['192.168.1.23', '192.168.1.34', 50200, 10004, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], 'уарэп-эмс': ['yau07tx', ['10.1.1.52', 50052, false, false], 'IP-адрес прибора УФ'], 'уарэп-яу07-2в': ['yau07tx', ['10.1.1.22', 50022, false, false], 'IP-адрес прибора ПРД-В2'], 'уарэп-яу07-2н': ['yau07tx', ['10.1.1.21', 50021, false, false], 'IP-адрес прибора ПРД-Н2'], From 62f7cf1590d4ca8d276d4894802354cd1134ab5c Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 15 Oct 2025 11:19:41 +0300 Subject: [PATCH 102/117] =?UTF-8?q?=D0=A7=D0=B8=D1=81=D1=82=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tabs-switch/lbl_ready.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/tabs-switch/lbl_ready.gd b/scenes/tabs-switch/lbl_ready.gd index cecc6a69..f23dcbbe 100644 --- a/scenes/tabs-switch/lbl_ready.gd +++ b/scenes/tabs-switch/lbl_ready.gd @@ -4,5 +4,5 @@ func _ready() -> void: var prd_dict = prd.prd_dict for prd_module in prd_dict.values(): ## Отправка команды на исполнение в ПРД - print('prd_module.unit_yau07.online: ', prd_module.unit_yau07.online) + pass pass From 4114fd17afff41812c4da5dee9dec884c106db78 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 15 Oct 2025 13:37:37 +0300 Subject: [PATCH 103/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=A8=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=20?= =?UTF-8?q?=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/settings.json b/settings.json index 2453de8d..427f4455 100644 --- a/settings.json +++ b/settings.json @@ -1,8 +1,8 @@ { "Адрес АФСП левого борта": "http://172.22.246.13:8081/selftest", "Адрес АФСП правого борта": "http://172.22.246.11:8082/selftest", - "Адрес БПО левого борта": "http://172.22.246.13:8081/selftest", - "Адрес БПО правого борта": "http://172.22.246.11:8082/selftest", + "Адрес БПО левого борта": "http://172.22.246.13:8081/selftest?presetType=bpo&400000000", + "Адрес БПО правого борта": "http://172.22.246.11:8082/selftest?presetType=bpo&400000000", "Виртуальная клавиатура": false, "Внешнее указание Трасса": false, "Внешнее управление": false, @@ -27,7 +27,7 @@ "Период опроса состояния БПО, секунды": "30", "Скрыть вкладку ЭМС 2": true, "Текущая версия ПО УАРЭП": "master b2633d8 Thu Sep 11 16:26:39 2025 +0300", - "Шаблон адреса сервера карт": "https://tile.openstreetmap.org/{z}/{x}/{y}.png", + "Шаблон адреса сервера карт": "http://10.1.1.2:8001/osm_tiles/{z}/{x}/{y}.png", "навигация": [ "*", 60000, @@ -37,18 +37,18 @@ "уареп-трасса": "127.0.0.1,127.0.0.1,50200,10004", "уарэп-5п28": [ "127.0.0.1", - 50000 + 50777 ], "уарэп-капсрпб": [ - "127.0.0.1", - "127.0.0.1", + "192.168.11.102", + "192.168.11.105", 42023, 42022, false, true ], "уарэп-спт25-1": [ - "COM4", + "/home/user/tty0", 0, 19200, "N", @@ -56,7 +56,7 @@ 1 ], "уарэп-спт25-2": [ - "CNCA0", + "/home/user/tty1", 0, 19200, "N", @@ -64,7 +64,7 @@ 1 ], "уарэп-щ3": [ - "/dev/ttyUSB0", + "/home/user/tty3", 7, 19200, "N", @@ -157,8 +157,8 @@ true ], "уарэп-яу07-частный": [ - "10.1.1.79", - 50079, + "10.1.1.253", + 50253, false, true ] From 2a97865a6dd663781e69ed5d4d0dc7925502e36c Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 15 Oct 2025 13:39:25 +0300 Subject: [PATCH 104/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA?= =?UTF-8?q?=20UART?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/network.gd b/scripts/network.gd index 74d6fa01..45b01e47 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -49,7 +49,9 @@ class SocketSerial extends SerialPort: return buffer func send_to(data: PackedByteArray): - if not is_open(): return + if not is_open(): + ProjectSettings.emit_signal('settings_changed') + return # var buffer = format_buffer(data) # Не проверено, но должно работать # Эта последовательность для запроса состояния, получена от разработчиков СПТ-25 const tx_tula: = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] From 25d39cb560887265aa19dcd365360206359fcf13 Mon Sep 17 00:00:00 2001 From: Maxim Date: Wed, 15 Oct 2025 14:06:16 +0300 Subject: [PATCH 105/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9E=D0=B1=D0=BE=D0=B1=D1=89=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20=D0=BF=D1=80=D0=B8=D0=B7=D0=BD=D0=B0?= =?UTF-8?q?=D0=BA=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B0=D0=B9=D0=BC=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B8=20?= =?UTF-8?q?=D0=B2=20=D0=B1=D0=B0=D0=B7=D0=BE=D0=B2=D1=8B=D0=B9=20=D0=B0?= =?UTF-8?q?=D0=B4=D1=80=D0=B5=D1=81=20=D1=8F=D1=87=D0=B5=D0=B9=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=AD=D0=9C=D0=A1-=D0=93=20=D0=B2=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BB=D0=B5=20=D0=BF=D1=80=D0=B4.=20=D0=9D?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D1=8E=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81?= =?UTF-8?q?=D0=B8=D0=B3=D0=BD=D0=B0=D0=BB=20=D0=B8=D0=B7=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=82=20=D0=BC=D0=BE=D0=B4?= =?UTF-8?q?=D1=83=D0=BB=D1=8F=20=D0=A4=D0=A1=20=D0=94=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20[PATCH]=20=D0=BE=D1=82=D0=BB?= =?UTF-8?q?=D0=B0=D0=B4=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=BB=D1=8F,=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B8=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D0=B0=20=D0=A2=D1=80?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=D0=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-k/pribor-prd-k.gd | 2 +- scenes/pribor-prd-n/pribor-prd-n.gd | 4 +- scenes/pribor-prd-v/pribor-prd-v.gd | 2 +- scenes/tabs-switch/lbl_ready.gd | 48 ++++++++++- scenes/tabs-switch/tab-switch.tscn | 4 +- scenes/tabs-switch/тренаж_режим.gd | 4 +- scenes/контроль/контроль.tscn | 126 ++++++++++++++++------------ scenes/работа/работа.tscn | 2 +- scripts/prd.gd | 11 +++ scripts/pribor-prd.gd | 57 +++++++------ scripts/signaller.gd | 5 ++ 11 files changed, 174 insertions(+), 91 deletions(-) diff --git a/scenes/pribor-prd-k/pribor-prd-k.gd b/scenes/pribor-prd-k/pribor-prd-k.gd index 92d616c9..12be8885 100644 --- a/scenes/pribor-prd-k/pribor-prd-k.gd +++ b/scenes/pribor-prd-k/pribor-prd-k.gd @@ -18,7 +18,7 @@ const constants_k: Dictionary = { 'ATT_UM_6': 0x3, 'ATT_UM_7': 0x2, 'POWER_UM': 100, - 'TIMER_DELAY': 5.0, + 'TIMER_DELAY': 10.0, 'STATE_MASHINE_TIMER': 0.3, } # Конфигурация параметров для каждого прибора diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index 8497ec61..cfd12958 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -16,7 +16,7 @@ const constants_n = { 'ATT_UM_2': 0x2, 'ATT_UM_3': 0x3, 'POWER_UM': 100, - 'TIMER_DELAY': 5.0, + 'TIMER_DELAY': 10.0, 'STATE_MASHINE_TIMER': 0.3, } # Конфигурация параметров для каждого прибора @@ -83,7 +83,7 @@ func _ready() -> void: setup_timer() set_default_state() find_labels(self) - + func initialize_connections() -> void: var unit_name = get_meta('unit_name')[0] diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index 40f55e16..a40768ad 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -16,7 +16,7 @@ const constants_v = { 'ATT_UM_4': 0x2, 'ATT_UM_5': 0x3, 'POWER_UM': 100, - 'TIMER_DELAY': 5.0, + 'TIMER_DELAY': 10.0, 'STATE_MASHINE_TIMER': 0.3, } # Конфигурация параметров для каждого прибора diff --git a/scenes/tabs-switch/lbl_ready.gd b/scenes/tabs-switch/lbl_ready.gd index f23dcbbe..f35d4eda 100644 --- a/scenes/tabs-switch/lbl_ready.gd +++ b/scenes/tabs-switch/lbl_ready.gd @@ -1,8 +1,48 @@ extends Label +# Используем более понятные имена переменных +const STATUS_GOOD := {"text": "Исправно", "color": Color.GREEN, "font_color": Color.BLACK} +const STATUS_BAD := {"text": "Отказ", "color": Color.RED, "font_color": Color.WHITE} +var _is_uf_status_initialized: bool = false +var is_prd_operational: bool = true +var is_uf_operational: bool = false + func _ready() -> void: - var prd_dict = prd.prd_dict + tooltip_text = 'Нет связи с приборами комплекса' + for prd_module in prd.prd_dict.values(): + prd_module.connect('update_serviceability', Callable(self, 'on_serviceability_changed').bind(prd_module)) + var unit_uf: = network.get_unit_instance('уарэп-эмс') + unit_uf.connect('data_received', Callable(self, 'on_uf_status_receive')) + add_theme_color_override("font_color", Color.BLACK) - for prd_module in prd_dict.values(): ## Отправка команды на исполнение в ПРД - pass - pass + +func on_serviceability_changed(unit_prd_module: Object) -> void: + var check_service: bool = true + for prd_module in prd.prd_dict.values(): + if prd_module.unit_yau07.online: + if not unit_prd_module.serviceability: + check_service = false + if check_service != is_prd_operational: + is_prd_operational = check_service + _update_serviceability_display() + + +func _update_serviceability_display() -> void: + var status := STATUS_GOOD if (is_uf_operational and is_prd_operational) else STATUS_BAD + text = status.text + modulate = status.color + tooltip_text = 'Результаты обобщенного признака работоспособности изделия' + add_theme_color_override("font_color", status.font_color) + + +func on_uf_status_receive(unit_uf: Object) -> void: + var KEMS_B = ((unit_uf.status[0] >> 0) & 1) and ((unit_uf.status[0] >> 3) & 1) + var EMS_B_1 = ((unit_uf.status[0] >> 1) & 1) and ((unit_uf.status[0] >> 4) & 1) + var EMS_B_2 = ((unit_uf.status[0] >> 2) & 1) and ((unit_uf.status[0] >> 5) & 1) + var IP27B = ((unit_uf.status[2] >> 6) & 1) + var check_service: bool = KEMS_B and EMS_B_1 and EMS_B_2 and IP27B + if not _is_uf_status_initialized or check_service != is_uf_operational: + is_uf_operational = check_service + _update_serviceability_display() + signaller.emit_signal('update_uf_serviceability', check_service) + _is_uf_status_initialized = true diff --git a/scenes/tabs-switch/tab-switch.tscn b/scenes/tabs-switch/tab-switch.tscn index 19727339..b33b2b9e 100644 --- a/scenes/tabs-switch/tab-switch.tscn +++ b/scenes/tabs-switch/tab-switch.tscn @@ -86,13 +86,13 @@ offset_right = 1600.0 offset_bottom = 27.0 tooltip_text = "Готовность аппаратуры к работе" mouse_filter = 0 -theme_override_colors/font_color = Color(0, 0, 0, 1) theme_override_font_sizes/font_size = 14 theme_override_styles/normal = SubResource("StyleBoxFlat_o1r22") -text = "Исправно" +text = "Нет связи" horizontal_alignment = 1 vertical_alignment = 1 script = ExtResource("8_tidwt") +metadata/_edit_lock_ = true [node name="remote_control" type="Label" parent="."] visible = false diff --git a/scenes/tabs-switch/тренаж_режим.gd b/scenes/tabs-switch/тренаж_режим.gd index d334ce3c..ace4117d 100644 --- a/scenes/tabs-switch/тренаж_режим.gd +++ b/scenes/tabs-switch/тренаж_режим.gd @@ -6,6 +6,6 @@ func _ready(): func _on_button_toggled(mode: bool): if mode: - tooltip_text = "Режим \"Тренаж\" задействован" + tooltip_text = "Режим \"Тренаж\" задействован\nТекущее состояние: включено" else: - tooltip_text = "Задейстовать режим \"Тренаж\"" + tooltip_text = "Задейстовать режим \"Тренаж\"\nТекущее состояние: отключено" diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index 5eb62062..b1d9612a 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -46,6 +46,7 @@ const PRIBORS_RES = \\ func on_line_changed(u, conn_node, _pribor_meta): conn_node.set_val(u.online) +func on_serv_changed(u, pribor_node, _pribor_meta): pribor_node.state = int(u.serviceability) func on_mode_changed(): @@ -78,6 +79,13 @@ func _ready(): for i in unit_names.size(): var unit_instance: = network.get_unit_instance(unit_names[i]) unit_instance.connect('line_changed', Callable(self, pribor_proc).bind(conn_node, unit_names)) + + for item in unit_names: + if prd.prd_dict.has(item): + var prd_module = prd.prd_dict[item] + prd_module.connect('update_serviceability', Callable(self, 'on_serviceability_changed').bind(prd_module, pribor_node)) + if item == 'уарэп-эмс': + signaller.connect('update_uf_serviceability', Callable(self, 'on_update_uf_serviceability').bind(pribor_node)) # Пиктограммы приборов, которые отображают состояние подключения только for pribor_node in get_tree().get_nodes_in_group('pribor_pics'): var unit_name = pribor_node.get_meta('unit_name') @@ -125,6 +133,18 @@ func on_pribor_press(pribor_path, header_text, pribor_node): pribor.set_meta('unit_name', unit_name) pribor.add_to_group('pribor_items') add_child(pribor) + + +func on_serviceability_changed(prd_module: Object, prd_pribor:Node)-> void: + if not prd_module.unit_yau07.online: + prd_pribor.state = 0 + return + prd_pribor.state = 1 if prd_module.serviceability else 2 + + +func on_update_uf_serviceability(uf_serviceaability: bool, uf_pribor: Node)-> void: + + uf_pribor.state = 1 if uf_serviceaability else 2 " [sub_resource type="SpriteFrames" id="SpriteFrames_foasq"] @@ -324,6 +344,58 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") +[node name="pribor_prd_n_1" type="TextureButton" parent="." groups=["pribor_buttons"]] +editor_description = "Кнопка для выбора прибора." +layout_mode = 0 +offset_left = 1048.0 +offset_top = 193.0 +offset_right = 1125.0 +offset_bottom = 309.0 +size_flags_horizontal = 15 +size_flags_vertical = 15 +toggle_mode = true +action_mode = 0 +texture_normal = ExtResource("6_i1yfn") +stretch_mode = 4 +flip_h = true +script = ExtResource("3_4pt7j") +state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +metadata/online_proc = "on_line_changed" +metadata/unit_name = ["уарэп-яу07-1н"] + +[node name="label" type="Label" parent="pribor_prd_n_1"] +layout_mode = 0 +offset_left = 8.0 +offset_top = -38.0 +offset_right = 60.0 +offset_bottom = -19.0 +text = "ПРД Н1" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="frame" type="NinePatchRect" parent="pribor_prd_n_1"] +visible = false +self_modulate = Color(0.890196, 0.486275, 0.196078, 1) +layout_mode = 0 +offset_left = -10.0 +offset_top = -24.0 +offset_right = 95.0 +offset_bottom = 126.0 +texture = ExtResource("4_rasbe") +region_rect = Rect2(-3, -3, 89, 89) +patch_margin_left = 16 +patch_margin_top = 16 +patch_margin_right = 16 +patch_margin_bottom = 16 + +[node name="connect_pribor" type="AnimatedSprite2D" parent="pribor_prd_n_1"] +light_mask = 3 +position = Vector2(35, -10) +scale = Vector2(0.625, 0.625) +sprite_frames = SubResource("SpriteFrames_foasq") +frame_progress = 0.72355 +script = ExtResource("11_u7tym") + [node name="pribor_uf" type="TextureButton" parent="." groups=["pribor_buttons"]] editor_description = "Кнопка для выбора прибора." layout_mode = 0 @@ -987,58 +1059,6 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="pribor_prd_n_1" type="TextureButton" parent="." groups=["pribor_buttons"]] -editor_description = "Кнопка для выбора прибора." -layout_mode = 0 -offset_left = 1048.0 -offset_top = 193.0 -offset_right = 1125.0 -offset_bottom = 309.0 -size_flags_horizontal = 15 -size_flags_vertical = 15 -toggle_mode = true -action_mode = 0 -texture_normal = ExtResource("6_i1yfn") -stretch_mode = 4 -flip_h = true -script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] -metadata/online_proc = "on_line_changed" -metadata/unit_name = ["уарэп-яу07-1н"] - -[node name="label" type="Label" parent="pribor_prd_n_1"] -layout_mode = 0 -offset_left = 8.0 -offset_top = -38.0 -offset_right = 60.0 -offset_bottom = -19.0 -text = "ПРД Н1" -horizontal_alignment = 1 -vertical_alignment = 1 - -[node name="frame" type="NinePatchRect" parent="pribor_prd_n_1"] -visible = false -self_modulate = Color(0.890196, 0.486275, 0.196078, 1) -layout_mode = 0 -offset_left = -10.0 -offset_top = -24.0 -offset_right = 95.0 -offset_bottom = 126.0 -texture = ExtResource("4_rasbe") -region_rect = Rect2(-3, -3, 89, 89) -patch_margin_left = 16 -patch_margin_top = 16 -patch_margin_right = 16 -patch_margin_bottom = 16 - -[node name="connect_pribor" type="AnimatedSprite2D" parent="pribor_prd_n_1"] -light_mask = 3 -position = Vector2(35, -10) -scale = Vector2(0.625, 0.625) -sprite_frames = SubResource("SpriteFrames_foasq") -frame_progress = 0.72355 -script = ExtResource("11_u7tym") - [node name="pribor_prd_k_1" type="TextureButton" parent="." groups=["pribor_buttons"]] editor_description = "Кнопка для выбора прибора." layout_mode = 0 @@ -1365,6 +1385,7 @@ points = PackedVector2Array(-8, 0, 608, 0) width = 2.0 default_color = Color(1, 1, 1, 0.352941) +[connection signal="toggled" from="pribor_prd_n_1" to="pribor_prd_n_1" method="_on_toggled"] [connection signal="toggled" from="pribor_uf" to="pribor_uf" method="_on_toggled"] [connection signal="toggled" from="pribor_rtr" to="pribor_rtr" method="_on_toggled"] [connection signal="toggled" from="pribor_afsp_1" to="pribor_afsp_1" method="_on_toggled"] @@ -1377,7 +1398,6 @@ default_color = Color(1, 1, 1, 0.352941) [connection signal="toggled" from="pribor_prd_n_3" to="pribor_prd_n_3" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_k_3" to="pribor_prd_k_3" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_v_1" to="pribor_prd_v_1" method="_on_toggled"] -[connection signal="toggled" from="pribor_prd_n_1" to="pribor_prd_n_1" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_k_1" to="pribor_prd_k_1" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_v_4" to="pribor_prd_v_4" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_n_4" to="pribor_prd_n_4" method="_on_toggled"] diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 006c55c8..f7485c34 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -342,8 +342,8 @@ text = "−" [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] [connection signal="toggled" from="chk_auto" to="." method="on_value_changed"] -[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] +[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] [connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"] [connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"] diff --git a/scripts/prd.gd b/scripts/prd.gd index 0ff163e3..46c8e08b 100644 --- a/scripts/prd.gd +++ b/scripts/prd.gd @@ -158,7 +158,9 @@ class PRD: var state = PrdState.WORK var cmd_array: Array ## Очередь команд var ug_online: bool = false ## Состояние ячейки УГ + var serviceability: bool = false var set_ug_state: bool = true ## Необходимо ли записать в УГ настройки + signal update_serviceability() func _init(u_name, u_yau07): prd_name = u_name @@ -197,6 +199,7 @@ class PRD: func on_line_changed(unit_ems): + emit_signal('update_serviceability') if not unit_ems.online: yemsg_board.ems_load = yemsg_board.LoadState.NOT_DEFINED yemsg_board.set_wait() @@ -223,6 +226,14 @@ class PRD: ug_online = (unit_yau07.status[0] >> 1) & 1 if not ug_online: set_ug_state = true + var ukp_1_online = (unit_yau07.status[0] >> 2) & 1 + var ukp_2_online = (unit_yau07.status[0] >> 3) & 1 + var ems_g_online = (unit_yau07.status[0] & 1) & 1 + var check_serviceability = ug_online and ukp_1_online and ukp_2_online and ems_g_online + if serviceability != check_serviceability: + serviceability = check_serviceability + emit_signal('update_serviceability') + func execute_cmd(): if not len(cmd_array): return diff --git a/scripts/pribor-prd.gd b/scripts/pribor-prd.gd index 965d279c..c717f50b 100644 --- a/scripts/pribor-prd.gd +++ b/scripts/pribor-prd.gd @@ -74,7 +74,7 @@ class TestPRD extends Node: var self_name: String var state: int = STATE_MASHINE.INIT var current_litera: int - var flag_timer_started: bool = false + var flag_write_isa: bool = false var flag_fs_status_ok: bool = false var flag_si_fs_input: bool = false var flag_si_fs_output: bool = false @@ -169,24 +169,25 @@ class TestPRD extends Node: state = STATE_MASHINE.FS_WORK STATE_MASHINE.FS_WORK: if ecms.size() and flag_fs_status_ok: + ems_6666_timer.start() _handle_fs_work_state() STATE_MASHINE.CHEK_KASSETA_Y5: if block_kasseta_y5_config['yau07']: state = STATE_MASHINE.WRITE_ISA STATE_MASHINE.WRITE_ISA: - _handle_ug_set_state(0x6) - await get_tree().create_timer(1.5).timeout - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x6) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.READ_ISA: if (unit_prd.cmd_state == unit_prd.CmdState.DONE) or (unit_prd.cmd_state == unit_prd.CmdState.FAIL): _handle_read_isa(module_prd, unit_prd, [constants.ADDR_UG_LITERA_1, constants.ADDR_UG_LITERA_2, constants.ADDR_UG_LITERA_3]) + flag_write_isa = false state = STATE_MASHINE.UG_SET_RAY STATE_MASHINE.UG_SET_RAY: var addr: int = constants.ADDR_UG_LITERA_1 if current_litera == 3 or current_litera == 5 or current_litera == 7: addr = constants.ADDR_UG_LITERA_2 if unit_prd.isa_ports.has(addr) and (unit_prd.cmd_state == unit_prd.CmdState.DONE): - control_timer.stop() if unit_prd.isa_ports[addr] & 0x07 == 0: state = STATE_MASHINE.UG_SET_RAY_1 elif unit_prd.isa_ports[addr] & 0x07 == 1: @@ -205,28 +206,36 @@ class TestPRD extends Node: state = STATE_MASHINE.UG_SET_RAY_0 STATE_MASHINE.UG_SET_RAY_0: - _handle_ug_set_state(0x0) - await get_tree().create_timer(0.5).timeout - state = STATE_MASHINE.READ_ISA + if flag_si_fs_input and not flag_write_isa: + control_timer.stop() + _handle_ug_set_state(0x0) + await get_tree().create_timer(0.5).timeout + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_1: - _handle_ug_set_state(0x1) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x1) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_2: - _handle_ug_set_state(0x2) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x2) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_3: - _handle_ug_set_state(0x3) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x3) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_4: - _handle_ug_set_state(0x4) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x4) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_5: - _handle_ug_set_state(0x5) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x5) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.IN_EMS_STOP: ems_6666_timer.stop() state = STATE_MASHINE.FS_TURN_OFF STATE_MASHINE.FS_TURN_OFF: + ems_6666_timer.stop() _handle_fs_turn_off_state() state = STATE_MASHINE.STOP_CONTROL STATE_MASHINE.STOP_CONTROL: @@ -289,7 +298,7 @@ class TestPRD extends Node: dic_att.RAY_DOU_NUM, log_text ] - on_ug_setting(module_prd, unit_prd, dic_att) + flag_write_isa = on_ug_setting(module_prd, unit_prd, dic_att) func _on_ems_6666_timer() -> void: @@ -304,7 +313,6 @@ class TestPRD extends Node: func _handle_stop_control_state() -> void: control_label.text = 'Выполняется завершение проверки ФС-%s' % current_litera - flag_timer_started = false _advance_to_next_fs() state = STATE_MASHINE.INIT @@ -348,7 +356,7 @@ class TestPRD extends Node: add_child(ems_6666_timer) ems_6666_timer.timeout.connect(_on_ems_6666_timer) - ems_6666_timer.wait_time = 1.5 + ems_6666_timer.wait_time = 1.0 func _process_dkm_status(status: PackedByteArray) -> void: @@ -422,16 +430,15 @@ class TestPRD extends Node: ## Установка угла и аттенюации для УМ - static func on_ug_setting(prd_module: Object, prd_unit: Object, settings_ug: Dictionary) -> void: + static func on_ug_setting(prd_module: Object, prd_unit: Object, settings_ug: Dictionary) -> bool: var result_1 = ((settings_ug.ATT_UM_1 & 0x07) << 3) | (settings_ug.RAY_DOU_NUM & 0x07) var result_2 = ((settings_ug.ATT_UM_2 & 0x07) << 3) | (settings_ug.RAY_DOU_NUM & 0x07) - - prd_module.cmd_array.append([prd_unit.CmdCode.WRITE_ISA, [ settings_ug.BASE_EMS_G, 6666, - settings_ug.ADDR_UG_LITERA_1, result_1, + prd_module.cmd_array.append([prd_unit.CmdCode.WRITE_ISA, [ settings_ug.ADDR_UG_LITERA_1, result_1, settings_ug.ADDR_UG_LITERA_2, result_2, settings_ug.ADDR_UG_LITERA_3, settings_ug.ATT_UM_3, ] ]) + return true static func _handle_read_isa(prd_module: Object, prd_unit: Object, read_isa_ports: Array) -> void: diff --git a/scripts/signaller.gd b/scripts/signaller.gd index c77682f3..8a4ca5cc 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -195,4 +195,9 @@ signal update_scale_map(new_scale) signal update_coordinates_map(new_coordinates) +## Вызывается при изменении исправности прибора УФ.[br] +## [param uf_serviceaability] - обновленное значение состояния исправности ([b]true[/b] +signal update_uf_serviceability(uf_serviceaability: bool) + + signal tool_tip(new_ctrl_pos) From 6b18e66f330050b365d594665d6919db6884a44c Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 15 Oct 2025 15:14:32 +0300 Subject: [PATCH 106/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20ERROR:=20res://scenes/tilemap/tilemap.gd:?= =?UTF-8?q?384=20-=20Invalid=20call=20function=20'get=5Funit=5Finstance'?= =?UTF-8?q?=20in=20base=20'Node=20(Network)':=20Attempt=20to=20call=20a=20?= =?UTF-8?q?method=20on=20a=20placeholder=20instance.=20Check=20if=20the=20?= =?UTF-8?q?script=20is=20in=20tool=20mode.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/network.gd b/scripts/network.gd index 45b01e47..43868ab5 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -1,3 +1,4 @@ +@tool class_name Network extends Node const YAU07_PROTO: = {'yau07tx': yau07.YaU07} @@ -213,6 +214,7 @@ func create_modbus(unit_name: StringName) -> sch_3.Sch3: func _ready() -> void: + if Engine.is_editor_hint(): return var sock_unicast: = create_socket_udp('уарэп-яу07-частный') var sock_broadcast: = create_socket_udp('уарэп-яу07-общий') var sock_navi: = create_socket_udp('навигация') From 5cec140cf387e9df0ee3a0e0da2b4ffe62acac9b Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 15 Oct 2025 15:18:49 +0300 Subject: [PATCH 107/117] =?UTF-8?q?=D0=A0=D0=B5=D0=B3=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=D1=8F.=20=D0=A6=D0=B2=D0=B5=D1=82=20=D0=BD=D0=B5?= =?UTF-8?q?=20=D1=82=D0=BE=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/контроль/контроль.tscn | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index b1d9612a..5ed8246a 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -410,7 +410,8 @@ action_mode = 0 texture_normal = ExtResource("2_0nvm1") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.74, 0.37, 1), Color(0.854902, 0.0705882, 0.0705882, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] +state = 1 metadata/unit_name = ["уарэп-эмс"] metadata/online_proc = "on_line_changed" @@ -462,7 +463,7 @@ action_mode = 0 texture_normal = ExtResource("3_hhadv") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = [&"уарэп-бпо-1", &"уарэп-бпо-2"] metadata/online_proc = "online_change_arr" @@ -525,7 +526,7 @@ action_mode = 0 texture_normal = ExtResource("9_iqgf5") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = [&"уарэп-афсп-левый"] metadata/online_proc = "on_line_changed" @@ -592,7 +593,7 @@ texture_normal = ExtResource("9_iqgf5") stretch_mode = 0 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = [&"уарэп-афсп-правый"] metadata/online_proc = "on_line_changed" @@ -656,7 +657,7 @@ action_mode = 0 texture_normal = ExtResource("5_kvnex") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-щ3", "уарэп-спт25-1", "уарэп-спт25-2"] metadata/online_proc = "online_change_arr" @@ -708,7 +709,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-2в"] metadata/online_proc = "on_line_changed" @@ -760,7 +761,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-2н"] metadata/online_proc = "on_line_changed" @@ -814,7 +815,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-2к"] metadata/online_proc = "on_line_changed" @@ -866,7 +867,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-3в"] metadata/online_proc = "on_line_changed" @@ -918,7 +919,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-3н"] metadata/online_proc = "on_line_changed" @@ -970,7 +971,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-3к"] metadata/online_proc = "on_line_changed" From 6eaa6fe09207470244b015a81ea720d909276fbe Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 15 Oct 2025 16:41:54 +0300 Subject: [PATCH 108/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9D=D0=B5=D1=82=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D1=91=D0=BC=D0=B0=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D0=BE=D1=82=20=D0=BD=D0=B0=D0=B2=D0=B8=D0=B3=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/navigation.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/navigation.gd b/scripts/navigation.gd index a5bd9170..6feda387 100644 --- a/scripts/navigation.gd +++ b/scripts/navigation.gd @@ -29,7 +29,7 @@ class NaviSource extends unit.Unit: if rx_data.size() < 28: emit_signal('parse_failed', self) return false - var flags: = rx_data.decode_u16(26) # Флаги достоверности полей структуры + var flags: = rx_data.decode_u16(28) # Флаги достоверности полей структуры data.clear() data['mode'] = akng_mode[(flags >> 4) & 3] # Режим работы АКНГ if flags & (1 << 0): From 9b0ca3a729f844b90dc38127443e7cac71c11697 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Wed, 15 Oct 2025 16:43:09 +0300 Subject: [PATCH 109/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA?= =?UTF-8?q?=20UART-=D0=BF=D0=BE=D1=80=D1=82=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/scripts/network.gd b/scripts/network.gd index 43868ab5..a8950163 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -21,13 +21,14 @@ class SocketSerial extends SerialPort: 'E': SerialPort.PARITY_EVEN, 'O': SerialPort.PARITY_ODD } static var tick: int + var unit_instance: unit.Unit - func on_serial_data(data: PackedByteArray, unit_instance: unit.Unit): + func on_serial_data(data: PackedByteArray): unit_instance.parse(data, tick) - func on_settings_changed(unit_instance: unit.Unit): + func on_settings_changed(): try_close() - var rc = try_open(on_serial_data.bind(unit_instance)) + var rc = try_open() if rc != Error.OK: log.message(log.ERROR, 'невозможно открыть %s для \"%s\"' % [self, unit_instance.name]) else: @@ -51,14 +52,14 @@ class SocketSerial extends SerialPort: func send_to(data: PackedByteArray): if not is_open(): - ProjectSettings.emit_signal('settings_changed') + try_open() return # var buffer = format_buffer(data) # Не проверено, но должно работать # Эта последовательность для запроса состояния, получена от разработчиков СПТ-25 const tx_tula: = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] var sz = write_raw(tx_tula) - if sz != tx_tula.size(): # TODO: Не совсем адекватное, но работает - ProjectSettings.emit_signal('settings_changed') + if sz != tx_tula.size(): + try_open() func _to_string() -> String: return 'последовательный порт \"%s\" @ %d (%s)' % [self.port, self.baudrate, 'открыт' if is_open() else 'закрыт'] @@ -79,12 +80,12 @@ class SocketSerial extends SerialPort: fcs = (fcs >> 1) ^ P_DIV if fcs & 1 else fcs >> 1 return (~fcs) & 0xffff - func try_open(parsing_proc: Callable) -> Error: + func try_open() -> Error: if is_open(): return Error.OK var rc: = open(port) if rc == Error.OK: - data_received.connect(parsing_proc) + data_received.connect(on_serial_data) start_monitoring(timeout) return rc @@ -191,8 +192,8 @@ func create_socket_tcp(unit_name: StringName) -> SocketTCP: ## [param unit_name] - Уникальное имя устройства[br] -func create_serial(unit_name: StringName) -> SocketSerial: - var st = settings.UnitProfiles[unit_name][1] +func create_serial(unit_instance: unit.Unit) -> SocketSerial: + var st = settings.UnitProfiles[unit_instance.name][1] var serial: = SocketSerial.new() serial.port = st[0] serial.baudrate = st[2] @@ -200,6 +201,7 @@ func create_serial(unit_name: StringName) -> SocketSerial: serial.timeout = 20000 serial.bytesize = st[4] serial.stopbits = st[5] + serial.unit_instance = unit_instance return serial @@ -283,9 +285,9 @@ func _ready() -> void: if proto in SERIAL_PROTO: var unit_instance = SERIAL_PROTO[proto].new(unit_name) - var serial: = create_serial(unit_name) + var serial: = create_serial(unit_instance) serial.connect('got_error', on_serial_got_error.bind(serial, unit_instance)) - ProjectSettings.connect('settings_changed', serial.on_settings_changed.bind(unit_instance)) + ProjectSettings.connect('settings_changed', serial.on_settings_changed) units_serial[unit_name] = unit_instance units[unit_name] = unit_instance serials[unit_name] = serial From 958c9775e20480177ec8b253de00b01fa107c20d Mon Sep 17 00:00:00 2001 From: Maxim Date: Thu, 16 Oct 2025 13:03:38 +0300 Subject: [PATCH 110/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9D=D0=B5=D0=B4=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=BE=D1=87=D0=BD=D0=B0=D1=8F=20=D0=BC?= =?UTF-8?q?=D0=BE=D1=89=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B2=D1=8B=D1=85=D0=BE=D0=B4=D0=B5=20=D1=83=D1=81=D0=B8=D0=BB?= =?UTF-8?q?=D0=B8=D1=82=D0=B5=D0=BB=D1=8F=20=D0=BC=D0=BE=D1=89=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/pribor-prd-n/pribor-prd-n.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index cfd12958..c69b5530 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -28,7 +28,7 @@ const PRIBOR_CONFIG_N := { } # Конфигурация частот и ширин для каждого ФС const FS_PARAMS_N := { - 2: {'freq': 900.0, 'width': 100.0}, + 2: {'freq': 932.0, 'width': 100.0}, 3: {'freq': 1157.0, 'width': 100.0} } enum STATE_VAL { NONE = 0, GOOD = 1, ERROR = 2 } From 64fa67ae40827e73f5471ecbea072a691c0af4b2 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 21 Oct 2025 08:21:01 +0300 Subject: [PATCH 111/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/tilemap/ship_mark.tscn | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scenes/tilemap/ship_mark.tscn b/scenes/tilemap/ship_mark.tscn index 78d04640..096387d0 100644 --- a/scenes/tilemap/ship_mark.tscn +++ b/scenes/tilemap/ship_mark.tscn @@ -3,6 +3,7 @@ [ext_resource type="Texture2D" uid="uid://cj1f2uy6qfvki" path="res://scenes/tilemap/23900.png" id="1_v0nwa"] [node name="23900" type="Sprite2D"] +position = Vector2(0.0, 0.0) rotation = 4.71239 -scale = Vector2(0.0257427, 0.0257427) +scale = Vector2(0.496934, 0.496934) texture = ExtResource("1_v0nwa") From b3a46a3a982aa7eba16d1c0d84e406c1d0af598d Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 21 Oct 2025 08:25:10 +0300 Subject: [PATCH 112/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=94=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20?= =?UTF-8?q?=D0=BE=D1=82=20=D0=BD=D0=B0=D0=B2=D0=B8=D0=B3=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20(=D0=90=D0=9A=D0=9D=D0=93)=20=D1=82=D0=B5=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=8C=20=D0=B8=D0=BC=D0=B5=D0=B5=D1=82=20=D0=B4=D1=80?= =?UTF-8?q?=D1=83=D0=B3=D0=BE=D0=B9=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/navigation.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/navigation.gd b/scripts/navigation.gd index 6feda387..2e8ed4a9 100644 --- a/scripts/navigation.gd +++ b/scripts/navigation.gd @@ -26,7 +26,7 @@ class NaviSource extends unit.Unit: if not online: online = true emit_signal('line_changed', self) - if rx_data.size() < 28: + if rx_data.size() < 32: emit_signal('parse_failed', self) return false var flags: = rx_data.decode_u16(28) # Флаги достоверности полей структуры From b9dec950581ae0f20d1faa981708219db495a756 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 21 Oct 2025 08:27:25 +0300 Subject: [PATCH 113/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f73f4dc6..14d22449 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,4 @@ # Разработка - После клонирования запустить скрипт `git-hooks-config.sh` +- Нужно обновить `settings.json` \ No newline at end of file From 61ba09156772d927000e7233bdb2ba6dcf58b1db Mon Sep 17 00:00:00 2001 From: sasha80 Date: Tue, 21 Oct 2025 09:03:05 +0300 Subject: [PATCH 114/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9D=D0=B0=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=20=D0=A1=D0=9A=D0=92=20=D0=B2=20?= =?UTF-8?q?Windows=20=D0=BD=D0=B5=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0?= =?UTF-8?q?=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- git-hooks-config.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/git-hooks-config.sh b/git-hooks-config.sh index 0b2cb93d..c3109721 100644 --- a/git-hooks-config.sh +++ b/git-hooks-config.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -echo ./git-hook.sh> ./.git/hooks/post-checkout -echo ./git-hook.sh> ./.git/hooks/post-commit -echo ./git-hook.sh> ./.git/hooks/post-merge +printf "#!/usr/bin/env bash\n./git-hook.sh"> ./.git/hooks/post-checkout +printf "#!/usr/bin/env bash\n./git-hook.sh"> ./.git/hooks/post-commit +printf "#!/usr/bin/env bash\n./git-hook.sh"> ./.git/hooks/post-merge ./git-hook.sh \ No newline at end of file From cef11684c7ac4c42f5c5cedc80ebf0b8980df215 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 23 Oct 2025 14:16:45 +0300 Subject: [PATCH 115/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20null=20reference?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/button-flat/nine-patch-button.gd | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scenes/button-flat/nine-patch-button.gd b/scenes/button-flat/nine-patch-button.gd index 10a93a27..7b9ed907 100644 --- a/scenes/button-flat/nine-patch-button.gd +++ b/scenes/button-flat/nine-patch-button.gd @@ -38,9 +38,10 @@ var _pressed: = false @export var disabled: bool = false: set(val): disabled = val - $button.set_disabled(val) - $back.disabled = val - $state.modulate.a = 0.5 if val else 1.0 + if is_inside_tree(): + $button.set_disabled(val) + $back.disabled = val + $state.modulate.a = 0.5 if val else 1.0 @export var pressed: bool = false: From 5c67baa10c43f96323bb2adc5ac296c7714c3332 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 23 Oct 2025 14:30:50 +0300 Subject: [PATCH 116/117] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=92=D0=B0=D0=B6=D0=BD=D0=BE=D0=B5=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=8F=D1=81=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 14d22449..3fc369dd 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ - [Прибор СПТ-25](http://gitea.srez.local:3000/Maxim/SPT-25) - [ПО 5П28 Пульт П16](http://gitea.srez.local:3000/MaD_CaT/imi-5p28) - [ПО 5П28 АКНГ](http://gitea.srez.local:3000/sasha80/imi-5p28-navi) +- [Трасса](http://gitea.srez.local:3000/lepshiy/imi-trassa) + +# Автоматизация тестирования + - [Запуск имитаторов](http://gitea.srez.local:3000/sasha80/uarep-ctl-test-launcher) # Сборка исполняемого файла из консоли @@ -30,4 +34,5 @@ # Разработка - После клонирования запустить скрипт `git-hooks-config.sh` -- Нужно обновить `settings.json` \ No newline at end of file +- В среде **Windows** запуск скрипта `git-hooks-config.sh` производить из оболочки `git bash` +- Нужно обновить `settings.json` From daaee9ec739dcef3b320f823b8d4caf718493372 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 23 Oct 2025 14:45:25 +0300 Subject: [PATCH 117/117] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=A1=D0=B1=D0=BE=D0=B9=20?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B0=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=20=D0=BE=D1=82=D0=BA=D1=80=D1=8B=D1=82=D0=B8=D0=B8?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0=20(=D0=B2=D0=BE?= =?UTF-8?q?=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=B0=D1=8F=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D1=87=D0=B8=D0=BD=D0=B0=20-=20=D0=BF=D0=BE=D0=B2=D1=80=D0=B5?= =?UTF-8?q?=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B2=20SerialPort)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/network.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/network.gd b/scripts/network.gd index a8950163..dea87069 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -1,4 +1,4 @@ -@tool +#@tool class_name Network extends Node const YAU07_PROTO: = {'yau07tx': yau07.YaU07}