Add mouse_shape_entered and mouse_shape_exited signals to CollisionObject2D.
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
This commit is contained in:
parent
a82765a464
commit
6f3e7f7cb0
|
@ -60,8 +60,11 @@ bool operator!=(const Pair<F, S> &pair, const Pair<F, S> &other) {
|
||||||
template <class F, class S>
|
template <class F, class S>
|
||||||
struct PairSort {
|
struct PairSort {
|
||||||
bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const {
|
bool operator()(const Pair<F, S> &A, const Pair<F, S> &B) const {
|
||||||
|
if (A.first != B.first) {
|
||||||
return A.first < B.first;
|
return A.first < B.first;
|
||||||
}
|
}
|
||||||
|
return A.second < B.second;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PAIR_H
|
#endif // PAIR_H
|
||||||
|
|
|
@ -234,12 +234,26 @@
|
||||||
</signal>
|
</signal>
|
||||||
<signal name="mouse_entered">
|
<signal name="mouse_entered">
|
||||||
<description>
|
<description>
|
||||||
Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set.
|
Emitted when the mouse pointer enters any of this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted.
|
||||||
</description>
|
</description>
|
||||||
</signal>
|
</signal>
|
||||||
<signal name="mouse_exited">
|
<signal name="mouse_exited">
|
||||||
<description>
|
<description>
|
||||||
Emitted when the mouse pointer exits all this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [code]collision_layer[/code] bit to be set.
|
Emitted when the mouse pointer exits all this object's shapes. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set. Note that moving between different shapes within a single [CollisionObject2D] won't cause this signal to be emitted.
|
||||||
|
</description>
|
||||||
|
</signal>
|
||||||
|
<signal name="mouse_shape_entered">
|
||||||
|
<argument index="0" name="shape_idx" type="int">
|
||||||
|
</argument>
|
||||||
|
<description>
|
||||||
|
Emitted when the mouse pointer enters any of this object's shapes or moves from one shape to another. [code]shape_idx[/code] is the child index of the newly entered [Shape2D]. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
|
||||||
|
</description>
|
||||||
|
</signal>
|
||||||
|
<signal name="mouse_shape_exited">
|
||||||
|
<argument index="0" name="shape_idx" type="int">
|
||||||
|
</argument>
|
||||||
|
<description>
|
||||||
|
Emitted when the mouse pointer exits any of this object's shapes. [code]shape_idx[/code] is the child index of the exited [Shape2D]. Requires [member input_pickable] to be [code]true[/code] and at least one [member collision_layer] bit to be set.
|
||||||
</description>
|
</description>
|
||||||
</signal>
|
</signal>
|
||||||
</signals>
|
</signals>
|
||||||
|
|
|
@ -346,6 +346,20 @@ void CollisionObject2D::_mouse_exit() {
|
||||||
emit_signal(SceneStringNames::get_singleton()->mouse_exited);
|
emit_signal(SceneStringNames::get_singleton()->mouse_exited);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CollisionObject2D::_mouse_shape_enter(int p_shape) {
|
||||||
|
if (get_script_instance()) {
|
||||||
|
get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_shape_enter, p_shape);
|
||||||
|
}
|
||||||
|
emit_signal(SceneStringNames::get_singleton()->mouse_shape_entered, p_shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollisionObject2D::_mouse_shape_exit(int p_shape) {
|
||||||
|
if (get_script_instance()) {
|
||||||
|
get_script_instance()->call(SceneStringNames::get_singleton()->_mouse_shape_exit, p_shape);
|
||||||
|
}
|
||||||
|
emit_signal(SceneStringNames::get_singleton()->mouse_shape_exited, p_shape);
|
||||||
|
}
|
||||||
|
|
||||||
void CollisionObject2D::set_only_update_transform_changes(bool p_enable) {
|
void CollisionObject2D::set_only_update_transform_changes(bool p_enable) {
|
||||||
only_update_transform_changes = p_enable;
|
only_update_transform_changes = p_enable;
|
||||||
}
|
}
|
||||||
|
@ -406,6 +420,8 @@ void CollisionObject2D::_bind_methods() {
|
||||||
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "viewport", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx")));
|
ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "viewport", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::INT, "shape_idx")));
|
||||||
ADD_SIGNAL(MethodInfo("mouse_entered"));
|
ADD_SIGNAL(MethodInfo("mouse_entered"));
|
||||||
ADD_SIGNAL(MethodInfo("mouse_exited"));
|
ADD_SIGNAL(MethodInfo("mouse_exited"));
|
||||||
|
ADD_SIGNAL(MethodInfo("mouse_shape_entered", PropertyInfo(Variant::INT, "shape_idx")));
|
||||||
|
ADD_SIGNAL(MethodInfo("mouse_shape_exited", PropertyInfo(Variant::INT, "shape_idx")));
|
||||||
|
|
||||||
ADD_GROUP("Pickable", "input_");
|
ADD_GROUP("Pickable", "input_");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_pickable"), "set_pickable", "is_pickable");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "input_pickable"), "set_pickable", "is_pickable");
|
||||||
|
|
|
@ -73,6 +73,9 @@ protected:
|
||||||
void _mouse_enter();
|
void _mouse_enter();
|
||||||
void _mouse_exit();
|
void _mouse_exit();
|
||||||
|
|
||||||
|
void _mouse_shape_enter(int p_shape);
|
||||||
|
void _mouse_shape_exit(int p_shape);
|
||||||
|
|
||||||
void set_only_update_transform_changes(bool p_enable);
|
void set_only_update_transform_changes(bool p_enable);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -724,7 +724,6 @@ void Viewport::_process_picking() {
|
||||||
bool send_event = true;
|
bool send_event = true;
|
||||||
if (is_mouse) {
|
if (is_mouse) {
|
||||||
Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
|
Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
|
||||||
|
|
||||||
if (!F) {
|
if (!F) {
|
||||||
physics_2d_mouseover.insert(res[i].collider_id, frame);
|
physics_2d_mouseover.insert(res[i].collider_id, frame);
|
||||||
co->_mouse_enter();
|
co->_mouse_enter();
|
||||||
|
@ -735,6 +734,13 @@ void Viewport::_process_picking() {
|
||||||
send_event = false;
|
send_event = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *SF = physics_2d_shape_mouseover.find(Pair(res[i].collider_id, res[i].shape));
|
||||||
|
if (!SF) {
|
||||||
|
physics_2d_shape_mouseover.insert(Pair(res[i].collider_id, res[i].shape), frame);
|
||||||
|
co->_mouse_shape_enter(res[i].shape);
|
||||||
|
} else {
|
||||||
|
SF->get() = frame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send_event) {
|
if (send_event) {
|
||||||
|
@ -746,25 +752,7 @@ void Viewport::_process_picking() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_mouse) {
|
if (is_mouse) {
|
||||||
List<Map<ObjectID, uint64_t>::Element *> to_erase;
|
_cleanup_mouseover_colliders(false, false, frame);
|
||||||
|
|
||||||
for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
|
|
||||||
if (E->get() != frame) {
|
|
||||||
Object *o = ObjectDB::get_instance(E->key());
|
|
||||||
if (o) {
|
|
||||||
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
|
|
||||||
if (co) {
|
|
||||||
co->_mouse_exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
to_erase.push_back(E);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (to_erase.size()) {
|
|
||||||
physics_2d_mouseover.erase(to_erase.front()->get());
|
|
||||||
to_erase.pop_front();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2607,26 +2595,7 @@ void Viewport::_drop_mouse_focus() {
|
||||||
void Viewport::_drop_physics_mouseover(bool p_paused_only) {
|
void Viewport::_drop_physics_mouseover(bool p_paused_only) {
|
||||||
physics_has_last_mousepos = false;
|
physics_has_last_mousepos = false;
|
||||||
|
|
||||||
List<Map<ObjectID, uint64_t>::Element *> to_erase;
|
_cleanup_mouseover_colliders(true, p_paused_only);
|
||||||
|
|
||||||
for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
|
|
||||||
Object *o = ObjectDB::get_instance(E->key());
|
|
||||||
if (o) {
|
|
||||||
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
|
|
||||||
if (co) {
|
|
||||||
if (p_paused_only && co->can_process()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
co->_mouse_exit();
|
|
||||||
to_erase.push_back(E);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (to_erase.size()) {
|
|
||||||
physics_2d_mouseover.erase(to_erase.front()->get());
|
|
||||||
to_erase.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef _3D_DISABLED
|
#ifndef _3D_DISABLED
|
||||||
if (physics_object_over.is_valid()) {
|
if (physics_object_over.is_valid()) {
|
||||||
|
@ -2642,6 +2611,59 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference) {
|
||||||
|
List<Map<ObjectID, uint64_t>::Element *> to_erase;
|
||||||
|
|
||||||
|
for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
|
||||||
|
if (!p_clean_all_frames && E->get() == p_frame_reference) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *o = ObjectDB::get_instance(E->key());
|
||||||
|
if (o) {
|
||||||
|
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
|
||||||
|
if (co) {
|
||||||
|
if (p_clean_all_frames && p_paused_only && co->can_process()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
co->_mouse_exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_erase.push_back(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (to_erase.size()) {
|
||||||
|
physics_2d_mouseover.erase(to_erase.front()->get());
|
||||||
|
to_erase.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-shape
|
||||||
|
List<Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *> shapes_to_erase;
|
||||||
|
|
||||||
|
for (Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>>::Element *E = physics_2d_shape_mouseover.front(); E; E = E->next()) {
|
||||||
|
if (!p_clean_all_frames && E->get() == p_frame_reference) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *o = ObjectDB::get_instance(E->key().first);
|
||||||
|
if (o) {
|
||||||
|
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
|
||||||
|
if (co) {
|
||||||
|
if (p_clean_all_frames && p_paused_only && co->can_process()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
co->_mouse_shape_exit(E->key().second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shapes_to_erase.push_back(E);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (shapes_to_erase.size()) {
|
||||||
|
physics_2d_shape_mouseover.erase(shapes_to_erase.front()->get());
|
||||||
|
shapes_to_erase.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Control *Viewport::_gui_get_focus_owner() {
|
Control *Viewport::_gui_get_focus_owner() {
|
||||||
return gui.key_focus;
|
return gui.key_focus;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define VIEWPORT_H
|
#define VIEWPORT_H
|
||||||
|
|
||||||
#include "core/math/transform_2d.h"
|
#include "core/math/transform_2d.h"
|
||||||
|
#include "core/templates/pair.h"
|
||||||
#include "scene/main/node.h"
|
#include "scene/main/node.h"
|
||||||
#include "scene/resources/texture.h"
|
#include "scene/resources/texture.h"
|
||||||
#include "scene/resources/world_2d.h"
|
#include "scene/resources/world_2d.h"
|
||||||
|
@ -271,7 +272,12 @@ private:
|
||||||
bool handle_input_locally = true;
|
bool handle_input_locally = true;
|
||||||
bool local_input_handled = false;
|
bool local_input_handled = false;
|
||||||
|
|
||||||
|
// Collider to frame
|
||||||
Map<ObjectID, uint64_t> physics_2d_mouseover;
|
Map<ObjectID, uint64_t> physics_2d_mouseover;
|
||||||
|
// Collider & shape to frame
|
||||||
|
Map<Pair<ObjectID, int>, uint64_t, PairSort<ObjectID, int>> physics_2d_shape_mouseover;
|
||||||
|
// Cleans up colliders corresponding to old frames or all of them.
|
||||||
|
void _cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paused_only, uint64_t p_frame_reference = 0);
|
||||||
|
|
||||||
Ref<World2D> world_2d;
|
Ref<World2D> world_2d;
|
||||||
Ref<World3D> world_3d;
|
Ref<World3D> world_3d;
|
||||||
|
|
|
@ -66,6 +66,8 @@ SceneStringNames::SceneStringNames() {
|
||||||
|
|
||||||
mouse_entered = StaticCString::create("mouse_entered");
|
mouse_entered = StaticCString::create("mouse_entered");
|
||||||
mouse_exited = StaticCString::create("mouse_exited");
|
mouse_exited = StaticCString::create("mouse_exited");
|
||||||
|
mouse_shape_entered = StaticCString::create("mouse_shape_entered");
|
||||||
|
mouse_shape_exited = StaticCString::create("mouse_shape_exited");
|
||||||
|
|
||||||
focus_entered = StaticCString::create("focus_entered");
|
focus_entered = StaticCString::create("focus_entered");
|
||||||
focus_exited = StaticCString::create("focus_exited");
|
focus_exited = StaticCString::create("focus_exited");
|
||||||
|
@ -170,6 +172,8 @@ SceneStringNames::SceneStringNames() {
|
||||||
|
|
||||||
_mouse_enter = StaticCString::create("_mouse_enter");
|
_mouse_enter = StaticCString::create("_mouse_enter");
|
||||||
_mouse_exit = StaticCString::create("_mouse_exit");
|
_mouse_exit = StaticCString::create("_mouse_exit");
|
||||||
|
_mouse_shape_enter = StaticCString::create("_mouse_shape_enter");
|
||||||
|
_mouse_shape_exit = StaticCString::create("_mouse_shape_exit");
|
||||||
|
|
||||||
_pressed = StaticCString::create("_pressed");
|
_pressed = StaticCString::create("_pressed");
|
||||||
_toggled = StaticCString::create("_toggled");
|
_toggled = StaticCString::create("_toggled");
|
||||||
|
|
|
@ -84,6 +84,8 @@ public:
|
||||||
|
|
||||||
StringName mouse_entered;
|
StringName mouse_entered;
|
||||||
StringName mouse_exited;
|
StringName mouse_exited;
|
||||||
|
StringName mouse_shape_entered;
|
||||||
|
StringName mouse_shape_exited;
|
||||||
StringName focus_entered;
|
StringName focus_entered;
|
||||||
StringName focus_exited;
|
StringName focus_exited;
|
||||||
|
|
||||||
|
@ -182,6 +184,8 @@ public:
|
||||||
|
|
||||||
StringName _mouse_enter;
|
StringName _mouse_enter;
|
||||||
StringName _mouse_exit;
|
StringName _mouse_exit;
|
||||||
|
StringName _mouse_shape_enter;
|
||||||
|
StringName _mouse_shape_exit;
|
||||||
|
|
||||||
StringName frame_changed;
|
StringName frame_changed;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue