0 votes

I wanted to do a rectangle drag selection of (1) units (KinematicBody2d with a RectangleShape2D as a child)

In order to do this I've created an (2) Area2d with a CollisionShape2D child with a RectangleShape2D inside, then I attached a script to see if the bodyentered and bodyexited are being triggered whenever the rectangle overlaps a unit.

To test it I have a tree that looks like

  • Node2D

    • Area2D (2)
    • KinematicBody2d (1)

So when I drag the mouse with the button clicked I resize the RectangleShape2D.shape and change its position. Finally what happens is that bodyentered and bodyexited are triggered, but every time I resize the rectangle (each frame) both methods are triggered again (bodyexited first, and then bodyentered, as if the rectangle were being deleted and created again).

Here is the code that resizes:

extends Area2D

var dragging = false
var color = Color(0, 0, 1, 0.3)

func _ready():
    $".".connect("body_entered", self, "select_unit")
    $".".connect("body_exited", self, "deselect_unit")
    pass

func select_unit(body):
    body.set_selected(true)

func deselect_unit(body):
    body.set_selected(false)

func _input(event):
    var mouse_pos = get_global_mouse_position()
    if event is InputEventMouseButton:
        match event.button_index:
            BUTTON_LEFT:
                if event.is_pressed() and not event.is_echo():
                    dragging = true
                    $rect.position.x = mouse_pos.x
                    $rect.position.y = mouse_pos.y
                elif not event.is_pressed():
                    dragging = false
                    print($rect.position.x, " ", $rect.position.y)
                    $rect.shape.extents.x = 0
                    $rect.shape.extents.y = 0
                    update()
    elif event is InputEventMouseMotion:
        if dragging:
            $rect.shape.extents.x += event.relative.x / 2
            $rect.shape.extents.y += event.relative.y / 2
            $rect.position.x += event.relative.x / 2
            $rect.position.y += event.relative.y / 2
            update()

func _draw():
    if dragging:
        var x = $rect.position.x - $rect.shape.extents.x
        var y = $rect.position.y - $rect.shape.extents.y
        var width = $rect.shape.extents.x * 2
        var height = $rect.shape.extents.y * 2
        var a_rect = Rect2(x , y, width, height)
        draw_rect(a_rect, color)

So is this the expected behavior? I mean the fact that every time I resize the shape the bodyentered and bodyexited are triggered again. If no, how could I do what I'm trying to do?

in Engine by (51 points)

1 Answer

0 votes

This is not the way we like to see on an area, I think it is a bug, but probably you won't get a good response anyway, for selections better "cast a shape".

use get_world2D().direct_space_state.intersect_shape and store the result with the list of bodies to work with it, you just need to construct the query object.

http://docs.godotengine.org/en/3.0/classes/class_world2d.html

http://docs.godotengine.org/en/3.0/classes/class_physics2ddirectspacestate.html#class-physics2ddirectspacestate-intersect-shape

by (7,946 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.