|
@@ -724,7 +724,6 @@ void Viewport::_process_picking() {
|
|
|
bool send_event = true;
|
|
|
if (is_mouse) {
|
|
|
Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
|
|
|
-
|
|
|
if (!F) {
|
|
|
physics_2d_mouseover.insert(res[i].collider_id, frame);
|
|
|
co->_mouse_enter();
|
|
@@ -735,6 +734,13 @@ void Viewport::_process_picking() {
|
|
|
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) {
|
|
@@ -746,25 +752,7 @@ void Viewport::_process_picking() {
|
|
|
}
|
|
|
|
|
|
if (is_mouse) {
|
|
|
- List<Map<ObjectID, uint64_t>::Element *> to_erase;
|
|
|
-
|
|
|
- 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();
|
|
|
- }
|
|
|
+ _cleanup_mouseover_colliders(false, false, frame);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2607,20 +2595,41 @@ void Viewport::_drop_mouse_focus() {
|
|
|
void Viewport::_drop_physics_mouseover(bool p_paused_only) {
|
|
|
physics_has_last_mousepos = false;
|
|
|
|
|
|
+ _cleanup_mouseover_colliders(true, p_paused_only);
|
|
|
+
|
|
|
+#ifndef _3D_DISABLED
|
|
|
+ if (physics_object_over.is_valid()) {
|
|
|
+ CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
|
|
|
+ if (co) {
|
|
|
+ if (!(p_paused_only && co->can_process())) {
|
|
|
+ co->_mouse_exit();
|
|
|
+ physics_object_over = ObjectID();
|
|
|
+ physics_object_capture = ObjectID();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#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_paused_only && co->can_process()) {
|
|
|
+ if (p_clean_all_frames && p_paused_only && co->can_process()) {
|
|
|
continue;
|
|
|
}
|
|
|
co->_mouse_exit();
|
|
|
- to_erase.push_back(E);
|
|
|
}
|
|
|
}
|
|
|
+ to_erase.push_back(E);
|
|
|
}
|
|
|
|
|
|
while (to_erase.size()) {
|
|
@@ -2628,18 +2637,31 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) {
|
|
|
to_erase.pop_front();
|
|
|
}
|
|
|
|
|
|
-#ifndef _3D_DISABLED
|
|
|
- if (physics_object_over.is_valid()) {
|
|
|
- CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over));
|
|
|
- if (co) {
|
|
|
- if (!(p_paused_only && co->can_process())) {
|
|
|
- co->_mouse_exit();
|
|
|
- physics_object_over = ObjectID();
|
|
|
- physics_object_capture = ObjectID();
|
|
|
+ // 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();
|
|
|
}
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
Control *Viewport::_gui_get_focus_owner() {
|