class_name SelectionManager extends Node signal added_to_group(nodes: Array[Node], id: String) signal removed_from_group(nodes: Array[Node], id: String) signal moved_to_group(nodes: Array[Node], previous_id: String, new_id: String) var selection_groups := {} signal selected_group_changed(previous_id: String, new_id: String) var selected_group := "": set(value): var previous_id := selected_group selected_group = value selected_group_changed.emit(previous_id, value) var node_count: int func _ready() -> void: Client.multi_select_finished.connect(_on_multi_select_finished) Client.placed_tower.connect(_on_placed_tower) func add_to_selection_group(nodes: Array[Node], id: String) -> void: if id not in selection_groups: selection_groups[id] = [] selection_groups[id].append_array(nodes) node_count += nodes.size() if not selected_group: reset_selected_group() added_to_group.emit(nodes, id) func remove_from_selection_group(nodes: Array[Node], id: String, fallback_id: String = "") -> void: for node in nodes: selection_groups[id].erase(node) if selection_groups[id].is_empty(): selection_groups.erase(id) if id == selected_group: if fallback_id and selection_groups.has(fallback_id): selected_group = fallback_id else: reset_selected_group() node_count -= nodes.size() removed_from_group.emit(nodes, id) func move_to_selection_group(nodes: Array[Node], previous_id: String, new_id: String) -> void: remove_from_selection_group(nodes, previous_id, new_id) add_to_selection_group(nodes, new_id) moved_to_group.emit(nodes, previous_id, new_id) func get_ordered_group_ids() -> Array:#Array[String]: # TODO: remove bound to Tower # TODO: use static function on Tower get_sort_conditions? var keys = selection_groups.keys() keys.sort_custom(func(a, b): var group_a = selection_groups[a] var group_b = selection_groups[b] return group_a.size() > group_b.size() ) keys.sort_custom(func(a, b): var group_a = selection_groups[a] var group_b = selection_groups[b] var node_a = group_a[0] var node_b = group_b[0] var level_a = 0 var level_b = 0 for component in node_a.components.values(): level_a += component.level for component in node_b.components.values(): level_b += component.level return level_a > level_b ) keys.sort_custom(func(a, b): var group_a = selection_groups[a] var group_b = selection_groups[b] return group_a[0].components.size() > group_b[0].components.size() ) return keys func get_selected_nodes() -> Array: if selected_group: return selection_groups[selected_group] return [] func get_nodes() -> Array: var nodes := [] for id in selection_groups: nodes.append_array(selection_groups[id]) return nodes func go_to_next(): var ids = get_ordered_group_ids() var current_idx = ids.find(selected_group) selected_group = ids[(current_idx + 1) % ids.size()] func go_to_previous(): var ids = get_ordered_group_ids() var current_idx = ids.find(selected_group) selected_group = ids[(current_idx - 1) % ids.size()] func has_selection() -> bool: return selection_groups.size() > 0 func has_node_in_group(node: Node, id: String) -> bool: return selection_groups.has(id) and selection_groups[id].has(node) func reset_selected_group(): var ids = get_ordered_group_ids() if ids.size() > 0: selected_group = ids[0] else: selected_group = "" func _on_multi_select_finished(_nodes: Array): #add_to_selection_group(nodes) reset_selected_group() func _on_placed_tower(tower: Tower): if tower.owner_id == multiplayer.get_unique_id(): tower.selected.connect(func(): _on_selected_tower(tower) ) tower.deselected.connect(func(): _on_deselected_tower(tower) ) tower.selection_group_id_changed.connect(func(previous_id: String): _on_tower_selection_group_id_changed(tower, previous_id) ) func _on_selected_tower(tower: Tower): if not has_node_in_group(tower, tower.selection_group_id): add_to_selection_group([tower], tower.selection_group_id) func _on_deselected_tower(tower: Tower): remove_from_selection_group([tower], tower.selection_group_id) func _on_tower_selection_group_id_changed(tower: Tower, previous_id: String): move_to_selection_group([tower], previous_id, tower.selection_group_id)