class_name work extends Panel ## Основной скрипт для режима "Работа". @export var Bip: PackedScene ## Индикатор излучения цели. @export var col_grey: Color ## Второй цвет для фона. @export var col_red: Color ## Первый цвет для фона. @export var drag_scale_band: float ## Масштаб изменения параметра от движения мыши для строба по радиальному размеру. @export var drag_scale_width: float ## Масштаб изменения параметра от движения мыши для строба по угловому размеру. @export var freq_high: float ## Верхняя рабочая частота, МГЦ. @export var freq_low: float ## Нижняя рабочая частота, МГЦ. @export var radius_center: Vector2 ## Координаты центра диаграммы пеленг-частота. @export var radius_internal: float ## Внутренний радиус диаграммы пеленг-частота. @export var radius_outter: float ## Внешний радиус диаграммы пеленг-частота. @export var strob_max_band: float ## Максимальная ширина строба по углу. @export var strob_max_width: float ## Максимальная ширина строба по углу. @export var strob_min_band: float ## Минимальная ширина строба по частоте. @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 ## Текущее состояние перетаскивания. var btn_select: BtnSel = BtnSel.SECTOR ## Текущее состояние кнопки выбора цели. var drag_pos_begin: Vector2 ## Точка начала перетаскивания. var max_zoom: int ## Максимальный уровень детализации. var min_zoom: int ## Минимальный уровень детализации. var shift_pressed: bool ## Кнопка SHIFT нажата. var strob_band_begin: float ## Ширина строба в момент начала перетаскивания. var strob_dir_begin: float ## Направление антенны в момент начала перетаскивания. var strob_width_begin: float ## Ширина строба по углу в момент начала перетаскивания. var view_mode: MapViewMode ## Режим отображения карты var thrs_dict: Dictionary ## Ссылка на словарь целей var gos_flag = true ## Флаг работать по своим целям var color_ecm: Color var color_select: Color var color_emit: Color var color_emit_sel: Color var color_closed: Color var col_btn_act: Color = Color.WHITE var color_closed_emit: Color var signal_conections: Array var course = 0.0 ## Курс корабля signal drag_begin ## Вызывается в момент начала перетаскивания. signal drag_continue ## Вызывается во время продолжения перетаскивания. signal drag_end ## Вызывается в момент завершения перетаскивания. ## Размеры карты для разных режимов РТО и РЛС соответственно const map_sizes = [ Rect2i(360, 360, 400, 400), Rect2i(82, 82, 955, 955)] var fs_band = prd.FS_BAND_RTO ## Текущий режим блоков ФС по частоте var fs_selected: Dictionary ## Словарь выбранных секторов var fs_active: Dictionary ## Словарь секторов назначенных на подавление var fs_emit: Dictionary ## Словарь секторов назначенных на подавление var fs_closed: Dictionary ## Словарь для секторов запрета var fs_failed: PackedInt32Array ## Индикация сломанных секторов (модули ФС). AntBandState.ANT_BAND_READY - исправен, AntBandState.ANT_BAND_FAILURE - сломан. ## Состояние перетаскивания. enum DragFSM { DRAG, ## В процессе. IDLE, ## Не активно, ожидание. OFF ## Выключено. } ## Режим выбора enum BtnSel { SECTOR, ## Выбор сектора. THREAT, ## Выбор цели. FS ## Выбор стробом. } ## Режим отображения карты enum MapViewMode { RTO = 0, ## Режим приоритет РТО (малая карта, широкие секторы) RLS = 1 ## Режим приоритет РЛС (большая карта, узкие секторы) } enum AntBandState { ANT_BAND_FAILED = 0, ANT_BAND_READY = 1, ANT_BAND_ASSIGNED = 2 } const VAL_TO_EVENT = { false: 'manual_control', ## Выбор целей и установка помех вручную. true: 'full_auto' } ## Выбор целей и установка помех автоматически. var SIGNALS_CONNECTIONS = [ [interfer, 'interfer_update', 'on_interfer_new'], [signaller, 'bip_pressed', 'on_bip_pressed'], [signaller, 'clear_klaster', 'clear_all_klaster'], [signaller, 'fs_selected', 'on_fs_selected'], [signaller, 'fs_update_color', 'set_fs_color'], [signaller, 'fs_update_state', 'on_fs_update_state'], [signaller, 'interfer_new', 'on_interfer_new'], [signaller, 'interfer_off_all', 'on_interfer_off_all'], [signaller, 'interfer_prinuditelno', 'on_chk_interfer_prinuditelno'], [signaller, 'interfer_prinuditelno', 'on_interfer_prinuditelno'], [signaller, 'interfer_selected', 'on_interfer_selected'], [signaller, 'map_user_panning', 'on_user_panning'], [signaller, 'prog_ecm_off', 'on_interfer_new'], [signaller, 'rto_threat_sel', 'on_rto_threat_sel'], [signaller, 'rto_threat_unsel', 'on_rto_threat_unsel'], [signaller, 'sector_klaster', 'sector_klaster'], [signaller, 'th_aoa_update', 'on_th_aoa_update'], [signaller, 'threat_selected', 'on_threat_selected'], [signaller, 'update_coordinates_map', 'on_update_coordinates_label'], [signaller, 'update_scale_map', 'on_update_scale_label'], [threats, 'threat_lost', 'on_threat_lost'], [threats, 'threat_new', 'on_threat_new'], [threats, 'threat_update', 'on_threat_update'], [threats, 'threats_resized', 'on_threats_resized'] ] ## Обработчик выбора цели. func on_threat_selected(th): on_rto_threat_sel(th.id) ## Встроенный обратный вызов. func on_enter_tree() -> void: call_deferred('on_button_strobe_pressed') func clear_all_klaster(): $canvas.clear_all_seczap() func on_user_panning(): $btn_center.button_pressed = false func on_settings_changed(): gos_flag = ProjectSettings.get_setting('application/config/Включить работу по своим целям', true) 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_closed = ProjectSettings.get_setting('application/interfer/closed_sectors', Color(0.0, 0.0, 0.0, 1.0)) min_zoom = ProjectSettings.get_setting('application/config/map_minimum_zoom', 5) max_zoom = ProjectSettings.get_setting('application/config/map_maximum_zoom', 19) color_emit_sel = color_select color_closed_emit = color_closed 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) color_closed *= Color(1.0, 1.0, 1.0, 0.0) color_closed_emit *= Color(1.0, 1.0, 1.0, 1.0) var json_col = ProjectSettings.get_setting('application/config/%s' % 'Цвет кнопки \"Подавление\"', '[1.0, 1.0, 1.0, 1.0]') var arr_col = JSON.parse_string(json_col) col_btn_act = Color(arr_col[0], arr_col[1], arr_col[2], arr_col[3]) if arr_col else Color.WHITE apply_colors() func apply_colors(): var is_light: bool = ProjectSettings.get_setting("application/config/Цвет темы программы", false) var style = StyleBoxFlat.new() if is_light: style.bg_color = Color.DARK_GRAY add_theme_stylebox_override("panel", style) else: style.bg_color = Color(0.12, 0.12, 0.12) add_theme_stylebox_override("panel", style) ## Обработчик сигнала изменения списка целей. func on_threats_resized(ths: Dictionary): count_threats(ths) thrs_dict = ths ## Обработчик нажатия на кнопку вид. func on_button_view_toggled(toggled: bool): signaller.emit_signal('map_mode_changed', int(toggled)) fs_band = prd.FS_BAND_RLS if toggled else prd.FS_BAND_RTO var s = map_sizes[int(toggled)] $tilemap.size = s.size $tilemap.position = s.position view_mode = MapViewMode.RLS if toggled else MapViewMode.RTO if view_mode != MapViewMode.RTO: fs_selected.clear() $btns_select/btn_strob.disabled = toggled $btns_select/btn_fs_sector.disabled = toggled $'canvas/строб'.visible = $btns_select/btn_strob.pressed and (not toggled) ## Встроенный обратный вызов. func _enter_tree() -> void: var timer1 = Timer.new() timer1.name = 'timer1' add_child(timer1) timer1.one_shot = true timer1.connect('timeout', Callable(self, 'on_enter_tree')) timer1.start(1.0) ## Встроенный обратный вызов. func _exit_tree() -> void: var timer1 = get_node('timer1') remove_child(timer1) timer1.queue_free() func init_fs_failed(): var sectors_count = $canvas.fs_default_colors.size() fs_failed.resize(sectors_count) for i in fs_failed.size(): fs_failed[i] = AntBandState.ANT_BAND_FAILED ## Производит инициализацию. func _ready(): ProjectSettings.connect('settings_changed', on_settings_changed) on_settings_changed() init_fs_failed() drag_fsm = DragFSM.OFF var btns_select: Array = get_tree().get_nodes_in_group('группа-режим-выбора') btns_select.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_select').bind(btn, btns_select))) on_button_select($btns_select/btn_fs_sector, 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))) $btn_close.button_connect('pressed', on_btn_close) $btn_work.button_connect('pressed', on_btn_work) 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) signaller.connect('режим_работа', connect_all) signaller.connect('режим_контроль', disconnect_all) signaller.connect('режим_журнал', disconnect_all) signaller.connect('режим_эмс', disconnect_all) signaller.connect('режим_эмс2', disconnect_all) signaller.connect('режим_настройки', disconnect_all) connect_all() func connect_all() -> void: signal_conections.clear() for item in SIGNALS_CONNECTIONS: var proc = Callable(self, item[2]) var rc = item[0].connect(item[1], proc) if rc == Error.OK: signal_conections.append([item[0], item[1], proc]) else: var ers = error_string(rc) push_error('%s: %s %s %s' % [ers, item[0], item[1], item[2]]) signaller.emit_signal('connect_work_signal') for th in thrs_dict.values(): var bip = Bip.instantiate() bip.name = '%d' % th.id map_threat_to_bip(th, bip) add_child(bip) func disconnect_all() -> void: for item in signal_conections: item[0].disconnect(item[1], item[2]) signal_conections.clear() var bips: Array = get_children().filter(func(item): return item.name.is_valid_int()) for bip in bips: remove_child(bip) bip.free() func sector_klaster(sector_data): if sector_data['draw']: var rect: Rect2 = sector_data['rect'] var color: Color = sector_data['color'] var id: int = sector_data['index'] $canvas.add_seczap(id, Vector4(rect.position.x, rect.position.y, rect.size.x, rect.size.y)) $canvas.set_seczap_color(id, color) func on_navi_data_received(data: Dictionary): var k = data.get('k', 0.0) $canvas.set_canvas_rotation(k) course = k func on_chk_interfer_prinuditelno(_interfer_sectors): $chk_auto.set_pressed_no_signal(false) on_value_changed(false) func on_value_changed(val: bool): signaller.emit_signal(VAL_TO_EVENT[val]) func get_all_nodes(root): var nodes = [] nodes.append(root) for child in root.get_children(): nodes.append_array(get_all_nodes(child)) return nodes ## Производит отображение цели на диаграмму. func map_threat_to_bip(th: threats.Threat, bip: Control) -> bool: var freq = th.freq var sector_key = null var sector_width = 50.0 for key in prd.FS_FREQ: var freq_range = prd.FS_FREQ[key] var _num_values = (freq_range[1] - freq_range[0]) / sector_width if freq_range[0] <= freq and freq <= freq_range[1]: sector_key = key break 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] freq_high = prd.FS_FREQ[sector_key][1] bip.position = tools.pos_calc( th.freq, th.aoa, radius_center, radius_internal, radius_outter, freq_low, freq_high) - bip.size / 2 return sector_key != null ## Обработчик сигнала обновления цели. func on_threat_update(th: threats.Threat): var bip = get_node('%d' % th.id) bip.update(th.tick_rx) if th.gos: bip.set_bip_color(Color.GREEN) else: bip.set_bip_color(Color.CORAL if th.proto else Color.WHITE) bip.visible = map_threat_to_bip(th, bip) ## Обработчик выбора помехи для цели. func on_interfer_new(ecm): 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: bip.set_ecm_visible(false) bip.set_track_visible(false) else: interfer.thrs.erase(ecm.ispp) update_fs_colors() ## Обработчик выключения всех помех. func on_interfer_off_all(): var bips: Array = get_children().filter(func(item): return item.name.is_valid_int()) for bip in bips: bip.set_ecm_visible(false) bip.set_track_visible(false) fs_active.clear() fs_emit.clear() update_fs_colors() ## Обработчик сигнала обнаружения цели. func on_threat_new(th) -> void: var bip = Bip.instantiate() bip.name = '%d' % th.id map_threat_to_bip(th, bip) add_child(bip) ## Обработчик сигнала потери цели. func on_threat_lost(th) -> void: var bip = get_node('%d' % th.id) remove_child(bip) bip.free() ## обработчик нажатия на цель на экране. func on_bip_pressed(th_id): if btn_select == BtnSel.THREAT: signaller.emit_signal('rto_threat_sel', th_id) ## Обработчик выбора РТО цели. func on_rto_threat_sel(th_id): var bips: Array = get_children().filter(func(item): return item.name.is_valid_int()) for item in bips: if th_id == item.name.to_int(): item.set_sel_visible(true) unsel_fs_all(false) else: item.set_sel_visible(false) var th = thrs_dict[th_id] var krp = interfer.get_krp(th) var ecm_btns: Array = get_tree().get_nodes_in_group('группа-режим-помехи') for btn in ecm_btns: set_btns_disabled(false, btn) var btn_meta = btn.get_meta('rfi_name') if krp == btn_meta: btn.set_rec_visible(true) else: btn.set_rec_visible(false) ## Обработчик снятия выбора РТО цели. func on_rto_threat_unsel(th_id): 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) var ecm_btns: Array = get_tree().get_nodes_in_group('группа-режим-помехи') for btn in ecm_btns: btn.set_rec_visible(false) ## Обработчик нажатия кнопки "Строб". Управляет отображением строба. 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) and (view_mode == MapViewMode.RTO)) ## Поведение радиокнопок в группе. Управляет состоянием кнопок выбора целей. func on_button_select(btn_this, btn_others) -> void: for btn_other in btn_others: btn_other.set_pressed(btn_this == btn_other) btn_select = btn_this.get_meta('state') on_button_strobe_pressed() signaller.emit_signal('rto_threat_unsel_all') unsel_fs_all(true) set_ecm_btns_state(true) ## Поведение радиокнопок в группе. Управляет состоянием кнопок в радиогруппе. func on_button_pressed(btn_this, btn_others) -> void: $chk_auto.set_pressed_no_signal(false) on_value_changed(false) for btn_other in btn_others: btn_other.set_pressed(btn_this == btn_other) var interfer_name: String = btn_this.get_meta('rfi_name', 'off') var fs_arr: Array = [] for key in fs_selected.keys(): fs_arr.append(prd.get_fs_param(key)) signaller.emit_signal('interfer_init', interfer_name, fs_arr, interfer.POW_DEFAULT) ## Управляет состоянием кнопок в радиогруппе при выборе помехи. func on_interfer_selected(ecm) -> void: var ecm_name: String if ecm != null: ecm_name = ecm.krp else: ecm_name = interfer.INTERFER_OFF var btns: Array = get_tree().get_nodes_in_group('группа-режим-помехи') for btn in btns: set_btns_disabled(false, btn) btn.get_meta('rfi_name') if ecm_name == btn.get_meta('rfi_name'): btn.set_pressed(true) else: btn.set_pressed(false) ## Возвращает ширину строба по направлению. func get_strob_width(pos: Vector2, prev: float) -> float: var strob_dir_width: float = prev + (drag_pos_begin.y - pos.y) * drag_scale_width strob_dir_width = tools.clip_value(strob_dir_width, strob_min_width, strob_max_width) return strob_dir_width ## Возвращает ширину строба по частоте. func get_strob_band(pos: Vector2, prev: float) -> float: var strob_dir_band: float = prev - (drag_pos_begin.y - pos.y) * drag_scale_band strob_dir_band = tools.clip_value(strob_dir_band, strob_min_band, strob_max_band) return strob_dir_band ## Устанавливает центр строба по частоте и направлению. func set_strob(pos: Vector2) -> void: var radp: Vector2 = tools.map_dec_to_rad(radius_center / 2.0, pos / 2.0) if radp.y < $canvas.get_radius_outter(): $canvas.set_strob_dir(radp.x) $canvas.set_strob_radius(radp.y) ## Обработка движения мыши для управления стробом. Вызывается во время движения мыши. 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) $canvas.set_strob_width(strob_width) else: var strob_band: float = get_strob_band(event.position, strob_band_begin) $canvas.set_strob_band(strob_band) elif drag_button == MOUSE_BUTTON_LEFT: set_strob(event.position) ## Обработка движения мыши для управления стробом. Вызывается при нажатии мыши. 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) elif drag_button == MOUSE_BUTTON_RIGHT: strob_width_begin = $canvas.get_strob_width() strob_band_begin = $canvas.get_strob_band() ## Обработчик событий ввода. Вызывается godot. func _input(event) -> void: if not is_visible_in_tree(): return if (event is InputEventMouseMotion) and (view_mode == MapViewMode.RTO): if drag_fsm == DragFSM.DRAG: emit_signal('drag_continue', event) elif event is InputEventMouseButton: drag_button = event.button_index if event.pressed: if drag_fsm == DragFSM.IDLE: drag_fsm = DragFSM.DRAG emit_signal('drag_begin', event) else: if btn_select == BtnSel.FS: sel_fs_sector(event) drag_fsm = DragFSM.IDLE emit_signal('drag_end', event) elif event is InputEventKey: if event.physical_keycode == KEY_SHIFT: shift_pressed = event.pressed ## Обработчик нажатия по сектору формирователя сигналов. func sel_fs_sector(event): if view_mode != MapViewMode.RTO: return 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 - course if angle < 0: angle += 360 var distance: float = event.position.distance_to(center + center_offset) var sector: int var band: int var has_band: bool = false for sec in prd.FS_SECTORS.values(): if angle >= sec[0] and angle <= sec[1]: sector = prd.FS_SECTORS.find_key(sec) for diap in fs_band.values(): if distance >= diap[0] and distance <= diap[1]: band = fs_band.find_key(diap) has_band = true if not has_band: return var fs_index = band * 4 + sector if event.button_index == MOUSE_BUTTON_LEFT: fs_selected[fs_index] = null else: fs_selected.erase(fs_index) update_fs_colors() signaller.emit_signal('rto_threat_unsel_all') var btn_state = len(fs_selected) == 0 set_ecm_btns_state(btn_state) func set_fs_color(ecms): fs_active.clear() fs_emit.clear() for ecm in ecms.values(): if not prd.fs_caps_id.has(ecm.nmfs): push_warning('нет такого модуля ФС: %d, но имеется: %s' % [ecm.nmfs, prd.fs_caps_id.keys()]) continue if ecm.krp != interfer.INTERFER_OFF: fs_active[prd.fs_caps_id[ecm.nmfs]] = null if ecm.svk == SVK_EMIT: fs_emit[prd.fs_caps_id[ecm.nmfs]] = null update_fs_colors() 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_closed: if key in fs_emit: fs_colors[key] = color_closed_emit else: fs_colors[key] = color_closed for key in fs_selected.keys(): if key in fs_emit: fs_colors[key] = color_emit_sel else: fs_colors[key] = color_select $canvas.set_band_colors(fs_colors) $canvas.set_band_failures(fs_failed) if fs_emit.size(): if $btn_activate.pressed: $btn_activate.self_modulate = col_btn_act else: $btn_activate.self_modulate = Color.WHITE else: $btn_activate.self_modulate = Color.WHITE func unsel_fs_all(need_btns_off: bool): fs_selected.clear() update_fs_colors() if need_btns_off: set_ecm_btns_state(true) func set_ecm_btns_state(value: bool): var btns: Array = get_tree().get_nodes_in_group('группа-режим-помехи') for btn in btns: btn.set_pressed(false) set_btns_disabled(value, btn) func on_fs_selected(ecm): var fs_index_arr: Array = [] prd.get_fs_index(ecm, fs_index_arr) fs_selected.clear() if view_mode != MapViewMode.RTO: return for item in fs_index_arr: fs_selected[item] = null update_fs_colors() func set_btns_disabled(value: bool, btn): var external_ctl = ProjectSettings.get_setting('application/config/Внешнее управление', false) if external_ctl: btn.set_pressed(false) btn.set_disabled(true) else: btn.set_disabled(value) func on_interfer_prinuditelno(prenuditelno_sectors): for key in prenuditelno_sectors: var sectors = [] for sector in prenuditelno_sectors[key]: sectors.append(prd.get_fs_param(sector)) signaller.emit_signal('interfer_init', key, sectors, interfer.POW_DEFAULT) update_fs_colors() var btns: Array = get_tree().get_nodes_in_group('группа-режим-помехи') for btn in btns: btn.set_pressed(false) set_btns_disabled(true, btn) ## Вызывается при получении информации о состоянии модулей ФС от КАПС РПБ. func on_fs_update_state(fs_dict: Dictionary): for key in fs_dict.keys(): fs_failed[key] = AntBandState.ANT_BAND_READY if fs_dict[key].ready else AntBandState.ANT_BAND_FAILED func on_btn_center_toggled(toggled_on: bool) -> void: $btn_center.tooltip_text = 'Центрирует карту на текущие координаты (%s)' % ('включено' if toggled_on else 'отключено') signaller.emit_signal('map_centered', toggled_on) func on_btn_activate_toggled(toggled_on: bool) -> void: $btn_activate.tooltip_text = 'Включает подавление (%s)' % ('включено' if toggled_on else 'отключено') signaller.emit_signal('emit_changed', toggled_on) if not toggled_on: $btn_activate.self_modulate = Color.WHITE func on_update_coordinates_label(coordinates_label) -> void: $coordinates_map.text = str(coordinates_label) func on_update_scale_label(scale_label) -> void: $scale_map.text = str(scale_label) func on_btn_close(): await get_tree().create_timer(0.2).timeout $btn_close.pressed = false fs_closed.merge(fs_selected) signaller.emit_signal('update_fs_closed', fs_closed) func on_btn_work(): await get_tree().create_timer(0.2).timeout $btn_work.pressed = false fs_closed.clear() for fs_index in prd.FS_PRD.keys(): if fs_index in fs_selected: continue fs_closed[fs_index] = null signaller.emit_signal('update_fs_closed', fs_closed) func _on_btn_all_work_pressed() -> void: fs_closed.clear() signaller.emit_signal('update_fs_closed', fs_closed) func on_th_aoa_update(ths): count_threats(ths) func count_threats(ths): $count_all_pad/count_all.text = '%02d' % ths.size() var c: int = 0 if gos_flag: c = ths.values().filter(func(th: threats.Threat): return th.proto != '').size() else: c = ths.values().filter(func(th: threats.Threat): return ((th.proto != '') and th.proto not in interfer.gos_protocols)).size() $count_danger_pad/count_danger.text = '%02d' % c