summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--doc/classes/XROrigin3D.xml3
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp23
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h2
-rw-r--r--editor/connections_dialog.cpp59
-rw-r--r--editor/connections_dialog.h3
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp16
-rw-r--r--modules/gdscript/gdscript_analyzer.h2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/class.gd4
-rw-r--r--modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out4
-rw-r--r--scene/3d/xr_nodes.cpp167
-rw-r--r--scene/3d/xr_nodes.h13
-rw-r--r--scene/resources/packed_scene.cpp6
-rw-r--r--scene/resources/packed_scene.h2
14 files changed, 226 insertions, 79 deletions
diff --git a/.gitignore b/.gitignore
index 1a83e4707e..b939bb16d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -154,6 +154,7 @@ gmon.out
# Jetbrains IDEs
.idea/
+.fleet/
# Kate
*.kate-swp
diff --git a/doc/classes/XROrigin3D.xml b/doc/classes/XROrigin3D.xml
index 7acee097e7..506d0fce41 100644
--- a/doc/classes/XROrigin3D.xml
+++ b/doc/classes/XROrigin3D.xml
@@ -13,6 +13,9 @@
<link title="XR documentation index">$DOCS_URL/tutorials/xr/index.html</link>
</tutorials>
<members>
+ <member name="current" type="bool" setter="set_current" getter="is_current" default="false">
+ Is this XROrigin3D node the current origin used by the [XRServer]?
+ </member>
<member name="world_scale" type="float" setter="set_world_scale" getter="get_world_scale" default="1.0">
Allows you to adjust the scale to your game's units. Most AR/VR platforms assume a scale of 1 game world unit = 1 real world meter.
[b]Note:[/b] This method is a passthrough to the [XRServer] itself.
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index fb90b776cf..d6636606d2 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -127,6 +127,11 @@ static bool default_capture_device_changed = false;
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
+#if defined(__GNUC__)
+// Workaround GCC warning from -Wcast-function-type.
+#define GetProcAddress (void *)GetProcAddress
+#endif
+
class CMMNotificationClient : public IMMNotificationClient {
LONG _cRef = 1;
IMMDeviceEnumerator *_pEnumerator = nullptr;
@@ -201,6 +206,20 @@ public:
static CMMNotificationClient notif_client;
+typedef const char *(CDECL *PWineGetVersionPtr)(void);
+
+bool AudioDriverWASAPI::is_running_on_wine() {
+ HMODULE nt_lib = LoadLibraryW(L"ntdll.dll");
+ if (!nt_lib) {
+ return false;
+ }
+
+ PWineGetVersionPtr wine_get_version = (PWineGetVersionPtr)GetProcAddress(nt_lib, "wine_get_version");
+ FreeLibrary(nt_lib);
+
+ return (bool)wine_get_version;
+}
+
Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_capture, bool reinit) {
WAVEFORMATEX *pwfex;
IMMDeviceEnumerator *enumerator = nullptr;
@@ -285,6 +304,10 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_c
}
using_audio_client_3 = !p_capture; // IID_IAudioClient3 is only used for adjustable output latency (not input)
+ if (using_audio_client_3 && is_running_on_wine()) {
+ using_audio_client_3 = false;
+ print_verbose("WASAPI: Wine detected, falling back to IAudioClient interface");
+ }
if (using_audio_client_3) {
hr = device->Activate(IID_IAudioClient3, CLSCTX_ALL, nullptr, (void **)&p_device->audio_client);
if (hr != S_OK) {
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index c30a54c042..e9f2794e97 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -79,6 +79,8 @@ class AudioDriverWASAPI : public AudioDriver {
SafeFlag exit_thread;
+ static bool is_running_on_wine();
+
static _FORCE_INLINE_ void write_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i, int32_t sample);
static _FORCE_INLINE_ int32_t read_sample(WORD format_tag, int bits_per_sample, BYTE *buffer, int i);
static void thread_func(void *p_udata);
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 2105a101d8..de7f5c8b88 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/scene_tree_dock.h"
#include "plugins/script_editor_plugin.h"
+#include "scene/resources/packed_scene.h"
static Node *_find_first_script(Node *p_root, Node *p_node) {
if (p_node != p_root && p_node->get_owner() != p_root) {
@@ -733,9 +734,11 @@ void ConnectionsDock::_disconnect_all() {
while (child) {
Connection connection = child->get_metadata(0);
- ConnectDialog::ConnectionData cd = connection;
- undo_redo->add_do_method(selected_node, "disconnect", cd.signal, cd.get_callable());
- undo_redo->add_undo_method(selected_node, "connect", cd.signal, cd.get_callable(), cd.binds, cd.flags);
+ if (!_is_connection_inherited(connection)) {
+ ConnectDialog::ConnectionData cd = connection;
+ undo_redo->add_do_method(selected_node, "disconnect", cd.signal, cd.get_callable());
+ undo_redo->add_undo_method(selected_node, "connect", cd.signal, cd.get_callable(), cd.binds, cd.flags);
+ }
child = child->get_next();
}
@@ -780,6 +783,26 @@ bool ConnectionsDock::_is_item_signal(TreeItem &p_item) {
return (p_item.get_parent() == tree->get_root() || p_item.get_parent()->get_parent() == tree->get_root());
}
+bool ConnectionsDock::_is_connection_inherited(Connection &p_connection) {
+ Node *scene_root = EditorNode::get_singleton()->get_edited_scene();
+ Ref<PackedScene> scn = ResourceLoader::load(scene_root->get_scene_file_path());
+ ERR_FAIL_NULL_V(scn, false);
+
+ Ref<SceneState> state = scn->get_state();
+ ERR_FAIL_NULL_V(state, false);
+
+ Node *source = Object::cast_to<Node>(p_connection.signal.get_object());
+ Node *target = Object::cast_to<Node>(p_connection.callable.get_object());
+
+ const NodePath source_path = scene_root->get_path_to(source);
+ const NodePath target_path = scene_root->get_path_to(target);
+ const StringName signal_name = p_connection.signal.get_name();
+ const StringName method_name = p_connection.callable.get_method();
+
+ // If it cannot be found in PackedScene, this connection was inherited.
+ return !state->has_connection(source_path, signal_name, target_path, method_name, true);
+}
+
/*
* Open connection dialog with TreeItem data to CREATE a brand-new connection.
*/
@@ -866,6 +889,19 @@ void ConnectionsDock::_handle_signal_menu_option(int p_option) {
}
}
+void ConnectionsDock::_signal_menu_about_to_popup() {
+ TreeItem *signal_item = tree->get_selected();
+
+ bool disable_disconnect_all = true;
+ for (int i = 0; i < signal_item->get_child_count(); i++) {
+ if (!signal_item->get_child(i)->has_meta("_inherited_connection")) {
+ disable_disconnect_all = false;
+ }
+ }
+
+ signal_menu->set_item_disabled(slot_menu->get_item_index(DISCONNECT_ALL), disable_disconnect_all);
+}
+
void ConnectionsDock::_handle_slot_menu_option(int p_option) {
TreeItem *item = tree->get_selected();
@@ -888,6 +924,13 @@ void ConnectionsDock::_handle_slot_menu_option(int p_option) {
}
}
+void ConnectionsDock::_slot_menu_about_to_popup() {
+ bool connection_is_inherited = tree->get_selected()->has_meta("_inherited_connection");
+
+ slot_menu->set_item_disabled(slot_menu->get_item_index(EDIT), connection_is_inherited);
+ slot_menu->set_item_disabled(slot_menu->get_item_index(DISCONNECT), connection_is_inherited);
+}
+
void ConnectionsDock::_rmb_pressed(Vector2 p_position, MouseButton p_button) {
if (p_button != MouseButton::RIGHT) {
return;
@@ -1001,7 +1044,7 @@ void ConnectionsDock::update_tree() {
name = base;
}
- if (!icon.is_valid()) {
+ if (icon.is_null()) {
icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons"));
}
@@ -1133,6 +1176,12 @@ void ConnectionsDock::update_tree() {
connection_item->set_text(0, path);
connection_item->set_metadata(0, connection);
connection_item->set_icon(0, get_theme_icon(SNAME("Slot"), SNAME("EditorIcons")));
+
+ if (_is_connection_inherited(connection)) {
+ // The scene inherits this connection.
+ connection_item->set_custom_color(0, get_theme_color(SNAME("warning_color"), SNAME("Editor")));
+ connection_item->set_meta("_inherited_connection", true);
+ }
}
}
@@ -1185,6 +1234,7 @@ ConnectionsDock::ConnectionsDock() {
signal_menu = memnew(PopupMenu);
add_child(signal_menu);
signal_menu->connect("id_pressed", callable_mp(this, &ConnectionsDock::_handle_signal_menu_option));
+ signal_menu->connect("about_to_popup", callable_mp(this, &ConnectionsDock::_signal_menu_about_to_popup));
signal_menu->add_item(TTR("Connect..."), CONNECT);
signal_menu->add_item(TTR("Disconnect All"), DISCONNECT_ALL);
signal_menu->add_item(TTR("Copy Name"), COPY_NAME);
@@ -1192,6 +1242,7 @@ ConnectionsDock::ConnectionsDock() {
slot_menu = memnew(PopupMenu);
add_child(slot_menu);
slot_menu->connect("id_pressed", callable_mp(this, &ConnectionsDock::_handle_slot_menu_option));
+ slot_menu->connect("about_to_popup", callable_mp(this, &ConnectionsDock::_slot_menu_about_to_popup));
slot_menu->add_item(TTR("Edit..."), EDIT);
slot_menu->add_item(TTR("Go to Method"), GO_TO_SCRIPT);
slot_menu->add_item(TTR("Disconnect"), DISCONNECT);
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 16a60306aa..126a0ca828 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -212,13 +212,16 @@ class ConnectionsDock : public VBoxContainer {
void _tree_item_selected();
void _tree_item_activated();
bool _is_item_signal(TreeItem &p_item);
+ bool _is_connection_inherited(Connection &p_connection);
void _open_connection_dialog(TreeItem &p_item);
void _open_connection_dialog(ConnectDialog::ConnectionData p_cd);
void _go_to_script(TreeItem &p_item);
void _handle_signal_menu_option(int p_option);
+ void _signal_menu_about_to_popup();
void _handle_slot_menu_option(int p_option);
+ void _slot_menu_about_to_popup();
void _rmb_pressed(Vector2 p_position, MouseButton p_button);
void _close();
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index e1beb2f374..b3ca8ff00a 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -1041,7 +1041,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
}
}
-void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node) {
+void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node, bool p_is_root) {
ERR_FAIL_COND_MSG(p_node == nullptr, "Trying to resolve type of a null node.");
switch (p_node->type) {
@@ -1114,7 +1114,7 @@ void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node) {
case GDScriptParser::Node::SUBSCRIPT:
case GDScriptParser::Node::TERNARY_OPERATOR:
case GDScriptParser::Node::UNARY_OPERATOR:
- reduce_expression(static_cast<GDScriptParser::ExpressionNode *>(p_node), true);
+ reduce_expression(static_cast<GDScriptParser::ExpressionNode *>(p_node), p_is_root);
break;
case GDScriptParser::Node::BREAK:
case GDScriptParser::Node::BREAKPOINT:
@@ -1411,7 +1411,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else?
p_for->variable->set_datatype(variable_type);
} else if (p_for->list) {
- resolve_node(p_for->list);
+ resolve_node(p_for->list, false);
if (p_for->list->datatype.has_container_element_type()) {
variable_type = p_for->list->datatype.get_container_element_type();
variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
@@ -1439,7 +1439,7 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
}
void GDScriptAnalyzer::resolve_while(GDScriptParser::WhileNode *p_while) {
- resolve_node(p_while->condition);
+ resolve_node(p_while->condition, false);
resolve_suite(p_while->loop);
p_while->set_datatype(p_while->loop->get_datatype());
@@ -1824,7 +1824,7 @@ void GDScriptAnalyzer::reduce_expression(GDScriptParser::ExpressionNode *p_expre
reduce_binary_op(static_cast<GDScriptParser::BinaryOpNode *>(p_expression));
break;
case GDScriptParser::Node::CALL:
- reduce_call(static_cast<GDScriptParser::CallNode *>(p_expression), p_is_root);
+ reduce_call(static_cast<GDScriptParser::CallNode *>(p_expression), false, p_is_root);
break;
case GDScriptParser::Node::CAST:
reduce_cast(static_cast<GDScriptParser::CastNode *>(p_expression));
@@ -2548,6 +2548,12 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
mark_lambda_use_self();
}
+#ifdef DEBUG_ENABLED
+ if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) {
+ parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
+ }
+#endif // DEBUG_ENABLED
+
call_type = return_type;
} else {
bool found = false;
diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h
index 3966b81b6e..217a856ce0 100644
--- a/modules/gdscript/gdscript_analyzer.h
+++ b/modules/gdscript/gdscript_analyzer.h
@@ -63,7 +63,7 @@ class GDScriptAnalyzer {
void resolve_class_body(GDScriptParser::ClassNode *p_class);
void resolve_function_signature(GDScriptParser::FunctionNode *p_function);
void resolve_function_body(GDScriptParser::FunctionNode *p_function);
- void resolve_node(GDScriptParser::Node *p_node);
+ void resolve_node(GDScriptParser::Node *p_node, bool p_is_root = true);
void resolve_suite(GDScriptParser::SuiteNode *p_suite);
void resolve_if(GDScriptParser::IfNode *p_if);
void resolve_for(GDScriptParser::ForNode *p_for);
diff --git a/modules/gdscript/tests/scripts/parser/features/class.gd b/modules/gdscript/tests/scripts/parser/features/class.gd
index 6652f85ad9..af24b32322 100644
--- a/modules/gdscript/tests/scripts/parser/features/class.gd
+++ b/modules/gdscript/tests/scripts/parser/features/class.gd
@@ -21,5 +21,5 @@ func test():
assert(test_sub.number == 25) # From Test.
assert(test_sub.other_string == "bye") # From TestSub.
- TestConstructor.new()
- TestConstructor.new(500)
+ var _test_constructor = TestConstructor.new()
+ _test_constructor = TestConstructor.new(500)
diff --git a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
index d73c5eb7cd..13f759dd46 100644
--- a/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
+++ b/modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out
@@ -1 +1,5 @@
GDTEST_OK
+>> WARNING
+>> Line: 6
+>> RETURN_VALUE_DISCARDED
+>> The function 'i_return_int()' returns a value, but this value is never used.
diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp
index 4401d22f30..fe4ccbc7dc 100644
--- a/scene/3d/xr_nodes.cpp
+++ b/scene/3d/xr_nodes.cpp
@@ -36,49 +36,37 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
-void XRCamera3D::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_ENTER_TREE: {
- // need to find our XROrigin3D parent and let it know we're its camera!
- XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
- if (origin != nullptr) {
- origin->set_tracked_camera(this);
- }
- } break;
+void XRCamera3D::_bind_tracker() {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL(xr_server);
- case NOTIFICATION_EXIT_TREE: {
- // need to find our XROrigin3D parent and let it know we're no longer its camera!
- XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent());
- if (origin != nullptr && origin->get_tracked_camera() == this) {
- origin->set_tracked_camera(nullptr);
- }
- } break;
+ tracker = xr_server->get_tracker(tracker_name);
+ if (tracker.is_valid()) {
+ tracker->connect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
+
+ Ref<XRPose> pose = tracker->get_pose(pose_name);
+ if (pose.is_valid()) {
+ set_transform(pose->get_adjusted_transform());
+ }
}
}
+void XRCamera3D::_unbind_tracker() {
+ if (tracker.is_valid()) {
+ tracker->disconnect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
+ }
+ tracker.unref();
+}
+
void XRCamera3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) {
if (p_tracker_name == tracker_name) {
- XRServer *xr_server = XRServer::get_singleton();
- ERR_FAIL_NULL(xr_server);
-
- tracker = xr_server->get_tracker(p_tracker_name);
- if (tracker.is_valid()) {
- tracker->connect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
-
- Ref<XRPose> pose = tracker->get_pose(pose_name);
- if (pose.is_valid()) {
- set_transform(pose->get_adjusted_transform());
- }
- }
+ _bind_tracker();
}
}
void XRCamera3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) {
if (p_tracker_name == tracker_name) {
- if (tracker.is_valid()) {
- tracker->disconnect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed));
- }
- tracker.unref();
+ _unbind_tracker();
}
}
@@ -213,6 +201,9 @@ XRCamera3D::XRCamera3D() {
xr_server->connect("tracker_added", callable_mp(this, &XRCamera3D::_changed_tracker));
xr_server->connect("tracker_updated", callable_mp(this, &XRCamera3D::_changed_tracker));
xr_server->connect("tracker_removed", callable_mp(this, &XRCamera3D::_removed_tracker));
+
+ // check if our tracker already exists and if so, bind it...
+ _bind_tracker();
}
XRCamera3D::~XRCamera3D() {
@@ -582,11 +573,22 @@ Plane XRAnchor3D::get_plane() const {
////////////////////////////////////////////////////////////////////////////////////////////////////
+Vector<XROrigin3D *> XROrigin3D::origin_nodes;
+
PackedStringArray XROrigin3D::get_configuration_warnings() const {
PackedStringArray warnings = Node::get_configuration_warnings();
if (is_visible() && is_inside_tree()) {
- if (tracked_camera == nullptr) {
+ bool has_camera = false;
+ for (int i = 0; !has_camera && i < get_child_count(); i++) {
+ XRCamera3D *camera = Object::cast_to<XRCamera3D>(get_child(i));
+ if (camera) {
+ // found it!
+ has_camera = true;
+ }
+ }
+
+ if (!has_camera) {
warnings.push_back(RTR("XROrigin3D requires an XRCamera3D child node."));
}
}
@@ -603,14 +605,10 @@ void XROrigin3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &XROrigin3D::set_world_scale);
ClassDB::bind_method(D_METHOD("get_world_scale"), &XROrigin3D::get_world_scale);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale");
-}
-void XROrigin3D::set_tracked_camera(XRCamera3D *p_tracked_camera) {
- tracked_camera = p_tracked_camera;
-}
-
-XRCamera3D *XROrigin3D::get_tracked_camera() const {
- return tracked_camera;
+ ClassDB::bind_method(D_METHOD("set_current", "enabled"), &XROrigin3D::set_current);
+ ClassDB::bind_method(D_METHOD("is_current"), &XROrigin3D::is_current);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
}
real_t XROrigin3D::get_world_scale() const {
@@ -629,6 +627,44 @@ void XROrigin3D::set_world_scale(real_t p_world_scale) {
xr_server->set_world_scale(p_world_scale);
}
+void XROrigin3D::set_current(bool p_enabled) {
+ current = p_enabled;
+
+ if (!is_inside_tree() || Engine::get_singleton()->is_editor_hint()) {
+ return;
+ }
+
+ // Notify us of any transform changes
+ set_notify_local_transform(current);
+ set_notify_transform(current);
+
+ if (current) {
+ for (int i = 0; i < origin_nodes.size(); i++) {
+ if (origin_nodes[i] != this) {
+ origin_nodes[i]->set_current(false);
+ }
+ }
+ } else {
+ bool found = false;
+ // We no longer have a current origin so find the first one we can make current
+ for (int i = 0; !found && i < origin_nodes.size(); i++) {
+ if (origin_nodes[i] != this) {
+ origin_nodes[i]->set_current(true);
+ found = true;
+ }
+ }
+ }
+}
+
+bool XROrigin3D::is_current() const {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // return as is
+ return current;
+ } else {
+ return current && is_inside_tree();
+ }
+}
+
void XROrigin3D::_notification(int p_what) {
// get our XRServer
XRServer *xr_server = XRServer::get_singleton();
@@ -636,34 +672,47 @@ void XROrigin3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- set_process_internal(true);
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ if (origin_nodes.is_empty()) {
+ // first entry always becomes current
+ current = true;
+ }
+
+ origin_nodes.push_back(this);
+
+ if (current) {
+ // set this again so we do whatever setup is needed.
+ set_current(true);
+ }
+ }
} break;
case NOTIFICATION_EXIT_TREE: {
- set_process_internal(false);
- } break;
-
- case NOTIFICATION_INTERNAL_PROCESS: {
- // set our world origin to our node transform
- xr_server->set_world_origin(get_global_transform());
+ if (!Engine::get_singleton()->is_editor_hint()) {
+ origin_nodes.erase(this);
- // check if we have a primary interface
- Ref<XRInterface> xr_interface = xr_server->get_primary_interface();
- if (xr_interface.is_valid() && tracked_camera != nullptr) {
- // get our positioning transform for our headset
- Transform3D t = xr_interface->get_camera_transform();
+ if (current) {
+ // We are no longer current
+ set_current(false);
+ }
+ }
+ } break;
- // now apply this to our camera
- tracked_camera->set_transform(t);
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED:
+ case NOTIFICATION_TRANSFORM_CHANGED: {
+ if (current && !Engine::get_singleton()->is_editor_hint()) {
+ xr_server->set_world_origin(get_global_transform());
}
} break;
}
- // send our notification to all active XE interfaces, they may need to react to it also
- for (int i = 0; i < xr_server->get_interface_count(); i++) {
- Ref<XRInterface> interface = xr_server->get_interface(i);
- if (interface.is_valid() && interface->is_initialized()) {
- interface->notification(p_what);
+ if (current) {
+ // send our notification to all active XE interfaces, they may need to react to it also
+ for (int i = 0; i < xr_server->get_interface_count(); i++) {
+ Ref<XRInterface> interface = xr_server->get_interface(i);
+ if (interface.is_valid() && interface->is_initialized()) {
+ interface->notification(p_what);
+ }
}
}
}
diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h
index ef846cc3a3..990fb61983 100644
--- a/scene/3d/xr_nodes.h
+++ b/scene/3d/xr_nodes.h
@@ -48,8 +48,8 @@ protected:
StringName pose_name = "default";
Ref<XRPositionalTracker> tracker;
- void _notification(int p_what);
-
+ void _bind_tracker();
+ void _unbind_tracker();
void _changed_tracker(const StringName p_tracker_name, int p_tracker_type);
void _removed_tracker(const StringName p_tracker_name, int p_tracker_type);
void _pose_changed(const Ref<XRPose> &p_pose);
@@ -180,7 +180,8 @@ class XROrigin3D : public Node3D {
GDCLASS(XROrigin3D, Node3D);
private:
- XRCamera3D *tracked_camera = nullptr;
+ bool current = false;
+ static Vector<XROrigin3D *> origin_nodes; // all origin nodes in tree
protected:
void _notification(int p_what);
@@ -189,12 +190,12 @@ protected:
public:
PackedStringArray get_configuration_warnings() const override;
- void set_tracked_camera(XRCamera3D *p_tracked_camera);
- XRCamera3D *get_tracked_camera() const;
-
real_t get_world_scale() const;
void set_world_scale(real_t p_world_scale);
+ void set_current(bool p_enabled);
+ bool is_current() const;
+
XROrigin3D() {}
~XROrigin3D() {}
};
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 1f71d583b1..1c99fa5554 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -1546,7 +1546,7 @@ Array SceneState::get_connection_binds(int p_idx) const {
return binds;
}
-bool SceneState::has_connection(const NodePath &p_node_from, const StringName &p_signal, const NodePath &p_node_to, const StringName &p_method) {
+bool SceneState::has_connection(const NodePath &p_node_from, const StringName &p_signal, const NodePath &p_node_to, const StringName &p_method, bool p_no_inheritance) {
// this method cannot be const because of this
Ref<SceneState> ss = this;
@@ -1578,6 +1578,10 @@ bool SceneState::has_connection(const NodePath &p_node_from, const StringName &p
}
}
+ if (p_no_inheritance) {
+ break;
+ }
+
ss = ss->get_base_scene_state();
} while (ss.is_valid());
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index 8e1a1d29b6..c6f82ddd5e 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -176,7 +176,7 @@ public:
int get_connection_unbinds(int p_idx) const;
Array get_connection_binds(int p_idx) const;
- bool has_connection(const NodePath &p_node_from, const StringName &p_signal, const NodePath &p_node_to, const StringName &p_method);
+ bool has_connection(const NodePath &p_node_from, const StringName &p_signal, const NodePath &p_node_to, const StringName &p_method, bool p_no_inheritance = false);
Vector<NodePath> get_editable_instances() const;