280 lines
12 KiB
GDScript
280 lines
12 KiB
GDScript
@tool
|
||
|
||
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 до количества созданных окон
|
||
|
||
|
||
var drag_button: MouseButton ## Кнопка мыши нажатая при перетаскивании
|
||
var drag_fsm: DragFSM = DragFSM.IDLE ## Текущее состояние перетаскивания
|
||
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 ## Ширина строба по углу в момент начала перетаскивания
|
||
|
||
|
||
signal drag_begin ## Вызывается в момент начала перетаскивания
|
||
signal drag_continue ## Вызывается во время продолжения перетаскивания
|
||
signal drag_end ## Вызывается в момент завершения перетаскивания
|
||
|
||
|
||
## Состояние перетаскивания
|
||
enum DragFSM {
|
||
DRAG, ## В процессе
|
||
IDLE, ## Не активно, ожидание
|
||
OFF ## Выключено
|
||
}
|
||
|
||
|
||
func on_button_view_toggled(toggled: bool): $canvas.set_view_mode(int(toggled))
|
||
|
||
|
||
## Обработчик сигнала изменения списка целей
|
||
func on_threats_resized(threats: Dictionary): $count_all_pad/count_all.text = '%02d' % threats.size()
|
||
|
||
|
||
##
|
||
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 _ready():
|
||
min_zoom = ProjectSettings.get_setting('application/config/map_minimum_zoom', 5)
|
||
max_zoom = ProjectSettings.get_setting('application/config/map_maximum_zoom', 19)
|
||
$btn_zoom.set_meta('zoom', min_zoom - 1)
|
||
$btn_strob.button_connect('pressed', Callable(self, 'on_button_strobe_pressed'))
|
||
$btn_view.button_connect('toggled', Callable(self, 'on_button_view_toggled'))
|
||
drag_fsm = DragFSM.OFF
|
||
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('zoom_complete', Callable(self, '_on_zoom_complete'))
|
||
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').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'))
|
||
interfer.connect('interfer_update', Callable(self, 'on_interfer_new'))
|
||
|
||
func on_enter_tree() -> void:
|
||
call_deferred('_on_btn_scale_pressed')
|
||
call_deferred('on_button_strobe_pressed')
|
||
$tilemap.position = $canvas.get_strob_center()
|
||
|
||
|
||
## Производит отображение цели на диаграмму
|
||
func map_threat_to_bip(th: threats.Threat, bip: Control):
|
||
bip.position = tools.pos_calc(
|
||
th.freq,
|
||
th.aoa,
|
||
radius_center,
|
||
radius_internal,
|
||
radius_outter,
|
||
freq_low,
|
||
freq_high)
|
||
|
||
|
||
## Обработчик сигнала обновления цели
|
||
func on_threat_update(th):
|
||
var bip = get_node('%d' % th.id)
|
||
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 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)
|
||
|
||
|
||
## Обработчик сигнала обнаружения цели
|
||
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_rto_threat_sel(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(true)
|
||
else:
|
||
item.set_sel_visible(false)
|
||
for btn in ecm_btns:
|
||
btn.set_disabled(false)
|
||
|
||
|
||
## Обработчик снятия выбора РТО цели
|
||
func on_rto_threat_unsel(th_id, ecm_btns):
|
||
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
|
||
for item in bips:
|
||
if th_id == item.name.to_int():
|
||
item.set_sel_visible(false)
|
||
break
|
||
for btn in ecm_btns:
|
||
btn.set_pressed(false)
|
||
btn.set_disabled(true)
|
||
|
||
|
||
func on_threat_selected(th, ecm_btns):
|
||
on_rto_threat_sel(th.id, ecm_btns)
|
||
|
||
|
||
## Обработчик нажатия кнопки "Строб". Управляет отображением строба
|
||
func on_button_strobe_pressed() -> void:
|
||
drag_fsm = DragFSM.IDLE if $btn_strob.is_pressed() else DragFSM.OFF
|
||
$canvas.set_strob_visible(drag_fsm == DragFSM.IDLE)
|
||
|
||
|
||
## Поведение радиокнопок в группе. Управляет состоянием кнопок в радиогруппе
|
||
func on_button_pressed(btn_this, btn_others) -> void:
|
||
for btn_other in btn_others: btn_other.set_pressed(btn_this == btn_other)
|
||
signaller.emit_signal('interfer_init', btn_this)
|
||
|
||
|
||
## Управляет состоянием кнопок в радиогруппе при выборе помехи
|
||
func on_interfer_selected(ecm, btns) -> void:
|
||
var ecm_name: String
|
||
if ecm != null:
|
||
ecm_name = ecm.krp
|
||
else:
|
||
ecm_name = interfer.INTERFER_OFF
|
||
for btn in btns:
|
||
btn.set_disabled(false)
|
||
btn.get_meta('rfi_name')
|
||
if ecm_name == btn.get_meta('rfi_name'):
|
||
btn.set_pressed(true)
|
||
else:
|
||
btn.set_pressed(false)
|
||
|
||
|
||
## Возвращает ширину строба по направлению
|
||
func get_strob_width(pos: Vector2, prev: float) -> float:
|
||
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, pos)
|
||
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 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:
|
||
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:
|
||
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:
|
||
drag_fsm = DragFSM.IDLE
|
||
emit_signal('drag_end', event)
|
||
elif event is InputEventKey:
|
||
if event.physical_keycode == KEY_SHIFT:
|
||
shift_pressed = event.pressed
|
||
|
||
|
||
## Вызывается по нажатию кнопки "Детализация"
|
||
func _on_btn_scale_pressed() -> void:
|
||
var zoom = $btn_zoom.get_meta('zoom')
|
||
zoom = zoom + 1 if zoom < max_zoom else min_zoom
|
||
signaller.emit_signal('zoom_changed', zoom)
|
||
|
||
|
||
## Вызывается по завершению изменения детализации карты
|
||
func _on_zoom_complete(zoom: int) -> void:
|
||
var prefix = $btn_zoom.get_meta('prefix')
|
||
$btn_zoom/lbl.text = '%s %d' % [prefix, zoom]
|
||
$btn_zoom.set_meta('zoom', zoom)
|