extends Control class_name SelectionManager var selecting:=false var drag_start: Vector2 var select_box: Rect2 @onready var box_color: Color = ProjectSettings.get_setting("game/interface/selection_rectangle_color",Color("#00ff0066")) @onready var box_color_outline: Color = ProjectSettings.get_setting("game/interface/selection_rectangle_color_outline",Color("#00ff00")) @onready var optimized_rect:bool = ProjectSettings.get_setting("game/interface/optimized_rectangle",false) @export var rect_style: StyleBoxFlat @onready var cam = get_viewport().get_camera_3d() func _ready() -> void: if optimized_rect:return func _unhandled_input(e: InputEvent) -> void: if e is InputEventMouseButton and e.button_index == MOUSE_BUTTON_LEFT: if e.pressed: selecting = true drag_start = e.position else: # when button is released selecting = false if drag_start.is_equal_approx(e.position): select_box = Rect2(e.position, Vector2.ZERO) # when just clicked print("one click") queue_redraw() update_selected_units() elif selecting and e is InputEventMouseMotion: var x_min = min(drag_start.x, e.position.x) var y_min = min(drag_start.y, e.position.y) select_box = Rect2(x_min,y_min, max(drag_start.x,e.position.x) - x_min, max(drag_start.y,e.position.y) - y_min) update_selected_units() queue_redraw() func check_raycast(mouse_pos:Vector2,collision_mask:int=4294967295) -> Dictionary: var from = cam.project_ray_origin(mouse_pos) var to = from + cam.project_ray_normal(mouse_pos) * 1000 #Magic number var query = PhysicsRayQueryParameters3D.new() query.from = from ; query.to = to query.collision_mask = collision_mask var space_state = cam.get_world_3d().direct_space_state return space_state.intersect_ray(query) #HACK :https://www.youtube.com/watch?v=NxW9t-YgJkM func update_selected_units() -> void: var units_array = get_tree().get_nodes_in_group('selectable-entity') var raycast = check_raycast(get_local_mouse_position(),2) for entity: Entity in units_array: #TODO: currently searching in all unit in the world. Should search in spawned in the chunk if entity.is_in_selection(select_box, cam): entity.select() elif entity.is_under_mouse(raycast): entity.select() else: entity.deselect() func _draw() -> void: if not selecting:return if select_box and rect_style: if optimized_rect: draw_rect(select_box,box_color) draw_rect(select_box,box_color_outline,false,2.0,true) elif rect_style: draw_style_box(rect_style,select_box)