summaryrefslogtreecommitdiffstats
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/node.cpp13
-rw-r--r--scene/main/node.h3
-rw-r--r--scene/main/scene_tree.cpp27
-rw-r--r--scene/main/scene_tree.h3
-rw-r--r--scene/main/viewport.cpp83
-rw-r--r--scene/main/viewport.h8
6 files changed, 133 insertions, 4 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index d921cc5b67..8dc7b4a87c 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -184,6 +184,7 @@ void Node::_notification(int p_notification) {
}
} break;
+ case NOTIFICATION_SUSPENDED:
case NOTIFICATION_PAUSED: {
if (is_physics_interpolated_and_enabled() && is_inside_tree()) {
reset_physics_interpolation();
@@ -695,6 +696,16 @@ void Node::_propagate_pause_notification(bool p_enable) {
data.blocked--;
}
+void Node::_propagate_suspend_notification(bool p_enable) {
+ notification(p_enable ? NOTIFICATION_SUSPENDED : NOTIFICATION_UNSUSPENDED);
+
+ data.blocked++;
+ for (KeyValue<StringName, Node *> &KV : data.children) {
+ KV.value->_propagate_suspend_notification(p_enable);
+ }
+ data.blocked--;
+}
+
Node::ProcessMode Node::get_process_mode() const {
return data.process_mode;
}
@@ -850,7 +861,7 @@ bool Node::can_process_notification(int p_what) const {
bool Node::can_process() const {
ERR_FAIL_COND_V(!is_inside_tree(), false);
- return _can_process(get_tree()->is_paused());
+ return !get_tree()->is_suspended() && _can_process(get_tree()->is_paused());
}
bool Node::_can_process(bool p_paused) const {
diff --git a/scene/main/node.h b/scene/main/node.h
index 799478fa35..e2f3ce9b78 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -300,6 +300,7 @@ private:
void _set_tree(SceneTree *p_tree);
void _propagate_pause_notification(bool p_enable);
+ void _propagate_suspend_notification(bool p_enable);
_FORCE_INLINE_ bool _can_process(bool p_paused) const;
_FORCE_INLINE_ bool _is_enabled() const;
@@ -439,6 +440,8 @@ public:
// Editor specific node notifications
NOTIFICATION_EDITOR_PRE_SAVE = 9001,
NOTIFICATION_EDITOR_POST_SAVE = 9002,
+ NOTIFICATION_SUSPENDED = 9003,
+ NOTIFICATION_UNSUSPENDED = 9004
};
/* NODE/TREE */
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 71d91b970e..60cecfcfe7 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -954,11 +954,14 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() {
void SceneTree::set_pause(bool p_enabled) {
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Pause can only be set from the main thread.");
+ ERR_FAIL_COND_MSG(suspended, "Pause state cannot be modified while suspended.");
if (p_enabled == paused) {
return;
}
+
paused = p_enabled;
+
#ifndef _3D_DISABLED
PhysicsServer3D::get_singleton()->set_active(!p_enabled);
#endif // _3D_DISABLED
@@ -972,6 +975,30 @@ bool SceneTree::is_paused() const {
return paused;
}
+void SceneTree::set_suspend(bool p_enabled) {
+ ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "Suspend can only be set from the main thread.");
+
+ if (p_enabled == suspended) {
+ return;
+ }
+
+ suspended = p_enabled;
+
+ Engine::get_singleton()->set_freeze_time_scale(p_enabled);
+
+#ifndef _3D_DISABLED
+ PhysicsServer3D::get_singleton()->set_active(!p_enabled && !paused);
+#endif // _3D_DISABLED
+ PhysicsServer2D::get_singleton()->set_active(!p_enabled && !paused);
+ if (get_root()) {
+ get_root()->_propagate_suspend_notification(p_enabled);
+ }
+}
+
+bool SceneTree::is_suspended() const {
+ return suspended;
+}
+
void SceneTree::_process_group(ProcessGroup *p_group, bool p_physics) {
// When reading this function, keep in mind that this code must work in a way where
// if any node is removed, this needs to continue working.
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 7e44541105..291e4a5a0c 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -143,6 +143,7 @@ private:
bool debug_navigation_hint = false;
#endif
bool paused = false;
+ bool suspended = false;
HashMap<StringName, Group> group_map;
bool _quit = false;
@@ -343,6 +344,8 @@ public:
void set_pause(bool p_enabled);
bool is_paused() const;
+ void set_suspend(bool p_enabled);
+ bool is_suspended() const;
#ifdef DEBUG_ENABLED
void set_debug_collisions_hint(bool p_enabled);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 54f66e8d4e..5a90eb8f3e 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3123,7 +3123,7 @@ void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND(p_event.is_null());
- if (disable_input) {
+ if (disable_input || disable_input_override) {
return;
}
@@ -3195,7 +3195,7 @@ void Viewport::push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local
local_input_handled = false;
- if (disable_input || !_can_consume_input_events()) {
+ if (disable_input || disable_input_override || !_can_consume_input_events()) {
return;
}
@@ -3298,7 +3298,7 @@ void Viewport::set_disable_input(bool p_disable) {
if (p_disable == disable_input) {
return;
}
- if (p_disable) {
+ if (p_disable && !disable_input_override) {
_drop_mouse_focus();
_mouse_leave_viewport();
_gui_cancel_tooltip();
@@ -3311,6 +3311,19 @@ bool Viewport::is_input_disabled() const {
return disable_input;
}
+void Viewport::set_disable_input_override(bool p_disable) {
+ ERR_MAIN_THREAD_GUARD;
+ if (p_disable == disable_input_override) {
+ return;
+ }
+ if (p_disable && !disable_input) {
+ _drop_mouse_focus();
+ _mouse_leave_viewport();
+ _gui_cancel_tooltip();
+ }
+ disable_input_override = p_disable;
+}
+
Variant Viewport::gui_get_drag_data() const {
ERR_READ_THREAD_GUARD_V(Variant());
return get_section_root_viewport()->gui.drag_data;
@@ -4237,6 +4250,22 @@ void Viewport::set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near,
}
}
+HashMap<StringName, real_t> Viewport::get_camera_3d_override_properties() const {
+ HashMap<StringName, real_t> props;
+
+ props["size"] = 0;
+ props["fov"] = 0;
+ props["z_near"] = 0;
+ props["z_far"] = 0;
+ ERR_READ_THREAD_GUARD_V(props);
+
+ props["size"] = camera_3d_override.size;
+ props["fov"] = camera_3d_override.fov;
+ props["z_near"] = camera_3d_override.z_near;
+ props["z_far"] = camera_3d_override.z_far;
+ return props;
+}
+
void Viewport::set_disable_3d(bool p_disable) {
ERR_MAIN_THREAD_GUARD;
disable_3d = p_disable;
@@ -4270,6 +4299,54 @@ Transform3D Viewport::get_camera_3d_override_transform() const {
return Transform3D();
}
+Vector3 Viewport::camera_3d_override_project_ray_normal(const Point2 &p_pos) const {
+ ERR_READ_THREAD_GUARD_V(Vector3());
+ Vector3 ray = camera_3d_override_project_local_ray_normal(p_pos);
+ return camera_3d_override.transform.basis.xform(ray).normalized();
+}
+
+Vector3 Viewport::camera_3d_override_project_local_ray_normal(const Point2 &p_pos) const {
+ ERR_READ_THREAD_GUARD_V(Vector3());
+ Size2 viewport_size = get_camera_rect_size();
+ Vector2 cpos = get_camera_coords(p_pos);
+ Vector3 ray;
+
+ if (camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) {
+ ray = Vector3(0, 0, -1);
+ } else {
+ Projection cm;
+ cm.set_perspective(camera_3d_override.fov, get_visible_rect().size.aspect(), camera_3d_override.z_near, camera_3d_override.z_far, false);
+
+ Vector2 screen_he = cm.get_viewport_half_extents();
+ ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -camera_3d_override.z_near).normalized();
+ }
+
+ return ray;
+}
+
+Vector3 Viewport::camera_3d_override_project_ray_origin(const Point2 &p_pos) const {
+ ERR_READ_THREAD_GUARD_V(Vector3());
+ Size2 viewport_size = get_camera_rect_size();
+ Vector2 cpos = get_camera_coords(p_pos);
+ ERR_FAIL_COND_V(viewport_size.y == 0, Vector3());
+
+ if (camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) {
+ Vector2 pos = cpos / viewport_size;
+ real_t vsize, hsize;
+ hsize = camera_3d_override.size * viewport_size.aspect();
+ vsize = camera_3d_override.size;
+
+ Vector3 ray;
+ ray.x = pos.x * (hsize)-hsize / 2;
+ ray.y = (1.0 - pos.y) * (vsize)-vsize / 2;
+ ray.z = -camera_3d_override.z_near;
+ ray = camera_3d_override.transform.xform(ray);
+ return ray;
+ } else {
+ return camera_3d_override.transform.origin;
+ };
+}
+
Ref<World3D> Viewport::get_world_3d() const {
ERR_READ_THREAD_GUARD_V(Ref<World3D>());
return world_3d;
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index a18dc1f6f0..92691ccbec 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -401,6 +401,7 @@ private:
DefaultCanvasItemTextureRepeat default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
bool disable_input = false;
+ bool disable_input_override = false;
void _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input);
void _gui_call_notification(Control *p_control, int p_what);
@@ -580,6 +581,8 @@ public:
void set_disable_input(bool p_disable);
bool is_input_disabled() const;
+ void set_disable_input_override(bool p_disable);
+
Vector2 get_mouse_position() const;
void warp_mouse(const Vector2 &p_position);
virtual void update_mouse_cursor_state();
@@ -770,6 +773,11 @@ public:
void set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far);
void set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far);
+ HashMap<StringName, real_t> get_camera_3d_override_properties() const;
+
+ Vector3 camera_3d_override_project_ray_normal(const Point2 &p_pos) const;
+ Vector3 camera_3d_override_project_ray_origin(const Point2 &p_pos) const;
+ Vector3 camera_3d_override_project_local_ray_normal(const Point2 &p_pos) const;
void set_disable_3d(bool p_disable);
bool is_3d_disabled() const;