summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/audio_stream_player_3d.cpp5
-rw-r--r--scene/3d/camera_3d.cpp15
-rw-r--r--scene/3d/camera_3d.h1
-rw-r--r--scene/3d/node_3d.cpp62
-rw-r--r--scene/3d/node_3d.h12
-rw-r--r--scene/3d/visibility_notifier_3d.cpp253
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.cpp203
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.h (renamed from scene/3d/visibility_notifier_3d.h)68
-rw-r--r--scene/3d/visual_instance_3d.cpp66
-rw-r--r--scene/3d/visual_instance_3d.h30
-rw-r--r--scene/3d/xr_nodes.cpp6
11 files changed, 374 insertions, 347 deletions
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index cad4330c17..9640043031 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -404,10 +404,7 @@ void AudioStreamPlayer3D::_notification(int p_what) {
break;
}
- List<Camera3D *> cameras;
- world_3d->get_camera_list(&cameras);
-
- for (List<Camera3D *>::Element *E = cameras.front(); E; E = E->next()) {
+ for (const Set<Camera3D *>::Element *E = world_3d->get_cameras().front(); E; E = E->next()) {
Camera3D *camera = E->get();
Viewport *vp = camera->get_viewport();
if (!vp->is_audio_listener()) {
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 1c9418ae83..62bbebe6e7 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -93,10 +93,6 @@ void Camera3D::_update_camera() {
}
get_viewport()->_camera_transform_changed_notify();
-
- if (get_world_3d().is_valid()) {
- get_world_3d()->_update_camera(this);
- }
}
void Camera3D::_notification(int p_what) {
@@ -500,6 +496,7 @@ void Camera3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_doppler_tracking", "mode"), &Camera3D::set_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_doppler_tracking"), &Camera3D::get_doppler_tracking);
ClassDB::bind_method(D_METHOD("get_frustum"), &Camera3D::get_frustum);
+ ClassDB::bind_method(D_METHOD("is_position_in_frustum", "world_point"), &Camera3D::is_position_in_frustum);
ClassDB::bind_method(D_METHOD("get_camera_rid"), &Camera3D::get_camera);
ClassDB::bind_method(D_METHOD("set_cull_mask_bit", "layer", "enable"), &Camera3D::set_cull_mask_bit);
@@ -623,6 +620,16 @@ Vector<Plane> Camera3D::get_frustum() const {
return cm.get_projection_planes(get_camera_transform());
}
+bool Camera3D::is_position_in_frustum(const Vector3 &p_position) const {
+ Vector<Plane> frustum = get_frustum();
+ for (int i = 0; i < frustum.size(); i++) {
+ if (frustum[i].is_point_over(p_position)) {
+ return false;
+ }
+ }
+ return true;
+}
+
void Camera3D::set_v_offset(float p_offset) {
v_offset = p_offset;
_update_camera();
diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h
index d9ebe78f1a..c6efc8f9a9 100644
--- a/scene/3d/camera_3d.h
+++ b/scene/3d/camera_3d.h
@@ -153,6 +153,7 @@ public:
bool get_cull_mask_bit(int p_layer) const;
virtual Vector<Plane> get_frustum() const;
+ bool is_position_in_frustum(const Vector3 &p_position) const;
void set_environment(const Ref<Environment> &p_environment);
Ref<Environment> get_environment() const;
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index e96e4df55c..e96b8ee1f9 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -32,6 +32,7 @@
#include "core/config/engine.h"
#include "core/object/message_queue.h"
+#include "scene/3d/visual_instance_3d.h"
#include "scene/main/scene_tree.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
@@ -148,6 +149,7 @@ void Node3D::_notification(int p_what) {
_notify_dirty();
notification(NOTIFICATION_ENTER_WORLD);
+ _update_visibility_parent(true);
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -161,6 +163,7 @@ void Node3D::_notification(int p_what) {
data.parent = nullptr;
data.C = nullptr;
data.top_level_active = false;
+ _update_visibility_parent(true);
} break;
case NOTIFICATION_ENTER_WORLD: {
data.inside_world = true;
@@ -282,8 +285,12 @@ Transform3D Node3D::get_local_gizmo_transform() const {
}
#endif
-Node3D *Node3D::get_parent_spatial() const {
- return data.parent;
+Node3D *Node3D::get_parent_node_3d() const {
+ if (data.top_level) {
+ return nullptr;
+ }
+
+ return Object::cast_to<Node3D>(get_parent());
}
Transform3D Node3D::get_relative_transform(const Node *p_parent) const {
@@ -690,6 +697,51 @@ void Node3D::force_update_transform() {
notification(NOTIFICATION_TRANSFORM_CHANGED);
}
+void Node3D::_update_visibility_parent(bool p_update_root) {
+ RID new_parent;
+
+ if (!visibility_parent_path.is_empty()) {
+ if (!p_update_root) {
+ return;
+ }
+ Node *parent = get_node_or_null(visibility_parent_path);
+ ERR_FAIL_COND_MSG(!parent, "Can't find visibility parent node at path: " + visibility_parent_path);
+ ERR_FAIL_COND_MSG(parent == this, "The visibility parent can't be the same node.");
+ GeometryInstance3D *gi = Object::cast_to<GeometryInstance3D>(parent);
+ ERR_FAIL_COND_MSG(!gi, "The visibility parent node must be a GeometryInstance3D, at path: " + visibility_parent_path);
+ new_parent = gi ? gi->get_instance() : RID();
+ } else if (data.parent) {
+ new_parent = data.parent->data.visibility_parent;
+ }
+
+ if (new_parent == data.visibility_parent) {
+ return;
+ }
+
+ data.visibility_parent = new_parent;
+
+ VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(this);
+ if (vi) {
+ RS::get_singleton()->instance_set_visibility_parent(vi->get_instance(), data.visibility_parent);
+ }
+
+ for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) {
+ Node3D *c = E->get();
+ c->_update_visibility_parent(false);
+ }
+}
+
+void Node3D::set_visibility_parent(const NodePath &p_path) {
+ visibility_parent_path = p_path;
+ if (is_inside_tree()) {
+ _update_visibility_parent(true);
+ }
+}
+
+NodePath Node3D::get_visibility_parent() const {
+ return visibility_parent_path;
+}
+
void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "local"), &Node3D::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &Node3D::get_transform);
@@ -703,7 +755,7 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scale"), &Node3D::get_scale);
ClassDB::bind_method(D_METHOD("set_global_transform", "global"), &Node3D::set_global_transform);
ClassDB::bind_method(D_METHOD("get_global_transform"), &Node3D::get_global_transform);
- ClassDB::bind_method(D_METHOD("get_parent_spatial"), &Node3D::get_parent_spatial);
+ ClassDB::bind_method(D_METHOD("get_parent_node_3d"), &Node3D::get_parent_node_3d);
ClassDB::bind_method(D_METHOD("set_ignore_transform_notification", "enabled"), &Node3D::set_ignore_transform_notification);
ClassDB::bind_method(D_METHOD("set_as_top_level", "enable"), &Node3D::set_as_top_level);
ClassDB::bind_method(D_METHOD("is_set_as_top_level"), &Node3D::is_set_as_top_level);
@@ -713,6 +765,9 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("force_update_transform"), &Node3D::force_update_transform);
+ ClassDB::bind_method(D_METHOD("set_visibility_parent", "path"), &Node3D::set_visibility_parent);
+ ClassDB::bind_method(D_METHOD("get_visibility_parent"), &Node3D::get_visibility_parent);
+
ClassDB::bind_method(D_METHOD("_update_gizmo"), &Node3D::_update_gizmo);
ClassDB::bind_method(D_METHOD("update_gizmo"), &Node3D::update_gizmo);
@@ -768,6 +823,7 @@ void Node3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, ""), "set_transform", "get_transform");
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "visibility_parent", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GeometryInstance3D"), "set_visibility_parent", "get_visibility_parent");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "Node3DGizmo", 0), "set_gizmo", "get_gizmo");
ADD_SIGNAL(MethodInfo("visibility_changed"));
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index 5f076ceb12..c7e36cf2ec 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -75,6 +75,8 @@ class Node3D : public Node {
bool top_level = false;
bool inside_world = false;
+ RID visibility_parent;
+
int children_lock = 0;
Node3D *parent = nullptr;
List<Node3D *> children;
@@ -95,12 +97,17 @@ class Node3D : public Node {
} data;
+ NodePath visibility_parent_path;
+
void _update_gizmo();
void _notify_dirty();
void _propagate_transform_changed(Node3D *p_origin);
void _propagate_visibility_changed();
+ void _propagate_visibility_parent();
+ void _update_visibility_parent(bool p_update_root);
+
protected:
_FORCE_INLINE_ void set_ignore_transform_notification(bool p_ignore) { data.ignore_notification = p_ignore; }
@@ -118,7 +125,7 @@ public:
NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 44,
};
- Node3D *get_parent_spatial() const;
+ Node3D *get_parent_node_3d() const;
Ref<World3D> get_world_3d() const;
@@ -196,6 +203,9 @@ public:
void force_update_transform();
+ void set_visibility_parent(const NodePath &p_path);
+ NodePath get_visibility_parent() const;
+
Node3D();
};
diff --git a/scene/3d/visibility_notifier_3d.cpp b/scene/3d/visibility_notifier_3d.cpp
deleted file mode 100644
index b230cb2fd7..0000000000
--- a/scene/3d/visibility_notifier_3d.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-/*************************************************************************/
-/* visibility_notifier_3d.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "visibility_notifier_3d.h"
-
-#include "core/config/engine.h"
-#include "scene/3d/camera_3d.h"
-#include "scene/3d/physics_body_3d.h"
-#include "scene/animation/animation_player.h"
-#include "scene/scene_string_names.h"
-
-void VisibilityNotifier3D::_enter_camera(Camera3D *p_camera) {
- ERR_FAIL_COND(cameras.has(p_camera));
- cameras.insert(p_camera);
- if (cameras.size() == 1) {
- emit_signal(SceneStringNames::get_singleton()->screen_entered);
- _screen_enter();
- }
-
- emit_signal(SceneStringNames::get_singleton()->camera_entered, p_camera);
-}
-
-void VisibilityNotifier3D::_exit_camera(Camera3D *p_camera) {
- ERR_FAIL_COND(!cameras.has(p_camera));
- cameras.erase(p_camera);
-
- emit_signal(SceneStringNames::get_singleton()->camera_exited, p_camera);
- if (cameras.size() == 0) {
- emit_signal(SceneStringNames::get_singleton()->screen_exited);
-
- _screen_exit();
- }
-}
-
-void VisibilityNotifier3D::set_aabb(const AABB &p_aabb) {
- if (aabb == p_aabb) {
- return;
- }
- aabb = p_aabb;
-
- if (is_inside_world()) {
- get_world_3d()->_update_notifier(this, get_global_transform().xform(aabb));
- }
-
- update_gizmo();
-}
-
-AABB VisibilityNotifier3D::get_aabb() const {
- return aabb;
-}
-
-void VisibilityNotifier3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_WORLD: {
- world = get_world_3d();
- ERR_FAIL_COND(!world.is_valid());
- world->_register_notifier(this, get_global_transform().xform(aabb));
- } break;
- case NOTIFICATION_TRANSFORM_CHANGED: {
- world->_update_notifier(this, get_global_transform().xform(aabb));
- } break;
- case NOTIFICATION_EXIT_WORLD: {
- ERR_FAIL_COND(!world.is_valid());
- world->_remove_notifier(this);
- } break;
- }
-}
-
-bool VisibilityNotifier3D::is_on_screen() const {
- return cameras.size() != 0;
-}
-
-void VisibilityNotifier3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_aabb", "rect"), &VisibilityNotifier3D::set_aabb);
- ClassDB::bind_method(D_METHOD("get_aabb"), &VisibilityNotifier3D::get_aabb);
- ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibilityNotifier3D::is_on_screen);
-
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb");
-
- ADD_SIGNAL(MethodInfo("camera_entered", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D")));
- ADD_SIGNAL(MethodInfo("camera_exited", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D")));
- ADD_SIGNAL(MethodInfo("screen_entered"));
- ADD_SIGNAL(MethodInfo("screen_exited"));
-}
-
-VisibilityNotifier3D::VisibilityNotifier3D() {
- set_notify_transform(true);
-}
-
-//////////////////////////////////////
-
-void VisibilityEnabler3D::_screen_enter() {
- for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
- _change_node_state(E->key(), true);
- }
-
- visible = true;
-}
-
-void VisibilityEnabler3D::_screen_exit() {
- for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
- _change_node_state(E->key(), false);
- }
-
- visible = false;
-}
-
-void VisibilityEnabler3D::_find_nodes(Node *p_node) {
- bool add = false;
- Variant meta;
-
- {
- RigidBody3D *rb = Object::cast_to<RigidBody3D>(p_node);
- if (rb && ((rb->get_mode() == RigidBody3D::MODE_DYNAMIC || rb->get_mode() == RigidBody3D::MODE_DYNAMIC_LOCKED))) {
- add = true;
- meta = rb->get_mode();
- }
- }
-
- {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
- if (ap) {
- add = true;
- }
- }
-
- if (add) {
- p_node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler3D::_node_removed), varray(p_node), CONNECT_ONESHOT);
- nodes[p_node] = meta;
- _change_node_state(p_node, false);
- }
-
- for (int i = 0; i < p_node->get_child_count(); i++) {
- Node *c = p_node->get_child(i);
- if (c->get_filename() != String()) {
- continue; //skip, instance
- }
-
- _find_nodes(c);
- }
-}
-
-void VisibilityEnabler3D::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-
- Node *from = this;
- //find where current scene starts
- while (from->get_parent() && from->get_filename() == String()) {
- from = from->get_parent();
- }
-
- _find_nodes(from);
- }
-
- if (p_what == NOTIFICATION_EXIT_TREE) {
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-
- for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
- if (!visible) {
- _change_node_state(E->key(), true);
- }
- E->key()->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &VisibilityEnabler3D::_node_removed));
- }
-
- nodes.clear();
- }
-}
-
-void VisibilityEnabler3D::_change_node_state(Node *p_node, bool p_enabled) {
- ERR_FAIL_COND(!nodes.has(p_node));
-
- if (enabler[ENABLER_FREEZE_BODIES]) {
- RigidBody3D *rb = Object::cast_to<RigidBody3D>(p_node);
- if (rb) {
- rb->set_sleeping(!p_enabled);
- }
- }
-
- if (enabler[ENABLER_PAUSE_ANIMATIONS]) {
- AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(p_node);
-
- if (ap) {
- ap->set_active(p_enabled);
- }
- }
-}
-
-void VisibilityEnabler3D::_node_removed(Node *p_node) {
- if (!visible) {
- _change_node_state(p_node, true);
- }
- nodes.erase(p_node);
-}
-
-void VisibilityEnabler3D::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_enabler", "enabler", "enabled"), &VisibilityEnabler3D::set_enabler);
- ClassDB::bind_method(D_METHOD("is_enabler_enabled", "enabler"), &VisibilityEnabler3D::is_enabler_enabled);
-
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "pause_animations"), "set_enabler", "is_enabler_enabled", ENABLER_PAUSE_ANIMATIONS);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "freeze_bodies"), "set_enabler", "is_enabler_enabled", ENABLER_FREEZE_BODIES);
-
- BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS);
- BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
- BIND_ENUM_CONSTANT(ENABLER_MAX);
-}
-
-void VisibilityEnabler3D::set_enabler(Enabler p_enabler, bool p_enable) {
- ERR_FAIL_INDEX(p_enabler, ENABLER_MAX);
- enabler[p_enabler] = p_enable;
-}
-
-bool VisibilityEnabler3D::is_enabler_enabled(Enabler p_enabler) const {
- ERR_FAIL_INDEX_V(p_enabler, ENABLER_MAX, false);
- return enabler[p_enabler];
-}
-
-VisibilityEnabler3D::VisibilityEnabler3D() {
- for (int i = 0; i < ENABLER_MAX; i++) {
- enabler[i] = true;
- }
-}
diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp
new file mode 100644
index 0000000000..682bcec449
--- /dev/null
+++ b/scene/3d/visible_on_screen_notifier_3d.cpp
@@ -0,0 +1,203 @@
+/*************************************************************************/
+/* visible_on_screen_notifier_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "visible_on_screen_notifier_3d.h"
+
+#include "core/config/engine.h"
+#include "scene/3d/camera_3d.h"
+#include "scene/3d/physics_body_3d.h"
+#include "scene/animation/animation_player.h"
+#include "scene/scene_string_names.h"
+
+void VisibleOnScreenNotifier3D::_visibility_enter() {
+ if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ on_screen = true;
+ emit_signal(SceneStringNames::get_singleton()->screen_entered);
+ _screen_enter();
+}
+void VisibleOnScreenNotifier3D::_visibility_exit() {
+ if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ on_screen = false;
+ emit_signal(SceneStringNames::get_singleton()->screen_exited);
+ _screen_exit();
+}
+
+void VisibleOnScreenNotifier3D::set_aabb(const AABB &p_aabb) {
+ if (aabb == p_aabb) {
+ return;
+ }
+ aabb = p_aabb;
+
+ RS::get_singleton()->visibility_notifier_set_aabb(get_base(), aabb);
+
+ update_gizmo();
+}
+
+AABB VisibleOnScreenNotifier3D::get_aabb() const {
+ return aabb;
+}
+
+bool VisibleOnScreenNotifier3D::is_on_screen() const {
+ return on_screen;
+}
+
+void VisibleOnScreenNotifier3D::_notification(int p_what) {
+ if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_EXIT_TREE) {
+ on_screen = false;
+ }
+}
+
+void VisibleOnScreenNotifier3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_aabb", "rect"), &VisibleOnScreenNotifier3D::set_aabb);
+ ClassDB::bind_method(D_METHOD("is_on_screen"), &VisibleOnScreenNotifier3D::is_on_screen);
+
+ ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb"), "set_aabb", "get_aabb");
+
+ ADD_SIGNAL(MethodInfo("screen_entered"));
+ ADD_SIGNAL(MethodInfo("screen_exited"));
+}
+
+Vector<Face3> VisibleOnScreenNotifier3D::get_faces(uint32_t p_usage_flags) const {
+ return Vector<Face3>();
+}
+
+VisibleOnScreenNotifier3D::VisibleOnScreenNotifier3D() {
+ RID notifier = RS::get_singleton()->visibility_notifier_create();
+ RS::get_singleton()->visibility_notifier_set_aabb(notifier, aabb);
+ RS::get_singleton()->visibility_notifier_set_callbacks(notifier, callable_mp(this, &VisibleOnScreenNotifier3D::_visibility_enter), callable_mp(this, &VisibleOnScreenNotifier3D::_visibility_exit));
+ set_base(notifier);
+}
+VisibleOnScreenNotifier3D::~VisibleOnScreenNotifier3D() {
+ RID base = get_base();
+ set_base(RID());
+ RS::get_singleton()->free(base);
+}
+
+//////////////////////////////////////
+
+void VisibleOnScreenEnabler3D::_screen_enter() {
+ _update_enable_mode(true);
+}
+
+void VisibleOnScreenEnabler3D::_screen_exit() {
+ _update_enable_mode(false);
+}
+
+void VisibleOnScreenEnabler3D::set_enable_mode(EnableMode p_mode) {
+ enable_mode = p_mode;
+ if (is_inside_tree()) {
+ _update_enable_mode(is_on_screen());
+ }
+}
+VisibleOnScreenEnabler3D::EnableMode VisibleOnScreenEnabler3D::get_enable_mode() {
+ return enable_mode;
+}
+
+void VisibleOnScreenEnabler3D::set_enable_node_path(NodePath p_path) {
+ if (enable_node_path == p_path) {
+ return;
+ }
+ enable_node_path = p_path;
+ if (is_inside_tree()) {
+ node_id = ObjectID();
+ Node *node = get_node(enable_node_path);
+ if (node) {
+ node_id = node->get_instance_id();
+ _update_enable_mode(is_on_screen());
+ }
+ }
+}
+NodePath VisibleOnScreenEnabler3D::get_enable_node_path() {
+ return enable_node_path;
+}
+
+void VisibleOnScreenEnabler3D::_update_enable_mode(bool p_enable) {
+ Node *node = static_cast<Node *>(ObjectDB::get_instance(node_id));
+ if (node) {
+ if (p_enable) {
+ switch (enable_mode) {
+ case ENABLE_MODE_INHERIT: {
+ node->set_process_mode(PROCESS_MODE_INHERIT);
+ } break;
+ case ENABLE_MODE_ALWAYS: {
+ node->set_process_mode(PROCESS_MODE_ALWAYS);
+ } break;
+ case ENABLE_MODE_WHEN_PAUSED: {
+ node->set_process_mode(PROCESS_MODE_WHEN_PAUSED);
+ } break;
+ }
+ } else {
+ node->set_process_mode(PROCESS_MODE_DISABLED);
+ }
+ }
+}
+void VisibleOnScreenEnabler3D::_notification(int p_what) {
+ if (p_what == NOTIFICATION_ENTER_TREE) {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ node_id = ObjectID();
+ Node *node = get_node(enable_node_path);
+ if (node) {
+ node_id = node->get_instance_id();
+ node->set_process_mode(PROCESS_MODE_DISABLED);
+ }
+ }
+
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+ node_id = ObjectID();
+ }
+}
+
+void VisibleOnScreenEnabler3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_enable_mode", "mode"), &VisibleOnScreenEnabler3D::set_enable_mode);
+ ClassDB::bind_method(D_METHOD("get_enable_mode"), &VisibleOnScreenEnabler3D::get_enable_mode);
+
+ ClassDB::bind_method(D_METHOD("set_enable_node_path", "path"), &VisibleOnScreenEnabler3D::set_enable_node_path);
+ ClassDB::bind_method(D_METHOD("get_enable_node_path"), &VisibleOnScreenEnabler3D::get_enable_node_path);
+
+ ADD_GROUP("Enabling", "enable_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "enable_mode", PROPERTY_HINT_ENUM, "Inherit,Always,WhenPaused"), "set_enable_mode", "get_enable_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "enable_node_path"), "set_enable_node_path", "get_enable_node_path");
+
+ BIND_ENUM_CONSTANT(ENABLE_MODE_INHERIT);
+ BIND_ENUM_CONSTANT(ENABLE_MODE_ALWAYS);
+ BIND_ENUM_CONSTANT(ENABLE_MODE_WHEN_PAUSED);
+}
+
+VisibleOnScreenEnabler3D::VisibleOnScreenEnabler3D() {
+}
diff --git a/scene/3d/visibility_notifier_3d.h b/scene/3d/visible_on_screen_notifier_3d.h
index 9f7705067f..fb7137c4f0 100644
--- a/scene/3d/visibility_notifier_3d.h
+++ b/scene/3d/visible_on_screen_notifier_3d.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* visibility_notifier_3d.h */
+/* visible_on_screen_notifier_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,74 +28,74 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef VISIBILITY_NOTIFIER_H
-#define VISIBILITY_NOTIFIER_H
+#ifndef VISIBLE_ON_SCREEN_NOTIFIER_3D_H
+#define VISIBLE_ON_SCREEN_NOTIFIER_3D_H
-#include "scene/3d/node_3d.h"
+#include "scene/3d/visual_instance_3d.h"
class World3D;
class Camera3D;
-class VisibilityNotifier3D : public Node3D {
- GDCLASS(VisibilityNotifier3D, Node3D);
-
- Ref<World3D> world;
- Set<Camera3D *> cameras;
+class VisibleOnScreenNotifier3D : public VisualInstance3D {
+ GDCLASS(VisibleOnScreenNotifier3D, VisualInstance3D);
AABB aabb = AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+private:
+ bool on_screen = false;
+ void _visibility_enter();
+ void _visibility_exit();
+
protected:
virtual void _screen_enter() {}
virtual void _screen_exit() {}
void _notification(int p_what);
static void _bind_methods();
- friend struct SpatialIndexer;
-
- void _enter_camera(Camera3D *p_camera);
- void _exit_camera(Camera3D *p_camera);
public:
void set_aabb(const AABB &p_aabb);
- AABB get_aabb() const;
+ virtual AABB get_aabb() const override;
bool is_on_screen() const;
- VisibilityNotifier3D();
+ virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
+
+ VisibleOnScreenNotifier3D();
+ ~VisibleOnScreenNotifier3D();
};
-class VisibilityEnabler3D : public VisibilityNotifier3D {
- GDCLASS(VisibilityEnabler3D, VisibilityNotifier3D);
+class VisibleOnScreenEnabler3D : public VisibleOnScreenNotifier3D {
+ GDCLASS(VisibleOnScreenEnabler3D, VisibleOnScreenNotifier3D);
public:
- enum Enabler {
- ENABLER_PAUSE_ANIMATIONS,
- ENABLER_FREEZE_BODIES,
- ENABLER_MAX
+ enum EnableMode {
+ ENABLE_MODE_INHERIT,
+ ENABLE_MODE_ALWAYS,
+ ENABLE_MODE_WHEN_PAUSED,
};
protected:
+ ObjectID node_id;
virtual void _screen_enter() override;
virtual void _screen_exit() override;
- bool visible = false;
-
- void _find_nodes(Node *p_node);
-
- Map<Node *, Variant> nodes;
- void _node_removed(Node *p_node);
- bool enabler[ENABLER_MAX];
-
- void _change_node_state(Node *p_node, bool p_enabled);
+ EnableMode enable_mode = ENABLE_MODE_INHERIT;
+ NodePath enable_node_path = NodePath("..");
void _notification(int p_what);
static void _bind_methods();
+ void _update_enable_mode(bool p_enable);
+
public:
- void set_enabler(Enabler p_enabler, bool p_enable);
- bool is_enabler_enabled(Enabler p_enabler) const;
+ void set_enable_mode(EnableMode p_mode);
+ EnableMode get_enable_mode();
+
+ void set_enable_node_path(NodePath p_path);
+ NodePath get_enable_node_path();
- VisibilityEnabler3D();
+ VisibleOnScreenEnabler3D();
};
-VARIANT_ENUM_CAST(VisibilityEnabler3D::Enabler);
+VARIANT_ENUM_CAST(VisibleOnScreenEnabler3D::EnableMode);
#endif // VISIBILITY_NOTIFIER_H
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index 6971c1ce2a..c16e3c2d78 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -150,40 +150,40 @@ Ref<Material> GeometryInstance3D::get_material_override() const {
return material_override;
}
-void GeometryInstance3D::set_lod_min_distance(float p_dist) {
- lod_min_distance = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_begin(float p_dist) {
+ visibility_range_begin = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_min_distance() const {
- return lod_min_distance;
+float GeometryInstance3D::get_visibility_range_begin() const {
+ return visibility_range_begin;
}
-void GeometryInstance3D::set_lod_max_distance(float p_dist) {
- lod_max_distance = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_end(float p_dist) {
+ visibility_range_end = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_max_distance() const {
- return lod_max_distance;
+float GeometryInstance3D::get_visibility_range_end() const {
+ return visibility_range_end;
}
-void GeometryInstance3D::set_lod_min_hysteresis(float p_dist) {
- lod_min_hysteresis = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_begin_margin(float p_dist) {
+ visibility_range_begin_margin = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_min_hysteresis() const {
- return lod_min_hysteresis;
+float GeometryInstance3D::get_visibility_range_begin_margin() const {
+ return visibility_range_begin_margin;
}
-void GeometryInstance3D::set_lod_max_hysteresis(float p_dist) {
- lod_max_hysteresis = p_dist;
- RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis);
+void GeometryInstance3D::set_visibility_range_end_margin(float p_dist) {
+ visibility_range_end_margin = p_dist;
+ RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
}
-float GeometryInstance3D::get_lod_max_hysteresis() const {
- return lod_max_hysteresis;
+float GeometryInstance3D::get_visibility_range_end_margin() const {
+ return visibility_range_end_margin;
}
void GeometryInstance3D::_notification(int p_what) {
@@ -357,17 +357,17 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lod_bias", "bias"), &GeometryInstance3D::set_lod_bias);
ClassDB::bind_method(D_METHOD("get_lod_bias"), &GeometryInstance3D::get_lod_bias);
- ClassDB::bind_method(D_METHOD("set_lod_max_hysteresis", "mode"), &GeometryInstance3D::set_lod_max_hysteresis);
- ClassDB::bind_method(D_METHOD("get_lod_max_hysteresis"), &GeometryInstance3D::get_lod_max_hysteresis);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_end_margin", "distance"), &GeometryInstance3D::set_visibility_range_end_margin);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_end_margin"), &GeometryInstance3D::get_visibility_range_end_margin);
- ClassDB::bind_method(D_METHOD("set_lod_max_distance", "mode"), &GeometryInstance3D::set_lod_max_distance);
- ClassDB::bind_method(D_METHOD("get_lod_max_distance"), &GeometryInstance3D::get_lod_max_distance);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_end", "distance"), &GeometryInstance3D::set_visibility_range_end);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_end"), &GeometryInstance3D::get_visibility_range_end);
- ClassDB::bind_method(D_METHOD("set_lod_min_hysteresis", "mode"), &GeometryInstance3D::set_lod_min_hysteresis);
- ClassDB::bind_method(D_METHOD("get_lod_min_hysteresis"), &GeometryInstance3D::get_lod_min_hysteresis);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_begin_margin", "distance"), &GeometryInstance3D::set_visibility_range_begin_margin);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_begin_margin"), &GeometryInstance3D::get_visibility_range_begin_margin);
- ClassDB::bind_method(D_METHOD("set_lod_min_distance", "mode"), &GeometryInstance3D::set_lod_min_distance);
- ClassDB::bind_method(D_METHOD("get_lod_min_distance"), &GeometryInstance3D::get_lod_min_distance);
+ ClassDB::bind_method(D_METHOD("set_visibility_range_begin", "distance"), &GeometryInstance3D::set_visibility_range_begin);
+ ClassDB::bind_method(D_METHOD("get_visibility_range_begin"), &GeometryInstance3D::get_visibility_range_begin);
ClassDB::bind_method(D_METHOD("set_shader_instance_uniform", "uniform", "value"), &GeometryInstance3D::set_shader_instance_uniform);
ClassDB::bind_method(D_METHOD("get_shader_instance_uniform", "uniform"), &GeometryInstance3D::get_shader_instance_uniform);
@@ -398,11 +398,11 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Baked,Dynamic"), "set_gi_mode", "get_gi_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, "1x,2x,4x,8x"), "set_lightmap_scale", "get_lightmap_scale");
- ADD_GROUP("LOD", "lod_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_distance", "get_lod_min_distance");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_min_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_min_hysteresis", "get_lod_min_hysteresis");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_distance", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_distance", "get_lod_max_distance");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "lod_max_hysteresis", PROPERTY_HINT_RANGE, "0,32768,0.01"), "set_lod_max_hysteresis", "get_lod_max_hysteresis");
+ ADD_GROUP("Visibility Range", "visibility_range_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_begin", "get_visibility_range_begin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end", "get_visibility_range_end");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end_margin", "get_visibility_range_end_margin");
//ADD_SIGNAL( MethodInfo("visibility_changed"));
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index 68d29ef81e..2d5699859b 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -107,10 +107,13 @@ public:
private:
ShadowCastingSetting shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
Ref<Material> material_override;
- float lod_min_distance = 0.0;
- float lod_max_distance = 0.0;
- float lod_min_hysteresis = 0.0;
- float lod_max_hysteresis = 0.0;
+
+ float visibility_range_begin = 0.0;
+ float visibility_range_end = 0.0;
+ float visibility_range_begin_margin = 0.0;
+ float visibility_range_end_margin = 0.0;
+
+ Vector<NodePath> visibility_range_children;
float lod_bias = 1.0;
@@ -136,17 +139,20 @@ public:
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
ShadowCastingSetting get_cast_shadows_setting() const;
- void set_lod_min_distance(float p_dist);
- float get_lod_min_distance() const;
+ void set_visibility_range_begin(float p_dist);
+ float get_visibility_range_begin() const;
+
+ void set_visibility_range_end(float p_dist);
+ float get_visibility_range_end() const;
- void set_lod_max_distance(float p_dist);
- float get_lod_max_distance() const;
+ void set_visibility_range_begin_margin(float p_dist);
+ float get_visibility_range_begin_margin() const;
- void set_lod_min_hysteresis(float p_dist);
- float get_lod_min_hysteresis() const;
+ void set_visibility_range_end_margin(float p_dist);
+ float get_visibility_range_end_margin() const;
- void set_lod_max_hysteresis(float p_dist);
- float get_lod_max_hysteresis() const;
+ void set_visibility_range_parent(const Node *p_parent);
+ void clear_visibility_range_parent();
void set_material_override(const Ref<Material> &p_material);
Ref<Material> get_material_override() const;
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index 5a4d9b5d7e..4f2c816934 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -520,9 +520,9 @@ TypedArray<String> XROrigin3D::get_configuration_warnings() const {
}
}
- bool vr_enabled = GLOBAL_GET("rendering/vr/enabled");
- if (!vr_enabled) {
- warnings.push_back(TTR("VR is not enabled in rendering project settings. Stereoscopic output is not supported unless this is enabled."));
+ bool xr_enabled = GLOBAL_GET("rendering/xr/enabled");
+ if (!xr_enabled) {
+ warnings.push_back(TTR("XR is not enabled in rendering project settings. Stereoscopic output is not supported unless this is enabled."));
}
return warnings;