diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4d7722 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Godot-specific ignores +.import/ +export.cfg +export_presets.cfg + +# Imported translations (automatically generated from CSV files) +*.translation + +# Mono-specific ignores +.mono/ +data_*/ +mono_crash.*.json + +# System/tool-specific ignores +.directory +*~ +/.idea/ +/build/ +/html/ +/commit.gd diff --git a/DejaVuSans.ttf b/DejaVuSans.ttf new file mode 100644 index 0000000..d35124b Binary files /dev/null and b/DejaVuSans.ttf differ diff --git a/DejaVuSansCondensed.ttf b/DejaVuSansCondensed.ttf new file mode 100644 index 0000000..552e1c9 Binary files /dev/null and b/DejaVuSansCondensed.ttf differ diff --git a/Selector.tscn b/Selector.tscn new file mode 100644 index 0000000..8ea6351 --- /dev/null +++ b/Selector.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://nine-patch.png" type="Texture" id=1] + +[node name="NinePatchRect" type="NinePatchRect"] +margin_right = 42.0 +margin_bottom = 33.0 +texture = ExtResource( 1 ) +draw_center = false +patch_margin_left = 8 +patch_margin_top = 8 +patch_margin_right = 8 +patch_margin_bottom = 8 +axis_stretch_horizontal = 1 +axis_stretch_vertical = 1 diff --git a/consts.gd b/consts.gd new file mode 100644 index 0000000..064bbe1 --- /dev/null +++ b/consts.gd @@ -0,0 +1,19 @@ +extends Node2D + +export (String, FILE) var MENU_SCENE_FILE = 'res://меню.tscn' + + + +# Адрес имитатора +const MAIN_ADDR = [ '10.1.1.5', 50005 ] +const DST_ADDR = [ '10.1.1.79', 50079 ] + + +const TABLE_ROW_HIGHT = 34 # Высота строки таблицы в пикселях +const TABLE_ROW_POINTS = [ Vector2(1, 0), Vector2(1247, 0), Vector2(1247, TABLE_ROW_HIGHT), Vector2(1, TABLE_ROW_HIGHT), Vector2(1, 0) ] +const TABLE_MARKER_ADJ = Vector2(22.0, 9.0) +const COLOR_ACCENT = Color(1.0, 0.6, 0.4, 1.0) +const COLOR_ACCENT_ADJ = Color(1.3, 1.3, 1.3, 1.0) +const COLOR_PAD = Color(0.085, 0.14, 0.18, 0.5) +const COLOR_HEADER = Color(0.19, 0.28, 0.37, 1.0) +const COLOR_HALF_ALPHA = Color(1.0, 1.0, 1.0, 0.5) diff --git a/edit-add-0.png b/edit-add-0.png new file mode 100644 index 0000000..941ae64 Binary files /dev/null and b/edit-add-0.png differ diff --git a/edit-add-0.png.import b/edit-add-0.png.import new file mode 100644 index 0000000..dbf2bc1 --- /dev/null +++ b/edit-add-0.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/edit-add-0.png-caa21a9bbc05466cba52fa8d3bc8c950.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://edit-add-0.png" +dest_files=[ "res://.import/edit-add-0.png-caa21a9bbc05466cba52fa8d3bc8c950.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/edit-add-1.png b/edit-add-1.png new file mode 100644 index 0000000..8b2642e Binary files /dev/null and b/edit-add-1.png differ diff --git a/edit-add-1.png.import b/edit-add-1.png.import new file mode 100644 index 0000000..81649f7 --- /dev/null +++ b/edit-add-1.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/edit-add-1.png-8bbd18fd95c5b5bd62e9c26d8f22f02b.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://edit-add-1.png" +dest_files=[ "res://.import/edit-add-1.png-8bbd18fd95c5b5bd62e9c26d8f22f02b.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..c98fbb6 Binary files /dev/null and b/icon.png differ diff --git a/icon.png.import b/icon.png.import new file mode 100644 index 0000000..a4c02e6 --- /dev/null +++ b/icon.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.png" +dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/main-font.tres b/main-font.tres new file mode 100644 index 0000000..1f2aa57 --- /dev/null +++ b/main-font.tres @@ -0,0 +1,9 @@ +[gd_resource type="DynamicFont" load_steps=2 format=2] + +[ext_resource path="res://DejaVuSansCondensed.ttf" type="DynamicFontData" id=1] + +[resource] +size = 20 +use_mipmaps = true +use_filter = true +font_data = ExtResource( 1 ) diff --git a/main.gd b/main.gd new file mode 100644 index 0000000..b772f4a --- /dev/null +++ b/main.gd @@ -0,0 +1,30 @@ +extends Node2D + +var sock = PacketPeerUDP.new() +onready var header_threads = get_node('tabs/threats/header_t') +onready var table_threads = get_node('tabs/threats/table_t') +onready var btn_add_threads = get_node('tabs/threats/btn_add') +onready var btn_del_threads = get_node('tabs/threats/btn_del') + +onready var header_pomehi = get_node('tabs/pomehi/header_p') +onready var table_pomehi = get_node('tabs/pomehi/table_p') + +# Called when the node enters the scene tree for the first time. +func _ready(): + sock.listen(Consts.MAIN_ADDR[1], Consts.MAIN_ADDR[0]) + sock.set_dest_address(Consts.DST_ADDR[0], Consts.DST_ADDR[1]) + Threats.init_treats(header_threads, table_threads, btn_add_threads, btn_del_threads) + Pomehi.init_pomehi(header_pomehi, table_pomehi) + var timer = Timer.new() + timer.connect('timeout',self,'on_timeout',[]) + add_child(timer) #to process + timer.start(1) #to start + + +func on_timeout(): + sock.put_packet(Threats.get_threats_data()) + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass diff --git a/main.tres b/main.tres new file mode 100644 index 0000000..20207a4 --- /dev/null +++ b/main.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/main.tscn b/main.tscn new file mode 100644 index 0000000..91ce2d9 --- /dev/null +++ b/main.tscn @@ -0,0 +1,69 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://table.gd" type="Script" id=1] +[ext_resource path="res://main.gd" type="Script" id=2] +[ext_resource path="res://edit-add-0.png" type="Texture" id=3] +[ext_resource path="res://edit-add-1.png" type="Texture" id=4] + +[node name="main" type="Node2D"] +script = ExtResource( 2 ) + +[node name="tabs" type="TabContainer" parent="."] +margin_right = 1594.0 +margin_bottom = 897.0 +tab_align = 0 + +[node name="threats" type="Panel" parent="tabs"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 42.0 +margin_right = -4.0 +margin_bottom = -4.0 + +[node name="table_t" type="GridContainer" parent="tabs/threats"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_top = 100.0 +margin_right = 1.0 +margin_bottom = 10.0 +script = ExtResource( 1 ) + +[node name="header_t" type="GridContainer" parent="tabs/threats"] +margin_top = 57.0 +margin_right = 1584.0 +margin_bottom = 96.0 +script = ExtResource( 1 ) + +[node name="btn_add" type="TextureButton" parent="tabs/threats"] +margin_left = 1533.0 +margin_top = -2.0 +margin_right = 1581.0 +margin_bottom = 46.0 +texture_normal = ExtResource( 3 ) +texture_pressed = ExtResource( 4 ) + +[node name="btn_del" type="TextureButton" parent="tabs/threats"] +margin_left = 1487.0 +margin_top = 3.0 +margin_right = 1527.0 +margin_bottom = 43.0 + +[node name="pomehi" type="Panel" parent="tabs"] +visible = false +margin_left = 4.0 +margin_top = 42.0 +margin_right = 1590.0 +margin_bottom = 893.0 + +[node name="table_p" type="GridContainer" parent="tabs/pomehi"] +margin_top = 100.0 +margin_right = 1587.0 +margin_bottom = 861.0 +script = ExtResource( 1 ) + +[node name="header_p" type="GridContainer" parent="tabs/pomehi"] +margin_top = 57.0 +margin_right = 32.0 +margin_bottom = 96.0 +script = ExtResource( 1 ) diff --git a/nine-patch.png b/nine-patch.png new file mode 100644 index 0000000..1649a7f Binary files /dev/null and b/nine-patch.png differ diff --git a/nine-patch.png.import b/nine-patch.png.import new file mode 100644 index 0000000..606cb00 --- /dev/null +++ b/nine-patch.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/nine-patch.png-57e7212ba67c39e7fc9011f4afa7baae.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://nine-patch.png" +dest_files=[ "res://.import/nine-patch.png-57e7212ba67c39e7fc9011f4afa7baae.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/pomehi.gd b/pomehi.gd new file mode 100644 index 0000000..f149406 --- /dev/null +++ b/pomehi.gd @@ -0,0 +1,124 @@ +extends Node + +var id_array: Array # Массив id целей +var pomehi : Dictionary # Словарь целей +var msg_counter : int = 0 # Счётчик отправленных пакетов + +const TableCellType1 = preload('res://ячейка-1.tscn') +const TableCellType2 = preload('res://кнопка-3.tscn') +const TableCellType3 = preload('res://кнопка-4.tscn') +const TableCellType4 = preload('res://заголовок.tscn') +const TableCellType5 = preload('res://ячейка-2.tscn') +const TableCellType6 = preload('res://кнопка-5.tscn') + +# Индекс колонки: 0 1 2 3 4 5 6 +const TABLE_HEADERS = [ 'Индекс', 'Состояние', 'Помеха', 'Мощность', 'Кур. уг.', 'Частота', 'Ш. диап.'] +const TABLE_HEADER_TYPES = [ TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4] +const TABLE_HEADER_ALIGNMENTS = [ HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER] +const TABLE_ROW_TYPES = [ TableCellType1, TableCellType6, TableCellType1, TableCellType1, TableCellType1, TableCellType1, TableCellType1] +const TABLE_ROW_ALIGNMENTS = [ HALIGN_CENTER, HALIGN_LEFT, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER] +const TABLE_COLUMN_SIZES = [ 82, 120, 82, 100, 82, 90, 150] + +const COLUMN_ISPP = 0 # Индекс сейанса постановки помехи +const COLUMN_SVK = 1 # Состояние выполнения помехи +const COLUMN_KRP = 2 # Помеха +const COLUMN_POWP = 3 # Мощность излучения +const COLUMN_KNI = 4 # Курсовой угол +const COLUMN_FREQ = 5 # Частота +const COLUMN_WIDTH = 6 # Ширина диапазона + + +# Индексы колонок, которым можно задавать выравнивание текста +const TABLE_ALLIGNED_COLUMNS = [ + COLUMN_ISPP, + COLUMN_KRP, + COLUMN_POWP, + COLUMN_KNI, + COLUMN_FREQ, + COLUMN_WIDTH, ] + + +# Состояние выполнения команды поставновки помехи +const SVK = ['<неопр.>', 'fhss', 'lfm', 'const'] + + +# Номера колонок +const COLUMN_OPT = [[COLUMN_SVK, SVK]] +const COLUMN_OPT_BTN = [COLUMN_SVK] +const ID_ARRAY_LEN = 100 # Размер пула номеров целей + +# Помеха +class Pomeha: + # параметры цели, второе значение, разрешение отправки. + var ispp : String + var svk : int + var krp : String + var powp : String + var kni : String + var freq : String + var width : String + + func _init(args : Array): + ispp = String(args[0]) + krp = String(args[1]) + powp = String(args[2]) + kni = String(args[3]) + freq = String(args[4]) + width = String(args[5]) + + + func update_rows(): + var new_rows: Array = [] + new_rows.append(String(ispp)) + new_rows.append(String(svk)) + new_rows.append(String(krp)) + new_rows.append(String(powp)) + new_rows.append(String(kni)) + new_rows.append(String(freq)) + new_rows.append(String(width)) + return new_rows + + +func selector_color_proc(_i_row: int): + return Consts.COLOR_ACCENT * Consts.COLOR_HALF_ALPHA + + +func init_table(table: Table, sizes: Array): + for i_row in table.get_rows_count(): + table.set_nodes_min_size(i_row, sizes) + table.set_selector_color_proc(self, 'selector_color_proc') + + +func init_opt_btns(row : int, table): + for item in COLUMN_OPT: + var i_col = item[0] + var opt_arr = item[1] + var cell = table.get_node2(i_col, row) + for opt in opt_arr: + cell.add_item(opt) + cell.select(0) + + +func init_pomehi(header, table): # Инициализация вкладки с целями + header.add_row(TABLE_HEADER_TYPES) + header.set_rows_text([TABLE_HEADERS]) + on_btn_add(table) + init_table(header, TABLE_COLUMN_SIZES) + init_table(table, TABLE_COLUMN_SIZES) + table.align_to_left_bottom(header, Vector2(0, 2)) + table.connect('row_pressed', self, 'on_row_pressed', [table]) + table.set_callbacks(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, [table]) + + +func on_btn_add(table): + var pomeha : = Pomeha.new([1,2,3,4,5,6]) + pomehi[String(1)] = pomeha + var row = pomeha.update_rows() + table.add_row(TABLE_ROW_TYPES) + table.set_row_text(table.get_rows_count()-1, row) + init_opt_btns(table.get_rows_count()-1, table) + table.set_callbacks(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, []) + + +func on_row_pressed(i_row: int, table): + pass diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..f26b08c --- /dev/null +++ b/project.godot @@ -0,0 +1,43 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +[application] + +config/name="Imi Skysens" +run/main_scene="res://main.tscn" +config/icon="res://icon.png" + +[autoload] + +Table="*res://table.gd" +Consts="*res://consts.gd" +Threats="*res://threats.gd" +Pomehi="*res://pomehi.gd" +Tools="*res://tools.gd" + +[display] + +window/size/width=1600 +window/size/height=900 +window/stretch/mode="2d" +window/stretch/aspect="keep" + +[gui] + +common/drop_mouse_on_gui_input_disabled=true +theme/custom_font="res://main-font.tres" + +[physics] + +common/enable_pause_aware_picking=true + +[rendering] + +environment/default_environment="res://main.tres" diff --git a/table.gd b/table.gd new file mode 100644 index 0000000..4907c9f --- /dev/null +++ b/table.gd @@ -0,0 +1,422 @@ +tool +extends GridContainer + +export (Color) var _selector_color = Color(1.0, 1.0, 1.0, 1.0) +export (int, 1, 256) var columns_count = 1 setget _set_columns_count +export (int, 1, 256) var rows_count = 1 setget _set_rows_count +export (String, FILE) var node_type_file = 'res://ячейка-1.tscn' +const Selector = preload('res://Selector.tscn') +const INDEX_FORMAT = '%02d_%02d' +const NODE_PREFIX = 'NODE_' +const DATA_PREFIX = 'DATA_' +const CONN_PREFIX = 'CONN_' +const SLCT_PREFIX = 'SLCT_' + +const NODE_KEY_FORMAT = NODE_PREFIX + INDEX_FORMAT +const DATA_KEY_FORMAT = DATA_PREFIX + INDEX_FORMAT +const CONNECTED_KEY_FORMAT = CONN_PREFIX + INDEX_FORMAT +const ROW_SELECTOR_KEY_FORMAT = SLCT_PREFIX + INDEX_FORMAT + +var nodes: = {} +var selector_color_proc: FuncRef +var selector_size_proc: FuncRef +signal row_pressed(i_row) # Вызывается при нажатии кнопкой мыши на строку +const MAX_INDEX = 99 # Максимальное значение индекса для колонки и строки. Связано с форматом ключа + + +func align_to_left_bottom(header, gap: = Vector2(0, 0)): + """ Выравнивает по нижнему левому углу. Используется для выравнивания по заголовку """ + rect_position.x = header.rect_position.x + gap.x + rect_position.y = header.rect_position.y + header.rect_size.y + gap.y + + +func _assert_meta(i_col: int, i_row: int, pname: String, node): + assert(node.has_meta(pname), 'ошибка: нет мета-свойства \"%s\" у ячейки (%s): колонка:%d ряд:%d' % [pname, typeof(node), i_col, i_row]) + + +func _set_columns_count(cc: int): + columns_count = cc + + +func _set_rows_count(rc: int): + rows_count = rc + + +func set_node_meta(i_col: int, i_row: int, pname: String, val) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var node = nodes[key] + node.set_meta(pname, val) + + +func get_node_meta(i_col: int, i_row: int, pname: String): + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var node = nodes[key] + _assert_meta(i_col, i_row, pname, node) + return node.get_meta(pname) + + +func set_node_property(i_col: int, i_row: int, pname: String, val) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var node = nodes[key] + node.set(pname, val) + + +func get_node_property(i_col: int, i_row: int, pname: String): + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var node = nodes[key] + return node.get(pname) + + +func get_node_key(format: String, i_col: int, i_row: int) -> String: + var key: String = format % [i_row, i_col] + assert(nodes.has(key), 'ошибка: нет такой ячейки: колонка:%d ряд:%d' % [i_col, i_row]) + return key + + +func get_key_indexes(key: String) -> Array: + var tokens: = key.split('_') + assert(tokens.size() == 3, 'ошибка: неверный ключ: \"%s\"' % key) + return [int(tokens[2]), int(tokens[1])] + + +func set_columns_min_size(sizes: Array) -> void: + for i_row in get_rows_count(): + set_nodes_min_size(i_row, sizes) + + +func set_columns_aligment(alignments: Array) -> void: + for i_row in get_rows_count(): + for i_col in alignments.size(): + set_node_alligment(i_col, i_row, alignments[i_col]) + + +func _input(event) -> void: + if event is InputEventMouseButton: + if not event.pressed: + return + if event.position.x < rect_position.x: + emit_signal('focus_exited') + return + if event.position.x > (rect_position.x + rect_size.x): + emit_signal('focus_exited') + return + if event.position.y < rect_position.y: + emit_signal('focus_exited') + return + if event.position.y > (rect_position.y + rect_size.y): + emit_signal('focus_exited') + return + var rows_count: = get_rows_count() + var parent = get_parent() + var y0 = parent.rect_position.y + for i_row in rows_count: + var rect = [0, 0, 0, 0] + get_node_rect(0, i_row, rect) + var y = rect[1] + rect_position.y + y0 + if event.position.y < y: + continue + if event.position.y > (y + rect[3]): + continue + emit_signal('row_pressed', i_row) + break + + +func _init() -> void: + selector_color_proc = FuncRef.new() + selector_color_proc.set_instance(self) + selector_color_proc.function = 'default_selector_color_proc' + assert(selector_color_proc.is_valid()) + selector_size_proc = FuncRef.new() + selector_size_proc.set_instance(self) + selector_size_proc.function = 'default_selector_size_proc' + assert(selector_size_proc.is_valid()) + + +func default_selector_color_proc(i_row: int): + return _selector_color + + +func set_selector_color_proc(instance: Object, function: String) -> void: + selector_color_proc.set_instance(instance) + selector_color_proc.function = function + assert(selector_color_proc.is_valid()) + + +func set_selector_size_proc(instance: Object, function: String) -> void: + selector_size_proc.set_instance(instance) + selector_size_proc.function = function + assert(selector_size_proc.is_valid()) + + +func default_selector_size_proc(i_row: int, rect: Array) -> void: + get_node_rect(0, i_row, rect) + rect[0] = rect[0] + rect_position.x - 1 + rect[1] = rect[1] + rect_position.y - 4 + rect[2] = rect_size.x + 2 + rect[3] = rect[3] + 8 + + +func clear_rows_selected(): + var rows_count: = get_rows_count() + for i_row in rows_count: + set_row_selected(i_row, false) + + +func set_row_selected(i_row: int, selected: bool = true) -> void: + var key: = ROW_SELECTOR_KEY_FORMAT % [i_row, 0] + var parent = get_parent() + if nodes.has(key) and (not selected): + var selector = nodes[key] + parent.remove_child(selector) + selector.queue_free() + nodes.erase(key) + elif (not nodes.has(key)) and selected: + var selector = Selector.instance() + var rect: = [0, 0, 0, 0] + selector_size_proc.call_func(i_row, rect) + selector.rect_position.x = rect[0] + selector.rect_position.y = rect[1] + selector.rect_size.x = rect[2] + selector.rect_size.y = rect[3] + selector.modulate = selector_color_proc.call_func(i_row) + nodes[key] = selector + parent.add_child(selector) + + +func is_row_selected(i_row: int) -> bool: + var key: = get_node_key(ROW_SELECTOR_KEY_FORMAT, 0, i_row) + return nodes.has(key) + + +func get_selected_rows(rows: Array) -> void: + for key in nodes.keys(): + if SLCT_PREFIX in key: + var indexes = get_key_indexes(key) + rows.append(indexes[1]) + + +func get_rows_count() -> int: + var rows_count: int = 0 + for key in nodes: + rows_count += int(NODE_PREFIX in key) + return rows_count / columns + + +func get_node2(i_col: int, i_row: int) -> Node: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + return nodes[key] + + +func set_node_user_data(i_col: int, i_row: int, user_data: Object) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[key] = user_data + + +func add_row(row_types: Array) -> void: + assert(row_types.size() < MAX_INDEX, 'ошибка: слишком много колонок, больше %d' % (MAX_INDEX + 1)) + set_columns(row_types.size()) + var rows_count: int = get_rows_count() + assert(rows_count < MAX_INDEX, 'ошибка: слишком много рядов, больше %d' % (MAX_INDEX + 1)) + for i_col in columns: + var node = row_types[i_col].instance() + var key: String = NODE_KEY_FORMAT % [rows_count, i_col] + node.name = key + add_child(node) + nodes[key] = node + + +func get_node_user_data(i_col: int, i_row: int) -> Object: + var key: = get_node_key(DATA_KEY_FORMAT, i_col, i_row) + return nodes[key] + + +func remove_row(i_row: int): + + var sel_key: String = ROW_SELECTOR_KEY_FORMAT % [i_row, 0] + if nodes.has(sel_key): + var selector = nodes[sel_key] + get_parent().remove_child(selector) + selector.queue_free() + nodes.erase(sel_key) + for i_col in columns: + var node_key: String = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var conn_key: String = CONNECTED_KEY_FORMAT % [i_row, i_col] + var data_key: String = DATA_KEY_FORMAT % [i_row, i_col] + var node = nodes[node_key] + nodes.erase(node_key) + remove_child(node) + node.queue_free() + + if nodes.has(data_key): + nodes.erase(data_key) + if nodes.has(conn_key): + var conn = nodes[conn_key] + var callback = conn[0] + var dest_node = conn[1] + node.disconnect('pressed', dest_node, callback) + nodes.erase(conn_key) + + +func rehash(swaps: Array): + """ Переназначает ключи в соответствии с размерами таблицы. + После вызова swaps содержит массив пар [<прежний ключ>, <текущий ключ>] """ + assert(not swaps.size(), 'ошибка: swaps не пустой') + var nodes_copy = {} + var i_col = 0 + var i_row = 0 + for key0 in nodes: + if NODE_PREFIX in key0: + var node_key1: String = NODE_KEY_FORMAT % [i_row, i_col] + nodes_copy[node_key1] = nodes[key0] + swaps.append([key0, node_key1]) + + var indxs = get_key_indexes(key0) + + var slct_key0: String = ROW_SELECTOR_KEY_FORMAT % [indxs[1], indxs[0]] + if nodes.has(slct_key0): + var slct_key1: String = ROW_SELECTOR_KEY_FORMAT % [i_row, i_col] + nodes_copy[slct_key1] = nodes[slct_key0] + + var conn_key0: String = CONNECTED_KEY_FORMAT % [indxs[1], indxs[0]] + if nodes.has(conn_key0): + var conn_key1: String = CONNECTED_KEY_FORMAT % [i_row, i_col] + nodes_copy[conn_key1] = nodes[conn_key0] + + var data_key0: String = DATA_KEY_FORMAT % [indxs[1], indxs[0]] + if nodes.has(data_key0): + var data_key1: String = DATA_KEY_FORMAT % [i_row, i_col] + nodes_copy[data_key1] = nodes[data_key0] + + i_col += 1 + if i_col == columns: + i_col = 0 + i_row += 1 + nodes.clear() + nodes.merge(nodes_copy) + + +func clear_rows() -> void: + """ Удаляет все строки таблицы """ + var rows_count: int = get_rows_count() + for i_row in rows_count: + remove_row(i_row) + + +func set_callbacks(dest_node: Node, event_name: String, callback: String, clmns: Array, user_data: Array) -> void: + """ Настраивает обратные вызовы для колонок. + :dest_node: Получатель события + :event_name: Имя события + :callback: Имя функции получателя события + :clmns: Индексы колонок + :user_data: Аргументы функции получателя события """ + var rows_count = get_rows_count() + for i_row in rows_count: + for i_col in clmns: + assert(i_col >= 0 and i_col < columns, 'ошибка: нет колонки %d' % i_col) + var node_key: String = NODE_KEY_FORMAT % [i_row, i_col] + var conn_key: String = CONNECTED_KEY_FORMAT % [i_row, i_col] + var node = nodes[node_key] + if nodes.has(conn_key): + var conn = nodes[conn_key] + var prev_callback = conn[0] + var prev_dest_node = conn[1] + node.disconnect(event_name, prev_dest_node, prev_callback) + assert (OK == node.connect(event_name, dest_node, callback, [node] + user_data)) + nodes[conn_key] = [callback, dest_node] + + +func set_rows_text(rows: Array) -> void: + for i_row in rows.size(): + for i_col in columns: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var node = nodes[key] + node.text = rows[i_row][i_col] + + +func set_nodes_min_size(i_row: int, sizes: Array) -> void: + for i_col in columns: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var node = nodes[key] + node.rect_min_size.x = sizes[i_col] + node.rect_size.x = sizes[i_col] + + +func set_node_text(i_col: int, i_row: int, val: String) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[key].text = val + + +func set_rows_state(rows: Array) -> void: + for i_row in rows.size(): + for i_col in columns: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[name].pressed = rows[i_row][i_col] + + +func set_node_state(i_col: int, i_row: int, val: bool) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[key].pressed = val + + +func set_node_frame(i_col: int, i_row: int, name: String, val: int) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var node = nodes[key] + var sprite = node.get_node(name) + sprite.frame = val + + +func set_node_editable(i_col: int, i_row: int, val: bool) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[key].editable = val + + +func set_node_alligment(i_col: int, i_row: int, val: int) -> void: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[key].align = val + + +func set_row_alligments(i_row: int, aligns: Array) -> void: + for i_col in columns: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[key].align = aligns[i_col] + + +func get_row_text(i_row: int) -> Array: + var row: = [] + for i_col in columns: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + row.append(nodes[key].text) + return row + + +func set_row_text(i_row: int, row: Array, i_begin: int = 0) -> void: + for i_col in row.size(): + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + nodes[key].text = row[i_col] + + +func get_rows_text() -> Array: + var rows_count: = get_rows_count() + var rows: = [] + for i_row in rows_count: + var row = get_row_text(i_row) + rows.append(row) + return rows + + +func get_row(i_row: int) -> Array: + var row: = [] + for i_col in columns: + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + row.append(nodes[key]) + return row + + +func get_node_rect(i_col: int, i_row: int, rect: Array) -> void: + assert(rect.size() >= 4, 'ошибка: мало элементов для возврата результата') + var key: = get_node_key(NODE_KEY_FORMAT, i_col, i_row) + var cell = nodes[key] + rect[0] = cell.rect_position.x + rect[1] = cell.rect_position.y + rect[2] = cell.rect_size.x + rect[3] = cell.rect_size.y diff --git a/threats.gd b/threats.gd new file mode 100644 index 0000000..4b0c5b2 --- /dev/null +++ b/threats.gd @@ -0,0 +1,403 @@ +extends Node + +var id_array: Array # Массив id целей +var treats : Dictionary # Словарь целей +var msg_counter : int = 0 # Счётчик отправленных пакетов + +const TableCellType1 = preload('res://ячейка-1.tscn') +const TableCellType2 = preload('res://кнопка-3.tscn') +const TableCellType3 = preload('res://кнопка-4.tscn') +const TableCellType4 = preload('res://заголовок.tscn') +const TableCellType5 = preload('res://ячейка-2.tscn') +const TableCellType6 = preload('res://кнопка-5.tscn') + +# Индекс колонки: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +const TABLE_HEADERS = ['ID Цели', 'Кур. уг.', 'Частота', 'Ш. диап.', 'Ампл.', 'T обнар.', 'Мод.', 'Реж. см. F', 'Ск. пер.', 'Протокол', 'Ст. дол.', 'Ст. шир.', 'Cт. выс.', 'Тек. дол.', 'Тек. шир.', 'Тек. выс.', ] +const TABLE_HEADER_TYPES = [ TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4, TableCellType4] +const TABLE_HEADER_ALIGNMENTS = [ HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER] +const TABLE_ROW_TYPES = [ TableCellType1, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType6, TableCellType6, TableCellType5, TableCellType6, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5] +const TABLE_ROW_ALIGNMENTS = [ HALIGN_CENTER, HALIGN_LEFT, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER, HALIGN_CENTER] +const TABLE_COLUMN_SIZES = [ 82, 82, 82, 82, 82, 90, 150, 150, 80, 150, 82, 82, 82, 82, 82, 82] + +const COLUMN_ID = 0 # Идентификатор цели +const COLUMN_AOA = 1 # Курсовой угол на источник сигнала, градусы +const COLUMN_FREQ = 2 # Частота несущей или центральная частота, МГц +const COLUMN_WIDTH = 3 # Ширина занимаемого диапазона частот, МГц +const COLUMN_POW = 4 # Уровень принимаемого сигнала, дБ +const COLUMN_TICK = 5 # Относительное время обнаружения сигнала, мс. +const COLUMN_TMOD = 6 # Вид модуляции +const COLUMN_FREQM = 7 # Режим смены частоты. +const COLUMN_BAUD = 8 # Скорость передачи данных, бит/с +const COLUMN_PROTO = 9 # Тип протокола источника сигнала. +const COLUMN_SLON = 10 # Координаты старта, долгота в градусах +const COLUMN_SLAT = 11 # Координаты старта, широта в градусах +const COLUMN_SALT = 12 # Координаты старта, высота от уровня моря, метры +const COLUMN_LAT = 13 # Текущие координаты, долгота в градусах +const COLUMN_LON = 14 # Текущие координаты, широта в градусах +const COLUMN_ALT = 15 # Текущая высота, метры + +# Индексы колонок, которым можно задавать выравнивание текста +const TABLE_ALLIGNED_COLUMNS = [ + COLUMN_ID, + COLUMN_AOA, + COLUMN_FREQ, + COLUMN_WIDTH, + COLUMN_POW, + COLUMN_TICK, + COLUMN_BAUD, + COLUMN_SLON, + COLUMN_SLAT, + COLUMN_SALT, + COLUMN_LAT, + COLUMN_LON, + COLUMN_ALT ] + +# Индексы колонок, в которых можно вводит текст +const TABLE_ENTRY_COLUMNS = [ + COLUMN_AOA, + COLUMN_FREQ, + COLUMN_WIDTH, + COLUMN_POW, + COLUMN_TICK, + COLUMN_BAUD, + COLUMN_SLON, + COLUMN_SLAT, + COLUMN_SALT, + COLUMN_LAT, + COLUMN_LON, + COLUMN_ALT ] + +# Типы модуляции +const MODE_TYPES = ['<неопр.>', 'am', 'ook', 'ask', 'fm', 'qpsk', 'oqpsk', 'pi4qpsk', 'qam16', + 'qam32', 'qam64', 'qam128', 'qam256', 'qam512', 'fsk', 'cpfsk', 'psk','ofdm'] + +# Режим смены частоты +const FREQM = ['<неопр.>', 'fhss', 'lfm', 'const'] + +# Протоколы радиомодема +const M_PROTO = ['<неопр.>', '3dlink', 'skyhopperpro', 'picardiooem', 'solo7', 'j11', + 'mavlink', 'ltm', 'hc12', 'df1', ] + +# Номера колонок +const COLUMN_OPT = [[COLUMN_TMOD, MODE_TYPES], [COLUMN_FREQM, FREQM], [COLUMN_PROTO, M_PROTO]] +const COLUMN_OPT_BTN = [COLUMN_TMOD, COLUMN_FREQM, COLUMN_PROTO] +const ID_ARRAY_LEN = 100 # Размер пула номеров целей + + +# Цель +class Threat: + # параметры цели, второе значение, разрешение отправки. + var row : Dictionary = { + 'id':[0,true], + 'aoa':[10.0,true], + 'freq':[2480.0,true], + 'width':[20.0,true], + 'power':[20.0,true], + 'tick':[10,true], + 'tmod':['',false], + 'freqm':['',false], + 'baud':[0.0,false], + 'proto':['',false], + 'slon':[0.0,false], + 'slat':[0.0,false], + 'salt':[0.0,false], + 'lat':[0.0,false], + 'lon':[0.0,false], + 'alt':[0.0,false], + } + + func _init(th_id : int): + row.id[0] = th_id + + func get_data(): + var data_to_send : Dictionary + for key in row.keys(): + var value = row[key] + var data = value[0] + var need_send = value[1] + if need_send: + data_to_send[key] = data + return data_to_send + + func update_rows(): + var new_rows: Array = [] + new_rows.append(_check_value(row.id)) + new_rows.append(_check_value(row.aoa)) + new_rows.append(_check_value(row.freq)) + new_rows.append(_check_value(row.width)) + new_rows.append(_check_value(row.power)) + new_rows.append(_check_value(row.tick)) + new_rows.append(_check_value(row.tmod)) + new_rows.append(_check_value(row.freqm)) + new_rows.append(_check_value(row.baud)) + new_rows.append(_check_value(row.proto)) + new_rows.append(_check_value(row.slon)) + new_rows.append(_check_value(row.slat)) + new_rows.append(_check_value(row.salt)) + new_rows.append(_check_value(row.lat)) + new_rows.append(_check_value(row.lon)) + new_rows.append(_check_value(row.alt)) + return new_rows + + + func _check_value(val): + if val[1]: + return String(val[0]) + else: + return '' + + + func set_aoa(val): + var value = float(val) + value = Tools.check_low_high(value, 0, 360) + value = Tools.check_len(val, value) + row.aoa[0] = value + row.aoa[1] = Tools.check_empty(value) + return value + + func set_freq(val): + var value = float(val) + value = Tools.check_negative(value) + value = Tools.check_len(val, value) + row.freq[0] = value + row.freq[1] = Tools.check_empty(value) + return value + + func set_width(val): + var value = float(val) + value = Tools.check_negative(value) + value = Tools.check_len(val, value) + row.width[0] = value + row.width[1] = Tools.check_empty(value) + return value + + func set_power(val): + var value = float(val) + value = Tools.check_negative(value) + value = Tools.check_len(val, value) + row.power[0] = value + row.power[1] = Tools.check_empty(value) + return value + + func set_tick(val): + var value = int(val) + value = Tools.check_low_high(value, 0, 60000) + value = Tools.check_len(val, value) + row.tick[0] = value + row.tick[1] = Tools.check_empty(value) + return value + + func set_baud(val): + var value = float(val) + value = Tools.check_negative(value) + value = Tools.check_len(val, value) + row.baud[0] = value + row.baud[1] = Tools.check_empty(value) + return value + + func set_slon(val): + var value = float(val) + value = Tools.check_low_high(value, -90, 90) + value = Tools.check_len(val, value) + row.slon[0] = value + row.slon[1] = Tools.check_empty(value) + return value + + func set_slat(val): + var value = float(val) + value = Tools.check_low_high(value, -180, 180) + value = Tools.check_len(val, value) + row.slat[0] = value + row.slat[1] = Tools.check_empty(value) + return value + + func set_salt(val): + var value = float(val) + value = Tools.check_len(val, value) + row.salt[0] = value + row.salt[1] = Tools.check_empty(value) + return value + + func set_lon(val): + var value = float(val) + value = Tools.check_low_high(value, -90, 90) + value = Tools.check_len(val, value) + row.lon[0] = value + row.lon[1] = Tools.check_empty(value) + return value + + func set_lat(val): + var value = float(val) + value = Tools.check_low_high(value, -180, 180) + value = Tools.check_len(val, value) + row.lat[0] = value + row.lat[1] = Tools.check_empty(value) + return value + + func set_alt(val): + var value = float(val) + value = Tools.check_len(val, value) + row.alt[0] = value + row.alt[1] = Tools.check_empty(value) + return value + + func set_tmod(val): + var value = String(val) + row.tmod[0] = value + row.tmod[1] = false if value == '<неопр.>' else true + return value + + func set_freqm(val): + var value = String(val) + row.freqm[0] = value + row.freqm[1] = false if value == '<неопр.>' else true + return value + + func set_proto(val): + var value = String(val) + row.proto[0] = value + row.proto[1] = false if value == '<неопр.>' else true + return value + + +func init_treats(header, table, btn_add, btn_del): # Инициализация вкладки с целями + for i in range(ID_ARRAY_LEN): # Заполняет массив ID целей + id_array.append(i+1) + header.add_row(TABLE_HEADER_TYPES) + header.set_rows_text([TABLE_HEADERS]) + on_btn_add(table) + init_table(header, TABLE_COLUMN_SIZES) + init_table(table, TABLE_COLUMN_SIZES) + table.align_to_left_bottom(header, Vector2(0, 2)) + table.connect('row_pressed', self, 'on_row_pressed', [table]) + table.set_callbacks(self, 'text_entered', 'on_edit_entry', TABLE_ENTRY_COLUMNS, [table]) + table.set_callbacks(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, [table]) + btn_add.connect('button_up', self, 'on_btn_add', [table]) + btn_del.connect('button_up', self, 'on_btn_del', [table]) + + +func selector_color_proc(_i_row: int): + return Consts.COLOR_ACCENT * Consts.COLOR_HALF_ALPHA + + +func init_table(table: Table, sizes: Array): + for i_row in table.get_rows_count(): + table.set_nodes_min_size(i_row, sizes) + table.set_selector_color_proc(self, 'selector_color_proc') + + +func init_opt_btns(row : int, table): + for item in COLUMN_OPT: + var i_col = item[0] + var opt_arr = item[1] + var cell = table.get_node2(i_col, row) + for opt in opt_arr: + cell.add_item(opt) + cell.select(0) + + +func on_item_selected(item_num, node, table): + var optbtn_text = node.text + var indexis = table.get_key_indexes(node.name) + var row_i = indexis[1] + var col_i = indexis[0] + var cell = table.get_node2(0,row_i) + var value = set_value(optbtn_text, cell.text, col_i) + + +func on_edit_entry(text : String, entry, table): + var indexis = table.get_key_indexes(entry.name) + var row_i = indexis[1] + var col_i = indexis[0] + var cell = table.get_node2(0,row_i) + var value = set_value(text, cell.text, col_i) + entry.text = String(value) + + +func set_value(val : String, treat_id : String, column : int): + var treat = treats[treat_id] + match column: + COLUMN_AOA: + return treat.set_aoa(val) + COLUMN_FREQ: + return treat.set_freq(val) + COLUMN_WIDTH: + return treat.set_width(val) + COLUMN_POW: + return treat.set_power(val) + COLUMN_TICK: + return treat.set_tick(val) + COLUMN_TMOD: + return treat.set_tmod(val) + COLUMN_FREQM: + return treat.set_freqm(val) + COLUMN_BAUD: + return treat.set_baud(val) + COLUMN_PROTO: + return treat.set_proto(val) + COLUMN_SLON: + return treat.set_slon(val) + COLUMN_SLAT: + return treat.set_slat(val) + COLUMN_SALT: + return treat.set_salt(val) + COLUMN_LAT: + return treat.set_lon(val) + COLUMN_LON: + return treat.set_lat(val) + COLUMN_ALT: + return treat.set_alt(val) + + +func on_row_pressed(i_row: int, table): + table.clear_rows_selected() + table.set_row_selected(i_row, true) + + +func on_btn_add(table): + var id = pop_id() + var threat : = Threat.new(id) + treats[String(id)] = threat + var row = threat.update_rows() + table.add_row(TABLE_ROW_TYPES) + table.set_row_text(table.get_rows_count()-1, row) + init_opt_btns(table.get_rows_count()-1, table) + table.set_callbacks(self, 'text_entered', 'on_edit_entry', TABLE_ENTRY_COLUMNS, []) + table.set_callbacks(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, []) + + +func on_btn_del(table): + var row_i = [] + table.get_selected_rows(row_i) + if len(row_i) > 0: + var cell = table.get_node2(0, row_i[0]) + treats.erase(cell.text) + table.remove_row(row_i[0]) + table.rehash([]) + + +func pop_id(): + var id = 0 + if len(id_array): + id = id_array[0] + id_array.remove(0) + return id + + +func push_id(id : int): + id_array.append(id) + + +func get_threats_data(): + var data_to_json : Dictionary + data_to_json['ts'] = 5 + msg_counter += 1 + data_to_json['ss'] = msg_counter + data_to_json['msvk'] = [] + data_to_json['mis'] = [] + for key in treats: + var data = treats[key].get_data() + data_to_json['mis'].append(data) + var json = to_json(data_to_json) + var pac = json.to_utf8() + return pac diff --git a/tools.gd b/tools.gd new file mode 100644 index 0000000..68c33f3 --- /dev/null +++ b/tools.gd @@ -0,0 +1,29 @@ +extends Node + + +func check_low_high(val, low, high): # Проверка min/max значений + if val > high: + return high + elif val < low: + return low + else: + return val + +func check_negative(val): # Проверка на отрицательное + if val < 0: + return 0 + else: + return val + +func check_len(val, value): + if len(val) < 1: + return '' + else: + return value + +func check_empty(val): + if String(val) == '': + return false + else: + return true + diff --git a/заголовок.tscn b/заголовок.tscn new file mode 100644 index 0000000..13849b8 --- /dev/null +++ b/заголовок.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=2 format=2] + +[sub_resource type="StyleBoxFlat" id=1] +bg_color = Color( 1, 0.596078, 0.4, 1 ) + +[node name="heder" type="Label"] +margin_right = 120.0 +margin_bottom = 30.0 +size_flags_horizontal = 15 +size_flags_vertical = 15 +custom_colors/font_color = Color( 0.0313726, 0.105882, 0.184314, 1 ) +custom_styles/normal = SubResource( 1 ) +align = 1 +valign = 1 +clip_text = true diff --git a/индикатор-1-0.png b/индикатор-1-0.png new file mode 100644 index 0000000..e283d07 Binary files /dev/null and b/индикатор-1-0.png differ diff --git a/индикатор-1-0.png.import b/индикатор-1-0.png.import new file mode 100644 index 0000000..ba6e272 --- /dev/null +++ b/индикатор-1-0.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/индикатор-1-0.png-fc0a1949f86e54aad24513db3cf620a1.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://индикатор-1-0.png" +dest_files=[ "res://.import/индикатор-1-0.png-fc0a1949f86e54aad24513db3cf620a1.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/индикатор-1-1.png b/индикатор-1-1.png new file mode 100644 index 0000000..f5d41fd Binary files /dev/null and b/индикатор-1-1.png differ diff --git a/индикатор-1-1.png.import b/индикатор-1-1.png.import new file mode 100644 index 0000000..023d9b8 --- /dev/null +++ b/индикатор-1-1.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/индикатор-1-1.png-8b27c7b615854227f833f39bac77ddc2.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://индикатор-1-1.png" +dest_files=[ "res://.import/индикатор-1-1.png-8b27c7b615854227f833f39bac77ddc2.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/кнопка-3-0.png b/кнопка-3-0.png new file mode 100644 index 0000000..b425642 Binary files /dev/null and b/кнопка-3-0.png differ diff --git a/кнопка-3-0.png.import b/кнопка-3-0.png.import new file mode 100644 index 0000000..f31b515 --- /dev/null +++ b/кнопка-3-0.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/кнопка-3-0.png-5f27389cf7d8b3614e031e6b8d168b3c.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://кнопка-3-0.png" +dest_files=[ "res://.import/кнопка-3-0.png-5f27389cf7d8b3614e031e6b8d168b3c.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/кнопка-3-1.png b/кнопка-3-1.png new file mode 100644 index 0000000..46216cc Binary files /dev/null and b/кнопка-3-1.png differ diff --git a/кнопка-3-1.png.import b/кнопка-3-1.png.import new file mode 100644 index 0000000..3ca06ce --- /dev/null +++ b/кнопка-3-1.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/кнопка-3-1.png-d6f5584c24056a03a792e757c3c765b0.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://кнопка-3-1.png" +dest_files=[ "res://.import/кнопка-3-1.png-d6f5584c24056a03a792e757c3c765b0.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/кнопка-3.tscn b/кнопка-3.tscn new file mode 100644 index 0000000..0b41009 --- /dev/null +++ b/кнопка-3.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://кнопка-3-1.png" type="Texture" id=1] +[ext_resource path="res://кнопка-3-0.png" type="Texture" id=2] + +[node name="TextureButton" type="TextureButton"] +modulate = Color( 1.5, 1.5, 1.5, 1 ) +margin_right = 140.0 +margin_bottom = 34.0 +toggle_mode = true +action_mode = 0 +texture_normal = ExtResource( 2 ) +texture_pressed = ExtResource( 1 ) +expand = true diff --git a/кнопка-4.tscn b/кнопка-4.tscn new file mode 100644 index 0000000..d249f13 --- /dev/null +++ b/кнопка-4.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://индикатор-1-1.png" type="Texture" id=1] +[ext_resource path="res://индикатор-1-0.png" type="Texture" id=2] + +[node name="indicator_1" type="TextureButton"] +modulate = Color( 1, 0.596078, 0.4, 1 ) +margin_right = 35.0 +margin_bottom = 29.0 +toggle_mode = true +button_mask = 0 +texture_normal = ExtResource( 2 ) +texture_pressed = ExtResource( 1 ) diff --git a/кнопка-5.tscn b/кнопка-5.tscn new file mode 100644 index 0000000..a95460e --- /dev/null +++ b/кнопка-5.tscn @@ -0,0 +1,5 @@ +[gd_scene format=2] + +[node name="OptionButton" type="OptionButton"] +margin_right = 80.0 +margin_bottom = 34.0 diff --git a/ячейка-1.tscn b/ячейка-1.tscn new file mode 100644 index 0000000..ce7cf15 --- /dev/null +++ b/ячейка-1.tscn @@ -0,0 +1,9 @@ +[gd_scene format=2] + +[node name="Label" type="Label"] +margin_right = 122.0 +margin_bottom = 34.0 +custom_colors/font_color = Color( 1, 0.596078, 0.4, 1 ) +align = 1 +valign = 1 +clip_text = true diff --git a/ячейка-2.tscn b/ячейка-2.tscn new file mode 100644 index 0000000..581e010 --- /dev/null +++ b/ячейка-2.tscn @@ -0,0 +1,11 @@ +[gd_scene format=2] + +[node name="LineEdit" type="LineEdit"] +margin_right = 82.0 +margin_bottom = 34.0 +custom_colors/font_color = Color( 1, 0.596078, 0.4, 1 ) +context_menu_enabled = false +shortcut_keys_enabled = false +middle_mouse_paste_enabled = false +caret_blink = true +caret_blink_speed = 0.13