diff --git a/addons/godot-logger/README.md b/addons/godot-logger/README.md index 416382e..0d6f598 100644 --- a/addons/godot-logger/README.md +++ b/addons/godot-logger/README.md @@ -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: diff --git a/addons/godot-logger/scripts/logger.gd b/addons/godot-logger/scripts/logger.gd index 1648f79..8110466 100644 --- a/addons/godot-logger/scripts/logger.gd +++ b/addons/godot-logger/scripts/logger.gd @@ -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: diff --git a/addons/godot-logger/scripts/logger_output.gd b/addons/godot-logger/scripts/logger_output.gd index 539daac..ae31ad2 100644 --- a/addons/godot-logger/scripts/logger_output.gd +++ b/addons/godot-logger/scripts/logger_output.gd @@ -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") diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..c6f5925 --- /dev/null +++ b/build.sh @@ -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}" diff --git a/data/main-font.tres b/data/main-font.tres index 92f7276..c54b9b0 100644 --- a/data/main-font.tres +++ b/data/main-font.tres @@ -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) diff --git a/data/Изделие МП-550.png b/data/Изделие МП-550.png index 41ae78a..0e22de5 100644 Binary files a/data/Изделие МП-550.png and b/data/Изделие МП-550.png differ diff --git a/data/Окно.png b/data/Окно.png new file mode 100644 index 0000000..18d7d28 Binary files /dev/null and b/data/Окно.png differ diff --git a/data/Окно.png.import b/data/Окно.png.import new file mode 100644 index 0000000..813193a --- /dev/null +++ b/data/Окно.png.import @@ -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 diff --git a/data/П16.png b/data/П16.png index 10ccda0..acc9be7 100644 Binary files a/data/П16.png and b/data/П16.png differ diff --git a/data/ПРД.png b/data/ПРД.png index d3ee562..b58fd7f 100644 Binary files a/data/ПРД.png and b/data/ПРД.png differ diff --git a/data/СПТ.png b/data/СПТ.png index 77a456a..6452b42 100644 Binary files a/data/СПТ.png and b/data/СПТ.png differ diff --git a/data/УФ.png b/data/УФ.png index d1937ff..fd227b4 100644 Binary files a/data/УФ.png and b/data/УФ.png differ diff --git a/data/Щ3.png b/data/Щ3.png index af4bee2..4ae77f8 100644 Binary files a/data/Щ3.png and b/data/Щ3.png differ diff --git a/project.godot b/project.godot index c198b86..9ca76b7 100644 --- a/project.godot +++ b/project.godot @@ -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 diff --git a/scenes/bip/bip.gd b/scenes/bip/bip.gd index ae49b23..49fbbf8 100644 --- a/scenes/bip/bip.gd +++ b/scenes/bip/bip.gd @@ -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)) + diff --git a/scenes/bip/bip.tscn b/scenes/bip/bip.tscn index f1601e5..c296aff 100644 --- a/scenes/bip/bip.tscn +++ b/scenes/bip/bip.tscn @@ -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"] diff --git a/scenes/button-flat/button-flat.tscn b/scenes/button-flat/button-flat.tscn index 2a6dca1..955e3f4 100644 --- a/scenes/button-flat/button-flat.tscn +++ b/scenes/button-flat/button-flat.tscn @@ -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) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index 968c90d..a383a98 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -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)) diff --git a/scenes/frame-ecm-list/frm-ecm-list.gd b/scenes/frame-ecm-list/frm-ecm-list.gd index c08ba4a..c073e96 100644 --- a/scenes/frame-ecm-list/frm-ecm-list.gd +++ b/scenes/frame-ecm-list/frm-ecm-list.gd @@ -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)) diff --git a/scenes/frame-ecm-list/frm-ecm-list.tscn b/scenes/frame-ecm-list/frm-ecm-list.tscn index 4c89832..fceb9ed 100644 --- a/scenes/frame-ecm-list/frm-ecm-list.tscn +++ b/scenes/frame-ecm-list/frm-ecm-list.tscn @@ -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 = "" diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index 00bca85..59de10e 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -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(): diff --git a/scenes/frame-ecm-params/scroll-ecm-params.gd b/scenes/frame-ecm-params/scroll-ecm-params.gd index f65b863..5e90d51 100644 --- a/scenes/frame-ecm-params/scroll-ecm-params.gd +++ b/scenes/frame-ecm-params/scroll-ecm-params.gd @@ -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')) diff --git a/scenes/frame-params/scroll-params.gd b/scenes/frame-params/scroll-params.gd index 45a6ce0..db0deac 100644 --- a/scenes/frame-params/scroll-params.gd +++ b/scenes/frame-params/scroll-params.gd @@ -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) diff --git a/scenes/frame-threats/scroll-threats.gd b/scenes/frame-threats/scroll-threats.gd index 3438a73..2440bb3 100644 --- a/scenes/frame-threats/scroll-threats.gd +++ b/scenes/frame-threats/scroll-threats.gd @@ -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() diff --git a/scenes/pribor-rtr/pribor-rtr.gd b/scenes/pribor-rtr/pribor-rtr.gd index 93ae032..e7b10fc 100644 --- a/scenes/pribor-rtr/pribor-rtr.gd +++ b/scenes/pribor-rtr/pribor-rtr.gd @@ -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]) diff --git a/scenes/tabs-switch/tab-switch.tscn b/scenes/tabs-switch/tab-switch.tscn index 746e897..605eb0a 100644 --- a/scenes/tabs-switch/tab-switch.tscn +++ b/scenes/tabs-switch/tab-switch.tscn @@ -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 diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index 3920258..8634bd4 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -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() diff --git a/scenes/tilemap/tilemap.tscn b/scenes/tilemap/tilemap.tscn index 406784f..6019bff 100644 --- a/scenes/tilemap/tilemap.tscn +++ b/scenes/tilemap/tilemap.tscn @@ -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"] diff --git a/scenes/настройки/настройки.gd b/scenes/настройки/настройки.gd index 18b07fa..cd817db 100644 --- a/scenes/настройки/настройки.gd +++ b/scenes/настройки/настройки.gd @@ -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('++ограниченный'): diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index a5f0eec..e65b5d4 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -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 diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 6e04b6c..d439ea0 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -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 diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index b735956..357d0d0 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -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"] diff --git a/scenes/эмс/кнопка-эмс.gd b/scenes/эмс/кнопка-эмс.gd index 37bcaf7..e8aa9c4 100644 --- a/scenes/эмс/кнопка-эмс.gd +++ b/scenes/эмс/кнопка-эмс.gd @@ -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") diff --git a/scenes/эмс/эмс.gd b/scenes/эмс/эмс.gd index 054309b..f05680d 100644 --- a/scenes/эмс/эмс.gd +++ b/scenes/эмс/эмс.gd @@ -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) diff --git a/scenes/эмс/эмс.tscn b/scenes/эмс/эмс.tscn index 489af88..5be27bc 100644 --- a/scenes/эмс/эмс.tscn +++ b/scenes/эмс/эмс.tscn @@ -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="."] diff --git a/scenes/эмс2/эмс2.tscn b/scenes/эмс2/эмс2.tscn new file mode 100644 index 0000000..06f453b --- /dev/null +++ b/scenes/эмс2/эмс2.tscn @@ -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 diff --git a/scripts/capsrpb.gd b/scripts/capsrpb.gd index bf790da..9f7b96b 100644 --- a/scripts/capsrpb.gd +++ b/scripts/capsrpb.gd @@ -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 diff --git a/scripts/file-table.gd b/scripts/file-table.gd index d2012c5..5b73492 100644 --- a/scripts/file-table.gd +++ b/scripts/file-table.gd @@ -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() diff --git a/scripts/hotkeys.gd b/scripts/hotkeys.gd index a75efc9..a01762c 100644 --- a/scripts/hotkeys.gd +++ b/scripts/hotkeys.gd @@ -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) diff --git a/scripts/interfer.gd b/scripts/interfer.gd index f7a1f13..f04dd08 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -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) diff --git a/scripts/mercator.gd b/scripts/mercator.gd index c876d45..47fca03 100644 --- a/scripts/mercator.gd +++ b/scripts/mercator.gd @@ -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: diff --git a/scripts/modbus.gd b/scripts/modbus.gd index b7fe105..fe3c1fe 100644 --- a/scripts/modbus.gd +++ b/scripts/modbus.gd @@ -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: diff --git a/scripts/repnetwork.gd b/scripts/repnetwork.gd index ffd8a7f..51bfef5 100644 --- a/scripts/repnetwork.gd +++ b/scripts/repnetwork.gd @@ -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) diff --git a/scripts/repsettings.gd b/scripts/repsettings.gd index 4ca1c06..9c94442 100644 --- a/scripts/repsettings.gd +++ b/scripts/repsettings.gd @@ -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] diff --git a/scripts/signaller.gd b/scripts/signaller.gd index 7771883..068b44f 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -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) diff --git a/scripts/tcp5p28.gd b/scripts/tcp5p28.gd index cc7811b..63fca15 100644 --- a/scripts/tcp5p28.gd +++ b/scripts/tcp5p28.gd @@ -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 diff --git a/scripts/threats.gd b/scripts/threats.gd index b26ae77..2c47cd5 100644 --- a/scripts/threats.gd +++ b/scripts/threats.gd @@ -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 diff --git a/scripts/tools.gd b/scripts/tools.gd index 77fb48c..d19a303 100644 --- a/scripts/tools.gd +++ b/scripts/tools.gd @@ -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: diff --git a/scripts/yau07.gd b/scripts/yau07.gd index e3832ad..b4b6e2f 100644 --- a/scripts/yau07.gd +++ b/scripts/yau07.gd @@ -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 diff --git a/scripts/yems-boards.gd b/scripts/yems-boards.gd index 347bea6..8e14f3d 100644 --- a/scripts/yems-boards.gd +++ b/scripts/yems-boards.gd @@ -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 diff --git a/scripts/yems-consts.gd b/scripts/yems-consts.gd index ac333c6..f4d56ee 100644 --- a/scripts/yems-consts.gd +++ b/scripts/yems-consts.gd @@ -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']]] diff --git a/scripts/yems-devs.gd b/scripts/yems-devs.gd index 0095586..c97f201 100644 --- a/scripts/yems-devs.gd +++ b/scripts/yems-devs.gd @@ -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 diff --git a/shaders/bip.gdshader b/shaders/bip.gdshader index db41b3f..b2671d2 100644 --- a/shaders/bip.gdshader +++ b/shaders/bip.gdshader @@ -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); }