Merge pull request #39421 from RandomShaper/pause_aware_picking_3.2
Implement pause-aware picking (3.2)
This commit is contained in:
commit
398a625a9f
6 changed files with 321 additions and 279 deletions
|
@ -1006,6 +1006,12 @@
|
|||
<member name="physics/common/enable_object_picking" type="bool" setter="" getter="" default="true">
|
||||
Enables [member Viewport.physics_object_picking] on the root viewport.
|
||||
</member>
|
||||
<member name="physics/common/enable_pause_aware_picking" type="bool" setter="" getter="" default="false">
|
||||
If enabled, 2D and 3D physics picking behaves this way in relation to pause:
|
||||
- When pause is started, every collision object that is hovered or captured (3D only) is released from that condition, getting the relevant mouse-exit callback, unless its pause mode makes it immune to pause.
|
||||
- During pause, picking only considers collision objects immune to pause, sending input events and enter/exit callbacks to them as expected.
|
||||
If disabled, the legacy behavior is used, which consists in queuing the picking input events during pause (so nodes won't get them) and flushing that queue on resume, against the state of the 2D/3D world at that point.
|
||||
</member>
|
||||
<member name="physics/common/physics_fps" type="int" setter="" getter="" default="60">
|
||||
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run.
|
||||
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.iterations_per_second] instead.
|
||||
|
|
|
@ -499,6 +499,7 @@ private:
|
|||
initial_settings["application/config/name"] = project_name->get_text();
|
||||
initial_settings["application/config/icon"] = "res://icon.png";
|
||||
initial_settings["rendering/environment/default_environment"] = "res://default_env.tres";
|
||||
initial_settings["physics/common/enable_pause_aware_picking"] = true;
|
||||
|
||||
if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("project.godot"), initial_settings, Vector<String>(), false) != OK) {
|
||||
set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
|
||||
|
|
|
@ -1194,6 +1194,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF("physics/common/physics_jitter_fix", 0.5));
|
||||
Engine::get_singleton()->set_target_fps(GLOBAL_DEF("debug/settings/fps/force_fps", 0));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/fps/force_fps", PropertyInfo(Variant::INT, "debug/settings/fps/force_fps", PROPERTY_HINT_RANGE, "0,120,1,or_greater"));
|
||||
GLOBAL_DEF("physics/common/enable_pause_aware_picking", false);
|
||||
|
||||
GLOBAL_DEF("debug/settings/stdout/print_fps", false);
|
||||
GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false);
|
||||
|
|
|
@ -478,6 +478,9 @@ bool SceneTree::iteration(float p_time) {
|
|||
emit_signal("physics_frame");
|
||||
|
||||
_notify_group_pause("physics_process_internal", Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
|
||||
if (GLOBAL_GET("physics/common/enable_pause_aware_picking")) {
|
||||
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_process_picking", true);
|
||||
}
|
||||
_notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
|
||||
_flush_ugc();
|
||||
MessageQueue::get_singleton()->flush(); //small little hack
|
||||
|
|
|
@ -418,7 +418,35 @@ void Viewport::_notification(int p_what) {
|
|||
VS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count);
|
||||
}
|
||||
|
||||
if (physics_object_picking && (to_screen_rect == Rect2() || Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED)) {
|
||||
if (!GLOBAL_GET("physics/common/enable_pause_aware_picking")) {
|
||||
_process_picking(false);
|
||||
}
|
||||
} break;
|
||||
case SceneTree::NOTIFICATION_WM_MOUSE_EXIT:
|
||||
case SceneTree::NOTIFICATION_WM_FOCUS_OUT: {
|
||||
|
||||
_drop_physics_mouseover();
|
||||
|
||||
if (gui.mouse_focus) {
|
||||
//if mouse is being pressed, send a release event
|
||||
_drop_mouse_focus();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::_process_picking(bool p_ignore_paused) {
|
||||
|
||||
if (!is_inside_tree())
|
||||
return;
|
||||
if (!physics_object_picking)
|
||||
return;
|
||||
if (to_screen_rect != Rect2() && Input::get_singleton()->get_mouse_mode() == Input::MOUSE_MODE_CAPTURED)
|
||||
return;
|
||||
|
||||
if (p_ignore_paused) {
|
||||
_drop_physics_mouseover(true);
|
||||
}
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
Vector2 last_pos(1e20, 1e20);
|
||||
|
@ -553,7 +581,7 @@ void Viewport::_notification(int p_what) {
|
|||
|
||||
if (res[i].collider_id && res[i].collider) {
|
||||
CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider);
|
||||
if (co) {
|
||||
if (co && (!p_ignore_paused || co->can_process())) {
|
||||
bool send_event = true;
|
||||
if (is_mouse) {
|
||||
Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
|
||||
|
@ -648,7 +676,7 @@ void Viewport::_notification(int p_what) {
|
|||
if (col) {
|
||||
|
||||
CollisionObject *co = Object::cast_to<CollisionObject>(result.collider);
|
||||
if (co) {
|
||||
if (co && (!p_ignore_paused || co->can_process())) {
|
||||
|
||||
_collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape);
|
||||
last_object = co;
|
||||
|
@ -689,20 +717,6 @@ void Viewport::_notification(int p_what) {
|
|||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
case SceneTree::NOTIFICATION_WM_MOUSE_EXIT:
|
||||
case SceneTree::NOTIFICATION_WM_FOCUS_OUT: {
|
||||
|
||||
_drop_physics_mouseover();
|
||||
|
||||
if (gui.mouse_focus) {
|
||||
//if mouse is being pressed, send a release event
|
||||
_drop_mouse_focus();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
RID Viewport::get_viewport_rid() const {
|
||||
|
||||
return viewport;
|
||||
|
@ -2735,28 +2749,42 @@ void Viewport::_drop_mouse_focus() {
|
|||
}
|
||||
}
|
||||
|
||||
void Viewport::_drop_physics_mouseover() {
|
||||
void Viewport::_drop_physics_mouseover(bool p_paused_only) {
|
||||
|
||||
physics_has_last_mousepos = false;
|
||||
|
||||
while (physics_2d_mouseover.size()) {
|
||||
Object *o = ObjectDB::get_instance(physics_2d_mouseover.front()->key());
|
||||
List<Map<ObjectID, uint64_t>::Element *> to_erase;
|
||||
|
||||
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);
|
||||
co->_mouse_exit();
|
||||
if (co) {
|
||||
if (p_paused_only && co->can_process()) {
|
||||
continue;
|
||||
}
|
||||
physics_2d_mouseover.erase(physics_2d_mouseover.front());
|
||||
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
|
||||
if (physics_object_over) {
|
||||
CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over));
|
||||
if (co) {
|
||||
if (!(p_paused_only && co->can_process())) {
|
||||
co->_mouse_exit();
|
||||
}
|
||||
}
|
||||
|
||||
physics_object_over = physics_object_capture = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -3297,6 +3325,8 @@ void Viewport::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("_own_world_changed"), &Viewport::_own_world_changed);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_process_picking", "ignore_paused"), &Viewport::_process_picking);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr");
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
|
||||
|
|
|
@ -406,7 +406,7 @@ private:
|
|||
void _canvas_layer_remove(CanvasLayer *p_canvas_layer);
|
||||
|
||||
void _drop_mouse_focus();
|
||||
void _drop_physics_mouseover();
|
||||
void _drop_physics_mouseover(bool p_paused_only = false);
|
||||
|
||||
void _update_canvas_items(Node *p_node);
|
||||
|
||||
|
@ -414,6 +414,7 @@ private:
|
|||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
void _process_picking(bool p_ignore_paused);
|
||||
static void _bind_methods();
|
||||
virtual void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue