Merge branch 'tmp'

This commit is contained in:
2024-09-27 11:41:54 +03:00
53 changed files with 1840 additions and 829 deletions

View File

@@ -33,7 +33,7 @@ Log.fatal(text)
const CUSTOM = Log.MAX << 1 # Bitwise left shift the MAX value for a custom level.
func _ready() -> void:
Log.add_level(CUSTOM, "Level Name")
Log.add_level(CUSTOM, "Level Name")
```
## Calling the custom level:

View File

@@ -1,21 +1,20 @@
# Copyright (c) 2020-2023 Mansur Isaev and contributors - MIT License
# See `LICENSE.md` included in the source distribution for details.
## Logger class.
class_name Logger
extends Node
## Класс журнал событий.
class_name Logger extends Node
## Emitted when the logger create a message.
## Выдается, когда журнал событий создаёт сообщение.
signal logged(message: Dictionary)
enum {
INFO = 1, ## Info level.
DEBUG = 1<<1, ## Warning level.
WARNING = 1<<2, ## Debug level.
ERROR = 1<<3, ## Error level.
FATAL = 1<<4, ## Fatal level.
MAX = FATAL, ## Bitwise left shift for custom levels.
INFO = 1, ## Информационный уровень.
DEBUG = 1<<1, ## Уровень предупреждения.
WARNING = 1<<2, ## Уровень отладки.
ERROR = 1<<3, ## Уровень ошибок.
FATAL = 1<<4, ## Критический уровень.
MAX = FATAL, ## Побитовый сдвиг влево для пользовательских уровней.
}
@@ -41,7 +40,7 @@ var _names = {
var _msg_array: Array
var _filters: Array
# Can be overridden to define custom default values.
## Преопределение пользовательских значений по умолчанию.
func _enter_tree() -> void:
set_log_enabled(ProjectSettings.get_setting("plugins/logger/log_enabled", true))
set_default_output_enabled(ProjectSettings.get_setting("plugins/logger/default_output", false))
@@ -58,11 +57,11 @@ func _enter_tree() -> void:
func _exit_tree() -> void:
_close_file()
## Return [param true] if logger has level.
## Возвращает [param true], если у журнала события есть уровень.
func has_level(level: int) -> bool:
return _names.has(level)
## Set the level enabled.
## Установить включенный уровень.
func set_level(level: int, enabled: bool) -> void:
assert(has_level(level), "Invalid level.")
if not has_level(level):
@@ -73,8 +72,8 @@ func set_level(level: int, enabled: bool) -> void:
else:
_level &= ~level
## Add a custom log level. The level value must be unique and be greater than [member MAX].
## To call the custom level use [method message] method.
## Добавить пользовательский уровень журнала. Значение уровня должно быть уникальным и превышать [member MAX].
## Для вызова пользовательского уровня используйте метод - [method message].
func add_level(level: int, nm: String) -> void:
assert(not has_level(level), "Has level.")
assert(level > MAX and not level % 2, "Invalid level.")
@@ -84,27 +83,27 @@ func add_level(level: int, nm: String) -> void:
_names[level] = nm
set_level(level, true)
## Return the level name.
## Возвращает имя уровня.
func get_level_name(level: int) -> String:
return _names[level]
## Set Log enabled. Disable ALL messages.
## Установить включенный журнал. Отключить ВСЕ сообщения.
func set_log_enabled(enabled: bool) -> void:
_log_enabled = enabled
## Return [param true] if Log enabled.
## Возвращает [param true], если журнал включен.
func is_log_enabled() -> bool:
return _log_enabled
## Set default output enabled.
## Установка выхода по умолчанию включена.
func set_default_output_enabled(enabled: bool) -> void:
_default_output_enabled = enabled
## Returns [param true] if default output is enabled.
## Возвращает [param true], если вывод по умолчанию включен.
func is_default_output_enabled() -> bool:
return _default_output_enabled
## Set file write enabled.
## Установить разрешение на запись файла.
func set_file_write_enabled(enabled: bool) -> void:
if _file_write_enabled == enabled:
return
@@ -116,11 +115,11 @@ func set_file_write_enabled(enabled: bool) -> void:
else:
_close_file()
## Returns [param true] if write to a file is enabled.
## Возвращает [param true], если запись в файл разрешена.
func is_file_write_enabled() -> bool:
return _file_write_enabled
## Set the path to the log file.
## Задать путь к файлу журнала.
func set_file_path(path: String) -> void:
assert(path.is_absolute_path(), "Invalid path.")
if not path.is_absolute_path() or _file_path == path:
@@ -131,32 +130,32 @@ func set_file_path(path: String) -> void:
if is_file_write_enabled():
_open_file()
## Return path to log file.
## Возвращает путь к файлу журнала.
func get_file_path() -> String:
return _file_path
## Create an info message.
## Создать информационное сообщение.
func info(text: String) -> void:
message(INFO, text)
## Create a debug message. Debug build only.
## Создать отладочное сообщение. Только для отладочной сборки.
func debug(text: String) -> void:
if OS.is_debug_build():
message(DEBUG, text)
## Create a warning message.
## Создать предупреждающее сообщение.
func warning(text: String) -> void:
message(WARNING, text)
## Create an error message.
## Создать сообщение об ошибке.
func error(text: String) -> void:
message(ERROR, text)
## Create a fatal error message.
## Создать сообщение о критической ошибке.
func fatal(text: String) -> void:
message(FATAL, text)
## Format string for log file.
## Форматировать строку для файла.
func format_file(msg: Dictionary) -> String:
return _format_file.format(
{
@@ -171,7 +170,7 @@ func format_file(msg: Dictionary) -> String:
}
)
## Format string for editor output.
## Форматировать строку для вывода редактора.
func format_stdout(msg: Dictionary) -> String:
return _format_default_output.format(
{
@@ -186,7 +185,7 @@ func format_stdout(msg: Dictionary) -> String:
}
)
## Create a message with a custom level.
## Создать сообщение с пользовательским уровнем.
func message(level: int, text: String) -> void:
assert(has_level(level), "Has not level.")
assert(text, "Invalid message text.")
@@ -207,7 +206,7 @@ func message(level: int, text: String) -> void:
_file.call_deferred('flush')
if _default_output_enabled:
print(format_stdout(msg))
print_debug(format_stdout(msg))
func _open_file() -> void:

View File

@@ -2,11 +2,10 @@
# See `LICENSE.md` included in the source distribution for details.
@tool
## LoggerOutput class.
class_name LoggerOutput
extends RichTextLabel
## Класс вывода журнала событий.
class_name LoggerOutput extends RichTextLabel
## Emited when handle [signal Logger.logged] signal.
## Выдаётся при ошибке сигнала - [signal Logger.logged].
signal handled()
@@ -33,11 +32,11 @@ func _exit_tree() -> void:
if is_instance_valid(_logger) and _logger.logged.is_connected(handle_message):
_logger.logged.disconnect(handle_message)
## Return the level color or [member Color.WHITE].
## Вернуть цвет уровня или [member Color.WHITE].
func get_color(level: int) -> Color:
return colors.get(level, Color.WHITE)
## Set the logger.
## Установить журнал событий.
func set_logger(logger: Logger) -> void:
assert(is_instance_valid(logger), "Invalid Logger.")
if not is_instance_valid(logger) or is_same(_logger, logger):
@@ -51,11 +50,11 @@ func set_logger(logger: Logger) -> void:
_logger = logger
## Return the logger.
## Вернуть журнал событий.
func get_logger() -> Logger:
return _logger
## Return formatted string from message.
## Вернуть строку после форматирования из сообщения.
func format(message: Dictionary) -> String:
return format_text.format(
{
@@ -70,7 +69,7 @@ func format(message: Dictionary) -> String:
}
)
## Handle the message.
## Обработать сообщение.
func handle_message(message: Dictionary) -> void:
push_color(get_color(message["level"]))
append_text(format(message) + "\n")

24
build.sh Normal file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
#
# Описание
#
# Этот скрипт создаёт исполняемый файл (загружаемый модуль) из файла проекта Godot
#
# Имя выходного исполняемого файла (загружаемый модуль)
TARGET_BIN="uarep-ctl.linux.x86_64"
# Целевой путь папки в которой будет расположен исполняемый файл (загружаемый модуль)
TARGET_PATH="./bin"
# Путь к исполняемому файлу редактора Godot
EDITOR="/opt/godot/Godot_v4.2.2-stable_linux.x86_64"
# Если используется своя сборка движка, то соответствующий файл
# (исполняемый модуль движка, шаблон экспорта) нужно заменить
# в этой папке: "~/.local/share/godot/export_templates/4.2.2.stable/"
# Путь к файлу проекта Godot
PROJECT_PATH="$(pwd)"
${EDITOR} --path "${PROJECT_PATH}" --export-release "Linux-X11" "${TARGET_PATH}/${TARGET_BIN}"

View File

@@ -11,6 +11,7 @@ cache/0/16/0/underline_thickness = 0.0
cache/0/16/0/scale = 1.0
cache/0/16/0/kerning_overrides/16/0 = Vector2(0, 0)
cache/0/16/0/kerning_overrides/14/0 = Vector2(0, 0)
cache/0/16/0/kerning_overrides/50/0 = Vector2(0, 0)
cache/0/14/0/ascent = 0.0
cache/0/14/0/descent = 0.0
cache/0/14/0/underline_position = 0.0
@@ -18,3 +19,12 @@ cache/0/14/0/underline_thickness = 0.0
cache/0/14/0/scale = 1.0
cache/0/14/0/kerning_overrides/16/0 = Vector2(0, 0)
cache/0/14/0/kerning_overrides/14/0 = Vector2(0, 0)
cache/0/14/0/kerning_overrides/50/0 = Vector2(0, 0)
cache/0/50/0/ascent = 0.0
cache/0/50/0/descent = 0.0
cache/0/50/0/underline_position = 0.0
cache/0/50/0/underline_thickness = 0.0
cache/0/50/0/scale = 1.0
cache/0/50/0/kerning_overrides/16/0 = Vector2(0, 0)
cache/0/50/0/kerning_overrides/14/0 = Vector2(0, 0)
cache/0/50/0/kerning_overrides/50/0 = Vector2(0, 0)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
data/Окно.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

34
data/Окно.png.import Normal file
View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://co5xj5uhjfk84"
path="res://.godot/imported/Окно.png-ff4b5eac96df23ad4cd8e06dc32f5bb8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://data/Окно.png"
dest_files=["res://.godot/imported/Окно.png-ff4b5eac96df23ad4cd8e06dc32f5bb8.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -24,9 +24,7 @@ config/map_tile_size=256
config/map_minimum_zoom=5
config/map_maximum_zoom=19
config/map_server_addr="https://b.tile.openstreetmap.org"
config/map_image_size_rto=Vector2i(512, 512)
config/map_image_size_rls=Vector2i(1024, 1024)
interfer/center_offset=Vector2(0, 25)
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)
@@ -89,12 +87,55 @@ window/vsync/vsync_mode=false
[editor]
movie_writer/mjpeg_quality=0.5
movie_writer/fps=24
version_control/autoload_on_startup=true
[editor_plugins]
enabled=PackedStringArray()
[file_customization]
folder_colors={
"res://addons/": "blue",
"res://data/": "yellow",
"res://modbus/": "blue",
"res://scenes/": "teal",
"res://scenes/bip/": "blue",
"res://scenes/button-flat/": "blue",
"res://scenes/button-scale/": "blue",
"res://scenes/cell/": "blue",
"res://scenes/count-all/": "blue",
"res://scenes/count-danger/": "blue",
"res://scenes/diagram/": "blue",
"res://scenes/frame-ecm-list/": "blue",
"res://scenes/frame-ecm-params/": "blue",
"res://scenes/frame-params/": "blue",
"res://scenes/frame-threats/": "blue",
"res://scenes/frame/": "blue",
"res://scenes/grid-buttons-ecm/": "blue",
"res://scenes/grid-side-panel/": "blue",
"res://scenes/pribor-afsp/": "purple",
"res://scenes/pribor-prd-k/": "purple",
"res://scenes/pribor-prd-n/": "purple",
"res://scenes/pribor-prd-v/": "purple",
"res://scenes/pribor-rtr/": "purple",
"res://scenes/pribor-uf/": "purple",
"res://scenes/pribor-uyep/": "purple",
"res://scenes/tabs-switch/": "blue",
"res://scenes/tilemap/": "blue",
"res://scenes/журнал/": "green",
"res://scenes/контроль/": "green",
"res://scenes/настройки/": "green",
"res://scenes/работа/": "green",
"res://scenes/эмс/": "green",
"res://scenes/эмс2/": "green",
"res://scripts/": "pink",
"res://shaders/": "pink",
"res://table/": "blue"
}
[global]
map_server_addr=false
@@ -111,6 +152,29 @@ theme/default_font_subpixel_positioning=3
theme/lcd_subpixel_layout=0
common/drop_mouse_on_gui_input_disabled=true
[input]
up={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"echo":false,"script":null)
]
}
down={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null)
]
}
left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null)
]
}
right={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null)
]
}
[input_devices]
buffering/agile_event_flushing=true
@@ -129,7 +193,6 @@ common/enable_object_picking=false
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.web="mobile"
gl_compatibility/item_buffer_size=8192
shader_compiler/shader_cache/strip_debug=true
textures/default_filters/anisotropic_filtering_level=0
anti_aliasing/screen_space_roughness_limiter/enabled=false

View File

@@ -1,16 +1,16 @@
extends Control
class_name bip_ extends Control
var selected: bool
# Функция присваивает заданое значение видимости селектору
## Функция присваивает заданое значение видимости селектору.
func set_sel_visible(value: bool):
selected = value
$selector.visible = value
# Функция присваивает заданое значение видимости селектору
## Функция присваивает заданое значение видимости селектору.
func set_track_visible(value: bool): $track.visible = value
# Функция присваивает заданое значение видимости индикатору выполнения
## Функция присваивает заданое значение видимости индикатору выполнения.
func set_ecm_visible(value: bool): $ecm_done.visible = value
@@ -23,3 +23,7 @@ func _on_bip_gui_input(event):
if selected:
signaller.emit_signal('rto_threat_unsel', name.to_int())
func update():
$bip.material.set('shader_parameter/tick_update', float(Time.get_ticks_msec()/1000))

View File

@@ -6,9 +6,7 @@
[sub_resource type="ShaderMaterial" id="ShaderMaterial_2dulj"]
shader = ExtResource("2_rt0la")
shader_parameter/color = Color(0.972549, 0.12549, 0.411765, 1)
shader_parameter/color_up = Color(1, 1, 1, 1)
shader_parameter/tick_update = 0
shader_parameter/tick_update = 0.0
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_w5pye"]

View File

@@ -11,7 +11,7 @@ resource_local_to_scene = true
shader = ExtResource("2_5ngiq")
shader_parameter/rotation = 0.0
shader_parameter/color = Vector4(1, 1, 1, 0.1)
shader_parameter/width = 1.0
shader_parameter/width = 3.0
shader_parameter/speed = 0.0
shader_parameter/disabled = false
shader_parameter/scale = Vector2(1, 1)

View File

@@ -1,6 +1,6 @@
extends Sprite2D
class_name Diagram extends Sprite2D
var fs_default_colors: Array # Цвета по умолчанию для блоков ФС
var fs_default_colors: Array ## Цвета по умолчанию для блоков ФС.
func _ready() -> void:
signaller.connect('map_mode_changed', Callable(self, 'set_view_mode'))
@@ -23,14 +23,14 @@ func get_strob_width() -> float: return $строб.material.get('shader_par
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_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')
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')
func set_view_mode(val: int): material.set('shader_parameter/mode', val);
func set_band_colors(val: Array): material.set('shader_parameter/ant_band_c', val)
## Закрашивание по умолчанию блоков ФС цветами из настроек
## Закрашивание по умолчанию блоков ФС цветами из настроек.
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))

View File

@@ -1,7 +1,7 @@
extends NinePatchRect
class_name frm_ecm_list extends NinePatchRect
# Called when the node enters the scene tree for the first time.
## Called when the node enters the scene tree for the first time.
func _ready():
$grd_forced/btn_cancel.button_connect('pressed', Callable(self, 'on_btn_cancel_pressed').bind($grd_forced/btn_cancel))

View File

@@ -55,6 +55,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "Включает принудительную помеху"
strips_rotation = 15.0
text = "СРН"
metadata/rfi_name = "ozp1"
@@ -63,6 +64,7 @@ editor_description = "Кнопка для принудительного вкл
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 15.0
text = "СПРС"
metadata/rfi_name = "ozp1"
@@ -71,6 +73,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "Кнопка для принудительного включения группы секторов в режим КУПД"
strips_rotation = 15.0
text = "КУПД"
metadata/rfi_name = "ozp1"
@@ -78,5 +81,6 @@ metadata/rfi_name = "ozp1"
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 15.0
text = "Отключить все"
metadata/rfi_name = "<off>"

View File

@@ -84,7 +84,6 @@ func _ready():
interfer.connect('interfer_update', Callable(self, 'on_interfer_update').bind(table_index))
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
call_deferred('init_table')
#$btn_cancel.button_connect('pressed', Callable(self, 'on_btn_cancel_pressed').bind($btn_cancel))
func init_table():

View File

@@ -1,4 +1,4 @@
extends ScrollContainer
class_name scroll_ecm_params extends ScrollContainer
## Отображает список параметров помехи в таблице.
@@ -33,7 +33,7 @@ func init_table():
$table.set_meta('id', 0)
# Called when the node enters the scene tree for the first time.
## Called when the node enters the scene tree for the first time.
func _ready():
signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected'))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))

View File

@@ -1,6 +1,6 @@
extends ScrollContainer
class_name scroll_params extends ScrollContainer
## Отображение параметров цели
## Отображение параметров цели.
const CellLineEdit = preload('res://table/ячейка-2.tscn') ## Ячейка таблицы.
const TableHeader = preload('res://table/header.tscn') ## Ячейка заголовок таблицы.
@@ -23,7 +23,7 @@ const TABLE_PARAMS = {
'rkrp': [5, 'Рекомендуемая помеха'] }
## Обрабатывает сигнал [signal threats.threat_selected]
## Обрабатывает сигнал [signal threats.threat_selected].
func on_threat_selected(th):
$table.set_meta('id', th.id)
on_threat_update(th)

View File

@@ -1,4 +1,4 @@
extends ScrollContainer
class_name scroll_threats extends ScrollContainer
## Отображает список целей в таблице.
@@ -46,7 +46,7 @@ func _ready() -> void:
call_deferred('init_table')
## Перестраивает индекс таблицы. Вызывать при удалении строки
## Перестраивает индекс таблицы. Вызывать при удалении строки.
func rehash(table_index: Dictionary):
var rows_count = $table.get_rows_count()
for i_row in rows_count:
@@ -54,21 +54,21 @@ func rehash(table_index: Dictionary):
table_index[int(item.text)] = i_row
## Обрабатывает сигнал [b]threat_update[/b]
## Обрабатывает сигнал [b]threat_update[/b].
func on_threat_update(th, table_index: Dictionary):
var row = map_th_to_row(th)
var i_row = table_index[th.id]
$table.set_row_text(i_row, row)
## Обрабатывает сигнал [b]threat_lost[/b]
## Обрабатывает сигнал [b]threat_lost[/b].
func on_threat_lost(th, table_index: Dictionary):
$table.remove_row(table_index[th.id])
table_index.clear()
rehash(table_index)
## Обрабатывает сигнал [b]threat_new[/b]
## Обрабатывает сигнал [b]threat_new[/b].
func on_threat_new(th, table_index):
var i_row = $table.get_rows_count()
$table.add_row(TABLE_ROW)
@@ -79,7 +79,7 @@ func on_threat_new(th, table_index):
table_index[th.id] = i_row
## Преобразует цель в строку таблицы
## Преобразует цель в строку таблицы.
func map_th_to_row(th) -> Array:
var row: = Array()
row.resize(TABLE_COLUMN_PARAM.size())
@@ -90,7 +90,7 @@ func map_th_to_row(th) -> Array:
return row
## Выделяет выбранную цель в таблице
## Выделяет выбранную цель в таблице.
func on_rto_threat_sel(th_id, tbl):
for i in tbl.get_rows_count():
var node = tbl.get_node2(0, i)
@@ -99,6 +99,6 @@ func on_rto_threat_sel(th_id, tbl):
break
## Снимает выделение цели
## Снимает выделение цели.
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()

View File

@@ -1,4 +1,4 @@
extends "res://scenes/контроль/прибор.gd"
class_name pribor_rtr extends "res://scenes/контроль/прибор.gd"
static var json_parser: JSON = JSON.new()
@@ -101,7 +101,7 @@ func map_value_to_item(data, item, value_name: StringName):
## 1. Поле [b]'ErCode'[/b] содержит [b]0[/b] - если нет ошибки, и другое значение - если есть ошибка.[br]
## 2. Для каждого проверяемого параметра устройства есть своё поле [b]'ErCode'[/b].[br]
## 3. Индикатор исправности у устройства один.[br]
## 3. Есть только один индикатор исправности при отображении состояния устройства.[br]
## 4. [i]Нет результата порверки[/i] - поле [param state] принимает значение [b]0[/b], [i]всё
## исправно[/i] - [b]1[/b], [i]хотябы один[/i] параметр с ошибкой - [b]2[/b].[br]
func map_error_codes_to_item(data, item, value_name: StringName):
@@ -123,11 +123,11 @@ func map_error_codes_to_item(data, item, value_name: StringName):
item.set(value_name, test_res)
## Вызывается при клике мыши на элементе контроля
## [param block_a] - Кликнутый элемент контроля
## Вызывается при клике мыши на элементе контроля.
## [param block_a] - Кликнутый элемент контроля.
func _on_item_pressed(block_a: Control):
var metas = block_a.get_meta_list()
print_debug(block_a)
for n in metas:
var v = block_a.get_meta(n)
print('%s:%s' % [n, v])
print_debug('%s:%s' % [n, v])

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=10 format=3 uid="uid://3slb0i3pvowc"]
[gd_scene load_steps=11 format=3 uid="uid://3slb0i3pvowc"]
[ext_resource type="Script" 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"]
@@ -6,6 +6,7 @@
[ext_resource type="PackedScene" uid="uid://trt0q8th3bn2" path="res://scenes/журнал/журнал.tscn" id="4_cu5k8"]
[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="FontFile" uid="uid://clrxfflc1wrhj" path="res://data/main-font.tres" id="7_i7l8n"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_fe3e1"]
@@ -39,6 +40,10 @@ layout_mode = 2
visible = false
layout_mode = 2
[node name="ЭМС2" parent="tab_switch" instance=ExtResource("6_rsg03")]
visible = false
layout_mode = 2
[node name="Настройки" parent="tab_switch" instance=ExtResource("6_i8iv3")]
visible = false
layout_mode = 2

View File

@@ -1,173 +1,665 @@
extends Sprite2D
@tool
extends CanvasGroup
class_name MercatorTileMap
## Возможные состояния конечного автомата заданий
enum TASK_STATE {
DONE, ## Выполнено
WAIT, ## Ожидание плитки
RUN, ## Запуск выполнения
CHECK, ## Проверка пустого места
ERROR ## Ошибка
}
## Отображение карт WEB Mercator
#http://10.1.1.220/osm_tiles/0/0/0.png
#https://tile.openstreetmap.org/{z}/{x}/{y}.png
@export var base_url: String = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png':
set(v):
if base_url != v:
base_url = v
_clean_all()
queue_redraw()
@export var zoom_step: float = 0.025
@export var tile_width: float = 256.0
@export var tile_height: float = 256.0
@export_range(1, 1000, 1) var max_concurrent_requests:int = 5
@export_range(100, 100000, 1) var max_cached_tiles: int = 200
@export_range(0, 25, 1) var max_zoom_level: int = 19
@export_range(0, 25, 1) var min_zoom_level: int = 0
@export_color_no_alpha() var back_color: = Color.BLACK
@export var animation_time: float = 1.0
## Координаты для проверок [lng, lat]
const TEST_DATA: = {
'Калиниград': [ 20.51095, 54.70649 ],
'Москва': [ 37.6156, 55.7522 ],
'Нью-Йорк': [ -74.006, 40.7143 ],
'Сидней': [ 151.20732, -33.8678500 ],
'Таганрог': [ 38.8969, 47.2362 ],
'Хельсинки': [ 24.9354, 60.1695 ],
'Азорские о-ва': [ 28.3996582, 38.5397568 ],
'Мехико': [ -99.12766, 19.42847 ],
'Белое море': [ 68.136606, 42.045546 ],
'море Беллинсгаузена': [ -72.406587, -74.857997 ],
'Фиджи': [ 178.065032, -17.713371 ],
'Ноль': [ 0.0, 0.0 ],
'Точка1': [ 170.0, 0.0 ],
'Точка2': [-170.0, 0.0 ],
'Море' : [ 19.4, 54.91 ] }
@export var size: Vector2i = Vector2i(400, 400):
set(v):
$canvas.size = v
_on_resize()
queue_redraw()
get:
return $canvas.size
const MAP_MODES: = {
0: 'application/config/map_image_size_rto',
1: 'application/config/map_image_size_rls' }
@export var ax: float = 0.0:
set(v):
_xyz.x = v
queue_redraw()
get:
return _xyz.x
const MAP_RELATIVE_RADIUSES: = {
0: 0.39,
1: 0.466
}
@export var ay: float = 0.0:
set(v):
_xyz.y = v
queue_redraw()
get:
return _xyz.y
var map_image: Image ## Изображение с картой
var map_tile_state: TASK_STATE ## Текущее состояние конечного автомата плитки
var map_bcs: Vector3 ## Яркость, контраст насыщенность
var map_server_addr: String ## Адрес сервера изображений карт в проекции Меркатора
var map_tile_format: String ##
var map_tile_stack: Array ## Стек для хранения плиток карты
var map_request: HTTPRequest ## Обработчик запросов http
var map_zoom: int ## Уровень детализации карты
var map_tile: Rect2i ## Область одной плитки: [x-координата области, y-координата области, x-индекс плитки, y-индекс плитки]
var map_mode: int ## Режим карты: 0 - приоритет РТО, 1 - приоритет РЛС
var prev_tiles_dic: Dictionary ##
var lnglat: Array ## Текущие координаты
var root_rect: Rect2i
@export var az: float = 0.0:
set(v):
_xyz.z = v
queue_redraw()
get:
return _xyz.z
var _xyz: Vector3 = Vector3(0, 0, min_zoom_level)
var _cache: Dictionary = {}
var _queue: Dictionary = {}
var _dragging: bool = false
var _drag_pos: Vector2 = Vector2.ZERO
var _last_cache_check: float = 0
var _rollover: bool = false
var _marks: Dictionary = {}
var _req_count: = 0
var image: = Image.new()
var image_load_proc: Callable
var now: = 0
var spr_mask: = Sprite2D.new()
var visible_marks_count: = 0
var mouse_wheel_count: = 0
var map_server_available: = false
## Вызывается после того, как загрузка плиток завершена
signal load_completed()
## Вызывается при запуске загрузки плиток
signal load_started()
## Вызывается при получении ответа от сервера карт
signal map_server_online()
## Вызывается при отсутствии ответа от сервера карт
signal map_server_offline()
const image_load_proc_names = {
'png': 'load_png_from_buffer',
'jpg': 'load_jpg_from_buffer',
'tga': 'load_tga_from_buffer',
'webp': 'load_webp_from_buffer' }
@export_enum('png', 'jpg', 'jpeg', 'tga', 'webp') var image_type: String = 'png':
set(v): image_load_proc = Callable(image, image_load_proc_names[v])
func _ready():
lnglat = TEST_DATA['Таганрог']
map_tile_state = TASK_STATE.DONE
map_request = HTTPRequest.new()
add_child(map_request)
map_request.request_completed.connect(self._map_request_completed)
map_bcs = ProjectSettings.get_setting('application/config/map_bcs', Vector3(1.0, 1.0, 1.0))
map_server_addr = ProjectSettings.get_setting('application/config/map_server_addr')
map_tile_format = ProjectSettings.get_setting('application/config/map_tile_format', '%s/%d/%d/%d.png')
var map_image_size = ProjectSettings.get_setting(MAP_MODES[0], Vector2i(512, 512))
var map_tile_size = ProjectSettings.get_setting('application/config/map_tile_size', 256)
map_image = Image.create(map_image_size.x, map_image_size.y, true, Image.FORMAT_RGB8)
map_tile = Rect2i(0, 0, map_tile_size, map_tile_size)
signaller.connect('zoom_changed', Callable(self, '_on_zoom_changed'))
signaller.connect('map_mode_changed', Callable(self, '_on_map_mode_changed'))
log.info('Адрес сервера поставщика карт: \"%s\"' % map_server_addr)
log.info('Модуль географической карты готов')
$canvas.connect('mouse_entered', func(): _rollover = true)
$canvas.connect('mouse_exited', func(): _rollover = false)
_on_resize()
image_type = 'png'
spr_mask.name = StringName('spr_mask')
spr_mask.material = CanvasItemMaterial.new()
spr_mask.material.blend_mode = CanvasItemMaterial.BLEND_MODE_SUB
spr_mask.add_to_group('gui_items')
$canvas.add_child(spr_mask)
func _on_map_mode_changed(mode: int) -> void:
var map_image_size = ProjectSettings.get_setting(MAP_MODES[mode])
material.set('shader_parameter/radius', MAP_RELATIVE_RADIUSES[mode])
map_image.fill(Color(0, 0, 0, 0))
map_image.resize(map_image_size.x, map_image_size.y)
map_tile_state = TASK_STATE.DONE
map_mode = mode
var tile: = mercator.create_tile(lnglat[0], lnglat[1], map_zoom)
map_tile_stack.clear()
map_tile_stack.append(tile)
prev_tiles_dic.clear()
func _on_resize() -> void:
var img_mask: = Image.create($canvas.size.x, $canvas.size.y, false, Image.FORMAT_RGBA8)
var c = $canvas.size / 2.0
var r = min($canvas.size.x, $canvas.size.y) / 2.0
var color = Color.WHITE
var sz = img_mask.get_size()
for x in sz.x:
for y in sz.y:
var dist = c.distance_to(Vector2(x, y))
color.a = smoothstep(r - 2.0, r + 2.0, dist)
img_mask.set_pixel(x, y, color)
spr_mask.texture = ImageTexture.create_from_image(img_mask)
spr_mask.position = $canvas.position + $canvas.size / 2.0
func mark_image_center(image: Image, color: Color = Color.RED):
var c = image.get_size() / 2
map_image.set_pixel(c.x - 1, c.y - 1, color)
map_image.set_pixel(c.x - 1, c.y, color)
map_image.set_pixel(c.x, c.y - 1, color)
map_image.set_pixel(c.x, c.y, color)
## Создаёт новую отметку из координат экрана
func add_mark_from_screen_pos(id: int, x: float, y: float, mark: Node):
if _marks.has(id):
return false
var wrld_pos = screen_to_world(_xyz, x, y)
var p = world_to_tile(wrld_pos.x, wrld_pos.y, _xyz.z)
var tile_index = xyz_to_idx(p.x, p.y, _xyz.z)
var dot = { 'position': wrld_pos, 'tile_index': tile_index, 'mark': mark }
_marks[id] = dot
add_child(mark)
fix_mark_position(dot)
return true
func _on_zoom_changed(zoom: int):
if map_tile_stack.size() != 0:
func get_marks_count(): return _marks.size()
func delete_mark(id: int):
if not _marks.has(id):
return false
_marks[id].mark.queue_free()
_marks.erase(id)
queue_redraw()
## Создаёт новую отметку из долготы и широты
func add_mark_from_lon_lat(id: int, lon: float, lat: float, mark: Node, gap_size: float = 32):
if _marks.has(id):
return false
var wrld_pos = lonlat_to_world(lon, lat)
var scr_pos = world_to_screen(wrld_pos.x, wrld_pos.y)
mark.set_global_position(scr_pos)
_marks[id] = {'position': wrld_pos, 'mark': mark, 'gap_size': gap_size }
add_child(mark)
queue_redraw()
return true
## Возвращает новую позицию для точки, если она выходит из поля видимости
func fix_mark_position(dot):
if is_mark_visible(dot):
return
map_zoom = zoom
var tile: = mercator.create_tile(lnglat[0], lnglat[1], zoom)
map_tile_stack.clear()
map_tile_stack.append(tile)
prev_tiles_dic.clear()
var v = 2 * tile_width * pow(2, _xyz.z)
if dot.position.x < _xyz.x - $canvas.size.x / v:
dot.position.x = _xyz.x - $canvas.size.x / v
elif dot.position.x > _xyz.x + $canvas.size.x / v:
dot.position.x = _xyz.x + $canvas.size.x / v
func img_tile_to_map_image(image: Image, dst_pos: Vector2i):
image.adjust_bcs(map_bcs.x, map_bcs.y, map_bcs.z)
map_image.blit_rect(image, map_tile, dst_pos)
func is_mark_visible(dot):
var screen_pos = world_to_screen(dot.position.x, dot.position.y)
return screen_pos.x > 0 and screen_pos.x < $canvas.size.x
func _process(_delta: float):
if (map_tile_state == TASK_STATE.DONE) and map_tile_stack.size():
var tile: mercator.Tile = map_tile_stack[-1]
var tile_addr: = map_tile_format % [map_server_addr, tile.z, tile.x , tile.y]
var rc = map_request.request(tile_addr)
if rc == OK:
map_tile_state = TASK_STATE.WAIT
func _input(e):
var lmp = get_local_mouse_position()
if not _rollover:
return
if e is InputEventMouseButton:
if e.pressed:
if e.button_index == MOUSE_BUTTON_WHEEL_DOWN:
mouse_wheel_count -= 1
queue_redraw()
elif e.button_index == MOUSE_BUTTON_WHEEL_UP:
mouse_wheel_count += 1
queue_redraw()
if e.button_index == MOUSE_BUTTON_LEFT:
_dragging = e.pressed
_drag_pos = screen_to_world(_xyz, lmp.x, lmp.y)
elif e is InputEventMouseMotion:
if _dragging:
var wp = screen_to_world(_xyz, lmp.x, lmp.y)
var diff = _drag_pos - wp
_xyz.x += diff.x
_xyz.y += diff.y
queue_redraw()
## Возвращает true, если видна область за краем карты
func is_border_visible():
var z = min(max_zoom_level, _xyz.z)
return screen_to_tile(0, 0, z).y != 0
func multiply_zoom(multiplier: float, pivot: Vector2):
var p1: = screen_to_world(_xyz, pivot.x, pivot.y)
_xyz.z = clampf(_xyz.z * multiplier, min_zoom_level, max_zoom_level)
var p2: = screen_to_world(_xyz, pivot.x, pivot.y)
_xyz.x -= p2.x - p1.x
_xyz.y -= p2.y - p1.y
func set_zoom(zoom: float, pivot=null):
if pivot == null:
pivot = $canvas.size / 2.0
var p1: = screen_to_world(_xyz, pivot.x, pivot.y)
_xyz.z = clampf(zoom, max_zoom_level, min_zoom_level)
var p2: = screen_to_world(_xyz, pivot.x, pivot.y)
_xyz.x -= p2.x - p1.x
_xyz.y -= p2.y - p1.y
func _draw():
var lmp = get_local_mouse_position()
if mouse_wheel_count > 0:
multiply_zoom(1.0 + zoom_step, lmp)
mouse_wheel_count -= 1
elif mouse_wheel_count < 0:
multiply_zoom(1.0 - zoom_step, lmp)
mouse_wheel_count += 1
var z = min(max_zoom_level, _xyz.z)
var t1 = screen_to_tile(0, 0, z)
var t2 = screen_to_tile($canvas.size.x, $canvas.size.y, z)
for tx in range(t1.x, t2.x + 1):
for ty in range(t1.y, t2.y + 1):
_draw_tile(tx, ty, z)
var n = pow(2, z)
var dx = n * tile_width
var c = $canvas.size / 2.0
var r = min($canvas.size.x, $canvas.size.y) / 2.0
visible_marks_count = 0
for dot in _marks.values():
var pos = world_to_screen(dot.position.x, dot.position.y)
if pos.x >= 0:
pos.x = fmod(pos.x, dx)
else:
log.error('%s: Невозможно сформировать запрос HTTP' % self)
map_tile_state = TASK_STATE.ERROR
elif map_tile_state == TASK_STATE.CHECK:
var root_tile: = mercator.Tile.new(root_rect.size.x, root_rect.size.y, map_zoom)
var neighbors_tiles = mercator.get_perimetr_tiles(root_tile, (map_image.get_size().x / map_tile.size.x) / 2)
var neighbors_tiles_dic = {}
for tile in neighbors_tiles:
neighbors_tiles_dic[[tile.x, tile.y]] = false
if neighbors_tiles_dic != prev_tiles_dic:
for tile in neighbors_tiles:
tile.is_root = false
map_tile_stack.push_front(tile)
prev_tiles_dic[[tile.x, tile.y]] = false
else:
if map_tile_stack.size() == 0:
signaller.emit_signal('zoom_complete', map_zoom)
map_tile_state = TASK_STATE.DONE
pos.x = -pos.x - 1
pos.x = int(dx - 1) - fmod(pos.x, dx)
dot.mark.position = pos
dot.mark.visible = c.distance_to(pos) < (r - dot.gap_size)
visible_marks_count += int(dot.mark.visible)
func _map_request_completed(result, response_code, headers, data):
func _clean_all():
_queue.clear()
_cache.clear()
_marks.clear()
_req_count = 0
for c in get_children().filter(func (item): return not item.is_in_group('gui_items')):
remove_child(c)
c.queue_free()
# get the tile from queue with the newest timestamp
func get_next_in_queue():
var tile = null
for idx in _queue:
var t = _queue.get(idx)
if not tile or t.t > tile.t:
tile = t
return tile
# delete oldest tiles from cache
func _clean_cache():
var overflow = _cache.size() - max_cached_tiles
if overflow <= 0:
return
var vals = _cache.values()
vals.sort_custom(func(t1, t2): return t1.t < t2.t)
for i in overflow:
_cache.erase(vals[i].i)
func _process(delta):
now += delta
# if cache is overflowing - clean it
if not _last_cache_check or now - _last_cache_check > 5:
_last_cache_check = now
_clean_cache()
while not _queue.is_empty() and (_req_count < max_concurrent_requests):
var tile = get_next_in_queue()
if not tile:
break
var req = HTTPRequest.new()
_req_count += 1
req.set_meta('tile', tile)
add_child(req)
req.name = NodePath(str(tile.i))
_queue.erase(tile.i)
req.request_completed.connect(_response.bind(req, tile))
if req.request(tile.url) != OK:
tile.t = now
remove_child(req)
req.queue_free()
_req_count -= 1
push_error('ошибка: запрос плитки \"%s\" не отправлен' % tile.url)
if _queue.is_empty():
emit_signal('load_completed')
# result, response_code, headers, body
func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: Tile):
_req_count -= 1
remove_child(req)
req.queue_free()
if result != HTTPRequest.RESULT_SUCCESS:
log.error('%s: Запрос не обработан. result: \"%s\", response_code: \"%s\", headers: \"%s\"' % [self, result, response_code, headers])
map_tile_state = TASK_STATE.ERROR
if map_server_available:
map_server_available = false
emit_signal('map_server_offline')
_queue[tile.i] = tile
return
var img_tile = Image.new()
var error = img_tile.load_png_from_buffer(data)
if error != OK:
log.error('%s: Полученые данные невозможно использовать для формироания изображения. result: \"%s\", response_code: \"%s\", headers: \"%s\"' % [self, result, response_code, headers])
map_tile_state = TASK_STATE.ERROR
if not map_server_available:
map_server_available = true
emit_signal('map_server_online')
if code == 404:
push_error('ошибка: на сервере нет \"%s\"' % tile.url)
return
var tile = map_tile_stack.pop_back()
map_tile_state = TASK_STATE.CHECK
if Error.OK != image_load_proc.call(body):
push_error('ошибка: не удалось получить изображение (неверный формат?) из \"%s\"' % tile.url)
return
if tile.is_root:
# Отображение корневой плитки
map_image.fill(Color(0, 0, 0, 0))
var bounds: = mercator.bounds(tile)
var lng_c = (bounds.east + bounds.west) / 2.0
var lat_c = (bounds.north + bounds.south) / 2.0
var sx: float = float(map_tile.size.x) / (bounds.east - bounds.west) * (lng_c - tile.lng) + map_tile.size.x / 2.0 # Cмещение в пискселях центра плитки от заданной точки по горизонтали.
var sy: float = float(map_tile.size.y) / (bounds.north - bounds.south) * (lat_c - tile.lat) - map_tile.size.y / 2.0 # Cмещение в пискселях центра плитки от заданной точки по вертикали.
var dst_pos: Vector2i = Vector2i(int(sx), int(-sy)) + map_tile.size * map_mode
img_tile_to_map_image(img_tile, dst_pos)
root_rect = Rect2i(dst_pos.x, dst_pos.y, tile.x, tile.y)
# create texture from image and add it to the cache
tile.texture = ImageTexture.create_from_image(image)
_cache[tile.i] = tile
# redraw the map
queue_redraw()
func _draw_subtile(tx: int, ty: int, tz: int, origx: int, origy: int, origz: float) -> bool:
var subtile = get_tile(tx, ty, tz)
if not subtile:
return false
var p1 = tile_to_screen(origx, origy, origz)
var p2 = tile_to_screen(origx + 1, origy + 1, origz)
var x1 = tile_to_screen(tx, ty, tz)
var x2 = tile_to_screen(tx + 1, ty + 1, tz)
var xdiff = x2.x - x1.x
var xrat1 = (p1.x - x1.x) / xdiff
var xrat2 = (p2.x - x1.x) / xdiff
var xwidth = xrat2 - xrat1
var ydiff = x2.y - x1.y
var yrat1 = (p1.y - x1.y) / ydiff
var yrat2 = (p2.y - x1.y) / ydiff
var yheight = yrat2 - yrat1
var rect = Rect2(xrat1 * tile_width, yrat1 * tile_height, xwidth * tile_width, yheight * tile_height)
if subtile.texture:
draw_texture_rect_region(subtile.texture, Rect2(p1, p2 - p1), rect)
return true
return false
func _draw_tile(tx: int, ty: int, z: float):
var tz = floor(z)
var p1 = tile_to_screen(tx, ty, z)
var p2 = tile_to_screen(tx + 1, ty + 1, z)
var tile = get_tile(tx, ty, tz)
if tile:
if tile.texture:
draw_texture_rect(tile.texture, Rect2(p1, p2 - p1), false, Color.WHITE, false)
else:
var zzz = tz
var txx = tx
var tyy = ty
while zzz > 1:
zzz -= 1
txx = floor(txx / 2.0)
tyy = floor(tyy / 2.0)
if _draw_subtile(txx, tyy, zzz, tx, ty,z):
break
## convert lon/lat to world coords
func lonlat_to_world(lon: float, lat: float) -> Vector2:
var x = lon / 180.0
var latsin = sin(deg_to_rad(lat) * sign(lat))
var y = (sign(lat) * (log((1.0 + latsin) / (1.0 - latsin)) / 2.0)) / PI
return Vector2(x, y)
## convert lon/lat to screen coords
func lonlat_to_screen(lon: float, lat: float) -> Vector2:
var w = lonlat_to_world(lon, lat)
return world_to_screen(w.x, w.y)
## convert lon/lat to tile coords
func lonlat_to_tile(lon: float, lat: float, z: float) -> Vector2:
var w = lonlat_to_world(lon,lat)
return world_to_tile(w.x, w.y, z)
## convert world coords to lon/lat
func world_to_lonlat(wx: float, wy: float) -> Vector2:
var lon = wx * 180.0
var lat = rad_to_deg(atan(sinh(wy * PI)))
return Vector2(lon, lat)
## convert screen coords to lon/lat
func screen_to_lonlat(sx: float, sy: float) -> Vector2:
var w = screen_to_world(_xyz, sx, sy)
return world_to_lonlat(w.x, w.y)
## convert tile coords to lon/lat
func tile_to_lonlat(tx: float, ty: float, tz: float) -> Vector2:
var w = tile_to_world(tx, ty, tz)
return world_to_lonlat(w.x, w.y)
## convert screen coords to world coords
func screen_to_world(xyz: Vector3, sx: float, sy: float) -> Vector2:
var n = pow(2.0, xyz.z)
var span_w = n * tile_width
var span_h = n * tile_height
var px = sx - $canvas.size.x / 2 + span_w / 2
var py = sy - $canvas.size.y / 2 + span_h / 2
var xr = px / span_w
var yr = py / span_h
var x = (xr * 2.0 - 1.0) + xyz.x
var y = ((-yr * 2.0) + 1.0) + xyz.y
return Vector2(x, y)
## convert screen coords to tile coords
func screen_to_tile(sx: float, sy: float, z: float) -> Vector2:
var world = screen_to_world(_xyz, sx, sy)
return world_to_tile(world.x, world.y, z)
## convert tile coords to screen coords
func tile_to_screen(tx: float, ty: float, tz: float) -> Vector2:
var w = tile_to_world(tx, ty, tz)
return world_to_screen(w.x, w.y)
## convert tile coords to world coords
func tile_to_world(tx: float, ty: float, tz: float) -> Vector2:
var n = pow(2.0, floor(tz))
var x = (tx / n) * 2.0 - 1.0
var y = -((ty / n) * 2.0 - 1.0)
return Vector2(x, y)
## convert world coords to tile coords
func world_to_tile(wx: float, wy: float, z: float) -> Vector2:
var n: = pow(2.0, floor(z))
var tx: = ((wx + 1.0) / 2.0) * n
var ty: = ((-wy + 1.0) / 2.0) * n
tx = floor(tx)
ty = floor(ty)
return Vector2(tx, ty)
## convert world coords to screen coords
func world_to_screen(wx: float, wy: float) -> Vector2:
var n: = pow(2.0, _xyz.z)
var w: = n * tile_width
var h: = n * tile_height
var xr: = ((wx - _xyz.x) + 1.0) / 2.0
var yr: = (-(wy - _xyz.y) + 1.0) / 2.0
var x = w * xr - w / 2.0 + $canvas.size.x / 2.0
var y = h * yr - h / 2.0 + $canvas.size.y / 2.0
return Vector2(x, y)
## get the tile index from xyz tile coords
func xyz_to_idx(x: float, y: float, z: float) -> int:
var i: = (pow(4.0, z) - 1.0) / 3.0
var n: = pow(2.0, z)
return int(i + (y * n + x))
func get_tile(x: int, y: int, z: int, create: bool = true) -> Tile:
var n = pow(2, z)
if x >= 0:
x %= int(n)
else:
# Отображение соседних плиток
var delta: = Vector2i(tile.x - root_rect.size.x, tile.y - root_rect.size.y)
var dst_pos: Vector2i = root_rect.position + delta * map_tile.size
img_tile_to_map_image(img_tile, dst_pos)
mark_image_center(map_image)
texture = ImageTexture.create_from_image(map_image)
x = -x - 1
x = int(n - 1) - (x % int(n))
# out of bounds
if z < 0 or y < 0 or y >= n:
return null
# get tile index
var idx = xyz_to_idx(x, y, z)
var tile = null
# retrieve from current requests...
var req = get_node_or_null(NodePath(str(idx)))
if req:
tile = req.get_meta('tile')
tile.t = now
return tile
# retrieve from cache
tile = _cache.get(idx)
if tile:
tile.t = now
return tile
# retrieve from queue
tile = _queue.get(idx)
if tile:
tile.t = now
return tile
# create a new tile - add it to queue
var queue_size: = _queue.size()
if create and (not $canvas/player.is_playing()):
tile = Tile.new(idx, x, y, z)
tile.url = base_url.replace('{x}', str(x)).replace('{y}', str(y)).replace('{z}', str(z))
tile.t = now
_queue[idx] = tile
if queue_size == 0 and _queue.size():
emit_signal('load_started')
return tile
func lonlat_to_dms(lon: float, lat: float) -> String:
var pf = 'N' if lat >= 0 else 'S'
lat = abs(lat)
var deg = floor(lat)
var minute = (lat - deg) * 60
var second = (minute - floor(minute)) * 60
var text = ('%02d' % deg) + ('%02d' % floor(minute)) + ('%02d' % floor(second)) + pf + ' '
pf = 'E' if lon >= 0 else 'W'
lon = abs(lon)
deg = floor(lon)
minute = (lon - deg) * 60
second = (minute - floor(minute)) * 60
text += ('%02d' % deg) + ('%02d' % floor(minute)) + ('%02d' % floor(second)) + pf
return text
class Tile:
var i: int = 0
var x: int = 0
var y: int = 0
var z: int = 0
var t: int = 0
var url: String = ''
var texture: Texture2D = null
func _init(i0: int, x0: int, y0: int, z0: int):
self.i = i0
self.x = x0
self.y = y0
self.z = z0
func haversine_m(lat1, lon1, lat2, lon2):
# Радиус Земли в метрах
var R: = 6372795.0
# Преобразование градусов в радианы
var rlat1: = deg_to_rad(lat1)
var rlon1: = deg_to_rad(lon1)
var rlat2: = deg_to_rad(lat2)
var rlon2: = deg_to_rad(lon2)
var cl1: = cos(rlat1)
var cl2: = cos(rlat2)
var sl1: = sin(rlat1)
var sl2: = sin(rlat2)
var delta: = rlon2 - rlon1
var cdelta: = cos(delta)
var sdelta: = sin(delta)
# вычисления длины большого круга
var y: = sqrt(pow(cl2 * sdelta, 2) + pow(cl1 * sl2 - sl1 * cl2 * cdelta, 2))
var x: = sl1 * sl2 + cl1 * cl2 * cdelta
var ad: = atan2(y, x)
var dist: = ad * R
return dist
func remove_closest_dot(screen_pos):
var closest_dot = find_at_screen_position(screen_pos)
if not closest_dot:
return
remove_child(closest_dot.mark)
closest_dot.mark.queue_free()
_marks.erase(closest_dot)
func find_at_screen_position(screen_pos: Vector2):
var closest_dot = null
var closest_distance = INF
for mark in _marks.values():
var dot_screen_pos = world_to_screen(mark.position.x, mark.position.y)
var distance = dot_screen_pos.distance_to(screen_pos)
if distance < closest_distance:
closest_distance = distance
closest_dot = mark
return closest_dot
func clear() -> void:
_clean_all()
queue_redraw()
func set_coordinates(lon: float, lat: float):
var anim: Animation = $canvas/player.get_animation('goto')
var wrld_pos = lonlat_to_world(lon, lat)
anim.track_insert_key(0, 0, _xyz.x)
anim.track_insert_key(1, 0, _xyz.y)
anim.track_insert_key(0, animation_time, wrld_pos.x)
anim.track_insert_key(1, animation_time, wrld_pos.y)
anim.length = animation_time
$canvas/player.play('goto')
func blend_mask(val: bool) -> void:
spr_mask.visible = val
queue_redraw()

View File

@@ -1,14 +1,27 @@
[gd_scene load_steps=4 format=3 uid="uid://bbq6nklh36yij"]
[gd_scene load_steps=3 format=3 uid="uid://ceknxxfu1loo5"]
[ext_resource type="Script" path="res://scenes/tilemap/tilemap.gd" id="1_mkfgj"]
[ext_resource type="Shader" path="res://shaders/tilemap.gdshader" id="1_tsdui"]
[ext_resource type="Script" path="res://scenes/tilemap/tilemap.gd" id="1_l64tp"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_pmqvj"]
resource_local_to_scene = true
shader = ExtResource("1_tsdui")
shader_parameter/radius = 0.39
[sub_resource type="CanvasTexture" id="CanvasTexture_58cl1"]
[node name="tilemap" type="Sprite2D"]
material = SubResource("ShaderMaterial_pmqvj")
position = Vector2(560, 560)
script = ExtResource("1_mkfgj")
[node name="tilemap" type="CanvasGroup" groups=["gui_items"]]
script = ExtResource("1_l64tp")
max_zoom_level = 21
az = 2.0
[node name="canvas" type="TextureRect" parent="." groups=["gui_items"]]
clip_contents = true
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = 400.0
offset_bottom = 400.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = SubResource("CanvasTexture_58cl1")
[node name="player" type="AnimationPlayer" parent="canvas" groups=["gui_items"]]
[connection signal="resized" from="canvas" to="." method="_on_resize"]

View File

@@ -1,7 +1,7 @@
extends Panel
class_name setting extends Panel
# Called when the node enters the scene tree for the first time.
## Вызывается, когда узел впервые попадает в дерево сцены.
func _ready() -> void:
$lbl_commit.text = 'Текущая версия ПО УАРЭП: \"%s\"' % commit.VCS_HEAD
if not OS.get_cmdline_args().has('++ограниченный'):

View File

@@ -244,9 +244,9 @@ text = "Управление элементами в режиме с огран
[node name="Label2" type="Label" parent="."]
layout_mode = 0
offset_left = 16.0
offset_left = 20.0
offset_top = 20.0
offset_right = 476.0
offset_right = 445.0
offset_bottom = 50.0
text = "Текущий режим доступа: полный"
vertical_alignment = 1
@@ -295,13 +295,13 @@ text = "Кнопка «Подавление».
layout_mode = 2
size_flags_horizontal = 6
size_flags_vertical = 6
button_pressed = true
disabled = true
[node name="lbl_commit" type="Label" parent="."]
layout_mode = 0
offset_left = 480.0
offset_left = 500.0
offset_top = 20.0
offset_right = 1040.0
offset_right = 1060.0
offset_bottom = 50.0
text = "Текущая версия ПО УАРЭП:"
vertical_alignment = 1

View File

@@ -1,43 +1,44 @@
@tool
extends Panel
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 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 до количества созданных окон
@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 btn_select: BtnSel = BtnSel.THREAT ## Текущее состояние кнопки выбора цели
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 drag_button: MouseButton ## Кнопка мыши нажатая при перетаскивании.
var drag_fsm: DragFSM = DragFSM.IDLE ## Текущее состояние перетаскивания.
var btn_select: BtnSel = BtnSel.THREAT ## Текущее состояние кнопки выбора цели.
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 ## Вызывается в момент завершения перетаскивания
signal drag_begin ## Вызывается в момент начала перетаскивания.
signal drag_continue ## Вызывается во время продолжения перетаскивания.
signal drag_end ## Вызывается в момент завершения перетаскивания.
## Границы секторов блоков ФС по частоте в режиме РТО
## Границы секторов блоков ФС по частоте в режиме РТО.
const fs_band_rto: Dictionary = {
0: [200.0, 250.0],
1: [250.0, 300.0],
@@ -47,7 +48,7 @@ const fs_band_rto: Dictionary = {
5: [450.0, 500.0],
6: [500.0, 550.0] }
## Границы секторов блоков ФС по частоте в режиме РЛС
## Границы секторов блоков ФС по частоте в режиме РЛС.
const fs_band_rls: Dictionary = {
0: [480.0, 490.0],
1: [490.0, 500.0],
@@ -57,7 +58,7 @@ const fs_band_rls: Dictionary = {
5: [530.0, 540.0],
6: [540.0, 550.0] }
## Границы секторов блоков ФС по пеленгу
## Границы секторов блоков ФС по пеленгу.
const fs_sectors: Dictionary = {
0: [0.0, 90.0],
3: [90.0, 180.0],
@@ -73,42 +74,52 @@ const fs_freq: Dictionary = {
5: [4400.0, 5200.0],
6: [5200.0, 6000.0] }
var fs_band = fs_band_rto # Текущий режим блоков ФС по частоте
var fs_selected: Dictionary # Словарь выбранных секторов
var fs_active: Dictionary # Словарь секторов назначенных на подавление
## Состояние перетаскивания
## Размеры карты для разных режимов РТО и РЛС соответственно
const map_sizes = [
Rect2i(360, 360, 400, 400),
Rect2i(82, 82, 955, 955)]
var fs_band = fs_band_rto ## Текущий режим блоков ФС по частоте
var fs_selected: Dictionary ## Словарь выбранных секторов
var fs_active: Dictionary ## Словарь секторов назначенных на подавление
## Состояние перетаскивания.
enum DragFSM {
DRAG, ## В процессе
IDLE, ## Не активно, ожидание
OFF ## Выключено
DRAG, ## В процессе.
IDLE, ## Не активно, ожидание.
OFF ## Выключено.
}
## Состояние перетаскивания
## Состояние перетаскивания.
enum BtnSel {
SECTOR, ## В процессе
THREAT, ## Не активно, ожидание
FS ## Выключено
SECTOR, ## В процессе.
THREAT, ## Не активно, ожидание.
FS ## Выключено.
}
## Обработчик сигнала изменения списка целей
## Обработчик сигнала изменения списка целей.
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)
## Обработчик нажатия на кнопку вид
## Встроенный обратный вызов.
func on_enter_tree() -> void: call_deferred('on_button_strobe_pressed')
## Обработчик нажатия на кнопку вид.
func on_button_view_toggled(toggled: bool):
signaller.emit_signal('map_mode_changed', int(toggled))
if toggled:
fs_band = fs_band_rls
else:
fs_band = fs_band_rto
fs_band = fs_band_rls if toggled else fs_band_rto
var s = map_sizes[int(toggled)]
$tilemap.size = s.size
$tilemap.position = s.position
##
## Встроенный обратный вызов.
func _enter_tree() -> void:
var timer1 = Timer.new()
timer1.name = 'timer1'
@@ -118,18 +129,18 @@ func _enter_tree() -> void:
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)
drag_fsm = DragFSM.OFF
$btn_zoom.set_meta('zoom', min_zoom - 1)
var btns_select: Array = $btns_select.get_children()
btns_select.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_select').bind(btn, btns_select)))
$btn_view.button_connect('toggled', Callable(self, 'on_button_view_toggled'))
@@ -139,7 +150,6 @@ func _ready():
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('bip_pressed', Callable(self, 'on_bip_pressed').bind(nodes))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel').bind(nodes))
@@ -151,13 +161,15 @@ func _ready():
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 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):
bip.position = tools.pos_calc(
th.freq,
@@ -169,13 +181,14 @@ func map_threat_to_bip(th: threats.Threat, bip: Control):
freq_high) - bip.size / 2
## Обработчик сигнала обновления цели
## Обработчик сигнала обновления цели.
func on_threat_update(th):
var bip = get_node('%d' % th.id)
bip.update()
map_threat_to_bip(th, bip)
## Обработчик выбора помехи для цели
## Обработчик выбора помехи для цели.
func on_interfer_new(ecm):
if interfer.thrs.has(ecm.ispp):
if interfer.thrs.has(ecm.ispp):
@@ -192,7 +205,7 @@ func on_interfer_new(ecm):
set_fs_color(ecm)
## Обработчик выключения всех помех
## Обработчик выключения всех помех.
func on_interfer_off_all():
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for bip in bips:
@@ -202,7 +215,7 @@ func on_interfer_off_all():
update_fs_colors()
## Обработчик сигнала обнаружения цели
## Обработчик сигнала обнаружения цели.
func on_threat_new(th) -> void:
var bip = Bip.instantiate()
bip.name = '%d' % th.id
@@ -210,20 +223,20 @@ func on_threat_new(th) -> void:
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, _ecm_btns):
if btn_select == BtnSel.THREAT:
signaller.emit_signal('rto_threat_sel', th_id)
## Обработчик выбора РТО цели
## Обработчик выбора РТО цели.
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:
@@ -236,7 +249,7 @@ func on_rto_threat_sel(th_id, ecm_btns):
set_btns_disabled(false, btn)
## Обработчик снятия выбора РТО цели
## Обработчик снятия выбора РТО цели.
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:
@@ -246,13 +259,13 @@ func on_rto_threat_unsel(th_id, _ecm_btns):
set_ecm_btns_state(true)
## Обработчик нажатия кнопки "Строб". Управляет отображением строба
## Обработчик нажатия кнопки "Строб". Управляет отображением строба.
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)
## Поведение радиокнопок в группе. Управляет состоянием кнопок выбора целей
## Поведение радиокнопок в группе. Управляет состоянием кнопок выбора целей.
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')
@@ -262,7 +275,7 @@ func on_button_select(btn_this, btn_others) -> void:
set_ecm_btns_state(true)
## Поведение радиокнопок в группе. Управляет состоянием кнопок в радиогруппе
## Поведение радиокнопок в группе. Управляет состоянием кнопок в радиогруппе.
func on_button_pressed(btn_this, btn_others) -> void:
var fs_arr: Array = []
for btn_other in btn_others: btn_other.set_pressed(btn_this == btn_other)
@@ -271,7 +284,7 @@ func on_button_pressed(btn_this, btn_others) -> void:
signaller.emit_signal('interfer_init', btn_this, fs_arr)
## Управляет состоянием кнопок в радиогруппе при выборе помехи
## Управляет состоянием кнопок в радиогруппе при выборе помехи.
func on_interfer_selected(ecm, btns) -> void:
var ecm_name: String
if ecm != null:
@@ -287,21 +300,21 @@ func on_interfer_selected(ecm, btns) -> void:
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():
@@ -309,7 +322,7 @@ func set_strob(pos: Vector2) -> void:
$canvas.set_strob_radius(radp.y)
## Обработка движения мыши для управления стробом. Вызывается во время движения мыши
## Обработка движения мыши для управления стробом. Вызывается во время движения мыши.
func _on_drag_continue(event) -> void:
if drag_button == MOUSE_BUTTON_RIGHT:
if shift_pressed:
@@ -322,7 +335,7 @@ func _on_drag_continue(event) -> void:
set_strob(event.position)
## Обработка движения мыши для управления стробом. Вызывается при нажатии мыши
## Обработка движения мыши для управления стробом. Вызывается при нажатии мыши.
func _on_drag_begin(event) -> void:
drag_pos_begin = event.position
if drag_button == MOUSE_BUTTON_LEFT:
@@ -332,7 +345,7 @@ func _on_drag_begin(event) -> void:
strob_band_begin = $canvas.get_strob_band()
## Обработчик событий ввода. Вызывается godot
## Обработчик событий ввода. Вызывается godot.
func _input(event) -> void:
if not is_visible_in_tree(): return
if event is InputEventMouseMotion:
@@ -355,21 +368,7 @@ func _input(event) -> void:
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)
# Обработчик нажатия по сектору формирователя сигналов
## Обработчик нажатия по сектору формирователя сигналов.
func sel_fs_sector(event):
if (event.button_index == MOUSE_BUTTON_LEFT) or (event.button_index == MOUSE_BUTTON_RIGHT):
var center: Vector2 = $tilemap.position

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=14 format=3 uid="uid://b276iygic5itk"]
[gd_scene load_steps=12 format=3 uid="uid://b276iygic5itk"]
[ext_resource type="Script" path="res://scenes/работа/работа.gd" id="1_niok4"]
[ext_resource type="PackedScene" uid="uid://nl1vklubr5kr" path="res://scenes/bip/bip.tscn" id="2_br3s6"]
@@ -7,16 +7,11 @@
[ext_resource type="PackedScene" uid="uid://dymo732qc2doa" path="res://scenes/count-all/count-all-pad.tscn" id="6_e3re7"]
[ext_resource type="PackedScene" uid="uid://bwti82byphl68" path="res://scenes/count-danger/count_danger_pad.tscn" id="7_2arls"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button-flat/button-flat.tscn" id="8_k0iv2"]
[ext_resource type="PackedScene" uid="uid://0uqi1ghf7sma" path="res://scenes/button-scale/btn-scale.tscn" id="9_oey3x"]
[ext_resource type="PackedScene" uid="uid://bbq6nklh36yij" path="res://scenes/tilemap/tilemap.tscn" id="10_gtwyg"]
[ext_resource type="PackedScene" uid="uid://ceknxxfu1loo5" path="res://scenes/tilemap/tilemap.tscn" id="10_gtwyg"]
[ext_resource type="PackedScene" uid="uid://b5kjdyxuwsot5" path="res://scenes/diagram/diagram.tscn" id="11_b6su4"]
[ext_resource type="Shader" path="res://shaders/tilemap.gdshader" id="11_ekapd"]
[ext_resource type="Script" path="res://scenes/работа/sld-mode.gd" id="12_gqdkl"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_4p7y1"]
resource_local_to_scene = true
shader = ExtResource("11_ekapd")
shader_parameter/radius = 0.39
[sub_resource type="ImageTexture" id="ImageTexture_cnmvt"]
[node name="Работа" type="Panel"]
script = ExtResource("1_niok4")
@@ -39,7 +34,8 @@ metadata/_edit_vertical_guides_ = []
[node name="canvas" parent="." instance=ExtResource("11_b6su4")]
[node name="tilemap" parent="." instance=ExtResource("10_gtwyg")]
material = SubResource("ShaderMaterial_4p7y1")
self_modulate = Color(1, 1, 1, 0.415686)
position = Vector2(360, 360)
[node name="grd_side" parent="." instance=ExtResource("3_s2j0e")]
layout_mode = 0
@@ -47,7 +43,6 @@ offset_left = 1114.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
@@ -106,27 +101,48 @@ offset_right = 111.0
offset_bottom = 953.0
size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 25.0
text = "Вид"
toggle_mode = true
[node name="btn_activate" parent="." instance=ExtResource("8_k0iv2")]
layout_mode = 2
offset_left = 954.0
offset_left = 906.0
offset_top = 1060.0
offset_right = 1106.0
offset_bottom = 1112.0
size_flags_horizontal = 3
size_flags_vertical = 3
strips_rotation = 15.0
text = "Подавление"
toggle_mode = true
[node name="btn_zoom" parent="." instance=ExtResource("9_oey3x")]
[node name="bt_navig_u" type="TextureButton" parent="."]
layout_mode = 0
offset_left = 12.0
offset_top = 986.0
offset_right = 112.0
offset_bottom = 1006.0
metadata/zoom = 4
offset_left = 530.0
offset_top = 428.0
offset_right = 570.0
offset_bottom = 468.0
[node name="bt_navig_l" type="TextureButton" parent="."]
layout_mode = 0
offset_left = 410.0
offset_top = 532.0
offset_right = 460.0
offset_bottom = 581.0
texture_normal = SubResource("ImageTexture_cnmvt")
[node name="bt_navig_r" type="TextureButton" parent="."]
layout_mode = 0
offset_left = 651.0
offset_top = 540.0
offset_right = 691.0
offset_bottom = 580.0
[node name="bt_navig_d" type="TextureButton" parent="."]
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="btns_select" type="GridContainer" parent="."]
layout_mode = 0
@@ -140,6 +156,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "Кнопка для выбора сектора при помощи клика мышкой"
strips_rotation = 25.0
text = "Строб"
toggle_mode = true
metadata/state = 0
@@ -149,6 +166,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "Кнопка для выбора сектора при помощи клика мышкой"
strips_rotation = 25.0
text = "Цель"
toggle_mode = true
metadata/state = 1
@@ -158,6 +176,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
tooltip_text = "Кнопка для выбора сектора при помощи клика мышкой"
strips_rotation = 25.0
text = "Сектор"
toggle_mode = true
metadata/state = 2
@@ -236,5 +255,4 @@ vertical_alignment = 1
[connection signal="drag_begin" from="." to="." method="_on_drag_begin"]
[connection signal="drag_continue" from="." to="." method="_on_drag_continue"]
[connection signal="pressed" from="btn_zoom" to="." method="_on_btn_scale_pressed"]
[connection signal="value_changed" from="vslider" to="vslider" method="_on_value_changed"]

View File

@@ -4,28 +4,28 @@ extends PanelContainer
@export var texture_state0: Texture2D = preload('res://data/кнопка-эмс-1.png'):
set(val): $state.set_texture(val)
set(val): $state.set_texture(val)
@export var texture_state1: Texture2D = preload('res://data/кнопка-эмс-0.png'):
set(val): $state.set_texture(val)
set(val): $state.set_texture(val)
@export var text: String = '':
set(val): $button.set_text(val)
get: return $button.get_text()
set(val): $button.set_text(val)
get: return $button.get_text()
@export var pressed: bool = false:
set(val): $button.set_pressed(val)
get: return $button.is_pressed()
set(val): $button.set_pressed(val)
get: return $button.is_pressed()
@export var toggle_mode: bool = false:
set(val):
if is_inside_tree():
$button.set_toggle_mode(val)
get: return $button.is_toggle_mode()
set(val):
if is_inside_tree():
$button.set_toggle_mode(val)
get: return $button.is_toggle_mode()
func set_text (val: String): $button.set_text(val)
@@ -33,8 +33,8 @@ func set_pressed (val: bool): $button.set_pressed(val)
func set_toggle_mode (val: bool):
if is_inside_tree():
$button.set_toggle_mode(val)
if is_inside_tree():
$button.set_toggle_mode(val)
func get_text(): return $button.get_text()
@@ -43,13 +43,13 @@ func is_toggle_mode(): return $button.is_toggle_mode()
func _on_button_toggled(val: bool):
if val: $state.set_texture(texture_state1)
else: $state.set_texture(texture_state0)
if val: $state.set_texture(texture_state1)
else: $state.set_texture(texture_state0)
func button_connect(button_signal: String, proc: Callable):
$button.connect(button_signal, proc)
$button.connect(button_signal, proc)
func _on_button_mouse_entered():
emit_signal("mouse_entered")
emit_signal("mouse_entered")

View File

@@ -1,6 +1,6 @@
extends Panel
class_name ems extends Panel
# Предзагрузка ячеек таблиц
## Предзагрузка ячеек таблиц.
const TableHeader = preload('res://table/header.tscn')
const CellYemsButton = preload('res://scenes/эмс/кнопка-эмс.tscn')
const CellLineEdit = preload('res://table/ячейка-2.tscn')
@@ -10,7 +10,7 @@ const CellLEEmpty = preload('res://scenes/эмс/line-edit-empty.tscn')
const CellFront = preload('res://scenes/cell/cell-front.tscn')
const CellFrontRear = preload('res://scenes/cell/cell-front-rear.tscn')
# Режимы работы выходов
## Режимы работы выходов.
const OUT_MODE: Array = ['Работа', 'Контроль', '1', '0'] #
const COLUMN_OPTS_BTN: Array = [5]
const TABLE_ENTRY_COLUMNS: Array = [2,3]
@@ -18,16 +18,16 @@ const OUT_SET_ROW: Array = [CellLineEdit, CellLEEmpty, CellLEEmpty, CellLEEmpty,
const IN_SET_ROW: Array = [CellLineEdit, CellLEEmpty, CellLEEmpty, CellLEEmpty, CellLEEmpty]
var g_boards: Dictionary # Словарь плат ЭМС
var posx: int = 125 # Позиция элементов по x
var posy: int = 70 # Позиция элементов по y
var g_boards: Dictionary ## Словарь плат ЭМС.
var posx: int = 125 ## Позиция элементов по x.
var posy: int = 70 ## Позиция элементов по y.
func _ready() -> void:
call_deferred('init_boards')
## Инициализация основных элементов экрана ЭМС
## Инициализация основных элементов экрана ЭМС.
func init_boards():
# Выставление позиций элементов ЭМС на экране
$scrollin.set_position(Vector2(posx,posy))
@@ -68,8 +68,8 @@ func on_btn_disconnect():
on_disconnect($scrl_out_set/tbl_out_set, selected_rows_out, 'выход')
## Разрывает связь входа и выхода, [param tbl] - таблица, [param selected_rows] - выбранные строки
## [param type_dev] - тип, 'вход' или 'выход'
## Разрывает связь входа и выхода, [param tbl] - таблица, [param selected_rows] - выбранные строки.
## [param type_dev] - тип, 'вход' или 'выход'.
func on_disconnect(tbl, selected_rows, type_dev: String):
var dev = tbl.get_node_user_data(0, 0)
var user_data: Array = tbl.get_node_user_data(0, selected_rows[0])
@@ -85,26 +85,26 @@ func on_disconnect(tbl, selected_rows, type_dev: String):
set_out_dev(dev)
## Обработчик нажатия кнопки "Прочитать"
## Обработчик нажатия кнопки "Прочитать".
func on_btn_flash_read(btn):
await get_tree().create_timer(0.1).timeout
btn.pressed = false
## Обработчик нажатия кнопки "Записать"
## Обработчик нажатия кнопки "Записать".
func on_btn_flash_write(btn):
await get_tree().create_timer(0.1).timeout
btn.pressed = false
## Инициализация таблицы с файлами настроек ЭМС
## Инициализация таблицы с файлами настроек ЭМС.
func init_tbl_files():
$scrl_files/tbl_files.set_header([TableHeader, TableHeader, TableHeader])
$scrl_files/tbl_files.set_header_text(['Имя файла', 'Дата изменения', 'Размер'])
$scrl_files/tbl_files.set_columns_min_size([200, 120, 70])
## Инициализация таблиц входов
## Инициализация таблиц входов.
func init_tbl_in():
# Инициализация основной таблицы входов, в ней отображается информация о параметрах и состоянии
var header_type: Array = [TableHeader, TableHeader, CellFront, CellFrontRear, TableHeader]
@@ -142,12 +142,12 @@ func init_tbl_in():
$scrl_in_set/tbl_in_set.connect('selected_changed', Callable(self, 'on_selected_changed_si'))
## Обработчик редактирования Entry в таблице параметров входов/выходов
## Обработчик редактирования Entry в таблице параметров входов/выходов.
func on_edit_entry(text : String, entry):
print_debug(text, entry)
## Обработчик выбора строки в таблице входов
## Обработчик выбора строки в таблице входов.
func on_selected_changed_in(i_row: int):
var selecter_rows: Array = []
$scrollin/tbl_in.get_selected_rows(selecter_rows)
@@ -156,19 +156,19 @@ func on_selected_changed_in(i_row: int):
set_in_dev(dev)
## Обработчик нажатия на таблицу входов
## Обработчик нажатия на таблицу входов.
func on_row_pressed_in(i_row: int):
on_row_pressed(i_row, $scrollin/tbl_in)
on_selected_changed_in(i_row)
## Выбор входного устройства, для отображения в таблице соединений входа и изменения параметров
## Выбор входного устройства, для отображения в таблице соединений входа и изменения параметров.
func set_in_dev(dev):
var row_type: Array = [CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit, CellState]
set_dev($scrl_in_set/tbl_in_set, dev, row_type, IN_SET_ROW, 'Список соединённых выходов :', [250, 100, 70, 70, 70])
## Обработчик выбора строки в таблице соединений входа и изменения параметров
## Обработчик выбора строки в таблице соединений входа и изменения параметров.
func on_selected_changed_si(i_row: int):
if i_row < 2:
return
@@ -181,7 +181,7 @@ func on_selected_changed_si(i_row: int):
on_row_pressed_out(i)
## Обработчик нажатия на таблицу соединений входа и изменения параметров
## Обработчик нажатия на таблицу соединений входа и изменения параметров.
func on_row_pressed_si(i_row: int):
if i_row < 2:
return
@@ -189,7 +189,7 @@ func on_row_pressed_si(i_row: int):
on_selected_changed_si(i_row)
## Инициализация таблиц выходов
## Инициализация таблиц выходов.
func init_tbl_out():
# Инициализация основной таблицы выходов, в ней отображается информация о параметрах и состоянии
var header_text = ['Выходы', 'Соединитель', 'мкс', 'мкс', 'Состояние', 'Режим']
@@ -225,7 +225,7 @@ func init_tbl_out():
$scrl_out_set/tbl_out_set.connect('selected_changed', Callable(self, 'on_selected_changed_so'))
## Обработчик выбора строки в таблице соединений выхода и изменения параметров
## Обработчик выбора строки в таблице соединений выхода и изменения параметров.
func on_selected_changed_so(i_row: int):
if i_row < 2:
return
@@ -238,7 +238,7 @@ func on_selected_changed_so(i_row: int):
on_row_pressed_in(i)
## Обработчик нажатия на таблицу соединений выхода и изменения параметров
## Обработчик нажатия на таблицу соединений выхода и изменения параметров.
func on_row_pressed_so(i_row: int):
if i_row < 2:
return
@@ -246,7 +246,7 @@ func on_row_pressed_so(i_row: int):
on_selected_changed_so(i_row)
## Обработчик выбора строки в таблице выходов
## Обработчик выбора строки в таблице выходов.
func on_selected_changed_out(i_row: int):
var selecter_rows: Array = []
$scrollout/tbl_out.get_selected_rows(selecter_rows)
@@ -255,13 +255,13 @@ func on_selected_changed_out(i_row: int):
set_out_dev(dev)
## Обработчик выбора строки в таблице выходов
## Обработчик выбора строки в таблице выходов.
func on_row_pressed_out(i_row: int):
on_row_pressed(i_row, $scrollout/tbl_out)
on_selected_changed_out(i_row)
## Выбор выходного устройства, для отображения в таблице соединений выхода и изменения параметров
## Выбор выходного устройства, для отображения в таблице соединений выхода и изменения параметров.
func set_out_dev(dev):
var row_type: Array = [CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit, CellState, CellOptBtn]
set_dev($scrl_out_set/tbl_out_set, dev, row_type, OUT_SET_ROW, 'Список соединённых входов :', [250, 100, 70, 70, 70, 100])
@@ -273,9 +273,12 @@ func set_out_dev(dev):
mode.select(mode_index)
## Выбор входного или выходного устройства [param tbl] - таблица, [param dev] - устройство,
## [param row_type] - массив с типами колонок, [param row_type_conn] - массив с пустыми LineEdit
## [param lbl_text] - текст отображаемый во 2 строке: пример: ('Список соединённых входов :')
## Выбор входного или выходного устройства.[br]
## [param tbl] - таблица,[br]
## [param dev] - устройство,[br]
## [param row_type] - массив с типами колонок,[br]
## [param row_type_conn] - массив с пустыми LineEdit,[br]
## [param lbl_text] - текст отображаемый во 2 строке: пример: ('Список соединённых входов :').[br]
func set_dev(tbl, dev, row_type, row_type_conn, lbl_text, row_size):
tbl.clear_rows()
tbl.add_row(row_type)
@@ -311,7 +314,7 @@ func set_dev(tbl, dev, row_type, row_type_conn, lbl_text, row_size):
tbl.connect_columns(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, [])
## Обработчик нажатия кнопки connect
## Обработчик нажатия кнопки connect.
func on_btn_connect():
var in_row_index: Array = []
var out_row_index: Array = []
@@ -326,9 +329,12 @@ func on_btn_connect():
add_connection_dev($scrl_in_set/tbl_in_set, out_dev, in_dev, IN_SET_ROW, out_user_data)
## образовывает связь между выбранным входом и выходом [param tbl] - таблица, [param dev1] - устройство1,
## [param dev2] - устройство 2, [param set_row] - массив с пустыми LineEdit
## [param user_data] - пользовательские данные устройства1
## Образовывает связь между выбранным входом и выходом.[br]
## [param tbl] - таблица,[br]
## [param dev1] - устройство1,[br]
## [param dev2] - устройство 2,[br]
## [param set_row] - массив с пустыми LineEdit,[br]
## [param user_data] - пользовательские данные устройства1.[br]
func add_connection_dev(tbl, dev1, dev2, set_row, user_data):
if not dev1.connector in dev2.connect_devs:
tbl.add_row(set_row)
@@ -340,15 +346,17 @@ func add_connection_dev(tbl, dev1, dev2, set_row, user_data):
dev2.connect_devs[dev1.connector] = user_data
## Отключает возможность редактирования LineEdit в таблице [param tbl] - таблица,
## [param num_col] - номер колонки, [param i_row] - номер столбца
## Отключает возможность редактирования LineEdit в таблице.[br]
## [param tbl] - таблица,[br]
## [param num_col] - номер колонки,[br]
## [param i_row] - номер столбца.[br]
func disable_edit(tbl, num_col: int, i_row: int):
for col in range(num_col):
var node: LineEdit = tbl.get_node2(col, i_row)
node.editable = false
## Обработчик выбора строки с таблице
## Обработчик выбора строки с таблице.
func on_row_pressed(i_row: int, tbl):
tbl.clear_rows_selected()
var is_row_selected = tbl.is_row_selected(i_row)

View File

@@ -29,6 +29,7 @@ offset_left = 1446.0
offset_top = 55.0
offset_right = 1583.0
offset_bottom = 85.0
strips_rotation = 10.0
text = "Прочитать"
[node name="btn_flash_write" parent="." instance=ExtResource("2_eju8r")]
@@ -37,6 +38,7 @@ offset_left = 1446.0
offset_top = 99.0
offset_right = 1583.0
offset_bottom = 129.0
strips_rotation = 10.0
text = "Записать"
[node name="btn_new" type="Button" parent="."]

345
scenes/эмс2/эмс2.tscn Normal file
View File

@@ -0,0 +1,345 @@
[gd_scene load_steps=2 format=3 uid="uid://musb21x2u0xs"]
[ext_resource type="Texture2D" uid="uid://co5xj5uhjfk84" path="res://data/Окно.png" id="1_k6k6b"]
[node name="ЭМС2" type="Panel"]
[node name="TextureRect2" type="TextureRect" parent="."]
layout_mode = 0
offset_top = 8.0
offset_right = 1597.0
offset_bottom = 712.0
texture = ExtResource("1_k6k6b")
[node name="Label2" type="Label" parent="TextureRect2"]
layout_mode = 0
offset_left = 795.0
offset_top = 8.0
offset_right = 868.0
offset_bottom = 27.0
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "Излучение"
[node name="Label3" type="Label" parent="TextureRect2"]
layout_mode = 0
offset_left = 813.0
offset_top = 293.0
offset_right = 864.0
offset_bottom = 312.0
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "Приём"
[node name="RichTextLabel" type="RichTextLabel" parent="TextureRect2"]
layout_mode = 0
offset_left = 11.0
offset_top = 36.0
offset_right = 126.0
offset_bottom = 286.0
[node name="RichTextLabel2" type="RichTextLabel" parent="TextureRect2"]
layout_mode = 0
offset_left = 12.0
offset_top = 318.0
offset_right = 127.0
offset_bottom = 568.0
[node name="GridContainer2" type="GridContainer" parent="."]
modulate = Color(0.8, 0.533333, 0.27451, 1)
self_modulate = Color(0.8, 0.533333, 0.27451, 1)
layout_mode = 0
offset_left = -8.0
offset_top = 840.0
offset_right = 1592.0
offset_bottom = 1208.0
[node name="Label11" type="Label" parent="."]
layout_mode = 0
offset_left = 1224.0
offset_top = 752.0
offset_right = 3304.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Запрет
приёма"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label11"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = -1
anchor_right = 1.0
anchor_bottom = 1.0
offset_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label14" type="Label" parent="."]
layout_mode = 0
offset_left = 1336.0
offset_top = 752.0
offset_right = 3736.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Исполнено"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label14"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label12" type="Label" parent="."]
layout_mode = 0
offset_left = 1464.0
offset_top = 752.0
offset_right = 3704.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Запрет
приёма"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label12"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label15" type="Label" parent="."]
layout_mode = 0
offset_left = 1096.0
offset_top = 752.0
offset_right = 3496.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Исполнено"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label15"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label13" type="Label" parent="."]
layout_mode = 0
offset_left = 976.0
offset_top = 752.0
offset_right = 3216.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Верхняя
Частота"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label13"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label16" type="Label" parent="."]
layout_mode = 0
offset_left = 856.0
offset_top = 752.0
offset_right = 3096.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Нижняя
частота"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label16"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = -0.000976563
offset_right = -0.000976563
grow_horizontal = 2
grow_vertical = 2
[node name="Label17" type="Label" parent="."]
layout_mode = 0
offset_left = 728.0
offset_top = 752.0
offset_right = 3128.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Кластер"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label17"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label18" type="Label" parent="."]
layout_mode = 0
offset_left = 600.0
offset_top = 752.0
offset_right = 3000.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Угол места"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label18"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Label19" type="Label" parent="."]
layout_mode = 0
offset_left = 472.0
offset_top = 752.0
offset_right = 2872.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Азимут"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label19"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 0.000610352
offset_top = 6.10352e-05
offset_right = 0.000488281
grow_horizontal = 2
grow_vertical = 2
[node name="Label20" type="Label" parent="."]
layout_mode = 0
offset_left = 344.0
offset_top = 752.0
offset_right = 2744.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Режим"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label20"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 0.000610352
offset_top = 6.10352e-05
offset_right = 0.000488281
grow_horizontal = 2
grow_vertical = 2
[node name="Label21" type="Label" parent="."]
layout_mode = 0
offset_left = 216.0
offset_top = 752.0
offset_right = 2616.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Изделие"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label21"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = 6.10352e-05
grow_horizontal = 2
grow_vertical = 2
[node name="Label22" type="Label" parent="."]
layout_mode = 0
offset_left = 88.0
offset_top = 752.0
offset_right = 2488.0
offset_bottom = 1872.0
scale = Vector2(0.05, 0.05)
theme_override_colors/font_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 350
text = "Комплекс
"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ColorRect2" type="ColorRect" parent="Label22"]
modulate = Color(0.8, 0.533333, 0.27451, 1)
show_behind_parent = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = 6.10352e-05
grow_horizontal = 2
grow_vertical = 2

View File

@@ -1,26 +1,26 @@
extends Node
class_name STC extends Node
## Реализация "Протокол информационного сопряжения
## СПО АСУ изделия «МП550» с СПО «Управления КАПС РПБ»"
## Реализация "Протокол информационного сопряжения.
## СПО АСУ изделия «МП550» с СПО «Управления КАПС РПБ».
const ONLINE_TIMEOUT = 3000 ## Время ожидания пакета от КАПС РПБ, мс
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм
const ONLINE_TIMEOUT = 3000 ## Время ожидания пакета от КАПС РПБ, мс.
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм.
class CapsRpb:
signal line_changed(unit: CapsRpb) ## Сигнал состояние связи изменилось
signal data_received(unit: CapsRpb) ## Сигнал данные приняты
signal command_fail(unit: CapsRpb) ## Сигнал при не выполнении команды
signal parse_error(unit: CapsRpb, msg: String) ## Сигнал ошибки разбора сообщения
signal line_changed(unit: CapsRpb) ## Сигнал состояние связи изменилось.
signal data_received(unit: CapsRpb) ## Сигнал данные приняты.
signal command_fail(unit: CapsRpb) ## Сигнал при не выполнении команды.
signal parse_error(unit: CapsRpb, msg: String) ## Сигнал ошибки разбора сообщения.
static var json_conv: = JSON.new()
var online: = false ## Состояние связи с источником сообщений
var name: String ## Имя экземпляра
var json_dic: Dictionary ## Аппарат для разбора сообщений
var tick: = 0 ## Тик время последнего обновления, мс
var tx_data: = PackedByteArray() ## Пакет для отправки
var tx_stack: Array ## Массив пакетов для отправки
var online: = false ## Состояние связи с источником сообщений.
var name: String ## Имя экземпляра.
var json_dic: Dictionary ## Аппарат для разбора сообщений.
var tick: = 0 ## Тик время последнего обновления, мс.
var tx_data: = PackedByteArray() ## Пакет для отправки.
var tx_stack: Array ## Массив пакетов для отправки.
func _to_string() -> String: return String('капсрпб: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
func _init(nm): self.name = nm

View File

@@ -9,30 +9,30 @@ var FILES_ROWS_ALIGNMENT = [ HORIZONTAL_ALIGNMENT_LEFT, HORIZONTAL_ALIGNM
func fill_files_table(tbl: table, folder: String, rows_types: Array):
var dir: = DirAccess.open(folder)
if dir == null:
return
var files: = []
var exclude_names: = ['.', '..']
dir.list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547
while true:
var file: = dir.get_next()
if file == '':
break
if file in exclude_names:
continue
var file_name = folder + '/' + file
var fd = FileAccess.open(file_name, FileAccess.READ)
if not fd:
continue
var glob_path = ProjectSettings.globalize_path(file_name)
var sz = fd.get_length()
var ut = fd.get_modified_time(file_name)
fd.close()
var mt = Time.get_datetime_dict_from_unix_time(ut)
var file_row = [file, '%d' % sz, '%d-%02d-%02d %02d:%02d' % [mt.year, mt.month, mt.day, mt.hour, mt.minute]]
tbl.add_row(rows_types)
var i_row = tbl.get_rows_count() - 1
tbl.set_row_text(i_row, file_row)
tbl.set_node_meta(0, i_row, 'file_path', glob_path)
dir.list_dir_end()
var dir: = DirAccess.open(folder)
if dir == null:
return
var files: = []
var exclude_names: = ['.', '..']
dir.list_dir_begin() # TODOGODOT4 fill missing arguments https://github.com/godotengine/godot/pull/40547
while true:
var file: = dir.get_next()
if file == '':
break
if file in exclude_names:
continue
var file_name = folder + '/' + file
var fd = FileAccess.open(file_name, FileAccess.READ)
if not fd:
continue
var glob_path = ProjectSettings.globalize_path(file_name)
var sz = fd.get_length()
var ut = fd.get_modified_time(file_name)
fd.close()
var mt = Time.get_datetime_dict_from_unix_time(ut)
var file_row = [file, '%d' % sz, '%d-%02d-%02d %02d:%02d' % [mt.year, mt.month, mt.day, mt.hour, mt.minute]]
tbl.add_row(rows_types)
var i_row = tbl.get_rows_count() - 1
tbl.set_row_text(i_row, file_row)
tbl.set_node_meta(0, i_row, 'file_path', glob_path)
dir.list_dir_end()

View File

@@ -1,20 +1,20 @@
extends Node
class_name HotKeys extends Node
func _ready() -> void:
signaller.connect('full_screen', Callable(self, 'toggle_full_screen').bind(0))
signaller.connect('full_screen', Callable(self, 'toggle_full_screen').bind(0))
func _input(event: InputEvent) -> void:
if event is InputEventKey:
if event.pressed and event.physical_keycode == KEY_F11:
signaller.emit_signal('full_screen')
if event is InputEventKey:
if event.pressed and event.physical_keycode == KEY_F11:
signaller.emit_signal('full_screen')
## Переключает режим окна программы полный - обычный экран
## Переключает режим окна программы полный - обычный экран.
func toggle_full_screen(id: int) -> void:
var mode = DisplayServer.window_get_mode(id)
mode = DisplayServer.WINDOW_MODE_WINDOWED \
if mode == DisplayServer.WINDOW_MODE_FULLSCREEN \
else DisplayServer.WINDOW_MODE_FULLSCREEN
DisplayServer.window_set_mode(mode, id)
var mode = DisplayServer.window_get_mode(id)
mode = DisplayServer.WINDOW_MODE_WINDOWED \
if mode == DisplayServer.WINDOW_MODE_FULLSCREEN \
else DisplayServer.WINDOW_MODE_FULLSCREEN
DisplayServer.window_set_mode(mode, id)

View File

@@ -1,8 +1,8 @@
extends Node
class_name Iterfer extends Node
## Представление помехи
## Представление помехи.
## Режимы помехи
## Режимы помехи.
const ITERFER_MODE = {
'off': ['Откл', ['freq', 'width'], 0],
'auto': ['АВТО', ['freq', 'width'], 1000],
@@ -27,16 +27,16 @@ const WIDTH_MAX = 120
const WIDTH_MIN = 0
const SOURCE_INTERFER = ['th','fs','cu']
const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей
const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей.
const INTERFER_OFF = 'off'
const STATE_TSMT = 5 ## Значение svk для цели, когда ответ ещё не получен
var msg_ss: int = 0 ## счётчик сообщений
var id_array: Array ## Массив id воздействий
var thrs: Dictionary ## Словарь воздействия для целей, ключ - id воздействия
var fs: Dictionary ## Словарь воздействий для секторов, ключ - id воздействия
var cu: Dictionary ## Словарь воздействий для 5П-28, ключ - id воздействия
const STATE_TSMT = 5 ## Значение svk для цели, когда ответ ещё не получен.
var msg_ss: int = 0 ## Счётчик сообщений.
var id_array: Array ## Массив id воздействий.
var thrs: Dictionary ## Словарь воздействия для целей, ключ - id воздействия.
var fs: Dictionary ## Словарь воздействий для секторов, ключ - id воздействия.
var cu: Dictionary ## Словарь воздействий для 5П-28, ключ - id воздействия.
## Сеанс помехи
## Сеанс помехи.
class Interfer:
var ss: int = 0 ## Счётчик сообщений.
var ispp: int = 0 ## Индекс сеанса.
@@ -48,7 +48,7 @@ class Interfer:
var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров).
var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров.
var tick_tx: int ## Тик время обновления цели, мс.
var source_interfer: String = '' ## Тип объекта по которой поставлена помеха
var source_interfer: String = '' ## Тип объекта по которой поставлена помеха.
func _to_string() -> String:
return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni]
@@ -94,7 +94,7 @@ signal interfer_resized(ecms: Dictionary) ## Вызывается пр
func _ready():
var ecms: Dictionary = {} ## Словарь помех
var ecms: Dictionary = {} ## Словарь помех.
for i in range(ID_INTERFERS_LEN): # Заполняет массив ID целей
id_array.append(i + 1)
var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп')
@@ -114,7 +114,7 @@ func _ready():
signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all').bind(unit, ecms))
# Проверяет состояние отправки пакета и если не доставлен, повторяет отправку
## Проверяет состояние отправки пакета и если не доставлен, повторяет отправку.
func on_timer_check_state(unit, ecms, resend_timeout):
var tick = Time.get_ticks_msec()
for ecm in ecms.values():
@@ -124,7 +124,7 @@ func on_timer_check_state(unit, ecms, resend_timeout):
ecm.tick_tx = tick
## Производит приём состояния помех. [param unit] -> [param ecms]
## Производит приём состояния помех. [param unit] -> [param ecms].
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
if not unit.json_dic.has('ts'): return
if not (unit.json_dic['ts'] is float): return
@@ -150,7 +150,7 @@ func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
call_deferred('emit_signal', 'interfer_resized', ecms)
## Вызыватся, когда пользователь выбрал помеху и выбраны цели
## Вызыватся, когда пользователь выбрал помеху и выбраны цели.
func on_interfer_create(btn, sel_threats, fs_arr, _unit, ecms):
for item in sel_threats:
var param: Dictionary = {}
@@ -262,5 +262,5 @@ func push_id(id : int):
id_array.sort()
## отправляет словаhь помех в юнит, для запаковки и отправки в 5П28
## Отправляет словарь помех в юнит, для запаковки и отправки в 5П28.
func on_get_interfers(unit, ecms): unit.pack_interfers(cu, ecms)

View File

@@ -1,12 +1,12 @@
extends Node
class_name Mercator extends Node
## Утилиты для работы с меркаторовскими XYZ-плитками.
const R2D: = 180.0 / PI
const RE: = 6378137.0 ## Радиус Земли экваториальный в метрах
const RP: = 6356752.31424518 ## Радиус Земли полярный в метрах
const CE: = 2.0 * PI * RE ## Длина окружности Земли в метрах по экватору
const CP: = 2.0 * PI * RP ## Длина окружности Земли в метрах через полюсы
const RE: = 6378137.0 ## Радиус Земли экваториальный в метрах.
const RP: = 6356752.31424518 ## Радиус Земли полярный в метрах.
const CE: = 2.0 * PI * RE ## Длина окружности Земли в метрах по экватору.
const CP: = 2.0 * PI * RP ## Длина окружности Земли в метрах через полюсы.
const EPSILON: = 1e-14
const LL_EPSILON: = 1e-11
const MAX_ZOOM: = 20
@@ -14,15 +14,15 @@ const MAX_NORTH = 85.051129
const MAX_SOUTH = -85.051129
## XYZ-плитка веб-меркатора [param x], [param y], [param z] индексы
# [b]x[/b] и [b]y[/b] плитки и уровень масштабирования [b]z[/b].
## XYZ-плитка веб-меркатора [param x], [param y], [param z] индексы.
## [b]x[/b] и [b]y[/b] плитки и уровень масштабирования [b]z[/b].
class Tile:
var x: int
var y: int
var z: int
var lng: float ## Координаты, которые плитка должна покрывать, долгота, градусы
var lat: float ## Широта, градусы
var is_root: bool ## Признак, что плитка корневая (покрывает координаты)
var lng: float ## Координаты, которые плитка должна покрывать, долгота, градусы.
var lat: float ## Широта, градусы.
var is_root: bool ## Признак, что плитка корневая (покрывает координаты).
func as_array(): return [self.x, self.y, self.z]
@@ -45,9 +45,8 @@ class Tile:
func _bound_index(index: int) -> int:
var mi: int = 2 ** z
if index < 0:
index *= -1
index %= mi
index = mi - index
index = -index - 1;
index = int(mi - 1) - (index % int(mi))
else:
index %= mi
return index
@@ -62,7 +61,7 @@ class LngLat:
var lng: float = 0.0 ## Долгота в десятичных градусах восточной долготы.
var lat: float = 0.0 ## Широта в десятичных градусах северной широты.
## Возвращает в виде массива
## Возвращает в виде массива.
func as_array() -> Array: return [self.lng, self.lat]
func _to_string() -> String: return '[%f, %f, %f]' % [self.x, self.y, self.z]
@@ -79,7 +78,7 @@ class LngLatBbox:
var east: float ## Восток
var north: float ## Север
## Возвращает в виде массива
## Возвращает в виде массива.
func as_array() -> Array: return [self.west, self.south, self.east, self.north]
func _to_string() -> String: return '[%f, %f, %f, %f]' % [self.west, self.south, self.east, self.north]
@@ -114,12 +113,12 @@ func radians(v: float) -> float: return (v * PI) / 180.0
func rshift(val: int, n: int) -> int: return (val % 0x100000000) >> n
# Возвращает арксинус гиперболический от значения [param val]
## Возвращает арксинус гиперболический от значения [param val].
func asinh(val: float): return log(val + sqrt(val * val + 1.0))
# Преобразует [param lon] в градусах восточной долготы, [param lat] в градусах
# северной долготы, [param alt] высоты в метрах в фиксированные координаты (x, y, z) Земли.
## Преобразует [param lon] в градусах восточной долготы, [param lat] в градусах.
## северной долготы, [param alt] высоты в метрах в фиксированные координаты (x, y, z) Земли.
func lnglat_to_ecef(lng: float, lat: float, alt: float = 0.0) -> Array:
alt += (RE + RP) / 2.0
var latrad: float = radians(lat)
@@ -148,23 +147,23 @@ func find_up_left(tiles: Array):
return null
## Lon./lat. to tile numbers
## [param lon]/[param lat]. для номера плитки.
func deg2num(lng: float, lat: float, zoom: int):
var n: = float(1 << zoom)
var xtile: = int((lng + 180.0) / 360.0 * n)
var ytile: = int((1.0 - asinh(tan(radians(lat))) / PI) / 2.0 * n)
return [xtile, ytile]
var n: = float(1 << zoom)
var xtile: = int((lng + 180.0) / 360.0 * n)
var ytile: = int((1.0 - asinh(tan(radians(lat))) / PI) / 2.0 * n)
return [xtile, ytile]
## Tile numbers to lon./lat.
## Номера плитки для [param lon]/[param lat].
func num2deg(x: int, y: int, zoom: int):
var n: = float(1 << zoom)
var lng: = float(x) / n * 360.0 - 180.0
var lat: = atan(sinh(PI * (1.0 - 2.0 * float(y) / n)))
return [lng, degrees(lat)]
var n: = float(1 << zoom)
var lng: = float(x) / n * 360.0 - 180.0
var lat: = atan(sinh(PI * (1.0 - 2.0 * float(y) / n)))
return [lng, degrees(lat)]
## Расстояние по горизонтали в метрах, представленное одним пикселем
## Расстояние по горизонтали в метрах, представленное одним пикселем.
## [param lat] - Широта, градусы.[br]
## [param zoom] - Уровень детализации.[br]
## [param size] - Размер плитки в пикселях.[br]
@@ -172,7 +171,7 @@ func dist_per_pixel(lat: float, zoom: int, size: int = 256) -> float:
return (CE / float(size)) * cos(radians(lat)) / float(2 ** zoom)
## Расстояние по горизонтали в метрах, представленное одной плиткой
## Расстояние по горизонтали в метрах, представленное одной плиткой.
## [param lat] - Широта, градусы.[br]
## [param zoom] - Уровень детализации.[br]
func dist_per_tile(lat: float, zoom: int) -> float:
@@ -226,7 +225,7 @@ func get_degrees_bounds(m: float, lng: float, lat: float) -> Array[float]:
return [x_y[0] - m, x_y[1] - m, x_y[0] + m, x_y[1] + m]
## Возвращает границы плиток в градусах
## Возвращает границы плиток в градусах.
func get_tiles_bounds(tiles: Array[Tile]) -> Array:
var mm = []
for t in tiles: mm.append(bounds(t).west)
@@ -245,7 +244,7 @@ func get_tiles_bounds(tiles: Array[Tile]) -> Array:
## Возвращает левую верхнюю долготу и широту плитки.[br]
## [param tile] Плитка.[br]
## [param tile] - Плитка.[br]
## [codeblock]
## >>> ul(Tile(x=0, y=0, z=1))
## LngLat(lng=-180.0, lat=85.0511287798066)
@@ -322,10 +321,10 @@ func lnglat(x: float, y: float, truncate: bool = false) -> LngLat:
return LngLat.new(ll[0], ll[1])
## Соседи плитки. [method neighbors] возвращает до восьми
## соседних плиток, при этом плитки будут опущены, если они не являются действительными, например.
## Tile(-1, -1, z). [param tile]: Плитка или последовательность int
## Может быть либо экземпляр Tile, либо 3 ints, X, Y, Z.
## Соседи плитки. [method neighbors] возвращает до восьми.[br]
## Cоседних плиток, при этом плитки будут опущены, если они не являются действительными, например:[br]
## Tile(-1, -1, z). [param tile]: Плитка или последовательность int.[br]
## Может быть либо экземпляр Tile, либо 3 ints, X, Y, Z.[br]
## [return] Массив
## [codeblock]
## >>> neighbors(Tile(486, 332, 10))
@@ -343,7 +342,7 @@ func neighbors(tile: Tile) -> Array:
return tiles
## Возвращает все плитки в радиусе [param r] вокруг заданной плитки [param tile]
## Возвращает все плитки в радиусе [param r] вокруг заданной плитки [param tile].
func get_allaround_tiles(tile: Tile, mr: int = 1) -> Array:
var xys = {}
var mi: int = 2 ** tile.z
@@ -361,7 +360,7 @@ func get_allaround_tiles(tile: Tile, mr: int = 1) -> Array:
return tiles
## Возвращает все плитки по периметру заданной плитки
## Возвращает все плитки по периметру заданной плитки.
func get_perimetr_tiles(tile: Tile, mr: int = 1) -> Array:
var tiles = []
for i in range(-mr, mr + 1):
@@ -375,7 +374,7 @@ func get_perimetr_tiles(tile: Tile, mr: int = 1) -> Array:
## Получение меркаторской граничной рамки веб-плитки.[br]
## [param tile] - Плитка.[br]
## [i]Эпсилон вычитается из правой границы и прибавляется к нижней[/i]
## [i]Эпсилон вычитается из правой границы и прибавляется к нижней.[/i]
func xy_bounds(tile: Tile, zoom: int) -> Bbox:
var tile_size = CE / pow(2, zoom)
var left = tile.x * tile_size - CE / 2
@@ -393,7 +392,7 @@ func _xy(lng: float, lat: float, truncate=false) -> Array:
return [x, y]
## Получение плитки, содержащей долготу и широту
## Получение плитки, содержащей долготу и широту.
## [param lng], [param lat] - Пара долготы и широты в десятичных градусах.[br]
## [param zoom] - Уровень масштабирования веб-меркатора.[br]
## [param truncate] - Нужно ли усекать вводимые данные до границ веб-меркатора.[br]
@@ -419,7 +418,7 @@ func create_tile(lng: float, lat: float, zoom: int, truncate: bool=false) -> Til
## Получение четверного ключа плитки.[br]
## [param tile] - Плитка
## [param tile] - Плитка.
func quadkey(tile: Tile, zoom: int) -> String:
var rs: = ''
for z in range(zoom, 0, -1):
@@ -650,7 +649,7 @@ func _get_bbox_zoom(bbox: Array):
## [param tile] - Плитка.[br]
## [param fid] - Идентификатор объекта.[br]
## [param props] - Необязательные дополнительные свойства признака.[br]
## [param projected] - Можно создать нестандартный веб-меркатор GeoJSON передав 'mercator'[br]
## [param projected] - Можно создать нестандартный веб-меркатор GeoJSON передав 'mercator'.[br]
## [param buffer] - Необязательное буферное расстояние для полигона GeoJSON.[br]
## [param precision] - Координаты GeoJSON будут усечены до данного количества знаков после запятой.[br]
func feature(tile: Tile, fid:String = 'null', props=null, projected='geographic', buffer=null) -> Dictionary:

View File

@@ -1,44 +1,44 @@
extends Node
class_name mod_bus extends Node
const ONLINE_TIMEOUT = 5.0 ## Время ожидания пакета от ячейки, секунды
const ONLINE_TIMEOUT = 5.0 ## Время ожидания пакета от ячейки, секунды.
class ModbusClient:
## Состояние автомата выполнения команды
## Состояние автомата выполнения команды.
enum CmdState {
DONE, ## Команда выполнена
FAIL, ## Команда не выполнена
SEND, ## Буфер готов для отправки
WAIT ## Ожидание выполнения
DONE, ## Команда выполнена.
FAIL, ## Команда не выполнена.
SEND, ## Буфер готов для отправки.
WAIT ## Ожидание выполнения.
}
var name: String
var unit: = 1 ## Адрес устройства Modbus
var cmd_state: = CmdState.DONE ## Код текущей команды
var tx_data: PackedByteArray ## Данные для отправки
var unit: = 1 ## Адрес устройства Modbus.
var cmd_state: = CmdState.DONE ## Код текущей команды.
var tx_data: PackedByteArray ## Данные для отправки.
var online: = false ## Флаг. Если установлен, устройство на связи. Активный уровень - [b]true[/b].
var tick_rx: = 0 ## Время приёма крайнего сообщения
var tick_tx: = 0 ## Время отправки крайнего сообщения
var tick_rx: = 0 ## Время приёма крайнего сообщения.
var tick_tx: = 0 ## Время отправки крайнего сообщения.
static var json_conv: = JSON.new()
signal command_done() ## Вызывается при успешном выполнении команды
signal command_fail() ## Вызывается при возникновении ошибки во время выполнения команды
signal line_changed() ## Вызывается при смене состояния связи с ячейкой
signal data_received() ## Вызывается при приёме сообщения, до его разбора
signal parse_failed(msg: String) ## Вызывается при возникновении ошибки во время разбора пакета. Передаёт сообщение об ошибке
signal command_done() ## Вызывается при успешном выполнении команды.
signal command_fail() ## Вызывается при возникновении ошибки во время выполнения команды.
signal line_changed() ## Вызывается при смене состояния связи с ячейкой.
signal data_received() ## Вызывается при приёме сообщения, до его разбора.
signal parse_failed(msg: String) ## Вызывается при возникновении ошибки во время разбора пакета. Передаёт сообщение об ошибке.
signal holding_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения
signal input_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов
signal info_received(msg: String) ## Вызывается при получении информационного сообщения
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации
signal holding_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
signal input_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов.
signal info_received(msg: String) ## Вызывается при получении информационного сообщения.
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
func _init(nm: String, u: int = 1):
unit = u
name = nm
## Изменяет состояние. Вызывать периодически[br]
## [param tick] - Текущщее время в мс[br]
## Изменяет состояние. Вызывать периодически.[br]
## [param tick] - Текущщее время в мс.[br]
func process(tick: int):
if online and ((tick - tick_rx) > ONLINE_TIMEOUT):
online = false
@@ -53,9 +53,9 @@ class ModbusClient:
cmd_state = CmdState.WAIT
return rc
## Производит разбор принятых данных. Вызывать при приёме данных на сокете[br]
## [param data] - Данные принятые на сокете[br]
## [param tick] - Текущщее время в мс[br]
## Производит разбор принятых данных. Вызывать при приёме данных на сокете.[br]
## [param data] - Данные принятые на сокете.[br]
## [param tick] - Текущщее время в мс.[br]
func parse(data: PackedByteArray, tick: int) -> bool:
tick_rx = tick
if not online:

View File

@@ -1,4 +1,4 @@
extends Node
class_name rep_network extends Node
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'jsontx': capsrpb.CapsRpb, 'udp-json-mbcs': modbus.ModbusClient}
@@ -11,17 +11,17 @@ class Socket extends PacketPeerUDP:
class SocketTCP extends TCPServer:
const RX_TIMEOUT: int = 1000 # Время сброса счётчика принятия части пакета
const RX_TIMEOUT: int = 1000 ## Время сброса счётчика принятия части пакета.
var peerstream: = PacketPeerStream.new()
var unit_key: Array # Клюс юнита
var head_len: int = 8 # Длинна заголовка команды
var len_place: int = 4 # Номер начального байта с длинной блока данных
var type_len: int = 4 # Количество байт в размере длинны
var rx_tick: int # Время приёма последнего пакета
var rx_all: bool = true # Флаг, что пакет принят полностью
var rx_len: int # Количество принятых байт
var rx_data: PackedByteArray # Принятые данные
var data_len: int # Размер ожидаемых данных
var unit_key: Array ## Клюс юнита.
var head_len: int = 8 ## Длинна заголовка команды.
var len_place: int = 4 ## Номер начального байта с длинной блока данных.
var type_len: int = 4 ## Количество байт в размере длинны.
var rx_tick: int ## Время приёма последнего пакета.
var rx_all: bool = true ## Флаг, что пакет принят полностью.
var rx_len: int ## Количество принятых байт.
var rx_data: PackedByteArray ## Принятые данные.
var data_len: int ## Размер ожидаемых данных.
func send_to(data):
var peer = peerstream.get_stream_peer()
@@ -69,8 +69,8 @@ func _ready() -> void:
sock_capsrpb = poll_sockets[2]
for unit_name in repsettings.UnitProfiles:
var setting = repsettings.UnitProfiles[unit_name]
var proto = setting[0]
var settings = repsettings.UnitProfiles[unit_name]
var proto = settings[0]
if proto in PROTOCOL_TYPES:
var unit = PROTOCOL_TYPES[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)

View File

@@ -1,7 +1,6 @@
extends Node
## Параметры
class_name rep_settings extends Node
## Параметры.
@export var UnitProfiles: = { \
# Название | Протокол | Адрес | Порт | Широковещательное | Привязывать к адресу | Комментарий
@@ -34,7 +33,7 @@ extends Node
'уарэп-спт25-2': ['uart', '/dev/tty3', 115200, false, 'Адрес прибора СПТ-25 (G2)'],
}
## Параметры цели
## Параметры цели.
@export var ThreatParams = {
'time_lost': 5000 ## Время после последнего обновления в мс, через которое цель считается потерянной.
}
@@ -43,7 +42,7 @@ extends Node
func _ready() -> void: log.info('Модуль настроек готов')
## Возвращает ключ устройства
## Возвращает ключ устройства.
func get_unit_key(unit_name: String) -> Array:
assert(UnitProfiles.has(unit_name), 'ошибка: нет такого устройства \"%s\"' % unit_name)
var item = UnitProfiles[unit_name]

View File

@@ -1,43 +1,43 @@
class_name Signaller extends Node
## Обмен сигналами между узлами. Здесь объявлены сигналы, которые используют
## Обмен сигналами между узлами. Здесь объявлены сигналы, которые используют.
## два и более узла, из разных файлов. Должен быть помещён в автозагрузку.
func conn(sgnl: Signal, clbl: Callable): connect(sgnl.get_name(), clbl)
## Вызывается при переходе в режим [b]Работа[/b]
## Вызывается при переходе в режим [b]Работа[/b].
signal режим_работа()
## Вызывается при переходе в режим [b]Контроль[/b]
## Вызывается при переходе в режим [b]Контроль[/b].
signal режимонтроль()
## Вызывается при переходе в режим [b]Журнал[/b]
## Вызывается при переходе в режим [b]Журнал[/b].
signal режимурнал()
## Вызывается при переходе в режим [b]ЭМС[/b]
## Вызывается при переходе в режим [b]ЭМС[/b].
signal режим_эмс()
## Вызывается при переходе в режим [b]Настройка[/b]
## Вызывается при переходе в режим [b]Настройка[/b].
signal режимастройки()
## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора цели и помехи[/b]
## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора цели и помехи[/b].
signal full_auto()
## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора цели[/b]
## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора цели[/b].
signal threat_auto()
## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора помехи[/b]
## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора помехи[/b].
signal interfer_auto()
## Вызывается, когда оператор переводит программу в режим [b]Ручной[/b]
## Вызывается, когда оператор переводит программу в режим [b]Ручной[/b].
signal manual_control()
@@ -59,21 +59,21 @@ signal full_screen(id: int)
## Вызывается, когда пользователь выбирает цель.[br]
## [param th_id] - Отметка цели на экране
## [param th_id] - Отметка цели на экране.
signal rto_threat_sel (th_id: int)
## Вызывается, когда пользователь нажимает на значёк цели.[br]
## [param th_id] - Отметка цели на экране
## [param th_id] - Отметка цели на экране.
signal bip_pressed (th_id: int)
## Вызывается, когда пользователь снимает выделение с цели.[br]
## [param th_id] - Отметка цели на экране
## [param th_id] - Отметка цели на экране.
signal rto_threat_unsel (th_id: int)
## Вызывается, когда пользователь снимает выделение со всех целей
## Вызывается, когда пользователь снимает выделение со всех целей.
signal rto_threat_unsel_all ()
@@ -100,40 +100,30 @@ signal interfer_new (ecm: interfer.Interfer)
signal interfer_off (ecm: interfer.Interfer, ecms: Dictionary, thrs: Dictionary)
## Вызывается при нажатии отключить все помехи
## Вызывается при нажатии отключить все помехи.
signal interfer_off_all ()
## Вызывается при получении внешнего целеуказания
## Вызывается при получении внешнего целеуказания.
## [param interfer_params] - Параметры полученной помехи от 5П-28.[br]
signal interfer_rcv(interfer_params: Array)
## Вызывается, когда отключается действующая помеха.[br]
## [param ecm] - Выбранная помеха
## [param ecm] - Выбранная помеха.
signal interfer_selected (ecm: interfer.Interfer)
## Вызывается, когда отключается выбираем помеху по сектору в таблице.[br]
## [param ecm] - Выбранная помеха
## [param ecm] - Выбранная помеха.
signal fs_selected(ecm: interfer.Interfer)
## Вызывается при запросе изменения уровня детализации карты.[br]
## [param zoom] - Вновь установленный уровень детализации
signal zoom_changed(zoom: int)
## Вызывается при завершении изменения уровня детализации карты.[br]
## [param zoom] - Вновь установленный уровень детализации
signal zoom_complete(zoom: int)
## Вызывается при изменении координат карты.[br]
## [param lan], [param lat] - Вновь установленные координаты.
signal map_coords_changed(lan: float, lat: float)
## Вызывается при изменении размера изображения для отображения карты.[br]
## [param mode] - Вновь установленный режим
## [param mode] - Вновь установленный режим.
signal map_mode_changed(mode: int)

View File

@@ -1,13 +1,13 @@
extends Node
class_name tcp5_p28 extends Node
## Реализация "Протокол информационного сопряжения
## СПО АСУ изделия «МП550» с СПО 5П-28"
## Реализация "Протокол информационного сопряжения.
## СПО АСУ изделия «МП550» с СПО 5П-28".
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от 5П-28, мс
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от 5П-28, мс.
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм.
## Тип модуляции для запаковки в пакет для 5П-28
## Тип модуляции для запаковки в пакет для 5П-28.
const MOD_TYPES: Array = ['',
'am',
'ook',
@@ -41,18 +41,18 @@ class TCP5P28:
const CMD_TYPE_TH: int = 2
const CMD_TYPE_IN: int = 3
signal line_changed(unit: TCP5P28) ## Сигнал состояние связи изменилось
signal data_received(unit: TCP5P28) ## Сигнал данные приняты
signal command_fail(unit: TCP5P28) ## Сигнал при не выполнении команды
signal parse_error(unit: TCP5P28, msg: String) ## Сигнал ошибки разбора сообщения
signal get_threats(unit: TCP5P28) ## Сигнал запрос целей
signal get_interfers(unit: TCP5P28) ## Запрос состояния выполнения целеуказания
signal line_changed(unit: TCP5P28) ## Сигнал состояние связи изменилось.
signal data_received(unit: TCP5P28) ## Сигнал данные приняты.
signal command_fail(unit: TCP5P28) ## Сигнал при не выполнении команды.
signal parse_error(unit: TCP5P28, msg: String) ## Сигнал ошибки разбора сообщения.
signal get_threats(unit: TCP5P28) ## Сигнал запрос целей.
signal get_interfers(unit: TCP5P28) ## Запрос состояния выполнения целеуказания.
var online: = false ## Состояние связи с источником сообщений
var name: String ## Имя экземпляра
var rx_tick: = 0 ## Тик время последнего приёма, мс
var tx_data: = PackedByteArray() ## Пакет для отправки
var tx_stack: Array ## Массив пакетов для отправки
var online: = false ## Состояние связи с источником сообщений.
var name: String ## Имя экземпляра.
var rx_tick: = 0 ## Тик время последнего приёма, мс.
var tx_data: = PackedByteArray() ## Пакет для отправки.
var tx_stack: Array ## Массив пакетов для отправки.
func _to_string() -> String: return String('капсрпб: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
func _init(nm): self.name = nm

View File

@@ -1,6 +1,6 @@
extends Node
## Работа с целями
## Работа с целями.
## Цель
@@ -26,7 +26,7 @@ class Threat:
var tick_rx: int ## Тик время обновления цели, мс.
var tmod: String ## Тип модуляции.
var width: float ## Ширина занимаемого диапазона частот, МГц.
var selected: bool ## Флаг, что цель выбрана
var selected: bool ## Флаг, что цель выбрана.
func _init(): clear_fflags()
func _to_string() -> String: return 'номер: %d пеленг: %0.1f частота: %0.1f МГц' % [id, aoa, freq]
@@ -62,7 +62,7 @@ func _ready() -> void:
signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(threats))
signaller.connect('interfer_init', Callable(self, 'on_interfer_init').bind(threats))
## Периодически удаляет устаревшие цели
## Периодически удаляет устаревшие цели.
func on_timer_check_lost(time_lost: int, threats: Dictionary):
var tick = Time.get_ticks_msec()
var sz: = threats.size()
@@ -74,7 +74,7 @@ func on_timer_check_lost(time_lost: int, threats: Dictionary):
call_deferred('emit_signal', 'threats_resized', threats)
## отправляет словарь целей в юнит, для запаковки и отправки в 5П28
## отправляет словарь целей в юнит, для запаковки и отправки в 5П28.
func on_get_threats(unit, threats): unit.pack_threats(threats)
@@ -82,7 +82,7 @@ func on_get_threats(unit, threats): unit.pack_threats(threats)
func on_rto_threat_unsel(th_id, threats): threats[th_id].selected = false
## Снимает выделение со всех целей
## Снимает выделение со всех целей.
func on_rto_threat_unsel_all(threats):
for th in threats.values():
signaller.emit_signal('rto_threat_unsel', th.id)
@@ -92,14 +92,14 @@ func on_rto_threat_unsel_all(threats):
func on_rto_threat_sel(th_id, threats): on_threat_selected(threats[th_id], threats)
## Выбирает цель, если выбрать в таблице
## Выбирает цель, если выбрать в таблице.
func on_threat_selected(th, threats):
for threat in threats.values():
threat.selected = false
th.selected = true
## Формирует список выбранных целей для включения помехи
## Формирует список выбранных целей для включения помехи.
func on_interfer_init(btn, fs_arr, threats):
var sel_threats: Array = []
for threat in threats.values():
@@ -109,7 +109,7 @@ func on_interfer_init(btn, fs_arr, threats):
signaller.emit_signal('interfer_create', btn, sel_threats, fs_arr)
## Производит приём целей
## Производит приём целей.
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, threats: Dictionary):
if not unit.json_dic.has('ts'): return
if unit.json_dic['ts'] != 5: return

View File

@@ -1,10 +1,10 @@
@tool
extends Node
class_name Tools extends Node
## Простые часто используемые функции
## Простые часто используемые функции.
## Возвращает округлённое значение [param v] с точностью [param a]
## Возвращает округлённое значение [param v] с точностью [param a].
func round_to(v: float, a: float) -> float: return snappedf(v, -a if v < 0 else a)
@@ -21,7 +21,7 @@ func radians(val: float): return (val * PI) / 180.0
func ibytes_to_word(buf: PackedByteArray, i: int) -> int: return buf[i] + (buf[i + 1] * 256)
## Возвращает расстояние от центра координат до точки
## Возвращает расстояние от центра координат до точки.
func hypot(x: float, y: float) -> float: return sqrt(x * x + y * y)
@@ -70,21 +70,21 @@ func get_string_slice(s_in: String, s_out: Array, i0: int, i1: int):
s_out[0] += s_in[i]
## Производит преобразование из декартовой в полярную систему координат
## Производит преобразование из декартовой в полярную систему координат.
func pos_calc(freq: float, aoa: float, pos0: Vector2, r0: float, r1: float, f0: float, f1: float):
var r = ((freq - f0) / (f1 - f0)) * r1 + r0
var aoa_rad = radians(aoa) - PI / 2.0
return Vector2(cos(aoa_rad), sin(aoa_rad)) * r + pos0
## Отсекает значение до заданного диапазона
## Отсекает значение до заданного диапазона.
func clip_value(val, val_min, val_max):
if val < val_min: val = val_min
if val > val_max: val = val_max
return val
## Возвращает массив с именами членов [param obj]
## Возвращает массив с именами членов [param obj].
func get_members_names(obj: Object) -> Array:
var pl = obj.get_property_list()
var names: = Array()
@@ -92,7 +92,7 @@ func get_members_names(obj: Object) -> Array:
return names
## Проверяет, что заданный массив [param val] похож на ip-адрес
## Проверяет, что заданный массив [param val] похож на ip-адрес.
func is_array_ipaddr(val: Array):
return (val.size() == 2) \
and (val[0] is String) \
@@ -111,7 +111,7 @@ func map_dec_to_rad(pos0: Vector2, pos: Vector2) -> Vector2:
return Vector2(ang + 360.0 * float(ang < 0.0), hypot(x1, y1))
## Переводит значение val из диапазона a0...a1 в диапазон b0...b1
## Переводит значение val из диапазона a0...a1 в диапазон b0...b1.
func map_range(val: float, a0: float, a1: float, b0: float, b1: float) -> float:
return (((val - a0) * (b1 - b0)) / (a1 - a0)) + b0
@@ -131,7 +131,7 @@ func is_point_in_polygon(pos: Vector2, p: PackedVector2Array) -> bool:
return odd_nodes > 0
## Записывает слово [param val] в элемент байтовго массива [param buf]
## Записывает слово [param val] в элемент байтовго массива [param buf].
## расположенный по индексу [param index] (младшее слово).[br]
## [i]Следует использовать встроенные в[/i] [b]PackedByteArray[/b] [i]методы вместо этой функции.[/i]
func set_wordi(buf: PackedByteArray, index: int, val: int) -> void:

View File

@@ -1,6 +1,6 @@
extends Node
class_name yau_07 extends Node
## Протокол ячейки ЯУ-07
## Протокол ячейки ЯУ-07.
const ONLINE_TIMEOUT = 5.0 ## Время ожидания пакета от ячейки, секунды
const RESEND_TIMEOUT = 0.3 ## Задержка для повторной отправки команды, секунды
@@ -8,47 +8,47 @@ const RETRY_COUNT = 5 ## Количество повторных отпр
const BUFFER_SIZE = 2048 ## Размер буфера для приёма датаграмм
## Ячейка ЯУ-07
## Ячейка ЯУ-07.
class YaU07:
## Коды выполняемых команд
## Коды выполняемых команд.
enum CmdCode {
READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07
WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07
WRITE_BLOCK = 60, ## Код команды "записать блок данных ISA" внешней шины ячейки ЯУ-07
READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07
READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07.
WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07.
WRITE_BLOCK = 60, ## Код команды "записать блок данных ISA" внешней шины ячейки ЯУ-07.
READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07.
}
## Состояние автомата выполнения команды
## Состояние автомата выполнения команды.
enum CmdState {
UNCK, ## Номер команды не ининциирован
SEND, ## Буфер готов для отправки
WAIT, ## Ожидание выполнения
DONE, ## Команда выполнена
FAIL ## Команда не выполнена
UNCK, ## Номер команды не ининциирован.
SEND, ## Буфер готов для отправки.
WAIT, ## Ожидание выполнения.
DONE, ## Команда выполнена.
FAIL ## Команда не выполнена.
}
signal line_changed(unit: YaU07) ## Вызывается когда меняется состояние связи с ячейкой
signal command_done(unit: YaU07) ## Вызывается после выполнения команды
signal command_fail(unit: YaU07) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена
signal line_changed(unit: YaU07) ## Вызывается когда меняется состояние связи с ячейкой.
signal command_done(unit: YaU07) ## Вызывается после выполнения команды.
signal command_fail(unit: YaU07) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена.
signal parse_failed(unit: YaU07)
var name: = String()
var cmd_num_rx: = 0 ## Номер команды принятый
var cmd_num_tx: = 0 ## Номер команды переданный
var cmd_state = CmdState.UNCK ## Состояние выполнения команды
var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07
var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду
var tick = 0.0 ## Текущее тик-время в мс
var cmd_tick_tx = 0.0 ## Время последней отправки команды
var cmd_tick_rx = 0.0 ## Время последнего приёма команды
var status: = PackedByteArray() ## Поле "состояние прибора"
var tx_data: = PackedByteArray() ## Буфер отправленный
var tx_len = 0 ## Длина последнего отправленного пакета
var isa_ports = {} ## Результат выполнения команды "читать порт"
var isa_block = {} ## Результат выполнения команды "читать массив из порта"
var online = false ## Состояние связи с ячейкой
var cmd_num_rx: = 0 ## Номер команды принятый.
var cmd_num_tx: = 0 ## Номер команды переданный.
var cmd_state = CmdState.UNCK ## Состояние выполнения команды.
var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07.
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07.
var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду.
var tick = 0.0 ## Текущее тик-время в мс.
var cmd_tick_tx = 0.0 ## Время последней отправки команды.
var cmd_tick_rx = 0.0 ## Время последнего приёма команды.
var status: = PackedByteArray() ## Поле "состояние прибора".
var tx_data: = PackedByteArray() ## Буфер отправленный.
var tx_len = 0 ## Длина последнего отправленного пакета.
var isa_ports = {} ## Результат выполнения команды "читать порт".
var isa_block = {} ## Результат выполнения команды "читать массив из порта".
var online = false ## Состояние связи с ячейкой.
func _to_string() -> String: return String('яу07: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
@@ -134,9 +134,9 @@ class YaU07:
tx_data.encode_u16(9, int(port[0]))
cmd_state = CmdState.SEND
return true
## Возвращает код команды ЯУ-07
## rx_data - Принятые данные
## Возвращает - Код команды не найден, 0...255 - код команды
## Возвращает код команды ЯУ-07.
## rx_data - Принятые данные.
## Возвращает - Код команды не найден, 0...255 - код команды.
func get_cmd_code(rx_data: PackedByteArray):
var rx_data_len = rx_data.size()
@@ -185,11 +185,11 @@ class YaU07:
return true
## Заполняет состояние прибора данными прочитанными из портов ЯУ-07
## для команд "читать порты" или "записать порты"[br]
## [param rx_data] - Принятые данные[br]
## Возвращает [b]true[/b] - Данные обработаны успешно[br]
## Возвращает [b]false[/b] - Данные не обработаны из за ошибки[br]
## Заполняет состояние прибора данными прочитанными из портов ЯУ-07.
## для команд "читать порты" или "записать порты".[br]
## [param rx_data] - Принятые данные.[br]
## Возвращает [b]true[/b] - Данные обработаны успешно.[br]
## Возвращает [b]false[/b] - Данные не обработаны из за ошибки.[br]
func parse(rx_data: PackedByteArray) -> bool:
cmd_tick_rx = tick

View File

@@ -1,15 +1,15 @@
extends Node
class_name yems_boards extends Node
class EmsBoard:
var id_board: String
var in_devs: Dictionary ## Словарь с входными устройствами
var out_devs: Dictionary ## Словарь с выходными устройствами
var base_addr_isa: int ## Базовый адрес ячейки isa
var in_tbl: Array
var out_tbl: Array
var id_board: String
var in_devs: Dictionary ## Словарь с входными устройствами.
var out_devs: Dictionary ## Словарь с выходными устройствами.
var base_addr_isa: int ## Базовый адрес ячейки isa.
var in_tbl: Array
var out_tbl: Array
func _init(id, base_addr, in_table, out_table):
id_board = id
in_tbl = in_table
out_tbl = out_table
base_addr_isa = base_addr
func _init(id, base_addr, in_table, out_table):
id_board = id
in_tbl = in_table
out_tbl = out_table
base_addr_isa = base_addr

View File

@@ -1,144 +1,144 @@
extends Node
class_name yerms_consts extends Node
##
## Таблица с данными для входов, первое значение - индекс устройства в ячейке КЭМС.
const INPUT_ROWS1 = [
[12,['283333 МР-231S, Строб ЭМС', 'X52', '0.00', '0.00']],
[13,['29НРЛС МР-231-3, УИЗП', 'X54', '0.00', '0.00']],
[14,['30НРЛС МР-231-3, Строб ЭМС', 'X55', '0.00', '0.00']],
[15,['31ЦИСВС-1010, УИЗП', 'X23', '0.00', '0.00']],
[21,['32НРЛС МР-231S, УИЗП', 'X21', '0.00', '0.00']],
[22,['33НРЛС МР-231S, Строб ЭМС', 'X22', '0.00', '0.00']],
[23,['34НРЛС МР-231-3, УИЗП', 'X24', '0.00', '0.00']],
[32,['352222 МР-231S, Строб ЭМС', 'X32', '0.00', '0.00']],
[33,['36НРЛС МР-231-3, УИЗП', 'X34', '0.00', '0.00']],
[34,['37НРЛС МР-231-3, Строб ЭМС', 'X35', '0.00', '0.00']],
[35,['38ЦИСВС-1010, УИЗП', 'X43', '0.00', '0.00']],
[38,['394302-01, 4302-04, УИЗП', 'X46', '0.00', '0.00']],
[31,['40НРЛС МР-231S, УИЗП', 'X51', '0.00', '0.00']]]
[12,['283333 МР-231S, Строб ЭМС', 'X52', '0.00', '0.00']],
[13,['29НРЛС МР-231-3, УИЗП', 'X54', '0.00', '0.00']],
[14,['30НРЛС МР-231-3, Строб ЭМС', 'X55', '0.00', '0.00']],
[15,['31ЦИСВС-1010, УИЗП', 'X23', '0.00', '0.00']],
[21,['32НРЛС МР-231S, УИЗП', 'X21', '0.00', '0.00']],
[22,['33НРЛС МР-231S, Строб ЭМС', 'X22', '0.00', '0.00']],
[23,['34НРЛС МР-231-3, УИЗП', 'X24', '0.00', '0.00']],
[32,['352222 МР-231S, Строб ЭМС', 'X32', '0.00', '0.00']],
[33,['36НРЛС МР-231-3, УИЗП', 'X34', '0.00', '0.00']],
[34,['37НРЛС МР-231-3, Строб ЭМС', 'X35', '0.00', '0.00']],
[35,['38ЦИСВС-1010, УИЗП', 'X43', '0.00', '0.00']],
[38,['394302-01, 4302-04, УИЗП', 'X46', '0.00', '0.00']],
[31,['40НРЛС МР-231S, УИЗП', 'X51', '0.00', '0.00']]]
## Таблица с данными для выходов, первое значение - индекс устройства в ячейке КЭМС
## Таблица с данными для выходов, первое значение - индекс устройства в ячейке КЭМС.
const OUTPUT_ROWS1 = [
[41,['41НРЛС МР-231S, БИ', 'X61', '0.00', '0.00']],
[42,['42НРЛС МР-231S', 'X62', '0.00', '0.00']],
[43,['43НРЛС МР-231-3, БИ', 'X64', '0.00', '0.00']],
[44,['44НРЛС МР-231-3', 'X65', '0.00', '0.00']],
[45,['45ЦИСВС-1010, БИ', 'X63', '0.00', '0.00']],
[46,['464302-01, 4302-04, БИ', 'X66', '0.00', '0.00']],
[48,['47НРЛС 11111111', 'X69', '0.00', '0.00']],
[62,['48НРЛС МР-231S', 'X62', '0.00', '0.00']],
[63,['49НРЛС МР-231-3, БИ', 'X64', '0.00', '0.00']],
[64,['50НРЛС МР-231-3', 'X65', '0.00', '0.00']],
[65,['51ЦИСВС-1010, БИ', 'X63', '0.00', '0.00']],
[66,['524302-01, 4302-04, БИ', 'X66', '0.00', '0.00']],
[68,['53НРЛС 11111111', 'X69', '0.00', '0.00']]]
[41,['41НРЛС МР-231S, БИ', 'X61', '0.00', '0.00']],
[42,['42НРЛС МР-231S', 'X62', '0.00', '0.00']],
[43,['43НРЛС МР-231-3, БИ', 'X64', '0.00', '0.00']],
[44,['44НРЛС МР-231-3', 'X65', '0.00', '0.00']],
[45,['45ЦИСВС-1010, БИ', 'X63', '0.00', '0.00']],
[46,['464302-01, 4302-04, БИ', 'X66', '0.00', '0.00']],
[48,['47НРЛС 11111111', 'X69', '0.00', '0.00']],
[62,['48НРЛС МР-231S', 'X62', '0.00', '0.00']],
[63,['49НРЛС МР-231-3, БИ', 'X64', '0.00', '0.00']],
[64,['50НРЛС МР-231-3', 'X65', '0.00', '0.00']],
[65,['51ЦИСВС-1010, БИ', 'X63', '0.00', '0.00']],
[66,['524302-01, 4302-04, БИ', 'X66', '0.00', '0.00']],
[68,['53НРЛС 11111111', 'X69', '0.00', '0.00']]]
## Таблица с данными для входов, первое значение - индекс устройства в ячейке КЭМС
## Таблица с данными для входов, первое значение - индекс устройства в ячейке КЭМС.
const INPUT_ROWS = [
[1,['УИЗП №1', 'Х7', '0.00', '0.00']],
[2,['УИЗПФ №1', 'Х8', '0.00', '0.00']],
[3,['УИЗП №2', 'Х10', '0.00', '0.00']],
[4,['УИЗПФ №2', 'Х11', '0.00', '0.00']],
[5,['УИЗП №3', 'Х13', '0.00', '0.00']],
[6,['УИЗПФ №3', 'Х14', '0.00', '0.00']],
[7,['УИЗП №4', 'Х16', '0.00', '0.00']],
[8,['УИЗПФ №4', 'Х17', '0.00', '0.00']],
[9,['УИЗП №5', 'Х19', '0.00', '0.00']],
[10,['УИЗПФ №5', 'Х20', '0.00', '0.00']],
[11,['УИЗП №6', 'Х22', '0.00', '0.00']],
[12,['УИЗПФ №6','Х23', '0.00', '0.00']],
[13,['УИЗП №7','Х25', '0.00', '0.00']],
[14,['УИЗПФ №7','Х26', '0.00', '0.00']],
[15,['СИ1 Л1','X31 : 2', '0.00', '0.00']],
[16,['СИ1 Л6','X31 : 5', '0.00', '0.00']],
[17,['СИ1 Л7','X31 : 8', '0.00', '0.00']],
[18,['СИ2 Л1','X32 : 2', '0.00', '0.00']],
[19,['СИ2 Л6','X32 : 5', '0.00', '0.00']],
[20,['СИ2 Л7','X32 : 8', '0.00', '0.00']],
[21,['СИ3 Л1','X33 : 2', '0.00', '0.00']],
[22,['СИ3 Л6','X33 : 5', '0.00', '0.00']],
[23,['СИ3 Л7','X33 : 8', '0.00', '0.00']],
[24,['СИ4 Л1','X34 : 2', '0.00', '0.00']],
[25,['СИ4 Л6','X34 : 5', '0.00', '0.00']],
[26,['СИ4 Л7','X34 : 8', '0.00', '0.00']],
[27,['СИ1 Л2','X38 : 2', '0.00', '0.00']],
[28,['СИ1 Л3','X38 : 5', '0.00', '0.00']],
[29,['СИ2 Л2','X39 : 2', '0.00', '0.00']],
[30,['СИ2 Л3','X39 : 5', '0.00', '0.00']],
[31,['СИ3 Л2','X40 : 2', '0.00', '0.00']],
[32,['СИ3 Л3','X40 : 5', '0.00', '0.00']],
[33,['СИ4 Л2','X41 : 2', '0.00', '0.00']],
[34,['СИ4 Л3','X41 : 5', '0.00', '0.00']],
[35,['СИ1 Л4','X42 : 2', '0.00', '0.00']],
[36,['СИ1 Л5','X42 : 5', '0.00', '0.00']],
[37,['СИ2 Л4','X43 : 2', '0.00', '0.00']],
[38,['СИ2 Л5','X43 : 5', '0.00', '0.00']],
[39,['СИ3 Л4','X44 : 2', '0.00', '0.00']],
[40,['СИ3 Л5','X44 : 5', '0.00', '0.00']],
[41,['СИ4 Л4','X45 : 2', '0.00', '0.00']],
[42,['СИ4 Л5','X45 : 5', '0.00', '0.00']],
[43,['БИ В Лб','Х49 : 37', '0.00', '0.00']],
[44,['БИ В ПрБ','Х49 : 31', '0.00', '0.00']],
[45,['БИ Г Лб','Х49 : 15', '0.00', '0.00']],
[46,['БИ Г ПрБ','Х49 : 8', '0.00', '0.00']],
[47,['БИ Д Лб','Х49 : 6', '0.00', '0.00']],
[48,['БИ Д ПрБ','Х49 : 10', '0.00', '0.00']],
[49,['БИ Е Лб','Х49 : 25', '0.00', '0.00']],
[50,['БИ Е ПрБ','Х49 : 40', '0.00', '0.00']],
[51,['СЗИ В Лб','Х49 : 42', '0.00', '0.00']],
[52,['СЗИ В ПрБ','Х49 : 32', '0.00', '0.00']],
[53,['СЗИ Г Лб','Х49 : 46', '0.00', '0.00']],
[54,['СЗИ Г ПрБ','Х49 : 32', '0.00', '0.00']],
[55,['СЗИ Д Лб','Х49 : 16', '0.00', '0.00']],
[56,['СЗИ Д ПрБ','Х49 : 47', '0.00', '0.00']],
[57,['СЗИ Е Лб','Х49 : 1', '0.00', '0.00']],
[58,['СЗИ Е ПрБ','Х49 : 50', '0.00', '0.00']]]
[1,['УИЗП №1', 'Х7', '0.00', '0.00']],
[2,['УИЗПФ №1', 'Х8', '0.00', '0.00']],
[3,['УИЗП №2', 'Х10', '0.00', '0.00']],
[4,['УИЗПФ №2', 'Х11', '0.00', '0.00']],
[5,['УИЗП №3', 'Х13', '0.00', '0.00']],
[6,['УИЗПФ №3', 'Х14', '0.00', '0.00']],
[7,['УИЗП №4', 'Х16', '0.00', '0.00']],
[8,['УИЗПФ №4', 'Х17', '0.00', '0.00']],
[9,['УИЗП №5', 'Х19', '0.00', '0.00']],
[10,['УИЗПФ №5', 'Х20', '0.00', '0.00']],
[11,['УИЗП №6', 'Х22', '0.00', '0.00']],
[12,['УИЗПФ №6','Х23', '0.00', '0.00']],
[13,['УИЗП №7','Х25', '0.00', '0.00']],
[14,['УИЗПФ №7','Х26', '0.00', '0.00']],
[15,['СИ1 Л1','X31 : 2', '0.00', '0.00']],
[16,['СИ1 Л6','X31 : 5', '0.00', '0.00']],
[17,['СИ1 Л7','X31 : 8', '0.00', '0.00']],
[18,['СИ2 Л1','X32 : 2', '0.00', '0.00']],
[19,['СИ2 Л6','X32 : 5', '0.00', '0.00']],
[20,['СИ2 Л7','X32 : 8', '0.00', '0.00']],
[21,['СИ3 Л1','X33 : 2', '0.00', '0.00']],
[22,['СИ3 Л6','X33 : 5', '0.00', '0.00']],
[23,['СИ3 Л7','X33 : 8', '0.00', '0.00']],
[24,['СИ4 Л1','X34 : 2', '0.00', '0.00']],
[25,['СИ4 Л6','X34 : 5', '0.00', '0.00']],
[26,['СИ4 Л7','X34 : 8', '0.00', '0.00']],
[27,['СИ1 Л2','X38 : 2', '0.00', '0.00']],
[28,['СИ1 Л3','X38 : 5', '0.00', '0.00']],
[29,['СИ2 Л2','X39 : 2', '0.00', '0.00']],
[30,['СИ2 Л3','X39 : 5', '0.00', '0.00']],
[31,['СИ3 Л2','X40 : 2', '0.00', '0.00']],
[32,['СИ3 Л3','X40 : 5', '0.00', '0.00']],
[33,['СИ4 Л2','X41 : 2', '0.00', '0.00']],
[34,['СИ4 Л3','X41 : 5', '0.00', '0.00']],
[35,['СИ1 Л4','X42 : 2', '0.00', '0.00']],
[36,['СИ1 Л5','X42 : 5', '0.00', '0.00']],
[37,['СИ2 Л4','X43 : 2', '0.00', '0.00']],
[38,['СИ2 Л5','X43 : 5', '0.00', '0.00']],
[39,['СИ3 Л4','X44 : 2', '0.00', '0.00']],
[40,['СИ3 Л5','X44 : 5', '0.00', '0.00']],
[41,['СИ4 Л4','X45 : 2', '0.00', '0.00']],
[42,['СИ4 Л5','X45 : 5', '0.00', '0.00']],
[43,['БИ В Лб','Х49 : 37', '0.00', '0.00']],
[44,['БИ В ПрБ','Х49 : 31', '0.00', '0.00']],
[45,['БИ Г Лб','Х49 : 15', '0.00', '0.00']],
[46,['БИ Г ПрБ','Х49 : 8', '0.00', '0.00']],
[47,['БИ Д Лб','Х49 : 6', '0.00', '0.00']],
[48,['БИ Д ПрБ','Х49 : 10', '0.00', '0.00']],
[49,['БИ Е Лб','Х49 : 25', '0.00', '0.00']],
[50,['БИ Е ПрБ','Х49 : 40', '0.00', '0.00']],
[51,['СЗИ В Лб','Х49 : 42', '0.00', '0.00']],
[52,['СЗИ В ПрБ','Х49 : 32', '0.00', '0.00']],
[53,['СЗИ Г Лб','Х49 : 46', '0.00', '0.00']],
[54,['СЗИ Г ПрБ','Х49 : 32', '0.00', '0.00']],
[55,['СЗИ Д Лб','Х49 : 16', '0.00', '0.00']],
[56,['СЗИ Д ПрБ','Х49 : 47', '0.00', '0.00']],
[57,['СЗИ Е Лб','Х49 : 1', '0.00', '0.00']],
[58,['СЗИ Е ПрБ','Х49 : 50', '0.00', '0.00']]]
## Таблица с данными для выходов, первое значение - индекс устройства в ячейке КЭМС
## Таблица с данными для выходов, первое значение - индекс устройства в ячейке КЭМС.
const OUTPUT_ROWS = [
[11,['Бланк №1','Х6', '0.00', '0.00']],
[12,['Бланк №2','Х9', '0.00', '0.00']],
[13,['Бланк №3','Х12', '0.00', '0.00']],
[14,['Бланк №4','Х15', '0.00', '0.00']],
[15,['Бланк №5','Х18', '0.00', '0.00']],
[16,['Бланк №6','Х21', '0.00', '0.00']],
[17,['Бланк №7','Х24', '0.00', '0.00']],
[18,['СЗИ1 Л1','X31 : 11', '0.00', '0.00']],
[19,['СЗИ1 Л6','X31 :14', '0.00', '0.00']],
[20,['СЗИ1 Л7','X31 : 17', '0.00', '0.00']],
[21,['СЗИ2 Л1','X32 : 11', '0.00', '0.00']],
[22,['СЗИ2 Л6','X32 : 14', '0.00', '0.00']],
[23,['СЗИ2 Л7','X32: 17', '0.00', '0.00']],
[24,['СЗИ3 Л1','X33 : 11', '0.00', '0.00']],
[25,['СЗИ3 Л6','X33 :14', '0.00', '0.00']],
[26,['СЗИ3 Л7','X33: 17', '0.00', '0.00']],
[27,['СЗИ4 Л1','X34 : 11', '0.00', '0.00']],
[28,['СЗИ4 Л6','X34 :14', '0.00', '0.00']],
[29,['СЗИ4 Л7','X34: 17', '0.00', '0.00']],
[30,['СЗИ1 Л2','X38 : 11', '0.00', '0.00']],
[31,['СЗИ1 Л3','X38 : 14', '0.00', '0.00']],
[32,['СЗИ2 Л2','X39 : 11', '0.00', '0.00']],
[33,['СЗИ2 Л3','X39 : 14', '0.00', '0.00']],
[34,['СЗИ3 Л2','X40 : 11', '0.00', '0.00']],
[35,['СЗИ3 Л3','X40 : 14', '0.00', '0.00']],
[36,['СЗИ4 Л2','X41 : 11', '0.00', '0.00']],
[37,['СЗИ4 Л3','X41 :14', '0.00', '0.00']],
[38,['СЗИ1 Л4','X42 : 11', '0.00', '0.00']],
[39,['СЗИ1 Л5','X42 :14', '0.00', '0.00']],
[40,['СЗИ2 Л4','X43 : 11', '0.00', '0.00']],
[41,['СЗИ2 Л5','X43 : 14', '0.00', '0.00']],
[42,['СЗИ3 Л4','X44 : 11', '0.00', '0.00']],
[43,['СЗИ3 Л5','X44 :14', '0.00', '0.00']],
[44,['СЗИ4 Л4','X45 : 11', '0.00', '0.00']],
[45,['СЗИ4 Л5','X45 : 14', '0.00', '0.00']],
[46,['БИ РТР №1','X47 : 2', '0.00', '0.00']],
[47,['БИ РТР №2','X47 : 5', '0.00', '0.00']],
[48,['БИ РТР №3','X47 : 8', '0.00', '0.00']],
[49,['БИ РТР №4','X47 : 11', '0.00', '0.00']],
[50,['СИ В Лб','Х49 : 21', '0.00', '0.00']],
[51,['СИ В ПрБ','Х49 : 19', '0.00', '0.00']],
[52,['СИ Г Лб','Х49 : 28', '0.00', '0.00']],
[53,['СИ Г ПрБ','Х49 : 30', '0.00', '0.00']],
[54,['СИ Д Лб','Х49 : 13', '0.00', '0.00']],
[55,['СИ Д ПрБ','Х49 : 11', '0.00', '0.00']],
[56,['СИ Е Лб','Х49 : 26', '0.00', '0.00']],
[57,['СИ Е ПрБ','Х49 : 35', '0.00', '0.00']]]
[11,['Бланк №1','Х6', '0.00', '0.00']],
[12,['Бланк №2','Х9', '0.00', '0.00']],
[13,['Бланк №3','Х12', '0.00', '0.00']],
[14,['Бланк №4','Х15', '0.00', '0.00']],
[15,['Бланк №5','Х18', '0.00', '0.00']],
[16,['Бланк №6','Х21', '0.00', '0.00']],
[17,['Бланк №7','Х24', '0.00', '0.00']],
[18,['СЗИ1 Л1','X31 : 11', '0.00', '0.00']],
[19,['СЗИ1 Л6','X31 :14', '0.00', '0.00']],
[20,['СЗИ1 Л7','X31 : 17', '0.00', '0.00']],
[21,['СЗИ2 Л1','X32 : 11', '0.00', '0.00']],
[22,['СЗИ2 Л6','X32 : 14', '0.00', '0.00']],
[23,['СЗИ2 Л7','X32: 17', '0.00', '0.00']],
[24,['СЗИ3 Л1','X33 : 11', '0.00', '0.00']],
[25,['СЗИ3 Л6','X33 :14', '0.00', '0.00']],
[26,['СЗИ3 Л7','X33: 17', '0.00', '0.00']],
[27,['СЗИ4 Л1','X34 : 11', '0.00', '0.00']],
[28,['СЗИ4 Л6','X34 :14', '0.00', '0.00']],
[29,['СЗИ4 Л7','X34: 17', '0.00', '0.00']],
[30,['СЗИ1 Л2','X38 : 11', '0.00', '0.00']],
[31,['СЗИ1 Л3','X38 : 14', '0.00', '0.00']],
[32,['СЗИ2 Л2','X39 : 11', '0.00', '0.00']],
[33,['СЗИ2 Л3','X39 : 14', '0.00', '0.00']],
[34,['СЗИ3 Л2','X40 : 11', '0.00', '0.00']],
[35,['СЗИ3 Л3','X40 : 14', '0.00', '0.00']],
[36,['СЗИ4 Л2','X41 : 11', '0.00', '0.00']],
[37,['СЗИ4 Л3','X41 :14', '0.00', '0.00']],
[38,['СЗИ1 Л4','X42 : 11', '0.00', '0.00']],
[39,['СЗИ1 Л5','X42 :14', '0.00', '0.00']],
[40,['СЗИ2 Л4','X43 : 11', '0.00', '0.00']],
[41,['СЗИ2 Л5','X43 : 14', '0.00', '0.00']],
[42,['СЗИ3 Л4','X44 : 11', '0.00', '0.00']],
[43,['СЗИ3 Л5','X44 :14', '0.00', '0.00']],
[44,['СЗИ4 Л4','X45 : 11', '0.00', '0.00']],
[45,['СЗИ4 Л5','X45 : 14', '0.00', '0.00']],
[46,['БИ РТР №1','X47 : 2', '0.00', '0.00']],
[47,['БИ РТР №2','X47 : 5', '0.00', '0.00']],
[48,['БИ РТР №3','X47 : 8', '0.00', '0.00']],
[49,['БИ РТР №4','X47 : 11', '0.00', '0.00']],
[50,['СИ В Лб','Х49 : 21', '0.00', '0.00']],
[51,['СИ В ПрБ','Х49 : 19', '0.00', '0.00']],
[52,['СИ Г Лб','Х49 : 28', '0.00', '0.00']],
[53,['СИ Г ПрБ','Х49 : 30', '0.00', '0.00']],
[54,['СИ Д Лб','Х49 : 13', '0.00', '0.00']],
[55,['СИ Д ПрБ','Х49 : 11', '0.00', '0.00']],
[56,['СИ Е Лб','Х49 : 26', '0.00', '0.00']],
[57,['СИ Е ПрБ','Х49 : 35', '0.00', '0.00']]]

View File

@@ -1,19 +1,19 @@
extends Node
class_name yems_dev extends Node
class InDev:
var id: int ## Идентификатор индекс устройства
var dev_name: String ## Имя подключаемого комплекса
var connector: String ## Номер разъёма в приборе
var delay: float ## Задержка фронта импульса
var offset: float ## Смещение фронта импульса
var state: int ## Состояние входа
var freq: int ## Предполагаемая частота на которой работает комплекс
var ports_data: Dictionary ## Словарь состояния портов устройства
var tbl_row_id: int ## Индекс устройства в таблице выходов
var out_dots: Array ## Список выходных устройств в порядке, как в таблице и точки матрицы
var connect_devs: Dictionary ## Список присоединённых устройств
var board: String ## Плата в которой находится устройство
var id: int ## Идентификатор индекс устройства.
var dev_name: String ## Имя подключаемого комплекса.
var connector: String ## Номер разъёма в приборе.
var delay: float ## Задержка фронта импульса.
var offset: float ## Смещение фронта импульса.
var state: int ## Состояние входа.
var freq: int ## Предполагаемая частота на которой работает комплекс.
var ports_data: Dictionary ## Словарь состояния портов устройства.
var tbl_row_id: int ## Индекс устройства в таблице выходов.
var out_dots: Array ## Список выходных устройств в порядке, как в таблице и точки матрицы.
var connect_devs: Dictionary ## Список присоединённых устройств.
var board: String ## Плата в которой находится устройство.
func _init(dev_id : int, params : Array, row_id : int):
id = dev_id
@@ -25,7 +25,7 @@ class InDev:
class OutDev extends InDev:
var mode: String ## Режим работы выхода
var mode: String ## Режим работы выхода.
func _init(dev_id : int, params : Array, row_id : int):
id = dev_id

View File

@@ -3,17 +3,24 @@ shader_type canvas_item;
#include "res://shaders/tools.gdshaderinc"
/* Закрашенная окружность */
uniform vec4 color: source_color = vec4(1, 1, 1, 1);
uniform vec4 color_up: source_color = vec4(1, 1, 1, 1); /* Цвет вспышки при обновлении */
uniform uint tick_update = 0; /* Время последнего обновления, мс */
const float time_delta = 0.1; /* Время вспышки при обновлении, c */
uniform float tick_update = 0.0; /* Время последнего обновления, мс */
const float time_delta = 0.5; /* Время вспышки при обновлении, c */
const float ds = 0.01; /* Относительное расстояние на котором выполняется сглаживание краёв */
const vec2 center = vec2(0.125, 0.125); /* Центр должен быть в (0.5, 0.5), но это не так */
const float radius = 0.075 - ds * 2.0; /* Радиус должен быть 0.5, но это не так */
const float alpha_offset = 0.15; /* Изменние скорости альфа канала */
void fragment()
{
float time_now = TIME;
float alpha = 1.0;
if ((time_now - tick_update) < time_delta)
{
alpha = (time_delta - (time_now - tick_update)) * alpha_offset;
}
else{
alpha = 0.0;
}
vec4 color = vec4(0.972549, 0.12549, 0.411765, 1.0 - alpha);
COLOR = color * smooth_px(length(UV - center), radius, ds);
}