diff --git a/Selector.tscn b/Selector.tscn deleted file mode 100644 index 5570abb..0000000 --- a/Selector.tscn +++ /dev/null @@ -1,15 +0,0 @@ -[gd_scene load_steps=2 format=2] - -[ext_resource path="res://nine-patch.png" type="Texture2D" id=1] - -[node name="NinePatchRect" type="NinePatchRect"] -offset_right = 42.0 -offset_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/bin/imi_skysens.x86_64 b/bin/imi_skysens.x86_64 new file mode 100644 index 0000000..cc92d96 Binary files /dev/null and b/bin/imi_skysens.x86_64 differ diff --git a/main.gd b/main.gd index 7a7474d..a07bb23 100644 --- a/main.gd +++ b/main.gd @@ -11,18 +11,18 @@ var sock = PacketPeerUDP.new() # Called when the node enters the scene tree for the first time. func _ready(): - sock.bind(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', Callable(self, 'on_timeout').bind()) - add_child(timer) #to process - timer.start(1) #to start + sock.bind(Consts.MAIN_ADDR[1], Consts.MAIN_ADDR[0]) + sock.set_dest_address(Consts.DST_ADDR[0], Consts.DST_ADDR[1]) + Threats.init_treats(table_threads, btn_add_threads, btn_del_threads) + Pomehi.init_pomehi(table_pomehi) + var timer = Timer.new() + timer.connect('timeout', Callable(self, 'on_timeout').bind()) + add_child(timer) #to process + timer.start(1) #to start func on_timeout(): - sock.put_packet(Threats.get_threats_data()) + sock.put_packet(Threats.get_threats_data()) # Called every frame. 'delta' is the elapsed time since the previous frame. diff --git a/main.tscn b/main.tscn index 8f9cedd..8693154 100644 --- a/main.tscn +++ b/main.tscn @@ -1,12 +1,12 @@ [gd_scene load_steps=5 format=3 uid="uid://87gtvqd7bbje"] -[ext_resource type="Script" path="res://main.gd" id="1_qcx24"] -[ext_resource type="Script" path="res://table.gd" id="2_y3x5h"] -[ext_resource type="Texture2D" uid="uid://cex4jiu1pcj3x" path="res://edit-add-0.png" id="3_5pb81"] -[ext_resource type="Texture2D" uid="uid://cx746np1wexnd" path="res://edit-add-1.png" id="4_i1fqu"] +[ext_resource type="Script" path="res://main.gd" id="1_o7op8"] +[ext_resource type="Script" path="res://table/table.gd" id="2_nv8t5"] +[ext_resource type="Texture2D" uid="uid://cex4jiu1pcj3x" path="res://edit-add-0.png" id="3_g7h67"] +[ext_resource type="Texture2D" uid="uid://cx746np1wexnd" path="res://edit-add-1.png" id="4_75pij"] [node name="main" type="Node2D"] -script = ExtResource("1_qcx24") +script = ExtResource("1_o7op8") [node name="tabs" type="TabContainer" parent="."] offset_right = 1594.0 @@ -16,20 +16,18 @@ offset_bottom = 897.0 layout_mode = 2 [node name="table_t" type="GridContainer" parent="tabs/threats"] -layout_mode = 0 +layout_mode = 1 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 +offset_left = 11.0 offset_top = 100.0 offset_right = 1.0 offset_bottom = 10.0 -script = ExtResource("2_y3x5h") - -[node name="header_t" type="GridContainer" parent="tabs/threats"] -layout_mode = 0 -offset_top = 57.0 -offset_right = 1584.0 -offset_bottom = 96.0 -script = ExtResource("2_y3x5h") +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("2_nv8t5") +node_type_file = "res://ячейка-1.tscn" [node name="btn_add" type="TextureButton" parent="tabs/threats"] layout_mode = 0 @@ -37,8 +35,8 @@ offset_left = 1533.0 offset_top = -2.0 offset_right = 1581.0 offset_bottom = 46.0 -texture_normal = ExtResource("3_5pb81") -texture_pressed = ExtResource("4_i1fqu") +texture_normal = ExtResource("3_g7h67") +texture_pressed = ExtResource("4_75pij") [node name="btn_del" type="TextureButton" parent="tabs/threats"] layout_mode = 0 @@ -56,11 +54,5 @@ layout_mode = 0 offset_top = 100.0 offset_right = 1587.0 offset_bottom = 861.0 -script = ExtResource("2_y3x5h") - -[node name="header_p" type="GridContainer" parent="tabs/pomehi"] -layout_mode = 0 -offset_top = 57.0 -offset_right = 32.0 -offset_bottom = 96.0 -script = ExtResource("2_y3x5h") +script = ExtResource("2_nv8t5") +node_type_file = "res://ячейка-1.tscn" diff --git a/pomehi.gd b/pomehi.gd index 4007fc0..1e1f441 100644 --- a/pomehi.gd +++ b/pomehi.gd @@ -10,10 +10,11 @@ const TableCellType3 = preload('res://кнопка-4.tscn') const TableCellType4 = preload('res://заголовок.tscn') const TableCellType5 = preload('res://ячейка-2.tscn') const TableCellType6 = preload('res://кнопка-5.tscn') +const TableHeader = preload('res://table/header.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_TYPES = [ TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader] const TABLE_HEADER_ALIGNMENTS = [ HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER] const TABLE_ROW_TYPES = [ TableCellType1, TableCellType6, TableCellType1, TableCellType1, TableCellType1, TableCellType1, TableCellType1] const TABLE_ROW_ALIGNMENTS = [ HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER] @@ -30,12 +31,12 @@ const COLUMN_WIDTH = 6 # Ширина диапазона # Индексы колонок, которым можно задавать выравнивание текста const TABLE_ALLIGNED_COLUMNS = [ - COLUMN_ISPP, - COLUMN_KRP, - COLUMN_POWP, - COLUMN_KNI, - COLUMN_FREQ, - COLUMN_WIDTH, ] + COLUMN_ISPP, + COLUMN_KRP, + COLUMN_POWP, + COLUMN_KNI, + COLUMN_FREQ, + COLUMN_WIDTH, ] # Состояние выполнения команды поставновки помехи @@ -49,75 +50,69 @@ 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 + # параметры цели, второе значение, разрешение отправки. + 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 = '%s' % args[0] - krp = '%s' % args[1] - powp = '%s' % args[2] - kni = '%s' % args[3] - freq = '%s' % args[4] - width = '%s' % args[5] + func _init(args : Array): + ispp = '%s' % args[0] + krp = '%s' % args[1] + powp = '%s' % args[2] + kni = '%s' % args[3] + freq = '%s' % args[4] + width = '%s' % args[5] - func update_rows(): - var new_rows: Array = [] - new_rows.append('%s' % ispp) - new_rows.append('%s' % svk) - new_rows.append('%s' % krp) - new_rows.append('%s' % powp) - new_rows.append('%s' % kni) - new_rows.append('%s' % freq) - new_rows.append('%s' % width) - return new_rows - - -func selector_color_proc(_i_row: int): - return Consts.COLOR_ACCENT * Consts.COLOR_HALF_ALPHA + func update_rows(): + var new_rows: Array = [] + new_rows.append('%s' % ispp) + new_rows.append('%s' % svk) + new_rows.append('%s' % krp) + new_rows.append('%s' % powp) + new_rows.append('%s' % kni) + new_rows.append('%s' % freq) + new_rows.append('%s' % width) + return new_rows 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') + for i_row in table.get_rows_count(): + table.set_nodes_min_size(i_row, sizes) 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) + 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', Callable(self, 'on_row_pressed').bind(table)) - table.set_callbacks(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, [table]) +func init_pomehi(table): # Инициализация вкладки с целями + table.set_header(TABLE_HEADER_TYPES) + table.set_header_text(TABLE_HEADERS) + on_btn_add(table) + init_table(table, TABLE_COLUMN_SIZES) + table.connect('row_pressed', Callable(self, 'on_row_pressed').bind(table)) + table.connect_columns(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['%d' % 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, []) + var pomeha : = Pomeha.new([1,2,3,4,5,6]) + pomehi['%d' % 1] = pomeha + var row = pomeha.update_rows() + table.add_row(TABLE_ROW_TYPES) + table.set_row_text(table.get_rows_count()-1, row) + table.set_columns_min_size(TABLE_COLUMN_SIZES) + init_opt_btns(table.get_rows_count()-1, table) + table.connect_columns(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, []) func on_row_pressed(i_row: int, table): - pass + pass diff --git a/project.godot b/project.godot index 7f0090b..507241e 100644 --- a/project.godot +++ b/project.godot @@ -21,7 +21,7 @@ Consts="*res://consts.gd" Threats="*res://threats.gd" Pomehi="*res://pomehi.gd" Tools="*res://tools.gd" -Table="*res://table.gd" +Table="*res://table/table.gd" [display] diff --git a/table.gd b/table.gd deleted file mode 100644 index 1efa7b2..0000000 --- a/table.gd +++ /dev/null @@ -1,416 +0,0 @@ -@tool -extends GridContainer - -@export var _selector_color: Color = Color(1.0, 1.0, 1.0, 1.0) -@export var columns_count: int = 1: set = _set_columns_count -@export var rows_count: int = 1: set = _set_rows_count -@export var node_type_file: String = '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: Callable -var selector_size_proc: Callable -signal row_pressed(i_row) # Вызывается при нажатии кнопкой мыши на строку -const MAX_INDEX = 99 # Максимальное значение индекса для колонки и строки. Связано с форматом ключа - - -func align_to_left_bottom(header, gap: = Vector2(0, 0)): - """ Выравнивает по нижнему левому углу. Используется для выравнивания по заголовку """ - position.x = header.position.x + gap.x - position.y = header.position.y + header.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 < position.x: - emit_signal('focus_exited') - return - if event.position.x > (position.x + size.x): - emit_signal('focus_exited') - return - if event.position.y < position.y: - emit_signal('focus_exited') - return - if event.position.y > (position.y + size.y): - emit_signal('focus_exited') - return - var rows_count: = get_rows_count() - var parent = get_parent() - var y0 = parent.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] + 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 = Callable(self, 'default_selector_color_proc') - assert(selector_color_proc.is_valid()) - selector_size_proc = Callable(self, '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 = Callable(instance, function) - assert(selector_color_proc.is_valid()) - - -func set_selector_size_proc(instance: Object, function: String) -> void: - selector_size_proc = Callable(instance, 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] + position.x - 1 - rect[1] = rect[1] + position.y - 4 - rect[2] = 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.instantiate() - var rect: = [0, 0, 0, 0] - selector_size_proc.call(i_row, rect) - selector.position.x = rect[0] - selector.position.y = rect[1] - selector.size.x = rect[2] - selector.size.y = rect[3] - selector.modulate = selector_color_proc.call(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].instantiate() - 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', Callable(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, Callable(prev_dest_node, prev_callback)) - assert (OK == node.connect(event_name, Callable(dest_node, callback).bind([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.custom_minimum_size.x = sizes[i_col] - node.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].button_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].button_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.position.x - rect[1] = cell.position.y - rect[2] = cell.size.x - rect[3] = cell.size.y diff --git a/table/header.tscn b/table/header.tscn new file mode 100644 index 0000000..24b90a1 --- /dev/null +++ b/table/header.tscn @@ -0,0 +1,12 @@ +[gd_scene load_steps=2 format=3 uid="uid://ch14g46swx74h"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2thpi"] +bg_color = Color(0.8, 0.533333, 0.27451, 1) + +[node name="header" type="Label"] +offset_right = 128.0 +offset_bottom = 23.0 +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_styles/normal = SubResource("StyleBoxFlat_2thpi") +horizontal_alignment = 1 +vertical_alignment = 1 diff --git a/table/nine-patch.png b/table/nine-patch.png new file mode 100644 index 0000000..1649a7f Binary files /dev/null and b/table/nine-patch.png differ diff --git a/table/nine-patch.png.import b/table/nine-patch.png.import new file mode 100644 index 0000000..2d8c80a --- /dev/null +++ b/table/nine-patch.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bw3yv3smvaxqn" +path="res://.godot/imported/nine-patch.png-798f7950fb3126b4e1ed0c39d9e4beba.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://table/nine-patch.png" +dest_files=["res://.godot/imported/nine-patch.png-798f7950fb3126b4e1ed0c39d9e4beba.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/table/node.tscn b/table/node.tscn new file mode 100644 index 0000000..120347d --- /dev/null +++ b/table/node.tscn @@ -0,0 +1,10 @@ +[gd_scene format=3 uid="uid://c1i4rwaajq7d5"] + +[node name="Label" type="LineEdit"] +offset_right = 121.0 +offset_bottom = 23.0 +theme_override_colors/font_color = Color(1, 0.596078, 0.4, 1) +editable = false +context_menu_enabled = false +caret_blink = true +caret_blink_interval = 0.1 diff --git a/table/selector.tscn b/table/selector.tscn new file mode 100644 index 0000000..47a6c74 --- /dev/null +++ b/table/selector.tscn @@ -0,0 +1,15 @@ +[gd_scene load_steps=2 format=3 uid="uid://pd3fcx55duj2"] + +[ext_resource type="Texture2D" uid="uid://bw3yv3smvaxqn" path="res://table/nine-patch.png" id="1_ik10p"] + +[node name="NinePatchRect" type="NinePatchRect"] +offset_right = 17.0 +offset_bottom = 16.0 +texture = ExtResource("1_ik10p") +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/table/table.gd b/table/table.gd new file mode 100644 index 0000000..68001e5 --- /dev/null +++ b/table/table.gd @@ -0,0 +1,594 @@ +extends GridContainer + +## Виджет "Таблица" + +@export var node_gap: = Vector2(0.0, 0.0) ## Зазор между ячейками, который не возможно вычислить или получить +@export var selector_color: = Color(1.0, 1.0, 1.0, 1.0) ## Окрашивающий цвет для индикатора выбранного ряда +@export var selector_key_down: Key = KEY_DOWN ## Клавиша увеличения индекса выбранного ряда +@export var selector_key_up: Key = KEY_UP ## Клавиша уменьшения индекса выбранного ряда +@export_file var node_type_file: = 'res://table/node.tscn': get = get_node_scene, set = load_node_scene ## Сцена ячейки устанавливаемая по умолчанию +@export_file var selector_type_file: = 'res://table/selector.tscn': set = load_selector_scene ## Сцена индикатора для выбранного ряда + +const HEAD_PREFIX = 'HEAD_' ## Префикс ключа заголовка таблицы +const INDEX_FORMAT = '%02d_%02d' ## Формат индекса ключа +const MAX_INDEX = 99 ## Максимальное значение индекса для колонки и строки. Связано с форматом индекса ключа +const NODE_PREFIX = 'NODE_' ## Префикс ключа ячейки таблицы +const SLCT_PREFIX = 'SLCT_' ## Префикс ключа индикатора выбранного ряда таблицы + +const HEAD_KEY_FORMAT = HEAD_PREFIX + INDEX_FORMAT ## Формат ключа заголовка +const NODE_KEY_FORMAT = NODE_PREFIX + INDEX_FORMAT ## Формат ключа ячейки +const ROW_SELECTOR_KEY_FORMAT = SLCT_PREFIX + INDEX_FORMAT ## Формат ключа индикаторов выбранного ряда +const META_NAME_USER_DATA = 'user_data' +const META_NAME_CALLEBLE = 'calleble' + +var header: GridContainer ## Заголовок таблицы +var in_focus: = false ## Фокус пользовательского ввода +var nodes: = {} ## Все ячейки таблицы и дополнительные элементы +var ScnNode: PackedScene ## Прототип ячейки таблицы +var ScnSelector: PackedScene ## Прототип индикатора выбранного ряда +var selector_color_proc: Callable ## Ссылка на процедуру генератора цвета индикатора выбранного ряда +var selector_size_proc: Callable ## Ссылка на процедуру генератора размера индикатора выбранного ряда + +signal row_pressed(i_row: int) ## Вызывается при нажатии кнопкой мыши на строку +signal selected_changed(i_row: int) ## Вызывается при изменении выбранного ряда. i_row - текущий выбранный ряд + +var scroll: Control +var scroll_adj: = Vector2(0, 0) + + +func get_node_scene(): return node_type_file +func _assert_meta(i_col: int, i_row: int, pname: String, node): assert(node.has_meta(pname), 'ошибка: нет мета-свойства \"%s\" у ячейки колонка:%d ряд:%d' % [pname, i_col, i_row]) +func get_node_user_data(i_col: int, i_row: int): return get_node_meta(i_col, i_row, META_NAME_USER_DATA) +func set_node_user_data(i_col: int, i_row: int, val) -> void: set_node_meta(i_col, i_row, META_NAME_USER_DATA, val) + + +## Закрепляет заголовок таблицы. [param scrl] - Прокрутка, +## [param prnt] - Родитель прокрутки заданный в редакторе +func pin_header(scrl: ScrollContainer, prnt: Control): + scrl.remove_child(header) + prnt.add_child(header) + ## TODO: Это значение следует получить из темы + var v_separation: = 3.0 + header.position = scrl.position - Vector2(0, header.size.y + v_separation) + scroll = scrl + scroll_adj = scrl.position + + +## Перемещает указатель на одну строку вверх +func selector_up(): + var i_rows: = [] + get_selected_rows(i_rows) + for i in i_rows: + set_row_selected(i, false) + var rows_count: = get_rows_count() + if not (i_rows.size() and (rows_count > 1)): + return + var i_row = i_rows[0] + i_row -= 1 + if i_row < 0: + i_row = rows_count - 1 + set_row_selected(i_row, true) + emit_signal('selected_changed', i_row) + + +## Перемещает указатель на одну строку вниз +func selector_down(): + var i_rows: = [] + get_selected_rows(i_rows) + for i in i_rows: + set_row_selected(i, false) + var rows_count: = get_rows_count() + if not (i_rows.size() and (rows_count > 1)): + return + var i_row = i_rows[0] + i_row += 1 + i_row %= rows_count + set_row_selected(i_row, true) + emit_signal('selected_changed', i_row) + + +## +func set_columns_alignments(alignments): + assert(columns == alignments.size()) + var rows_count: = get_rows_count() + for i_row in rows_count: + for i_col in alignments.size(): + set_node_alligment(i_col, i_row, alignments[i_col]) + + +## +func load_selector_scene(file_name: String): + selector_type_file = file_name + ScnSelector = load(file_name) + + +## +func load_node_scene(file_name: String): + node_type_file = file_name + ScnNode = load(file_name) + + +## +func _ready(): + ScnSelector = load(selector_type_file) + ScnNode = load(node_type_file) + assert(ScnSelector) + assert(ScnNode) + + +## Выравнивает по нижнему левому углу. Используется для выравнивания по заголовку +func align_to_left_bottompos(hdr: Control, gap: = Vector2(0, 0)): + position.x = hdr.position.x + gap.x + position.y = hdr.position.y + hdr.size.y + gap.y + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. +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) + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. +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) + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. +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) + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. +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) + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда +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: + var rows_count: = get_rows_count() + for i_row in rows_count: + set_nodes_min_size(i_row, sizes) + set_nodes_min_size(0, sizes, HEAD_KEY_FORMAT) + + +## +func set_columns_aligment(alignments: Array) -> void: + var rows_count: = get_rows_count() + for i_row in 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 InputEventKey: + if in_focus and event.pressed: + if event.keycode == selector_key_up: + selector_up() + elif event.keycode == selector_key_down: + selector_down() + elif event is InputEventMouseButton: + if not event.pressed: + return + if check_event_pos(event.position, scroll): + if not in_focus: + in_focus = true + emit_signal('focus_entered') + elif not check_event_pos(event.position, scroll): + if in_focus: + in_focus = false + emit_signal('focus_exited') + + +## +func _init() -> void: + selector_color_proc = Callable(self, 'defaultselector_color_proc') + assert(selector_color_proc.is_valid()) + selector_size_proc = Callable(self, 'default_selector_size_proc') + assert(selector_size_proc.is_valid()) + scroll = self + + +## +func check_event_pos(event_pos: Vector2, obj: Control): + return \ + (event_pos.x > obj.position.x) \ + and (event_pos.x < (obj.position.x + obj.size.x)) \ + and (event_pos.y > obj.position.y) \ + and (event_pos.y < (obj.position.y + obj.size.y)) + + +## +func defaultselector_color_proc(_i_row: int): + return selector_color + + +## +func setselector_color_proc(instance: Object, function: String) -> void: + selector_color_proc = Callable(instance, function) + assert(selector_color_proc.is_valid()) + + +## +func set_selector_size_proc(instance: Object, function: String) -> void: + selector_size_proc = Callable(instance, function) + assert(selector_size_proc.is_valid()) + + +## [param i_row] - Индекс ряда +func default_selector_size_proc(i_row: int, rect: Array) -> void: + get_row_rect(i_row, rect) + rect[0] += position.x - node_gap.x / 2.0 + rect[1] += position.y - node_gap.y / 2.0 + rect[2] += node_gap.x + rect[3] += node_gap.y + + +## +func clear_rows_selected(): + var rows_count: = get_rows_count() + for i_row in rows_count: + set_row_selected(i_row, false) + + +## [param i_row] - Индекс ряда. +func set_row_selected(i_row: int, selected: bool = true) -> void: + var key: = ROW_SELECTOR_KEY_FORMAT % [i_row, 0] + var node = nodes[NODE_KEY_FORMAT % [i_row, 0]] + if nodes.has(key) and (not selected): + var selector = nodes[key] + node.remove_child(selector) + selector.queue_free() + nodes.erase(key) + elif (not nodes.has(key)) and selected: + var selector = ScnSelector.instantiate() + var rect: = [0, 0, 0, 0] + selector_size_proc.call(i_row, rect) + selector.size.x = rect[2] + selector.size.y = rect[3] + selector.modulate = selector_color_proc.call(i_row) + selector.z_index = z_index + 1 + nodes[key] = selector + node.add_child(selector) + + +## [param i_row] - Индекс ряда. +func is_row_selected(i_row: int) -> bool: + var key: = ROW_SELECTOR_KEY_FORMAT % [i_row, 0] + return nodes.has(key) + + +## [param i_row] - Индексы рядов. +func get_selected_rows(i_rows: Array) -> void: + for key in nodes.keys(): + if SLCT_PREFIX in key: + var indexes = get_key_indexes(key) + i_rows.append(indexes[1]) + + +## Возвращает количество рядов +func get_rows_count() -> int: + var nodes_count: int = 0 + for key in nodes: + nodes_count += int(NODE_PREFIX in key) + return nodes_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 add_row(row_types: Array) -> void: + assert(row_types.size() < MAX_INDEX, 'ошибка: слишком много колонок, больше %d' % (MAX_INDEX + 1)) + if columns == 1: + set_columns(row_types.size()) + else: + assert(columns == row_types.size(), 'ошибка: %s количество колонок установлено ранее - %d, но требуется %d' % [self, columns, row_types.size()]) + var i_row: int = get_rows_count() + assert(i_row < MAX_INDEX, 'ошибка: слишком много рядов, больше %d' % (MAX_INDEX + 1)) + for i_col in columns: + var node_type = row_types[i_col] + var node = node_type.instantiate() + assert(node.name == node.name, 'ошибка: экземпляр не имеет поля \"name\"') + var head = nodes[HEAD_KEY_FORMAT % [0, i_col]] + node.custom_minimum_size.x = head.custom_minimum_size.x + node.set_deferred('size.x', head.size.x) + var node_key: String = NODE_KEY_FORMAT % [i_row, i_col] + node.name = node_key + add_child(node) + nodes[node_key] = node + var conn = Callable(self, '_on_focus_entered').bind(node) + node.connect('focus_entered', conn) + set_node_meta(i_col, i_row, 'callable_focus_entered', conn) + + +## +func _on_focus_entered(node): + var indexes = get_key_indexes(node.name) + emit_signal('row_pressed', indexes[1]) + + +## +func set_header(header_types: Array): + assert(header_types.size() < MAX_INDEX, 'ошибка: количество колонок в заголовке: %d больше допустимого: %d' % [header_types.size(), MAX_INDEX + 1]) + if columns == 1: + set_columns(header_types.size()) + else: + assert(columns == header_types.size(), 'ошибка: количество колонок в заголовке %d, но ранее установлено: %d' % [header_types.size(), columns]) + var do_adj: = false + if not header: + header = GridContainer.new() + header.position = position + header.columns = header_types.size() + header.size.x = size.x + var parent = scroll.get_parent() + parent.add_child(header) + do_adj = true + else: + var childrens = header.get_children() + for node in childrens: + childrens.erase(node.name) + childrens.remove_child(node) + node.queue_free() + for i_col in columns: + var node = header_types[i_col].instantiate() + var key: String = HEAD_KEY_FORMAT % [0, i_col] + node.name = key + nodes[key] = node + header.add_child(node) + if do_adj: + var rect = [0, 0, 0, 0] + get_node_rect(0, 0, rect, HEAD_KEY_FORMAT) + position.y += rect[3] + + +## +func set_header_text(headers: Array): + assert(columns == headers.size()) + set_row_text(0, headers, 0, HEAD_KEY_FORMAT) + + +## +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] + var prnt = selector.get_parent() + prnt.remove_child(selector) + selector.queue_free() + nodes.erase(sel_key) + + for i_col in columns: + + var node_key: String = NODE_KEY_FORMAT % [i_row, i_col] + var node = nodes[node_key] + + var conn = get_node_meta(i_col, i_row, 'callable_focus_entered') + node.disconnect('focus_entered', conn) + + if node.has_meta(META_NAME_CALLEBLE): + conn = node.get_meta(META_NAME_CALLEBLE) + node.disconnect('pressed', conn) + + remove_child(node) + nodes.erase(node_key) + node.queue_free() + rehash() + + +## +func next_index(indexes: Array) -> void: + indexes[0].x += 1 + if indexes[0].x == columns: + indexes[0].x = 0 + indexes[0].y += 1 + + +## +func swap_nodes(nodes_copy, node_key_format, i0, i1) -> void: + var key0 = node_key_format % [i0.y, i0.x] + var key1 = node_key_format % [i1.y, i1.x] + nodes_copy[key1] = nodes[key0] + nodes_copy[key1].name = key1 + + +## Переназначает ключи в соответствии с размерами таблицы. +func rehash(): + var i_node: = [Vector2i()] + var i_hdr: = [Vector2i()] + var i_slct: = [Vector2i()] + var nodes_copy = {} + for key in nodes: + var iv = get_key_indexes(key) + var i0 = Vector2(iv[0], iv[1]) + if HEAD_PREFIX in key: + swap_nodes(nodes_copy, HEAD_KEY_FORMAT, i0, i_hdr[0]) + next_index(i_hdr) + elif NODE_PREFIX in key: + swap_nodes(nodes_copy, NODE_KEY_FORMAT, i0, i_node[0]) + next_index(i_node) + elif SLCT_PREFIX in key: + swap_nodes(nodes_copy, ROW_SELECTOR_KEY_FORMAT, i0, i_slct[0]) + next_index(i_slct) + nodes.clear() + nodes.merge(nodes_copy) + + +## Удаляет все строки таблицы +func clear_rows() -> void: + var rows_count: int = get_rows_count() + for i_row in range(rows_count - 1, -1, -1): + remove_row(i_row) + + +## Настраевает обратные вызовы для колонок. +## [param dest_node] - Получатель события[br] +## [param event_name] - Имя события[br] +## [param callback] - Имя функции получателя события[br] +## [param clmns] - Индексы колонок[br] +## [param user_data] - Аргументы функции получателя события[br] +func connect_columns(dest_node: Node, event_name: String, callback: String, clmns: Array, user_data: Array) -> void: + 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 = get_node2(i_col, i_row) + if node.has_meta(META_NAME_CALLEBLE): + var conn = node.get_meta(META_NAME_CALLEBLE) + node.disconnect(event_name, conn) + var conn = Callable(dest_node, callback).bind([node] + user_data) + assert (OK == node.connect(event_name, conn)) + node.set_meta(META_NAME_CALLEBLE, conn) + +## +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, key_format: String = NODE_KEY_FORMAT) -> void: + for i_col in columns: + var key: = get_node_key(key_format, i_col, i_row) + var node = nodes[key] + node.custom_minimum_size.x = sizes[i_col] + node.set_deferred('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[key].button_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].button_pressed = val + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. +func set_node_frame(i_col: int, i_row: int, node_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(node_name) + sprite.frame = val + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. +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 + + +## [param i_col] - индекс колонки. [param i_row] - индекс ряда. +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) + if 'horizontal_alignment' in nodes[key]: + nodes[key].horizontal_alignment = val + elif 'alignment' in nodes[key]: + nodes[key].alignment = val + + +## [param i_row] - индекс ряда. +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] + + +## [param i_row] - индекс ряда. +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, key_format: String = NODE_KEY_FORMAT) -> void: + assert(i_begin >= 0) + assert((columns - i_begin) <= row.size()) + for i_col in columns - i_begin: + var key: = get_node_key(key_format, i_col + i_begin, 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 + + +## Возвращает массив ячеек из ряда [param i_row] +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 + + +## Возвращает прямоугольник [param rect] занимаемый ячейкой в ряду [param i_row] и колонке [param i_col]. +## [param key_format] - Формат ключа ячейки +func get_node_rect(i_col: int, i_row: int, rect: Array, key_format: String = NODE_KEY_FORMAT) -> void: + assert(rect.size() >= 4, 'ошибка: мало элементов для возврата результата') + var key: = get_node_key(key_format, i_col, i_row) + var cell = nodes[key] + rect[0] = cell.position.x + rect[1] = cell.position.y + rect[2] = cell.size.x + rect[3] = cell.size.y + + +## Возвращает прямоугольник [param rect] занимаемый рядом [param i_row]. [param key_format] - Формат ключа ячейки +func get_row_rect(i_row: int, rect: Array, key_format: String = NODE_KEY_FORMAT) -> void: + assert(rect.size() >= 4, 'ошибка: мало элементов для возврата результата') + var cell0 = nodes[get_node_key(key_format, 0, i_row)] + var cell1 = nodes[get_node_key(key_format, columns - 1, i_row)] + rect[0] = cell0.position.x + scroll_adj.x + rect[1] = cell0.position.y + scroll_adj.y + rect[2] = (cell1.position.x - cell0.position.x) + cell1.size.x + rect[3] = cell0.size.y diff --git a/threats.gd b/threats.gd index 38c140e..3dffceb 100644 --- a/threats.gd +++ b/threats.gd @@ -12,10 +12,11 @@ const TableCellType3 = preload('res://кнопка-4.tscn') const TableCellType4 = preload('res://заголовок.tscn') const TableCellType5 = preload('res://ячейка-2.tscn') const TableCellType6 = preload('res://кнопка-5.tscn') +const TableHeader = preload('res://table/header.tscn') # Индекс колонки: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const TABLE_HEADERS = ['ID Цели', 'Курc.град', 'Частота', 'Ш. диап.', 'Ампл.', '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_TYPES = [ TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader] const TABLE_HEADER_ALIGNMENTS = [ HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_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 = [ HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_LEFT, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER] @@ -40,45 +41,45 @@ 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 ] + 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 ] + 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'] + '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', ] + 'mavlink', 'ltm', 'hc12', 'df1', ] # Номера колонок const COLUMN_OPT = [[COLUMN_TMOD, MODE_TYPES], [COLUMN_FREQM, FREQM], [COLUMN_PROTO, M_PROTO]] @@ -88,319 +89,313 @@ 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], - } + # параметры цели, второе значение, разрешение отправки. + 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 _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 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 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 '%s' % val[0] - else: - return '' + func _check_value(val): + if val[1]: + return '%s' % 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_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_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_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_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_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_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_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_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_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_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_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_pressed(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_alt_pressed(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 = str(val) - row.tmod[0] = value - row.tmod[1] = false if value == '<неопр.>' else true - return value + func set_tmod(val): + var value = str(val) + row.tmod[0] = value + row.tmod[1] = false if value == '<неопр.>' else true + return value - func set_freqm(val): - var value = str(val) - row.freqm[0] = value - row.freqm[1] = false if value == '<неопр.>' else true - return value + func set_freqm(val): + var value = str(val) + row.freqm[0] = value + row.freqm[1] = false if value == '<неопр.>' else true + return value - func set_proto(val): - var value = str(val) - row.proto[0] = value - row.proto[1] = false if value == '<неопр.>' else true - return value + func set_proto(val): + var value = str(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) - g_table = table - table.align_to_left_bottom(header, Vector2(0, 2)) - table.connect('row_pressed', Callable(self, 'on_row_pressed').bind(table)) - table.set_callbacks(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, []) - table.set_callbacks(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, []) - btn_add.connect('button_up', Callable(self, 'on_btn_add').bind(table)) - btn_del.connect('button_up', Callable(self, 'on_btn_del').bind(table)) - - -func selector_color_proc(_i_row: int): - return Consts.COLOR_ACCENT * Consts.COLOR_HALF_ALPHA +func init_treats(table, btn_add, btn_del): # Инициализация вкладки с целями + for i in range(ID_ARRAY_LEN): # Заполняет массив ID целей + id_array.append(i+1) + table.set_header(TABLE_HEADER_TYPES) + table.set_header_text(TABLE_HEADERS) + on_btn_add(table) + init_table(table, TABLE_COLUMN_SIZES) + g_table = table + table.set_columns_min_size(TABLE_COLUMN_SIZES) + table.connect('row_pressed', Callable(self, 'on_row_pressed').bind(table)) + table.connect_columns(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, []) + table.connect_columns(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, []) + btn_add.connect('button_up', Callable(self, 'on_btn_add').bind(table)) + btn_del.connect('button_up', Callable(self, 'on_btn_del').bind(table)) 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') + for i_row in table.get_rows_count(): + #table.set_nodes_min_size(i_row, sizes) + pass 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) + 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): - var optbtn_text = node.text - var indexis = g_table.get_key_indexes(node.name) - var row_i = indexis[1] - var col_i = indexis[0] - var cell = g_table.get_node2(0,row_i) - var value = set_value(optbtn_text, cell.text, col_i) + var optbtn_text = node.text + var indexis = g_table.get_key_indexes(node.name) + var row_i = indexis[1] + var col_i = indexis[0] + var cell = g_table.get_node2(0,row_i) + var value = set_value(optbtn_text, cell.text, col_i) func on_edit_entry(text : String, entry): - var indexis = g_table.get_key_indexes(entry[0].name) - var row_i = indexis[1] - var col_i = indexis[0] - var cell = g_table.get_node2(0,row_i) - var value = set_value(text, cell.text, col_i) - entry[0].text = str(value) + var indexis = g_table.get_key_indexes(entry[0].name) + var row_i = indexis[1] + var col_i = indexis[0] + var cell = g_table.get_node2(0,row_i) + var value = set_value(text, cell.text, col_i) + entry[0].text = str(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_pressed(val) + 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_pressed(val) func on_row_pressed(i_row: int, table): - table.clear_rows_selected() - table.set_row_selected(i_row, true) + 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['%d' % 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_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, []) - table.set_callbacks(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, []) + var id = pop_id() + var threat : = Threat.new(id) + treats['%d' % 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.connect_columns(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, []) + table.connect_columns(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([]) + 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]) func pop_id(): - var id = 0 - if len(id_array): - id = id_array[0] - id_array.remove_at(0) - return id + var id = 0 + if len(id_array): + id = id_array[0] + id_array.remove_at(0) + return id func push_id(id : int): - id_array.append(id) + 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 = JSON.new().stringify(data_to_json) - var pac = json.to_utf8_buffer() - return pac + 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 = JSON.new().stringify(data_to_json) + var pac = json.to_utf8_buffer() + return pac diff --git a/tools.gd b/tools.gd index e8ba765..0f83f25 100644 --- a/tools.gd +++ b/tools.gd @@ -2,29 +2,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 + 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 + if val < 0: + return 0 + else: + return val func check_len(val, value): - if len(val) < 1: - return '' - else: - return value + if len(val) < 1: + return '' + else: + return value func check_empty(val): - - if str(val) == '': - return false - else: - return true + + if str(val) == '': + return false + else: + return true diff --git a/кнопка-4.tscn b/кнопка-4.tscn index 44e3a6d..ba3d67d 100644 --- a/кнопка-4.tscn +++ b/кнопка-4.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://ccxre8mwhndjk"] -[ext_resource type="Texture2D" uid="uid://b3ext3w4ftgg2" path="res://индикатор-1-1.png" id="1"] -[ext_resource type="Texture2D" uid="uid://dag8n0gknjwak" path="res://индикатор-1-0.png" id="2"] +[ext_resource type="Texture2D" uid="uid://dag8n0gknjwak" path="res://индикатор-1-0.png" id="1_1mkdt"] +[ext_resource type="Texture2D" uid="uid://b3ext3w4ftgg2" path="res://индикатор-1-1.png" id="2_21ih5"] [node name="indicator_1" type="TextureButton"] modulate = Color(1, 0.596078, 0.4, 1) @@ -9,5 +9,5 @@ offset_right = 35.0 offset_bottom = 29.0 toggle_mode = true button_mask = 0 -texture_normal = ExtResource("2") -texture_pressed = ExtResource("1") +texture_normal = ExtResource("1_1mkdt") +texture_pressed = ExtResource("2_21ih5")