Refactor VisibilityNotifier3D
* This is the 3D counterpart to #49632 * Implemented a bit different as 3D works using instancing After merged, both 2D and 3D classes will most likely be renamed in a separate PR to DisplayNotifier2D/3D.
This commit is contained in:
parent
341cb8da31
commit
6e98c4cd50
23 changed files with 318 additions and 476 deletions
|
@ -3702,7 +3702,7 @@
|
|||
</constant>
|
||||
<constant name="INSTANCE_OCCLUDER" value="11" enum="InstanceType">
|
||||
</constant>
|
||||
<constant name="INSTANCE_MAX" value="12" enum="InstanceType">
|
||||
<constant name="INSTANCE_MAX" value="13" enum="InstanceType">
|
||||
Represents the size of the [enum InstanceType] enum.
|
||||
</constant>
|
||||
<constant name="INSTANCE_GEOMETRY_MASK" value="30" enum="InstanceType">
|
||||
|
|
|
@ -179,13 +179,6 @@
|
|||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="update_worlds">
|
||||
<return type="void">
|
||||
</return>
|
||||
<description>
|
||||
Forces update of the 2D and 3D worlds.
|
||||
</description>
|
||||
</method>
|
||||
<method name="warp_mouse">
|
||||
<return type="void">
|
||||
</return>
|
||||
|
|
|
@ -12,44 +12,19 @@
|
|||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="is_enabler_enabled" qualifiers="const">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="enabler" type="int" enum="VisibilityEnabler3D.Enabler">
|
||||
</argument>
|
||||
<description>
|
||||
Returns whether the enabler identified by given [enum Enabler] constant is active.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_enabler">
|
||||
<return type="void">
|
||||
</return>
|
||||
<argument index="0" name="enabler" type="int" enum="VisibilityEnabler3D.Enabler">
|
||||
</argument>
|
||||
<argument index="1" name="enabled" type="bool">
|
||||
</argument>
|
||||
<description>
|
||||
Sets active state of the enabler identified by given [enum Enabler] constant.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="freeze_bodies" type="bool" setter="set_enabler" getter="is_enabler_enabled" default="true">
|
||||
If [code]true[/code], [RigidBody3D] nodes will be paused.
|
||||
<member name="enable_mode" type="int" setter="set_enable_mode" getter="get_enable_mode" enum="VisibilityEnabler3D.EnableMode" default="0">
|
||||
</member>
|
||||
<member name="pause_animations" type="bool" setter="set_enabler" getter="is_enabler_enabled" default="true">
|
||||
If [code]true[/code], [AnimationPlayer] nodes will be paused.
|
||||
<member name="enable_node_path" type="NodePath" setter="set_enable_node_path" getter="get_enable_node_path" default="NodePath("..")">
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="ENABLER_PAUSE_ANIMATIONS" value="0" enum="Enabler">
|
||||
This enabler will pause [AnimationPlayer] nodes.
|
||||
<constant name="ENABLE_MODE_INHERIT" value="0" enum="EnableMode">
|
||||
</constant>
|
||||
<constant name="ENABLER_FREEZE_BODIES" value="1" enum="Enabler">
|
||||
This enabler will freeze [RigidBody3D] nodes.
|
||||
<constant name="ENABLE_MODE_ALWAYS" value="1" enum="EnableMode">
|
||||
</constant>
|
||||
<constant name="ENABLER_MAX" value="2" enum="Enabler">
|
||||
Represents the size of the [enum Enabler] enum.
|
||||
<constant name="ENABLE_MODE_WHEN_PAUSED" value="2" enum="EnableMode">
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="VisibilityNotifier3D" inherits="Node3D" version="4.0">
|
||||
<class name="VisibilityNotifier3D" inherits="VisualInstance3D" version="4.0">
|
||||
<brief_description>
|
||||
Detects approximately when the node is visible on screen.
|
||||
</brief_description>
|
||||
|
@ -26,20 +26,6 @@
|
|||
</member>
|
||||
</members>
|
||||
<signals>
|
||||
<signal name="camera_entered">
|
||||
<argument index="0" name="camera" type="Camera3D">
|
||||
</argument>
|
||||
<description>
|
||||
Emitted when the VisibilityNotifier3D enters a [Camera3D]'s view.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="camera_exited">
|
||||
<argument index="0" name="camera" type="Camera3D">
|
||||
</argument>
|
||||
<description>
|
||||
Emitted when the VisibilityNotifier3D exits a [Camera3D]'s view.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="screen_entered">
|
||||
<description>
|
||||
Emitted when the VisibilityNotifier3D enters the screen.
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -36,27 +36,23 @@
|
|||
#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();
|
||||
void VisibilityNotifier3D::_visibility_enter() {
|
||||
if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
|
||||
return;
|
||||
}
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->camera_entered, p_camera);
|
||||
on_screen = true;
|
||||
emit_signal(SceneStringNames::get_singleton()->screen_entered);
|
||||
_screen_enter();
|
||||
}
|
||||
|
||||
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::_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 VisibilityNotifier3D::set_aabb(const AABB &p_aabb) {
|
||||
|
@ -65,9 +61,7 @@ void VisibilityNotifier3D::set_aabb(const AABB &p_aabb) {
|
|||
}
|
||||
aabb = p_aabb;
|
||||
|
||||
if (is_inside_world()) {
|
||||
get_world_3d()->_update_notifier(this, get_global_transform().xform(aabb));
|
||||
}
|
||||
RS::get_singleton()->visibility_notifier_set_aabb(get_base(), aabb);
|
||||
|
||||
update_gizmo();
|
||||
}
|
||||
|
@ -76,178 +70,129 @@ 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 on_screen;
|
||||
}
|
||||
|
||||
bool VisibilityNotifier3D::is_on_screen() const {
|
||||
return cameras.size() != 0;
|
||||
void VisibilityNotifier3D::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_EXIT_TREE) {
|
||||
on_screen = false;
|
||||
}
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
Vector<Face3> VisibilityNotifier3D::get_faces(uint32_t p_usage_flags) const {
|
||||
return Vector<Face3>();
|
||||
}
|
||||
|
||||
VisibilityNotifier3D::VisibilityNotifier3D() {
|
||||
set_notify_transform(true);
|
||||
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, &VisibilityNotifier3D::_visibility_enter), callable_mp(this, &VisibilityNotifier3D::_visibility_exit));
|
||||
set_base(notifier);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void VisibilityEnabler3D::_screen_enter() {
|
||||
for (Map<Node *, Variant>::Element *E = nodes.front(); E; E = E->next()) {
|
||||
_change_node_state(E->key(), true);
|
||||
}
|
||||
|
||||
visible = true;
|
||||
_update_enable_mode(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;
|
||||
_update_enable_mode(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::set_enable_mode(EnableMode p_mode) {
|
||||
enable_mode = p_mode;
|
||||
if (is_inside_tree()) {
|
||||
_update_enable_mode(is_on_screen());
|
||||
}
|
||||
}
|
||||
VisibilityEnabler3D::EnableMode VisibilityEnabler3D::get_enable_mode() {
|
||||
return enable_mode;
|
||||
}
|
||||
|
||||
void VisibilityEnabler3D::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 VisibilityEnabler3D::get_enable_node_path() {
|
||||
return enable_node_path;
|
||||
}
|
||||
|
||||
void VisibilityEnabler3D::_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 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();
|
||||
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);
|
||||
}
|
||||
|
||||
_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();
|
||||
node_id = ObjectID();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
ClassDB::bind_method(D_METHOD("set_enable_mode", "mode"), &VisibilityEnabler3D::set_enable_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_enable_mode"), &VisibilityEnabler3D::get_enable_mode);
|
||||
|
||||
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);
|
||||
ClassDB::bind_method(D_METHOD("set_enable_node_path", "path"), &VisibilityEnabler3D::set_enable_node_path);
|
||||
ClassDB::bind_method(D_METHOD("get_enable_node_path"), &VisibilityEnabler3D::get_enable_node_path);
|
||||
|
||||
BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS);
|
||||
BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
|
||||
BIND_ENUM_CONSTANT(ENABLER_MAX);
|
||||
}
|
||||
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");
|
||||
|
||||
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];
|
||||
BIND_ENUM_CONSTANT(ENABLE_MODE_INHERIT);
|
||||
BIND_ENUM_CONSTANT(ENABLE_MODE_ALWAYS);
|
||||
BIND_ENUM_CONSTANT(ENABLE_MODE_WHEN_PAUSED);
|
||||
}
|
||||
|
||||
VisibilityEnabler3D::VisibilityEnabler3D() {
|
||||
for (int i = 0; i < ENABLER_MAX; i++) {
|
||||
enabler[i] = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,34 +31,34 @@
|
|||
#ifndef VISIBILITY_NOTIFIER_H
|
||||
#define VISIBILITY_NOTIFIER_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 VisibilityNotifier3D : public VisualInstance3D {
|
||||
GDCLASS(VisibilityNotifier3D, 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;
|
||||
|
||||
virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
|
||||
|
||||
VisibilityNotifier3D();
|
||||
};
|
||||
|
||||
|
@ -66,36 +66,35 @@ class VisibilityEnabler3D : public VisibilityNotifier3D {
|
|||
GDCLASS(VisibilityEnabler3D, VisibilityNotifier3D);
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(VisibilityEnabler3D::Enabler);
|
||||
VARIANT_ENUM_CAST(VisibilityEnabler3D::EnableMode);
|
||||
|
||||
#endif // VISIBILITY_NOTIFIER_H
|
||||
|
|
|
@ -413,7 +413,6 @@ bool SceneTree::physics_process(float p_time) {
|
|||
_flush_ugc();
|
||||
MessageQueue::get_singleton()->flush(); //small little hack
|
||||
flush_transform_notifications();
|
||||
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
|
||||
root_lock--;
|
||||
|
||||
_flush_delete_queue();
|
||||
|
@ -445,7 +444,6 @@ bool SceneTree::process(float p_time) {
|
|||
_flush_ugc();
|
||||
MessageQueue::get_singleton()->flush(); //small little hack
|
||||
flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
|
||||
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
|
||||
|
||||
root_lock--;
|
||||
|
||||
|
|
|
@ -183,14 +183,6 @@ public:
|
|||
|
||||
/////////////////////////////////////
|
||||
|
||||
void Viewport::update_worlds() {
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
find_world_3d()->_update(get_tree()->get_frame());
|
||||
}
|
||||
|
||||
void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
|
||||
Transform3D object_transform = p_object->get_global_transform();
|
||||
Transform3D camera_transform = p_camera->get_global_transform();
|
||||
|
@ -3513,8 +3505,6 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("input", "event", "in_local_coords"), &Viewport::input, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("unhandled_input", "event", "in_local_coords"), &Viewport::unhandled_input, DEFVAL(false));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("update_worlds"), &Viewport::update_worlds);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &Viewport::set_use_own_world_3d);
|
||||
ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &Viewport::is_using_own_world_3d);
|
||||
|
||||
|
|
|
@ -397,8 +397,6 @@ private:
|
|||
|
||||
void _gui_input_event(Ref<InputEvent> p_event);
|
||||
|
||||
void update_worlds();
|
||||
|
||||
_FORCE_INLINE_ Transform2D _get_input_pre_xform() const;
|
||||
|
||||
Ref<InputEvent> _make_input_local(const Ref<InputEvent> &ev);
|
||||
|
|
|
@ -37,206 +37,15 @@
|
|||
#include "scene/scene_string_names.h"
|
||||
#include "servers/navigation_server_3d.h"
|
||||
|
||||
struct SpatialIndexer {
|
||||
Octree<VisibilityNotifier3D> octree;
|
||||
|
||||
struct NotifierData {
|
||||
AABB aabb;
|
||||
OctreeElementID id;
|
||||
};
|
||||
|
||||
Map<VisibilityNotifier3D *, NotifierData> notifiers;
|
||||
struct CameraData {
|
||||
Map<VisibilityNotifier3D *, uint64_t> notifiers;
|
||||
};
|
||||
|
||||
Map<Camera3D *, CameraData> cameras;
|
||||
|
||||
enum {
|
||||
VISIBILITY_CULL_MAX = 32768
|
||||
};
|
||||
|
||||
Vector<VisibilityNotifier3D *> cull;
|
||||
|
||||
bool changed;
|
||||
uint64_t pass;
|
||||
uint64_t last_frame;
|
||||
|
||||
void _notifier_add(VisibilityNotifier3D *p_notifier, const AABB &p_rect) {
|
||||
ERR_FAIL_COND(notifiers.has(p_notifier));
|
||||
notifiers[p_notifier].aabb = p_rect;
|
||||
notifiers[p_notifier].id = octree.create(p_notifier, p_rect);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _notifier_update(VisibilityNotifier3D *p_notifier, const AABB &p_rect) {
|
||||
Map<VisibilityNotifier3D *, NotifierData>::Element *E = notifiers.find(p_notifier);
|
||||
ERR_FAIL_COND(!E);
|
||||
if (E->get().aabb == p_rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
E->get().aabb = p_rect;
|
||||
octree.move(E->get().id, E->get().aabb);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _notifier_remove(VisibilityNotifier3D *p_notifier) {
|
||||
Map<VisibilityNotifier3D *, NotifierData>::Element *E = notifiers.find(p_notifier);
|
||||
ERR_FAIL_COND(!E);
|
||||
|
||||
octree.erase(E->get().id);
|
||||
notifiers.erase(p_notifier);
|
||||
|
||||
List<Camera3D *> removed;
|
||||
for (Map<Camera3D *, CameraData>::Element *F = cameras.front(); F; F = F->next()) {
|
||||
Map<VisibilityNotifier3D *, uint64_t>::Element *G = F->get().notifiers.find(p_notifier);
|
||||
|
||||
if (G) {
|
||||
F->get().notifiers.erase(G);
|
||||
removed.push_back(F->key());
|
||||
}
|
||||
}
|
||||
|
||||
while (!removed.is_empty()) {
|
||||
p_notifier->_exit_camera(removed.front()->get());
|
||||
removed.pop_front();
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _add_camera(Camera3D *p_camera) {
|
||||
ERR_FAIL_COND(cameras.has(p_camera));
|
||||
CameraData vd;
|
||||
cameras[p_camera] = vd;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _update_camera(Camera3D *p_camera) {
|
||||
Map<Camera3D *, CameraData>::Element *E = cameras.find(p_camera);
|
||||
ERR_FAIL_COND(!E);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void _remove_camera(Camera3D *p_camera) {
|
||||
ERR_FAIL_COND(!cameras.has(p_camera));
|
||||
List<VisibilityNotifier3D *> removed;
|
||||
for (Map<VisibilityNotifier3D *, uint64_t>::Element *E = cameras[p_camera].notifiers.front(); E; E = E->next()) {
|
||||
removed.push_back(E->key());
|
||||
}
|
||||
|
||||
while (!removed.is_empty()) {
|
||||
removed.front()->get()->_exit_camera(p_camera);
|
||||
removed.pop_front();
|
||||
}
|
||||
|
||||
cameras.erase(p_camera);
|
||||
}
|
||||
|
||||
void _update(uint64_t p_frame) {
|
||||
if (p_frame == last_frame) {
|
||||
return;
|
||||
}
|
||||
last_frame = p_frame;
|
||||
|
||||
if (!changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Map<Camera3D *, CameraData>::Element *E = cameras.front(); E; E = E->next()) {
|
||||
pass++;
|
||||
|
||||
Camera3D *c = E->key();
|
||||
|
||||
Vector<Plane> planes = c->get_frustum();
|
||||
|
||||
int culled = octree.cull_convex(planes, cull.ptrw(), cull.size());
|
||||
|
||||
VisibilityNotifier3D **ptr = cull.ptrw();
|
||||
|
||||
List<VisibilityNotifier3D *> added;
|
||||
List<VisibilityNotifier3D *> removed;
|
||||
|
||||
for (int i = 0; i < culled; i++) {
|
||||
//notifiers in frustum
|
||||
|
||||
Map<VisibilityNotifier3D *, uint64_t>::Element *H = E->get().notifiers.find(ptr[i]);
|
||||
if (!H) {
|
||||
E->get().notifiers.insert(ptr[i], pass);
|
||||
added.push_back(ptr[i]);
|
||||
} else {
|
||||
H->get() = pass;
|
||||
}
|
||||
}
|
||||
|
||||
for (Map<VisibilityNotifier3D *, uint64_t>::Element *F = E->get().notifiers.front(); F; F = F->next()) {
|
||||
if (F->get() != pass) {
|
||||
removed.push_back(F->key());
|
||||
}
|
||||
}
|
||||
|
||||
while (!added.is_empty()) {
|
||||
added.front()->get()->_enter_camera(E->key());
|
||||
added.pop_front();
|
||||
}
|
||||
|
||||
while (!removed.is_empty()) {
|
||||
E->get().notifiers.erase(removed.front()->get());
|
||||
removed.front()->get()->_exit_camera(E->key());
|
||||
removed.pop_front();
|
||||
}
|
||||
}
|
||||
changed = false;
|
||||
}
|
||||
|
||||
SpatialIndexer() {
|
||||
pass = 0;
|
||||
last_frame = 0;
|
||||
changed = false;
|
||||
cull.resize(VISIBILITY_CULL_MAX);
|
||||
}
|
||||
};
|
||||
|
||||
void World3D::_register_camera(Camera3D *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_add_camera(p_camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_update_camera(Camera3D *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_update_camera(p_camera);
|
||||
cameras.insert(p_camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_remove_camera(Camera3D *p_camera) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_remove_camera(p_camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_register_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_notifier_add(p_notifier, p_rect);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_update_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_notifier_update(p_notifier, p_rect);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_remove_notifier(VisibilityNotifier3D *p_notifier) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_notifier_remove(p_notifier);
|
||||
#endif
|
||||
}
|
||||
|
||||
void World3D::_update(uint64_t p_frame) {
|
||||
#ifndef _3D_DISABLED
|
||||
indexer->_update(p_frame);
|
||||
cameras.erase(p_camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -307,12 +116,6 @@ PhysicsDirectSpaceState3D *World3D::get_direct_space_state() {
|
|||
return PhysicsServer3D::get_singleton()->space_get_direct_state(space);
|
||||
}
|
||||
|
||||
void World3D::get_camera_list(List<Camera3D *> *r_cameras) {
|
||||
for (Map<Camera3D *, SpatialIndexer::CameraData>::Element *E = indexer->cameras.front(); E; E = E->next()) {
|
||||
r_cameras->push_back(E->key());
|
||||
}
|
||||
}
|
||||
|
||||
void World3D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_space"), &World3D::get_space);
|
||||
ClassDB::bind_method(D_METHOD("get_navigation_map"), &World3D::get_navigation_map);
|
||||
|
@ -349,20 +152,10 @@ World3D::World3D() {
|
|||
NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);
|
||||
NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/3d/default_cell_size", 0.3));
|
||||
NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 0.3));
|
||||
|
||||
#ifdef _3D_DISABLED
|
||||
indexer = nullptr;
|
||||
#else
|
||||
indexer = memnew(SpatialIndexer);
|
||||
#endif
|
||||
}
|
||||
|
||||
World3D::~World3D() {
|
||||
PhysicsServer3D::get_singleton()->free(space);
|
||||
RenderingServer::get_singleton()->free(scenario);
|
||||
NavigationServer3D::get_singleton()->free(navigation_map);
|
||||
|
||||
#ifndef _3D_DISABLED
|
||||
memdelete(indexer);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -48,27 +48,21 @@ private:
|
|||
RID space;
|
||||
RID navigation_map;
|
||||
RID scenario;
|
||||
SpatialIndexer *indexer;
|
||||
|
||||
Ref<Environment> environment;
|
||||
Ref<Environment> fallback_environment;
|
||||
Ref<CameraEffects> camera_effects;
|
||||
|
||||
Set<Camera3D *> cameras;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
friend class Camera3D;
|
||||
friend class VisibilityNotifier3D;
|
||||
|
||||
void _register_camera(Camera3D *p_camera);
|
||||
void _update_camera(Camera3D *p_camera);
|
||||
void _remove_camera(Camera3D *p_camera);
|
||||
|
||||
void _register_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect);
|
||||
void _update_notifier(VisibilityNotifier3D *p_notifier, const AABB &p_rect);
|
||||
void _remove_notifier(VisibilityNotifier3D *p_notifier);
|
||||
friend class Viewport;
|
||||
void _update(uint64_t p_frame);
|
||||
|
||||
public:
|
||||
RID get_space() const;
|
||||
RID get_navigation_map() const;
|
||||
|
@ -83,7 +77,7 @@ public:
|
|||
void set_camera_effects(const Ref<CameraEffects> &p_camera_effects);
|
||||
Ref<CameraEffects> get_camera_effects() const;
|
||||
|
||||
void get_camera_list(List<Camera3D *> *r_cameras);
|
||||
_FORCE_INLINE_ const Set<Camera3D *> &get_cameras() const { return cameras; }
|
||||
|
||||
PhysicsDirectSpaceState3D *get_direct_space_state();
|
||||
|
||||
|
|
|
@ -621,9 +621,18 @@ public:
|
|||
bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
|
||||
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
|
||||
|
||||
RID particles_collision_instance_create(RID p_collision) override { return RID(); };
|
||||
void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override{};
|
||||
void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override{};
|
||||
RID particles_collision_instance_create(RID p_collision) override { return RID(); }
|
||||
void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
|
||||
void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
|
||||
|
||||
/* VISIBILITY NOTIFIER */
|
||||
virtual RID visibility_notifier_allocate() override { return RID(); }
|
||||
virtual void visibility_notifier_initialize(RID p_notifier) override {}
|
||||
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
|
||||
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
|
||||
|
||||
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
|
||||
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
|
||||
|
||||
/* GLOBAL VARIABLES */
|
||||
|
||||
|
|
|
@ -5535,6 +5535,59 @@ void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_
|
|||
pci->active = p_active;
|
||||
}
|
||||
|
||||
/* VISIBILITY NOTIFIER */
|
||||
|
||||
RID RendererStorageRD::visibility_notifier_allocate() {
|
||||
return visibility_notifier_owner.allocate_rid();
|
||||
}
|
||||
void RendererStorageRD::visibility_notifier_initialize(RID p_notifier) {
|
||||
visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
|
||||
}
|
||||
void RendererStorageRD::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
|
||||
VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
|
||||
ERR_FAIL_COND(!vn);
|
||||
vn->aabb = p_aabb;
|
||||
vn->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
|
||||
}
|
||||
void RendererStorageRD::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
|
||||
VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
|
||||
ERR_FAIL_COND(!vn);
|
||||
vn->enter_callback = p_enter_callbable;
|
||||
vn->exit_callback = p_exit_callable;
|
||||
}
|
||||
|
||||
AABB RendererStorageRD::visibility_notifier_get_aabb(RID p_notifier) const {
|
||||
const VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
|
||||
ERR_FAIL_COND_V(!vn, AABB());
|
||||
return vn->aabb;
|
||||
}
|
||||
void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
|
||||
VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_notifier);
|
||||
ERR_FAIL_COND(!vn);
|
||||
|
||||
if (p_enter) {
|
||||
if (!vn->enter_callback.is_null()) {
|
||||
if (p_deferred) {
|
||||
vn->enter_callback.call_deferred(nullptr, 0);
|
||||
} else {
|
||||
Variant r;
|
||||
Callable::CallError ce;
|
||||
vn->enter_callback.call(nullptr, 0, r, ce);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!vn->exit_callback.is_null()) {
|
||||
if (p_deferred) {
|
||||
vn->exit_callback.call_deferred(nullptr, 0);
|
||||
} else {
|
||||
Variant r;
|
||||
Callable::CallError ce;
|
||||
vn->exit_callback.call(nullptr, 0, r, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SKELETON API */
|
||||
|
||||
RID RendererStorageRD::skeleton_allocate() {
|
||||
|
@ -7590,6 +7643,9 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
|
|||
} else if (particles_collision_owner.owns(p_base)) {
|
||||
ParticlesCollision *pc = particles_collision_owner.getornull(p_base);
|
||||
p_instance->update_dependency(&pc->dependency);
|
||||
} else if (visibility_notifier_owner.owns(p_base)) {
|
||||
VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_base);
|
||||
p_instance->update_dependency(&vn->dependency);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7628,6 +7684,9 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
|
|||
if (particles_collision_owner.owns(p_rid)) {
|
||||
return RS::INSTANCE_PARTICLES_COLLISION;
|
||||
}
|
||||
if (visibility_notifier_owner.owns(p_rid)) {
|
||||
return RS::INSTANCE_VISIBLITY_NOTIFIER;
|
||||
}
|
||||
|
||||
return RS::INSTANCE_NONE;
|
||||
}
|
||||
|
@ -8704,6 +8763,10 @@ bool RendererStorageRD::free(RID p_rid) {
|
|||
}
|
||||
particles_collision->dependency.deleted_notify(p_rid);
|
||||
particles_collision_owner.free(p_rid);
|
||||
} else if (visibility_notifier_owner.owns(p_rid)) {
|
||||
VisibilityNotifier *vn = visibility_notifier_owner.getornull(p_rid);
|
||||
vn->dependency.deleted_notify(p_rid);
|
||||
visibility_notifier_owner.free(p_rid);
|
||||
} else if (particles_collision_instance_owner.owns(p_rid)) {
|
||||
particles_collision_instance_owner.free(p_rid);
|
||||
} else if (render_target_owner.owns(p_rid)) {
|
||||
|
|
|
@ -947,6 +947,17 @@ private:
|
|||
|
||||
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
|
||||
|
||||
/* visibility_notifier */
|
||||
|
||||
struct VisibilityNotifier {
|
||||
AABB aabb;
|
||||
Callable enter_callback;
|
||||
Callable exit_callback;
|
||||
Dependency dependency;
|
||||
};
|
||||
|
||||
mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
|
||||
|
||||
/* Skeleton */
|
||||
|
||||
struct Skeleton {
|
||||
|
@ -2253,6 +2264,14 @@ public:
|
|||
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
|
||||
RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
|
||||
|
||||
virtual RID visibility_notifier_allocate();
|
||||
virtual void visibility_notifier_initialize(RID p_notifier);
|
||||
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb);
|
||||
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable);
|
||||
|
||||
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
|
||||
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
|
||||
|
||||
//used from 2D and 3D
|
||||
virtual RID particles_collision_instance_create(RID p_collision);
|
||||
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
|
||||
|
|
|
@ -207,6 +207,7 @@ public:
|
|||
|
||||
virtual void update() = 0;
|
||||
virtual void render_probes() = 0;
|
||||
virtual void update_visibility_notifiers() = 0;
|
||||
|
||||
virtual bool free(RID p_rid) = 0;
|
||||
|
||||
|
|
|
@ -506,6 +506,9 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
|
|||
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
|
||||
RSG::storage->free(collision->instance);
|
||||
} break;
|
||||
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
|
||||
//none
|
||||
} break;
|
||||
case RS::INSTANCE_REFLECTION_PROBE: {
|
||||
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
|
||||
scene_render->free(reflection_probe->instance);
|
||||
|
@ -615,6 +618,11 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
|
|||
RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
|
||||
instance->base_data = collision;
|
||||
} break;
|
||||
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
|
||||
InstanceVisibilityNotifierData *vnd = memnew(InstanceVisibilityNotifierData);
|
||||
vnd->base = p_base;
|
||||
instance->base_data = vnd;
|
||||
} break;
|
||||
case RS::INSTANCE_REFLECTION_PROBE: {
|
||||
InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
|
||||
reflection_probe->owner = instance;
|
||||
|
@ -1549,6 +1557,9 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
|
|||
case RS::INSTANCE_VOXEL_GI: {
|
||||
idata.instance_data_rid = static_cast<InstanceVoxelGIData *>(p_instance->base_data)->probe_instance.get_id();
|
||||
} break;
|
||||
case RS::INSTANCE_VISIBLITY_NOTIFIER: {
|
||||
idata.visibility_notifier = static_cast<InstanceVisibilityNotifierData *>(p_instance->base_data);
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
@ -1758,6 +1769,9 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
|
|||
new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
|
||||
|
||||
} break;
|
||||
case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {
|
||||
new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
|
||||
} break;
|
||||
case RenderingServer::INSTANCE_LIGHT: {
|
||||
new_aabb = RSG::storage->light_get_aabb(p_instance->base);
|
||||
|
||||
|
@ -2613,6 +2627,15 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
|
|||
|
||||
} else if (base_type == RS::INSTANCE_LIGHTMAP) {
|
||||
cull_result.lightmaps.push_back(RID::from_uint64(idata.instance_data_rid));
|
||||
} else if (base_type == RS::INSTANCE_VISIBLITY_NOTIFIER) {
|
||||
InstanceVisibilityNotifierData *vnd = idata.visibility_notifier;
|
||||
if (!vnd->list_element.in_list()) {
|
||||
visible_notifier_list_lock.lock();
|
||||
visible_notifier_list.add(&vnd->list_element);
|
||||
visible_notifier_list_lock.unlock();
|
||||
vnd->just_visible = true;
|
||||
}
|
||||
vnd->visible_in_frame = RSG::rasterizer->get_frame_number();
|
||||
} else if (((1 << base_type) & RS::INSTANCE_GEOMETRY_MASK) && !(idata.flags & InstanceData::FLAG_CAST_SHADOWS_ONLY)) {
|
||||
bool keep = true;
|
||||
|
||||
|
@ -3849,6 +3872,28 @@ TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RI
|
|||
return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);
|
||||
}
|
||||
|
||||
void RendererSceneCull::update_visibility_notifiers() {
|
||||
SelfList<InstanceVisibilityNotifierData> *E = visible_notifier_list.first();
|
||||
while (E) {
|
||||
SelfList<InstanceVisibilityNotifierData> *N = E->next();
|
||||
|
||||
InstanceVisibilityNotifierData *visibility_notifier = E->self();
|
||||
if (visibility_notifier->just_visible) {
|
||||
visibility_notifier->just_visible = false;
|
||||
|
||||
RSG::storage->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);
|
||||
} else {
|
||||
if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {
|
||||
visible_notifier_list.remove(E);
|
||||
|
||||
RSG::storage->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);
|
||||
}
|
||||
}
|
||||
|
||||
E = N;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
/* Passthrough to Scene Render */
|
||||
/*******************************/
|
||||
|
|
|
@ -118,6 +118,8 @@ public:
|
|||
virtual void occluder_initialize(RID p_occluder);
|
||||
virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
|
||||
|
||||
/* VISIBILITY NOTIFIER API */
|
||||
|
||||
RendererSceneOcclusionCull *dummy_occlusion_culling;
|
||||
|
||||
/* SCENARIO API */
|
||||
|
@ -243,6 +245,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct InstanceVisibilityNotifierData;
|
||||
|
||||
struct InstanceData {
|
||||
// Store instance pointer as well as common instance processing information,
|
||||
// to make processing more cache friendly.
|
||||
|
@ -271,6 +275,7 @@ public:
|
|||
union {
|
||||
uint64_t instance_data_rid;
|
||||
RendererSceneRender::GeometryInstance *instance_geometry;
|
||||
InstanceVisibilityNotifierData *visibility_notifier;
|
||||
};
|
||||
Instance *instance = nullptr;
|
||||
int32_t parent_array_index = -1;
|
||||
|
@ -611,6 +616,18 @@ public:
|
|||
RID instance;
|
||||
};
|
||||
|
||||
struct InstanceVisibilityNotifierData : public InstanceBaseData {
|
||||
bool just_visible = false;
|
||||
uint64_t visible_in_frame = 0;
|
||||
RID base;
|
||||
SelfList<InstanceVisibilityNotifierData> list_element;
|
||||
InstanceVisibilityNotifierData() :
|
||||
list_element(this) {}
|
||||
};
|
||||
|
||||
SpinLock visible_notifier_list_lock;
|
||||
SelfList<InstanceVisibilityNotifierData>::List visible_notifier_list;
|
||||
|
||||
struct InstanceLightData : public InstanceBaseData {
|
||||
RID instance;
|
||||
uint64_t last_version;
|
||||
|
@ -1123,6 +1140,8 @@ public:
|
|||
|
||||
void set_scene_render(RendererSceneRender *p_scene_render);
|
||||
|
||||
virtual void update_visibility_notifiers();
|
||||
|
||||
RendererSceneCull();
|
||||
virtual ~RendererSceneCull();
|
||||
};
|
||||
|
|
|
@ -557,6 +557,14 @@ public:
|
|||
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
|
||||
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
|
||||
|
||||
virtual RID visibility_notifier_allocate() = 0;
|
||||
virtual void visibility_notifier_initialize(RID p_notifier) = 0;
|
||||
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
|
||||
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
|
||||
|
||||
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
|
||||
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
|
||||
|
||||
//used from 2D and 3D
|
||||
virtual RID particles_collision_instance_create(RID p_collision) = 0;
|
||||
virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
|
||||
|
|
|
@ -118,6 +118,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
|
|||
RSG::rasterizer->end_frame(p_swap_buffers);
|
||||
|
||||
RSG::canvas->update_visibility_notifiers();
|
||||
RSG::scene->update_visibility_notifiers();
|
||||
|
||||
while (frame_drawn_callbacks.front()) {
|
||||
Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
|
||||
|
|
|
@ -529,6 +529,12 @@ public:
|
|||
FUNC1(particles_collision_height_field_update, RID)
|
||||
FUNC2(particles_collision_set_height_field_resolution, RID, ParticlesCollisionHeightfieldResolution)
|
||||
|
||||
/* VISIBILITY_NOTIFIER */
|
||||
|
||||
FUNCRIDSPLIT(visibility_notifier)
|
||||
FUNC2(visibility_notifier_set_aabb, RID, const AABB &)
|
||||
FUNC3(visibility_notifier_set_callbacks, RID, const Callable &, const Callable &)
|
||||
|
||||
#undef server_name
|
||||
#undef ServerName
|
||||
//from now on, calls forwarded to this singleton
|
||||
|
@ -549,7 +555,7 @@ public:
|
|||
|
||||
/* OCCLUDER */
|
||||
FUNCRIDSPLIT(occluder)
|
||||
FUNC3(occluder_set_mesh, RID, const PackedVector3Array &, const PackedInt32Array &);
|
||||
FUNC3(occluder_set_mesh, RID, const PackedVector3Array &, const PackedInt32Array &)
|
||||
|
||||
#undef server_name
|
||||
#undef ServerName
|
||||
|
|
|
@ -722,6 +722,17 @@ public:
|
|||
|
||||
virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
|
||||
|
||||
/* VISIBILITY NOTIFIER API */
|
||||
|
||||
virtual RID visibility_notifier_create() = 0;
|
||||
virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
|
||||
virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
|
||||
|
||||
/* OCCLUDER API */
|
||||
|
||||
virtual RID occluder_create() = 0;
|
||||
virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) = 0;
|
||||
|
||||
/* CAMERA API */
|
||||
|
||||
virtual RID camera_create() = 0;
|
||||
|
@ -734,11 +745,6 @@ public:
|
|||
virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0;
|
||||
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
|
||||
|
||||
/* OCCLUDER API */
|
||||
|
||||
virtual RID occluder_create() = 0;
|
||||
virtual void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) = 0;
|
||||
|
||||
/* VIEWPORT TARGET API */
|
||||
|
||||
enum CanvasItemTextureFilter {
|
||||
|
@ -1148,6 +1154,7 @@ public:
|
|||
INSTANCE_VOXEL_GI,
|
||||
INSTANCE_LIGHTMAP,
|
||||
INSTANCE_OCCLUDER,
|
||||
INSTANCE_VISIBLITY_NOTIFIER,
|
||||
INSTANCE_MAX,
|
||||
|
||||
INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES)
|
||||
|
|
Loading…
Reference in a new issue