summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/core_bind.cpp26
-rw-r--r--core/core_bind.h5
-rw-r--r--core/debugger/remote_debugger_peer.cpp12
-rw-r--r--core/debugger/remote_debugger_peer.h2
-rw-r--r--core/io/file_access_network.cpp11
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/http_client.cpp6
-rw-r--r--core/io/ip.cpp24
-rw-r--r--core/io/resource_format_binary.cpp10
-rw-r--r--core/io/resource_loader.cpp5
-rw-r--r--core/math/aabb.h8
-rw-r--r--core/math/color.cpp47
-rw-r--r--core/math/color.h12
-rw-r--r--core/os/thread.cpp81
-rw-r--r--core/os/thread.h71
-rw-r--r--core/os/thread_dummy.cpp41
-rw-r--r--core/os/thread_dummy.h47
-rw-r--r--core/os/threaded_array_processor.h15
-rw-r--r--core/string/ustring.cpp104
-rw-r--r--core/string/ustring.h13
-rw-r--r--core/templates/thread_work_pool.cpp16
-rw-r--r--core/templates/thread_work_pool.h6
-rw-r--r--core/variant/variant_call.cpp14
-rw-r--r--doc/classes/ArrayMesh.xml2
-rw-r--r--doc/classes/HTTPClient.xml2
-rw-r--r--doc/classes/HTTPRequest.xml2
-rw-r--r--doc/classes/LineEdit.xml6
-rw-r--r--doc/classes/Material.xml6
-rw-r--r--doc/classes/OS.xml16
-rw-r--r--doc/classes/PopupMenu.xml6
-rw-r--r--doc/classes/ProjectSettings.xml16
-rw-r--r--doc/classes/RenderingDevice.xml106
-rw-r--r--doc/classes/RenderingServer.xml2
-rw-r--r--doc/classes/RichTextLabel.xml6
-rw-r--r--doc/classes/String.xml113
-rw-r--r--doc/classes/TabContainer.xml6
-rw-r--r--doc/classes/Tabs.xml6
-rw-r--r--doc/classes/TileMap.xml2
-rw-r--r--doc/classes/TreeItem.xml12
-rw-r--r--doc/classes/Viewport.xml14
-rw-r--r--doc/classes/VisualShaderNodeSDFRaymarch.xml4
-rw-r--r--drivers/alsa/audio_driver_alsa.cpp17
-rw-r--r--drivers/alsa/audio_driver_alsa.h2
-rw-r--r--drivers/alsamidi/midi_driver_alsamidi.cpp13
-rw-r--r--drivers/alsamidi/midi_driver_alsamidi.h2
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.cpp16
-rw-r--r--drivers/pulseaudio/audio_driver_pulseaudio.h2
-rw-r--r--drivers/unix/dir_access_unix.cpp2
-rw-r--r--drivers/unix/os_unix.cpp9
-rw-r--r--drivers/unix/thread_posix.cpp96
-rw-r--r--drivers/unix/thread_posix.h38
-rw-r--r--drivers/wasapi/audio_driver_wasapi.cpp11
-rw-r--r--drivers/wasapi/audio_driver_wasapi.h2
-rw-r--r--drivers/windows/thread_windows.cpp88
-rw-r--r--drivers/windows/thread_windows.h67
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.cpp14
-rw-r--r--drivers/xaudio2/audio_driver_xaudio2.h2
-rw-r--r--editor/audio_stream_preview.cpp6
-rw-r--r--editor/editor_data.cpp10
-rw-r--r--editor/editor_data.h1
-rw-r--r--editor/editor_file_system.cpp33
-rw-r--r--editor/editor_file_system.h4
-rw-r--r--editor/editor_node.cpp8
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_resource_preview.cpp11
-rw-r--r--editor/editor_resource_preview.h2
-rw-r--r--editor/fileserver/editor_file_server.cpp12
-rw-r--r--editor/fileserver/editor_file_server.h4
-rw-r--r--editor/import/collada.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp2
-rw-r--r--main/main.cpp123
-rw-r--r--modules/bullet/bullet_physics_server.cpp32
-rw-r--r--modules/bullet/bullet_physics_server.h32
-rw-r--r--modules/bullet/rigid_body_bullet.cpp14
-rw-r--r--modules/bullet/rigid_body_bullet.h12
-rw-r--r--modules/bullet/shape_bullet.cpp10
-rw-r--r--modules/bullet/space_bullet.cpp12
-rw-r--r--modules/bullet/space_bullet.h10
-rw-r--r--modules/cvtt/image_compress_cvtt.cpp5
-rw-r--r--modules/gdnative/android/android_gdn.cpp2
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp412
-rw-r--r--modules/gdnative/nativescript/api_generator.h1
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp9
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp10
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.h2
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs98
-rw-r--r--modules/mono/mono_gd/support/android_support.cpp18
-rw-r--r--modules/opensimplex/noise_texture.cpp16
-rw-r--r--modules/opensimplex/noise_texture.h2
-rw-r--r--modules/theora/video_stream_theora.cpp7
-rw-r--r--modules/theora/video_stream_theora.h2
-rw-r--r--modules/webxr/doc_classes/WebXRInterface.xml122
-rw-r--r--modules/webxr/godot_webxr.h1
-rw-r--r--modules/webxr/native/library_godot_webxr.js23
-rw-r--r--modules/webxr/webxr_interface_js.cpp31
-rw-r--r--modules/webxr/webxr_interface_js.h2
-rw-r--r--platform/android/api/jni_singleton.h2
-rw-r--r--platform/android/audio_driver_jandroid.cpp8
-rw-r--r--platform/android/dir_access_jandroid.cpp14
-rw-r--r--platform/android/export/export.cpp7
-rw-r--r--platform/android/java_class_wrapper.cpp6
-rw-r--r--platform/android/java_godot_io_wrapper.cpp26
-rw-r--r--platform/android/java_godot_lib_jni.cpp8
-rw-r--r--platform/android/java_godot_view_wrapper.cpp8
-rw-r--r--platform/android/java_godot_wrapper.cpp42
-rw-r--r--platform/android/net_socket_android.cpp6
-rw-r--r--platform/android/string_android.h4
-rw-r--r--platform/android/thread_jandroid.cpp115
-rw-r--r--platform/android/thread_jandroid.h42
-rw-r--r--platform/iphone/export/export.cpp7
-rw-r--r--platform/javascript/audio_driver_javascript.cpp6
-rw-r--r--platform/javascript/audio_driver_javascript.h2
-rw-r--r--platform/javascript/detect.py11
-rw-r--r--platform/javascript/export/export.cpp7
-rw-r--r--platform/linuxbsd/display_server_x11.cpp8
-rw-r--r--platform/linuxbsd/display_server_x11.h2
-rw-r--r--platform/linuxbsd/joypad_linux.cpp24
-rw-r--r--platform/linuxbsd/joypad_linux.h2
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp2
-rw-r--r--platform/uwp/os_uwp.cpp3
-rw-r--r--platform/uwp/thread_uwp.cpp61
-rw-r--r--platform/uwp/thread_uwp.h59
-rw-r--r--platform/windows/os_windows.cpp3
-rw-r--r--scene/3d/navigation_region_3d.cpp7
-rw-r--r--scene/3d/navigation_region_3d.h2
-rw-r--r--scene/3d/visibility_notifier_3d.cpp9
-rw-r--r--scene/3d/visibility_notifier_3d.h2
-rw-r--r--scene/main/http_request.cpp8
-rw-r--r--scene/main/http_request.h2
-rw-r--r--scene/resources/default_theme/default_theme.cpp4
-rw-r--r--servers/audio/audio_driver_dummy.cpp17
-rw-r--r--servers/audio/audio_driver_dummy.h2
-rw-r--r--servers/audio/effects/audio_effect_record.cpp6
-rw-r--r--servers/audio/effects/audio_effect_record.h2
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h6
-rw-r--r--servers/physics_2d/physics_server_2d_sw.cpp4
-rw-r--r--servers/physics_2d/physics_server_2d_sw.h4
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.cpp12
-rw-r--r--servers/physics_2d/physics_server_2d_wrap_mt.h6
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp16
-rw-r--r--servers/physics_2d/space_2d_sw.cpp8
-rw-r--r--servers/physics_3d/body_3d_sw.h2
-rw-r--r--servers/physics_3d/physics_server_3d_sw.cpp2
-rw-r--r--servers/physics_3d/physics_server_3d_sw.h2
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp10
-rw-r--r--servers/physics_3d/space_3d_sw.cpp6
-rw-r--r--servers/physics_server_2d.cpp10
-rw-r--r--servers/physics_server_2d.h48
-rw-r--r--servers/physics_server_3d.cpp12
-rw-r--r--servers/physics_server_3d.h56
-rw-r--r--servers/rendering/rendering_device.cpp4
-rw-r--r--servers/rendering/rendering_server_wrap_mt.cpp10
-rw-r--r--servers/rendering/rendering_server_wrap_mt.h2
-rw-r--r--servers/rendering/shader_language.cpp2
-rw-r--r--tests/test_command_queue.h16
-rw-r--r--tests/test_object.h213
-rw-r--r--tests/test_physics_3d.cpp14
-rw-r--r--tests/test_string.h21
160 files changed, 1757 insertions, 1672 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 99c68eb433..456a97e5e5 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1995,24 +1995,13 @@ Error _Thread::start(Object *p_instance, const StringName &p_method, const Varia
Thread::Settings s;
s.priority = (Thread::Priority)p_priority;
- thread = Thread::create(_start_func, ud, s);
- if (!thread) {
- active = false;
- target_method = StringName();
- target_instance = nullptr;
- userdata = Variant();
- return ERR_CANT_CREATE;
- }
+ thread.start(_start_func, ud, s);
return OK;
}
String _Thread::get_id() const {
- if (!thread) {
- return String();
- }
-
- return itos(thread->get_id());
+ return itos(thread.get_id());
}
bool _Thread::is_active() const {
@@ -2020,18 +2009,13 @@ bool _Thread::is_active() const {
}
Variant _Thread::wait_to_finish() {
- ERR_FAIL_COND_V_MSG(!thread, Variant(), "Thread must exist to wait for its completion.");
ERR_FAIL_COND_V_MSG(!active, Variant(), "Thread must be active to wait for its completion.");
- Thread::wait_to_finish(thread);
+ thread.wait_to_finish();
Variant r = ret;
active = false;
target_method = StringName();
target_instance = nullptr;
userdata = Variant();
- if (thread) {
- memdelete(thread);
- }
- thread = nullptr;
return r;
}
@@ -2047,10 +2031,6 @@ void _Thread::_bind_methods() {
BIND_ENUM_CONSTANT(PRIORITY_HIGH);
}
-_Thread::~_Thread() {
- ERR_FAIL_COND_MSG(active, "Reference to a Thread object was lost while the thread is still running...");
-}
-
////// _ClassDB //////
PackedStringArray _ClassDB::get_class_list() const {
diff --git a/core/core_bind.h b/core/core_bind.h
index 0fe5d9c80c..3305c93089 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -554,7 +554,7 @@ protected:
volatile bool active = false;
Object *target_instance = nullptr;
StringName target_method;
- Thread *thread = nullptr;
+ Thread thread;
static void _bind_methods();
static void _start_func(void *ud);
@@ -570,9 +570,6 @@ public:
String get_id() const;
bool is_active() const;
Variant wait_to_finish();
-
- _Thread() {}
- ~_Thread();
};
VARIANT_ENUM_CAST(_Thread::Priority);
diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp
index 2e388d5934..857e3af268 100644
--- a/core/debugger/remote_debugger_peer.cpp
+++ b/core/debugger/remote_debugger_peer.cpp
@@ -65,12 +65,8 @@ int RemoteDebuggerPeerTCP::get_max_message_size() const {
}
void RemoteDebuggerPeerTCP::close() {
- if (thread) {
- running = false;
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = nullptr;
- }
+ running = false;
+ thread.wait_to_finish();
tcp_client->disconnect_from_host();
out_buf.resize(0);
in_buf.resize(0);
@@ -85,7 +81,7 @@ RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp) {
connected = true;
#ifndef NO_THREADS
running = true;
- thread = Thread::create(_thread_func, this);
+ thread.start(_thread_func, this);
#endif
} else {
tcp_client.instance();
@@ -188,7 +184,7 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
connected = true;
#ifndef NO_THREADS
running = true;
- thread = Thread::create(_thread_func, this);
+ thread.start(_thread_func, this);
#endif
return OK;
}
diff --git a/core/debugger/remote_debugger_peer.h b/core/debugger/remote_debugger_peer.h
index c759c65568..652e2d9d20 100644
--- a/core/debugger/remote_debugger_peer.h
+++ b/core/debugger/remote_debugger_peer.h
@@ -58,7 +58,7 @@ class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
private:
Ref<StreamPeerTCP> tcp_client;
Mutex mutex;
- Thread *thread = nullptr;
+ Thread thread;
List<Array> in_queue;
List<Array> out_queue;
int out_left = 0;
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 1d9aa846eb..97838fd14c 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -201,7 +201,7 @@ Error FileAccessNetworkClient::connect(const String &p_host, int p_port, const S
return ERR_INVALID_PARAMETER;
}
- thread = Thread::create(_thread_func, this);
+ thread.start(_thread_func, this);
return OK;
}
@@ -214,12 +214,9 @@ FileAccessNetworkClient::FileAccessNetworkClient() {
}
FileAccessNetworkClient::~FileAccessNetworkClient() {
- if (thread) {
- quit = true;
- sem.post();
- Thread::wait_to_finish(thread);
- memdelete(thread);
- }
+ quit = true;
+ sem.post();
+ thread.wait_to_finish();
}
void FileAccessNetwork::_set_block(int p_offset, const Vector<uint8_t> &p_block) {
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 6aec2869fc..1f5de3e5dd 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -48,7 +48,7 @@ class FileAccessNetworkClient {
List<BlockRequest> block_requests;
Semaphore sem;
- Thread *thread = nullptr;
+ Thread thread;
bool quit = false;
Mutex mutex;
Mutex blockrequest_mutex;
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index a2fcf074ae..18afdc678e 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -736,14 +736,14 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
String query = "";
Array keys = p_dict.keys();
for (int i = 0; i < keys.size(); ++i) {
- String encoded_key = String(keys[i]).http_escape();
+ String encoded_key = String(keys[i]).uri_encode();
Variant value = p_dict[keys[i]];
switch (value.get_type()) {
case Variant::ARRAY: {
// Repeat the key with every values
Array values = value;
for (int j = 0; j < values.size(); ++j) {
- query += "&" + encoded_key + "=" + String(values[j]).http_escape();
+ query += "&" + encoded_key + "=" + String(values[j]).uri_encode();
}
break;
}
@@ -754,7 +754,7 @@ String HTTPClient::query_string_from_dict(const Dictionary &p_dict) {
}
default: {
// Add the key-value pair
- query += "&" + encoded_key + "=" + String(value).http_escape();
+ query += "&" + encoded_key + "=" + String(value).uri_encode();
}
}
}
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 6fb812e78d..df95785000 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -71,7 +71,7 @@ struct _IP_ResolverPrivate {
Mutex mutex;
Semaphore sem;
- Thread *thread;
+ Thread thread;
//Semaphore* semaphore;
bool thread_abort;
@@ -141,7 +141,7 @@ IP::ResolverID IP::resolve_hostname_queue_item(const String &p_hostname, IP::Typ
} else {
resolver->queue[id].response = IP_Address();
resolver->queue[id].status = IP::RESOLVER_STATUS_WAITING;
- if (resolver->thread) {
+ if (resolver->thread.is_started()) {
resolver->sem.post();
} else {
resolver->resolve_queues();
@@ -285,26 +285,14 @@ IP::IP() {
singleton = this;
resolver = memnew(_IP_ResolverPrivate);
-#ifndef NO_THREADS
-
resolver->thread_abort = false;
-
- resolver->thread = Thread::create(_IP_ResolverPrivate::_thread_function, resolver);
-#else
- resolver->thread = nullptr;
-#endif
+ resolver->thread.start(_IP_ResolverPrivate::_thread_function, resolver);
}
IP::~IP() {
-#ifndef NO_THREADS
- if (resolver->thread) {
- resolver->thread_abort = true;
- resolver->sem.post();
- Thread::wait_to_finish(resolver->thread);
- memdelete(resolver->thread);
- }
-
-#endif
+ resolver->thread_abort = true;
+ resolver->sem.post();
+ resolver->thread.wait_to_finish();
memdelete(resolver);
}
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index ae4643a19f..fad58d65fd 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -261,11 +261,11 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
r_v = v;
} break;
case VARIANT_COLOR: {
- Color v;
- v.r = f->get_real();
- v.g = f->get_real();
- v.b = f->get_real();
- v.a = f->get_real();
+ Color v; // Colors should always be in single-precision.
+ v.r = f->get_float();
+ v.g = f->get_float();
+ v.b = f->get_float();
+ v.a = f->get_float();
r_v = v;
} break;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 1a2b1ed033..d66511a39f 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -362,7 +362,8 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
print_lt("REQUEST: load count: " + itos(thread_loading_count) + " / wait count: " + itos(thread_waiting_count) + " / suspended count: " + itos(thread_suspended_count) + " / active: " + itos(thread_loading_count - thread_suspended_count));
- load_task.thread = Thread::create(_thread_load_function, &thread_load_tasks[local_path]);
+ load_task.thread = memnew(Thread);
+ load_task.thread->start(_thread_load_function, &thread_load_tasks[local_path]);
load_task.loader_id = load_task.thread->get_id();
}
@@ -489,7 +490,7 @@ RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
if (load_task.requests == 0) {
if (load_task.thread) { //thread may not have been used
- Thread::wait_to_finish(load_task.thread);
+ load_task.thread->wait_to_finish();
memdelete(load_task.thread);
}
thread_load_tasks.erase(local_path);
diff --git a/core/math/aabb.h b/core/math/aabb.h
index 2861358e32..e16246902a 100644
--- a/core/math/aabb.h
+++ b/core/math/aabb.h
@@ -107,8 +107,8 @@ public:
Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const;
Variant intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const;
- _FORCE_INLINE_ void quantize(float p_unit);
- _FORCE_INLINE_ AABB quantized(float p_unit) const;
+ _FORCE_INLINE_ void quantize(real_t p_unit);
+ _FORCE_INLINE_ AABB quantized(real_t p_unit) const;
_FORCE_INLINE_ void set_end(const Vector3 &p_end) {
size = p_end - position;
@@ -430,7 +430,7 @@ void AABB::grow_by(real_t p_amount) {
size.z += 2.0 * p_amount;
}
-void AABB::quantize(float p_unit) {
+void AABB::quantize(real_t p_unit) {
size += position;
position.x -= Math::fposmodp(position.x, p_unit);
@@ -448,7 +448,7 @@ void AABB::quantize(float p_unit) {
size -= position;
}
-AABB AABB::quantized(float p_unit) const {
+AABB AABB::quantized(real_t p_unit) const {
AABB ret = *this;
ret.quantize(p_unit);
return ret;
diff --git a/core/math/color.cpp b/core/math/color.cpp
index 588aedf821..0398d43838 100644
--- a/core/math/color.cpp
+++ b/core/math/color.cpp
@@ -544,12 +544,12 @@ Color Color::operator*(const Color &p_color) const {
a * p_color.a);
}
-Color Color::operator*(real_t p_rvalue) const {
+Color Color::operator*(float p_scalar) const {
return Color(
- r * p_rvalue,
- g * p_rvalue,
- b * p_rvalue,
- a * p_rvalue);
+ r * p_scalar,
+ g * p_scalar,
+ b * p_scalar,
+ a * p_scalar);
}
void Color::operator*=(const Color &p_color) {
@@ -559,11 +559,11 @@ void Color::operator*=(const Color &p_color) {
a = a * p_color.a;
}
-void Color::operator*=(real_t p_rvalue) {
- r = r * p_rvalue;
- g = g * p_rvalue;
- b = b * p_rvalue;
- a = a * p_rvalue;
+void Color::operator*=(float p_scalar) {
+ r = r * p_scalar;
+ g = g * p_scalar;
+ b = b * p_scalar;
+ a = a * p_scalar;
}
Color Color::operator/(const Color &p_color) const {
@@ -574,12 +574,12 @@ Color Color::operator/(const Color &p_color) const {
a / p_color.a);
}
-Color Color::operator/(real_t p_rvalue) const {
+Color Color::operator/(float p_scalar) const {
return Color(
- r / p_rvalue,
- g / p_rvalue,
- b / p_rvalue,
- a / p_rvalue);
+ r / p_scalar,
+ g / p_scalar,
+ b / p_scalar,
+ a / p_scalar);
}
void Color::operator/=(const Color &p_color) {
@@ -589,18 +589,11 @@ void Color::operator/=(const Color &p_color) {
a = a / p_color.a;
}
-void Color::operator/=(real_t p_rvalue) {
- if (p_rvalue == 0) {
- r = 1.0;
- g = 1.0;
- b = 1.0;
- a = 1.0;
- } else {
- r = r / p_rvalue;
- g = g / p_rvalue;
- b = b / p_rvalue;
- a = a / p_rvalue;
- }
+void Color::operator/=(float p_scalar) {
+ r = r / p_scalar;
+ g = g / p_scalar;
+ b = b / p_scalar;
+ a = a / p_scalar;
}
Color Color::operator-() const {
diff --git a/core/math/color.h b/core/math/color.h
index 779f770761..d3b27a9c65 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -78,14 +78,14 @@ struct Color {
void operator-=(const Color &p_color);
Color operator*(const Color &p_color) const;
- Color operator*(real_t p_rvalue) const;
+ Color operator*(float p_scalar) const;
void operator*=(const Color &p_color);
- void operator*=(real_t p_rvalue);
+ void operator*=(float p_scalar);
Color operator/(const Color &p_color) const;
- Color operator/(real_t p_rvalue) const;
+ Color operator/(float p_scalar) const;
void operator/=(const Color &p_color);
- void operator/=(real_t p_rvalue);
+ void operator/=(float p_scalar);
bool is_equal_approx(const Color &p_color) const;
@@ -259,8 +259,8 @@ bool Color::operator<(const Color &p_color) const {
}
}
-_FORCE_INLINE_ Color operator*(real_t p_real, const Color &p_color) {
- return p_color * p_real;
+_FORCE_INLINE_ Color operator*(float p_scalar, const Color &p_color) {
+ return p_color * p_scalar;
}
#endif // COLOR_H
diff --git a/core/os/thread.cpp b/core/os/thread.cpp
index 0ed8825452..936e5d5500 100644
--- a/core/os/thread.cpp
+++ b/core/os/thread.cpp
@@ -30,30 +30,70 @@
#include "thread.h"
-Thread *(*Thread::create_func)(ThreadCreateCallback, void *, const Settings &) = nullptr;
-Thread::ID (*Thread::get_thread_id_func)() = nullptr;
-void (*Thread::wait_to_finish_func)(Thread *) = nullptr;
+#include "core/object/script_language.h"
+
+#if !defined(NO_THREADS)
+
Error (*Thread::set_name_func)(const String &) = nullptr;
+void (*Thread::set_priority_func)(Thread::Priority) = nullptr;
+void (*Thread::init_func)() = nullptr;
+void (*Thread::term_func)() = nullptr;
+
+Thread::ID Thread::main_thread_id = 1;
+Thread::ID Thread::last_thread_id = 1;
+thread_local Thread::ID Thread::caller_id = 1;
-Thread::ID Thread::_main_thread_id = 0;
+void Thread::_set_platform_funcs(
+ Error (*p_set_name_func)(const String &),
+ void (*p_set_priority_func)(Thread::Priority),
+ void (*p_init_func)(),
+ void (*p_term_func)()) {
+ Thread::set_name_func = p_set_name_func;
+ Thread::set_priority_func = p_set_priority_func;
+ Thread::init_func = p_init_func;
+ Thread::term_func = p_term_func;
+}
-Thread::ID Thread::get_caller_id() {
- if (get_thread_id_func) {
- return get_thread_id_func();
+void Thread::callback(Thread *p_self, const Settings &p_settings, Callback p_callback, void *p_userdata) {
+ Thread::caller_id = p_self->id;
+ if (set_priority_func) {
+ set_priority_func(p_settings.priority);
+ }
+ if (init_func) {
+ init_func();
+ }
+ ScriptServer::thread_enter(); //scripts may need to attach a stack
+ p_callback(p_userdata);
+ ScriptServer::thread_exit();
+ if (term_func) {
+ term_func();
}
- return 0;
}
-Thread *Thread::create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings) {
- if (create_func) {
- return create_func(p_callback, p_user, p_settings);
+void Thread::start(Thread::Callback p_callback, void *p_user, const Settings &p_settings) {
+ if (id != 0) {
+#ifdef DEBUG_ENABLED
+ WARN_PRINT("A Thread object has been re-started without wait_to_finish() having been called on it. Please do so to ensure correct cleanup of the thread.");
+#endif
+ thread.detach();
+ std::thread empty_thread;
+ thread.swap(empty_thread);
}
- return nullptr;
+ id = atomic_increment(&last_thread_id);
+ std::thread new_thread(&Thread::callback, this, p_settings, p_callback, p_user);
+ thread.swap(new_thread);
}
-void Thread::wait_to_finish(Thread *p_thread) {
- if (wait_to_finish_func) {
- wait_to_finish_func(p_thread);
+bool Thread::is_started() const {
+ return id != 0;
+}
+
+void Thread::wait_to_finish() {
+ if (id != 0) {
+ thread.join();
+ std::thread empty_thread;
+ thread.swap(empty_thread);
+ id = 0;
}
}
@@ -64,3 +104,14 @@ Error Thread::set_name(const String &p_name) {
return ERR_UNAVAILABLE;
}
+
+Thread::~Thread() {
+ if (id != 0) {
+#ifdef DEBUG_ENABLED
+ WARN_PRINT("A Thread object has been destroyed without wait_to_finish() having been called on it. Please do so to ensure correct cleanup of the thread.");
+#endif
+ thread.detach();
+ }
+}
+
+#endif
diff --git a/core/os/thread.h b/core/os/thread.h
index 993c7ad33d..b5449d2ed6 100644
--- a/core/os/thread.h
+++ b/core/os/thread.h
@@ -31,13 +31,20 @@
#ifndef THREAD_H
#define THREAD_H
-#include "core/string/ustring.h"
#include "core/typedefs.h"
-typedef void (*ThreadCreateCallback)(void *p_userdata);
+#if !defined(NO_THREADS)
+#include <thread>
+#endif
+
+class String;
class Thread {
public:
+ typedef void (*Callback)(void *p_userdata);
+
+ typedef uint64_t ID;
+
enum Priority {
PRIORITY_LOW,
PRIORITY_NORMAL,
@@ -49,30 +56,60 @@ public:
Settings() { priority = PRIORITY_NORMAL; }
};
- typedef uint64_t ID;
+private:
+#if !defined(NO_THREADS)
+ friend class Main;
-protected:
- static Thread *(*create_func)(ThreadCreateCallback p_callback, void *, const Settings &);
- static ID (*get_thread_id_func)();
- static void (*wait_to_finish_func)(Thread *);
- static Error (*set_name_func)(const String &);
+ static ID main_thread_id;
+ static ID last_thread_id;
- friend class Main;
+ ID id = 0;
+ static thread_local ID caller_id;
+ std::thread thread;
- static ID _main_thread_id;
+ static void callback(Thread *p_self, const Settings &p_settings, Thread::Callback p_callback, void *p_userdata);
- Thread() {}
+ static Error (*set_name_func)(const String &);
+ static void (*set_priority_func)(Thread::Priority);
+ static void (*init_func)();
+ static void (*term_func)();
+#endif
public:
- virtual ID get_id() const = 0;
+ static void _set_platform_funcs(
+ Error (*p_set_name_func)(const String &),
+ void (*p_set_priority_func)(Thread::Priority),
+ void (*p_init_func)() = nullptr,
+ void (*p_term_func)() = nullptr);
+
+#if !defined(NO_THREADS)
+ _FORCE_INLINE_ ID get_id() const { return id; }
+ // get the ID of the caller thread
+ _FORCE_INLINE_ static ID get_caller_id() { return caller_id; }
+ // get the ID of the main thread
+ _FORCE_INLINE_ static ID get_main_id() { return main_thread_id; }
static Error set_name(const String &p_name);
- _FORCE_INLINE_ static ID get_main_id() { return _main_thread_id; } ///< get the ID of the main thread
- static ID get_caller_id(); ///< get the ID of the caller function ID
- static void wait_to_finish(Thread *p_thread); ///< waits until thread is finished, and deallocates it.
- static Thread *create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings = Settings()); ///< Static function to create a thread, will call p_callback
- virtual ~Thread() {}
+ void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings());
+ bool is_started() const;
+ ///< waits until thread is finished, and deallocates it.
+ void wait_to_finish();
+
+ ~Thread();
+#else
+ _FORCE_INLINE_ ID get_id() const { return 0; }
+ // get the ID of the caller thread
+ _FORCE_INLINE_ static ID get_caller_id() { return 0; }
+ // get the ID of the main thread
+ _FORCE_INLINE_ static ID get_main_id() { return 0; }
+
+ static Error set_name(const String &p_name) { return ERR_UNAVAILABLE; }
+
+ void start(Thread::Callback p_callback, void *p_user, const Settings &p_settings = Settings()) {}
+ bool is_started() const { return false; }
+ void wait_to_finish() {}
+#endif
};
#endif // THREAD_H
diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp
deleted file mode 100644
index a72e1298d1..0000000000
--- a/core/os/thread_dummy.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* thread_dummy.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 "thread_dummy.h"
-
-#include "core/os/memory.h"
-
-Thread *ThreadDummy::create(ThreadCreateCallback p_callback, void *p_user, const Thread::Settings &p_settings) {
- return memnew(ThreadDummy);
-}
-
-void ThreadDummy::make_default() {
- Thread::create_func = &ThreadDummy::create;
-}
diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h
deleted file mode 100644
index 0bd59ea309..0000000000
--- a/core/os/thread_dummy.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*************************************************************************/
-/* thread_dummy.h */
-/*************************************************************************/
-/* 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. */
-/*************************************************************************/
-
-#ifndef THREAD_DUMMY_H
-#define THREAD_DUMMY_H
-
-#include "core/os/rw_lock.h"
-#include "core/os/semaphore.h"
-#include "core/os/thread.h"
-
-class ThreadDummy : public Thread {
- static Thread *create(ThreadCreateCallback p_callback, void *p_user, const Settings &p_settings = Settings());
-
-public:
- virtual ID get_id() const { return 0; };
-
- static void make_default();
-};
-
-#endif // THREAD_DUMMY_H
diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h
index 57f3de20bf..9538ac5957 100644
--- a/core/os/threaded_array_processor.h
+++ b/core/os/threaded_array_processor.h
@@ -74,18 +74,17 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us
data.elements = p_elements;
data.process(data.index); //process first, let threads increment for next
- Vector<Thread *> threads;
+ int thread_count = OS::get_singleton()->get_processor_count();
+ Thread *threads = memnew_arr(Thread, thread_count);
- threads.resize(OS::get_singleton()->get_processor_count());
-
- for (int i = 0; i < threads.size(); i++) {
- threads.write[i] = Thread::create(process_array_thread<ThreadArrayProcessData<C, U>>, &data);
+ for (int i = 0; i < thread_count; i++) {
+ threads[i].start(process_array_thread<ThreadArrayProcessData<C, U>>, &data);
}
- for (int i = 0; i < threads.size(); i++) {
- Thread::wait_to_finish(threads[i]);
- memdelete(threads[i]);
+ for (int i = 0; i < thread_count; i++) {
+ threads[i].wait_to_finish();
}
+ memdelete_arr(threads);
}
#else
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 6b6d0a8ab4..0b6311dadf 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -1409,8 +1409,9 @@ String String::num(double p_num, int p_decimals) {
if (digit == MAX_DIGITS) //no point in going to infinite
break;
- if ((dec - (double)((int)dec)) < 1e-6)
+ if (dec - (double)((int)dec) < 1e-6) {
break;
+ }
}
if (digit == p_decimals)
@@ -2096,8 +2097,9 @@ String::String(const StrRange &p_range) {
copy_from(p_range.c_str, p_range.len);
}
-int64_t String::hex_to_int(bool p_with_prefix) const {
- if (p_with_prefix && length() < 3) {
+int64_t String::hex_to_int() const {
+ int len = length();
+ if (len == 0) {
return 0;
}
@@ -2109,10 +2111,7 @@ int64_t String::hex_to_int(bool p_with_prefix) const {
s++;
}
- if (p_with_prefix) {
- if (s[0] != '0' || s[1] != 'x') {
- return 0;
- }
+ if (len > 2 && s[0] == '0' && s[1] == 'x') {
s += 2;
}
@@ -2139,8 +2138,9 @@ int64_t String::hex_to_int(bool p_with_prefix) const {
return hex * sign;
}
-int64_t String::bin_to_int(bool p_with_prefix) const {
- if (p_with_prefix && length() < 3) {
+int64_t String::bin_to_int() const {
+ int len = length();
+ if (len == 0) {
return 0;
}
@@ -2152,10 +2152,7 @@ int64_t String::bin_to_int(bool p_with_prefix) const {
s++;
}
- if (p_with_prefix) {
- if (s[0] != '0' || s[1] != 'b') {
- return 0;
- }
+ if (len > 2 && s[0] == '0' && s[1] == 'b') {
s += 2;
}
@@ -3255,8 +3252,8 @@ float String::similarity(const String &p_string) const {
int src_size = src_bigrams.size();
int tgt_size = tgt_bigrams.size();
- double sum = src_size + tgt_size;
- double inter = 0;
+ int sum = src_size + tgt_size;
+ int inter = 0;
for (int i = 0; i < src_size; i++) {
for (int j = 0; j < tgt_size; j++) {
if (src_bigrams[i] == tgt_bigrams[j]) {
@@ -3483,7 +3480,7 @@ String String::right(int p_pos) const {
return substr(p_pos, (length() - p_pos));
}
-char32_t String::ord_at(int p_idx) const {
+char32_t String::unicode_at(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, length(), 0);
return operator[](p_idx);
}
@@ -3755,7 +3752,7 @@ bool String::is_valid_string() const {
return valid;
}
-String String::http_escape() const {
+String String::uri_encode() const {
const CharString temp = utf8();
String res;
for (int i = 0; i < temp.length(); ++i) {
@@ -3779,23 +3776,25 @@ String String::http_escape() const {
return res;
}
-String String::http_unescape() const {
+String String::uri_decode() const {
String res;
for (int i = 0; i < length(); ++i) {
- if (ord_at(i) == '%' && i + 2 < length()) {
- char32_t ord1 = ord_at(i + 1);
+ if (unicode_at(i) == '%' && i + 2 < length()) {
+ char32_t ord1 = unicode_at(i + 1);
if ((ord1 >= '0' && ord1 <= '9') || (ord1 >= 'A' && ord1 <= 'Z')) {
- char32_t ord2 = ord_at(i + 2);
+ char32_t ord2 = unicode_at(i + 2);
if ((ord2 >= '0' && ord2 <= '9') || (ord2 >= 'A' && ord2 <= 'Z')) {
char bytes[3] = { (char)ord1, (char)ord2, 0 };
res += (char)strtol(bytes, nullptr, 16);
i += 2;
}
} else {
- res += ord_at(i);
+ res += unicode_at(i);
}
+ } else if (unicode_at(i) == '+') {
+ res += ' ';
} else {
- res += ord_at(i);
+ res += unicode_at(i);
}
}
return String::utf8(res.ascii());
@@ -4250,7 +4249,7 @@ bool String::is_valid_ip_address() const {
continue;
}
if (n.is_valid_hex_number(false)) {
- int64_t nint = n.hex_to_int(false);
+ int64_t nint = n.hex_to_int();
if (nint < 0 || nint > 0xffff) {
return false;
}
@@ -4345,63 +4344,6 @@ String String::plus_file(const String &p_file) const {
return *this + "/" + p_file;
}
-String String::percent_encode() const {
- CharString cs = utf8();
- String encoded;
- for (int i = 0; i < cs.length(); i++) {
- uint8_t c = cs[i];
- if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '~' || c == '.') {
- char p[2] = { (char)c, 0 };
- encoded += p;
- } else {
- char p[4] = { '%', 0, 0, 0 };
- static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
-
- p[1] = hex[c >> 4];
- p[2] = hex[c & 0xF];
- encoded += p;
- }
- }
-
- return encoded;
-}
-
-String String::percent_decode() const {
- CharString pe;
-
- CharString cs = utf8();
- for (int i = 0; i < cs.length(); i++) {
- uint8_t c = cs[i];
- if (c == '%' && i < length() - 2) {
- uint8_t a = LOWERCASE(cs[i + 1]);
- uint8_t b = LOWERCASE(cs[i + 2]);
-
- if (a >= '0' && a <= '9') {
- c = (a - '0') << 4;
- } else if (a >= 'a' && a <= 'f') {
- c = (a - 'a' + 10) << 4;
- } else {
- continue;
- }
-
- uint8_t d = 0;
-
- if (b >= '0' && b <= '9') {
- d = (b - '0');
- } else if (b >= 'a' && b <= 'f') {
- d = (b - 'a' + 10);
- } else {
- continue;
- }
- c += d;
- i += 2;
- }
- pe += c;
- }
-
- return String::utf8(pe.ptr());
-}
-
String String::property_name_encode() const {
// Escape and quote strings with extended ASCII or further Unicode characters
// as well as '"', '=' or ' ' (32)
diff --git a/core/string/ustring.h b/core/string/ustring.h
index 654e327320..821941036f 100644
--- a/core/string/ustring.h
+++ b/core/string/ustring.h
@@ -318,8 +318,8 @@ public:
bool is_numeric() const;
double to_float() const;
- int64_t hex_to_int(bool p_with_prefix = true) const;
- int64_t bin_to_int(bool p_with_prefix = true) const;
+ int64_t hex_to_int() const;
+ int64_t bin_to_int() const;
int64_t to_int() const;
static int64_t to_int(const char *p_str, int p_len = -1);
@@ -366,7 +366,7 @@ public:
String get_extension() const;
String get_basename() const;
String plus_file(const String &p_file) const;
- char32_t ord_at(int p_idx) const;
+ char32_t unicode_at(int p_idx) const;
void erase(int p_pos, int p_chars);
@@ -409,17 +409,14 @@ public:
String xml_escape(bool p_escape_quotes = false) const;
String xml_unescape() const;
- String http_escape() const;
- String http_unescape() const;
+ String uri_encode() const;
+ String uri_decode() const;
String c_escape() const;
String c_escape_multiline() const;
String c_unescape() const;
String json_escape() const;
String word_wrap(int p_chars_per_line) const;
- String percent_encode() const;
- String percent_decode() const;
-
String property_name_encode() const;
bool is_valid_identifier() const;
diff --git a/core/templates/thread_work_pool.cpp b/core/templates/thread_work_pool.cpp
index ea784e510c..17969a2c90 100644
--- a/core/templates/thread_work_pool.cpp
+++ b/core/templates/thread_work_pool.cpp
@@ -32,14 +32,15 @@
#include "core/os/os.h"
-void ThreadWorkPool::_thread_function(ThreadData *p_thread) {
+void ThreadWorkPool::_thread_function(void *p_user) {
+ ThreadData *thread = static_cast<ThreadData *>(p_user);
while (true) {
- p_thread->start.wait();
- if (p_thread->exit.load()) {
+ thread->start.wait();
+ if (thread->exit.load()) {
break;
}
- p_thread->work->work();
- p_thread->completed.post();
+ thread->work->work();
+ thread->completed.post();
}
}
@@ -54,7 +55,7 @@ void ThreadWorkPool::init(int p_thread_count) {
for (uint32_t i = 0; i < thread_count; i++) {
threads[i].exit.store(false);
- threads[i].thread = memnew(std::thread(ThreadWorkPool::_thread_function, &threads[i]));
+ threads[i].thread.start(&ThreadWorkPool::_thread_function, &threads[i]);
}
}
@@ -68,8 +69,7 @@ void ThreadWorkPool::finish() {
threads[i].start.post();
}
for (uint32_t i = 0; i < thread_count; i++) {
- threads[i].thread->join();
- memdelete(threads[i].thread);
+ threads[i].thread.wait_to_finish();
}
memdelete_arr(threads);
diff --git a/core/templates/thread_work_pool.h b/core/templates/thread_work_pool.h
index 7c3508814f..19ab1dda3a 100644
--- a/core/templates/thread_work_pool.h
+++ b/core/templates/thread_work_pool.h
@@ -33,9 +33,9 @@
#include "core/os/memory.h"
#include "core/os/semaphore.h"
+#include "core/os/thread.h"
#include <atomic>
-#include <thread>
class ThreadWorkPool {
std::atomic<uint32_t> index;
@@ -64,7 +64,7 @@ class ThreadWorkPool {
};
struct ThreadData {
- std::thread *thread;
+ Thread thread;
Semaphore start;
Semaphore completed;
std::atomic<bool> exit;
@@ -75,7 +75,7 @@ class ThreadWorkPool {
uint32_t thread_count = 0;
BaseWork *current_work = nullptr;
- static void _thread_function(ThreadData *p_thread);
+ static void _thread_function(void *p_user);
public:
template <class C, class M, class U>
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 6ff7602b4e..2fd8134fbd 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -929,7 +929,7 @@ static void _register_variant_builtin_methods() {
bind_method(String, get_extension, sarray(), varray());
bind_method(String, get_basename, sarray(), varray());
bind_method(String, plus_file, sarray("file"), varray());
- bind_method(String, ord_at, sarray("at"), varray());
+ bind_method(String, unicode_at, sarray("at"), varray());
bind_method(String, dedent, sarray(), varray());
// FIXME: String needs to be immutable when binding
//bind_method(String, erase, sarray("position", "chars"), varray());
@@ -950,13 +950,11 @@ static void _register_variant_builtin_methods() {
bind_method(String, get_file, sarray(), varray());
bind_method(String, xml_escape, sarray("escape_quotes"), varray(false));
bind_method(String, xml_unescape, sarray(), varray());
- bind_method(String, http_escape, sarray(), varray());
- bind_method(String, http_unescape, sarray(), varray());
+ bind_method(String, uri_encode, sarray(), varray());
+ bind_method(String, uri_decode, sarray(), varray());
bind_method(String, c_escape, sarray(), varray());
bind_method(String, c_unescape, sarray(), varray());
bind_method(String, json_escape, sarray(), varray());
- bind_method(String, percent_encode, sarray(), varray());
- bind_method(String, percent_decode, sarray(), varray());
bind_method(String, is_valid_identifier, sarray(), varray());
bind_method(String, is_valid_integer, sarray(), varray());
@@ -968,8 +966,8 @@ static void _register_variant_builtin_methods() {
bind_method(String, to_int, sarray(), varray());
bind_method(String, to_float, sarray(), varray());
- bind_method(String, hex_to_int, sarray("with_prefix"), varray(true));
- bind_method(String, bin_to_int, sarray("with_prefix"), varray(true));
+ bind_method(String, hex_to_int, sarray(), varray());
+ bind_method(String, bin_to_int, sarray(), varray());
bind_method(String, lpad, sarray("min_length", "character"), varray(" "));
bind_method(String, rpad, sarray("min_length", "character"), varray(" "));
@@ -1212,7 +1210,7 @@ static void _register_variant_builtin_methods() {
bind_method(Basis, transposed, sarray(), varray());
bind_method(Basis, orthonormalized, sarray(), varray());
bind_method(Basis, determinant, sarray(), varray());
- bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, float) const>(&Basis::rotated), sarray("axis", "phi"), varray());
+ bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, real_t) const>(&Basis::rotated), sarray("axis", "phi"), varray());
bind_method(Basis, scaled, sarray("scale"), varray());
bind_method(Basis, get_scale, sarray(), varray());
bind_method(Basis, get_euler, sarray(), varray());
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 1f532f4843..e2c4ed1430 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -215,6 +215,8 @@
<member name="custom_aabb" type="AABB" setter="set_custom_aabb" getter="get_custom_aabb" default="AABB( 0, 0, 0, 0, 0, 0 )">
Overrides the [AABB] with one defined by user for use with frustum culling. Especially useful to avoid unexpected culling when using a shader to offset vertices.
</member>
+ <member name="shadow_mesh" type="ArrayMesh" setter="set_shadow_mesh" getter="get_shadow_mesh">
+ </member>
</members>
<constants>
</constants>
diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml
index b6594aac39..9ff682f79d 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -175,7 +175,7 @@
var result = new HTTPClient().Request(HTTPClient.Method.Post, "index.php", headers, queryString);
[/csharp]
[/codeblocks]
- [b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example.
+ [b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.uri_encode] for an example.
</description>
</method>
<method name="request_raw">
diff --git a/doc/classes/HTTPRequest.xml b/doc/classes/HTTPRequest.xml
index f2ab93033a..a65f66c72a 100644
--- a/doc/classes/HTTPRequest.xml
+++ b/doc/classes/HTTPRequest.xml
@@ -203,7 +203,7 @@
<description>
Creates request on the underlying [HTTPClient]. If there is no configuration errors, it tries to connect using [method HTTPClient.connect_to_host] and passes parameters onto [method HTTPClient.request].
Returns [constant OK] if request is successfully created. (Does not imply that the server has responded), [constant ERR_UNCONFIGURED] if not in the tree, [constant ERR_BUSY] if still processing previous request, [constant ERR_INVALID_PARAMETER] if given string is not a valid URL format, or [constant ERR_CANT_CONNECT] if not using thread and the [HTTPClient] cannot connect to host.
- [b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.http_escape] for an example.
+ [b]Note:[/b] The [code]request_data[/code] parameter is ignored if [code]method[/code] is [constant HTTPClient.METHOD_GET]. This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See [method String.uri_encode] for an example.
</description>
</method>
<method name="request_raw">
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 790bf58359..61ecff52e3 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -383,12 +383,12 @@
<theme_item name="font_selected_color" type="Color" default="Color( 0, 0, 0, 1 )">
Font color for selected text (inside the selection rectangle).
</theme_item>
- <theme_item name="font_uneditable_color" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )">
- Font color when editing is disabled.
- </theme_item>
<theme_item name="font_size" type="int">
Font size of the [LineEdit]'s text.
</theme_item>
+ <theme_item name="font_uneditable_color" type="Color" default="Color( 0.88, 0.88, 0.88, 0.5 )">
+ Font color when editing is disabled.
+ </theme_item>
<theme_item name="minimum_spaces" type="int" default="12">
Minimum horizontal space for the text (not counting the clear button and content margins). This value is measured in count of space characters (i.e. this amount of space characters can be displayed without scrolling).
</theme_item>
diff --git a/doc/classes/Material.xml b/doc/classes/Material.xml
index 10a7061bef..0d287a5d1d 100644
--- a/doc/classes/Material.xml
+++ b/doc/classes/Material.xml
@@ -11,6 +11,12 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
+ <method name="inspect_native_shader_code">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<members>
<member name="next_pass" type="Material" setter="set_next_pass" getter="get_next_pass">
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index e209fc9ad9..8620de1378 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -136,14 +136,6 @@
Returns the keycode of the given string (e.g. "Escape").
</description>
</method>
- <method name="get_thread_caller_id" qualifiers="const">
- <return type="int">
- </return>
- <description>
- Returns the ID of the current thread. This can be used in logs to ease debugging of multi-threaded applications.
- [b]Note:[/b] Thread IDs are not deterministic and may be reused across application restarts.
- </description>
- </method>
<method name="get_cmdline_args">
<return type="PackedStringArray">
</return>
@@ -330,6 +322,14 @@
[b]Note:[/b] This method is implemented on Windows.
</description>
</method>
+ <method name="get_thread_caller_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the ID of the current thread. This can be used in logs to ease debugging of multi-threaded applications.
+ [b]Note:[/b] Thread IDs are not deterministic and may be reused across application restarts.
+ </description>
+ </method>
<method name="get_ticks_msec" qualifiers="const">
<return type="int">
</return>
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 4be81e256e..47e8e57a4e 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -717,12 +717,12 @@
<theme_item name="font" type="Font">
[Font] used for the menu items.
</theme_item>
- <theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
- The default text [Color] for menu items' names.
- </theme_item>
<theme_item name="font_accelerator_color" type="Color" default="Color( 0.7, 0.7, 0.7, 0.8 )">
The text [Color] used for shortcuts and accelerators that show next to the menu item name when defined. See [method get_item_accelerator] for more info on accelerators.
</theme_item>
+ <theme_item name="font_color" type="Color" default="Color( 0.88, 0.88, 0.88, 1 )">
+ The default text [Color] for menu items' names.
+ </theme_item>
<theme_item name="font_disabled_color" type="Color" default="Color( 0.4, 0.4, 0.4, 0.8 )">
[Color] used for disabled menu items' text.
</theme_item>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index a82cf9a2a9..fc618206ed 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1052,6 +1052,8 @@
Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_jitter_fix] instead.
</member>
+ <member name="rendering/cluster_builder/max_clustered_elements" type="float" setter="" getter="" default="512">
+ </member>
<member name="rendering/environment/default_clear_color" type="Color" setter="" getter="" default="Color( 0.3, 0.3, 0.3, 1 )">
Default background clear color. Overridable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method RenderingServer.set_default_clear_color].
</member>
@@ -1116,6 +1118,8 @@
<member name="rendering/quality/depth_prepass/enable" type="bool" setter="" getter="" default="true">
If [code]true[/code], performs a previous depth pass before rendering materials. This increases performance in scenes with high overdraw, when complex materials and lighting are used.
</member>
+ <member name="rendering/quality/directional_shadow/16_bits" type="bool" setter="" getter="" default="true">
+ </member>
<member name="rendering/quality/directional_shadow/size" type="int" setter="" getter="" default="4096">
The directional shadow's size in pixels. Higher values will result in sharper shadows, at the cost of performance. The value will be rounded up to the nearest power of 2.
</member>
@@ -1134,6 +1138,8 @@
[b]FIXME:[/b] No longer valid after DisplayServer split:
In such cases, this property is not updated, so use [code]OS.get_current_video_driver[/code] to query it at run-time.
</member>
+ <member name="rendering/quality/gi/use_half_resolution" type="bool" setter="" getter="" default="false">
+ </member>
<member name="rendering/quality/gi_probes/anisotropic" type="bool" setter="" getter="" default="false">
If [code]true[/code], take additional samples when rendering objects affected by a [GIProbe] to reduce artifacts from only sampling in one direction.
</member>
@@ -1225,7 +1231,9 @@
<member name="rendering/quality/shading/force_vertex_shading.mobile" type="bool" setter="" getter="" default="true">
Lower-end override for [member rendering/quality/shading/force_vertex_shading] on mobile devices, due to performance concerns or driver support.
</member>
- <member name="rendering/quality/shadow_atlas/quadrant_0_subdiv" type="int" setter="" getter="" default="1">
+ <member name="rendering/quality/shadow_atlas/16_bits" type="bool" setter="" getter="" default="true">
+ </member>
+ <member name="rendering/quality/shadow_atlas/quadrant_0_subdiv" type="int" setter="" getter="" default="2">
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/quality/shadow_atlas/quadrant_1_subdiv" type="int" setter="" getter="" default="2">
@@ -1285,9 +1293,11 @@
<member name="rendering/quality/texture_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false">
If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
</member>
- <member name="rendering/sdfgi/frames_to_converge" type="int" setter="" getter="" default="1">
+ <member name="rendering/sdfgi/frames_to_converge" type="int" setter="" getter="" default="4">
+ </member>
+ <member name="rendering/sdfgi/frames_to_update_lights" type="int" setter="" getter="" default="2">
</member>
- <member name="rendering/sdfgi/probe_ray_count" type="int" setter="" getter="" default="2">
+ <member name="rendering/sdfgi/probe_ray_count" type="int" setter="" getter="" default="1">
</member>
<member name="rendering/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000">
</member>
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index 7cdc9ffaca..d0fb2b9d47 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -7,6 +7,30 @@
<tutorials>
</tutorials>
<methods>
+ <method name="barrier">
+ <return type="void">
+ </return>
+ <argument index="0" name="from" type="int" default="7">
+ </argument>
+ <argument index="1" name="to" type="int" default="7">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="buffer_clear">
+ <return type="int" enum="Error">
+ </return>
+ <argument index="0" name="buffer" type="RID">
+ </argument>
+ <argument index="1" name="offset" type="int">
+ </argument>
+ <argument index="2" name="size_bytes" type="int">
+ </argument>
+ <argument index="3" name="post_barrier" type="int" default="7">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="buffer_get_data">
<return type="PackedByteArray">
</return>
@@ -26,7 +50,7 @@
</argument>
<argument index="3" name="data" type="PackedByteArray">
</argument>
- <argument index="4" name="sync_with_draw" type="bool" default="true">
+ <argument index="4" name="post_barrier" type="int" default="7">
</argument>
<description>
</description>
@@ -36,8 +60,6 @@
</return>
<argument index="0" name="name" type="String">
</argument>
- <argument index="1" name="sync_to_draw" type="bool">
- </argument>
<description>
</description>
</method>
@@ -94,6 +116,8 @@
<method name="compute_list_end">
<return type="void">
</return>
+ <argument index="0" name="post_barrier" type="int" default="7">
+ </argument>
<description>
</description>
</method>
@@ -131,6 +155,32 @@
<description>
</description>
</method>
+ <method name="draw_command_begin_label">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="draw_command_end_label">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="draw_command_insert_label">
+ <return type="void">
+ </return>
+ <argument index="0" name="name" type="String">
+ </argument>
+ <argument index="1" name="color" type="Color">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="draw_list_begin">
<return type="int">
</return>
@@ -272,6 +322,8 @@
<method name="draw_list_end">
<return type="void">
</return>
+ <argument index="0" name="post_barrier" type="int" default="7">
+ </argument>
<description>
</description>
</method>
@@ -302,7 +354,9 @@
</return>
<argument index="0" name="size" type="Vector2i">
</argument>
- <argument index="1" name="validate_with_format" type="int" default="-1">
+ <argument index="1" name="samples" type="int" enum="RenderingDevice.TextureSamples" default="0">
+ </argument>
+ <argument index="2" name="validate_with_format" type="int" default="-1">
</argument>
<description>
</description>
@@ -318,7 +372,7 @@
<method name="framebuffer_format_create_empty">
<return type="int">
</return>
- <argument index="0" name="size" type="Vector2i">
+ <argument index="0" name="samples" type="int" enum="RenderingDevice.TextureSamples" default="0">
</argument>
<description>
</description>
@@ -347,6 +401,12 @@
<description>
</description>
</method>
+ <method name="full_barrier">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_captured_timestamp_cpu_time" qualifiers="const">
<return type="int">
</return>
@@ -485,6 +545,16 @@
<description>
</description>
</method>
+ <method name="set_resource_name">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="RID">
+ </argument>
+ <argument index="1" name="name" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="shader_compile_from_source">
<return type="RDShaderBytecode">
</return>
@@ -562,7 +632,7 @@
</argument>
<argument index="5" name="layer_count" type="int">
</argument>
- <argument index="6" name="sync_with_draw" type="bool" default="false">
+ <argument index="6" name="post_barrier" type="int" default="7">
</argument>
<description>
</description>
@@ -588,7 +658,7 @@
</argument>
<argument index="8" name="dst_layer" type="int">
</argument>
- <argument index="9" name="sync_with_draw" type="bool" default="false">
+ <argument index="9" name="post_barrier" type="int" default="7">
</argument>
<description>
</description>
@@ -674,7 +744,7 @@
</argument>
<argument index="1" name="to_texture" type="RID">
</argument>
- <argument index="2" name="sync_with_draw" type="bool" default="false">
+ <argument index="2" name="post_barrier" type="int" default="7">
</argument>
<description>
</description>
@@ -688,7 +758,7 @@
</argument>
<argument index="2" name="data" type="PackedByteArray">
</argument>
- <argument index="3" name="sync_with_draw" type="bool" default="false">
+ <argument index="3" name="post_barrier" type="int" default="7">
</argument>
<description>
</description>
@@ -745,6 +815,14 @@
</method>
</methods>
<constants>
+ <constant name="BARRIER_MASK_RASTER" value="1">
+ </constant>
+ <constant name="BARRIER_MASK_COMPUTE" value="2">
+ </constant>
+ <constant name="BARRIER_MASK_TRANSFER" value="4">
+ </constant>
+ <constant name="BARRIER_MASK_ALL" value="7">
+ </constant>
<constant name="DATA_FORMAT_R4G4_UNORM_PACK8" value="0" enum="DataFormat">
</constant>
<constant name="DATA_FORMAT_R4G4B4A4_UNORM_PACK16" value="1" enum="DataFormat">
@@ -1507,13 +1585,15 @@
</constant>
<constant name="INITIAL_ACTION_CLEAR" value="0" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_KEEP" value="1" enum="InitialAction">
+ <constant name="INITIAL_ACTION_CLEAR_REGION" value="1" enum="InitialAction">
+ </constant>
+ <constant name="INITIAL_ACTION_KEEP" value="2" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_DROP" value="2" enum="InitialAction">
+ <constant name="INITIAL_ACTION_DROP" value="3" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_CONTINUE" value="3" enum="InitialAction">
+ <constant name="INITIAL_ACTION_CONTINUE" value="4" enum="InitialAction">
</constant>
- <constant name="INITIAL_ACTION_MAX" value="4" enum="InitialAction">
+ <constant name="INITIAL_ACTION_MAX" value="5" enum="InitialAction">
</constant>
<constant name="FINAL_ACTION_READ" value="0" enum="FinalAction">
</constant>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 4be97b7d3d..efc751bb94 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -2949,6 +2949,8 @@
</argument>
<argument index="1" name="size" type="int">
</argument>
+ <argument index="2" name="use_16_bits" type="bool" default="false">
+ </argument>
<description>
Sets the size of the shadow atlas's images (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
</description>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 2c18bc493a..35eae32c7b 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -597,12 +597,12 @@
<theme_item name="focus" type="StyleBox">
The background The background used when the [RichTextLabel] is focused.
</theme_item>
+ <theme_item name="font_selected_color" type="Color" default="Color( 0, 0, 0, 1 )">
+ The color of selected text, used when [member selection_enabled] is [code]true[/code].
+ </theme_item>
<theme_item name="font_shadow_color" type="Color" default="Color( 0, 0, 0, 0 )">
The color of the font's shadow.
</theme_item>
- <theme_item name="font_selected_color" type="Color" default="Color( 0.49, 0.49, 0.49, 1 )">
- The color of selected text, used when [member selection_enabled] is [code]true[/code].
- </theme_item>
<theme_item name="italics_font" type="Font">
The font used for italics text.
</theme_item>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index fcc70d166e..c03f6357ab 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -63,9 +63,18 @@
<method name="bin_to_int">
<return type="int">
</return>
- <argument index="0" name="with_prefix" type="bool" default="true">
- </argument>
<description>
+ Converts a string containing a binary number into an integer. Binary strings can either be prefixed with [code]0b[/code] or not, and they can also start with a [code]-[/code] before the optional prefix.
+ [codeblocks]
+ [gdscript]
+ print("0x101".bin_to_int()) # Prints "5".
+ print("101".bin_to_int()) # Prints "5".
+ [/gdscript]
+ [csharp]
+ GD.Print("0x101".BinToInt()); // Prints "5".
+ GD.Print("101".BinToInt()); // Prints "5".
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="c_escape">
@@ -221,34 +230,18 @@
<method name="hex_to_int">
<return type="int">
</return>
- <argument index="0" name="with_prefix" type="bool" default="true">
- </argument>
- <description>
- Converts a string containing a hexadecimal number into a decimal integer. If [code]with_prefix[/code] is [code]true[/code], the hexadecimal string should start with the [code]0x[/code] prefix, otherwise [code]0[/code] is returned.
- [codeblock]
- print("0xff".hex_to_int()) # Print "255"
- print("ab".hex_to_int(false)) # Print "171"
- [/codeblock]
- </description>
- </method>
- <method name="http_escape">
- <return type="String">
- </return>
<description>
- Escapes (encodes) a string to URL friendly format. Also referred to as 'URL encode'.
- [codeblock]
- print("https://example.org/?escaped=" + "Godot Engine:'docs'".http_escape())
- [/codeblock]
- </description>
- </method>
- <method name="http_unescape">
- <return type="String">
- </return>
- <description>
- Unescapes (decodes) a string in URL encoded format. Also referred to as 'URL decode'.
- [codeblock]
- print("https://example.org/?escaped=" + "Godot%20Engine%3A%27docs%27".http_unescape())
- [/codeblock]
+ Converts a string containing a hexadecimal number into an integer. Hexadecimal strings can either be prefixed with [code]0x[/code] or not, and they can also start with a [code]-[/code] before the optional prefix.
+ [codeblocks]
+ [gdscript]
+ print("0xff".hex_to_int()) # Prints "255".
+ print("ab".hex_to_int()) # Prints "171".
+ [/gdscript]
+ [csharp]
+ GD.Print("0xff".HexToInt()); // Prints "255".
+ GD.Print("ab".HexToInt()); // Prints "171".
+ [/csharp]
+ [/codeblocks]
</description>
</method>
<method name="insert">
@@ -547,15 +540,6 @@
<description>
</description>
</method>
- <method name="ord_at">
- <return type="int">
- </return>
- <argument index="0" name="at" type="int">
- </argument>
- <description>
- Returns the character code at position [code]at[/code].
- </description>
- </method>
<method name="pad_decimals">
<return type="String">
</return>
@@ -574,20 +558,6 @@
Formats a number to have an exact number of [code]digits[/code] before the decimal point.
</description>
</method>
- <method name="percent_decode">
- <return type="String">
- </return>
- <description>
- Decode a percent-encoded string. See [method percent_encode].
- </description>
- </method>
- <method name="percent_encode">
- <return type="String">
- </return>
- <description>
- Percent-encodes a string. Encodes parameters in a URL when sending a HTTP GET request (and bodies of form-urlencoded POST requests).
- </description>
- </method>
<method name="plus_file">
<return type="String">
</return>
@@ -878,6 +848,45 @@
Removes a given string from the end if it ends with it or leaves the string unchanged.
</description>
</method>
+ <method name="unicode_at">
+ <return type="int">
+ </return>
+ <argument index="0" name="at" type="int">
+ </argument>
+ <description>
+ Returns the character code at position [code]at[/code].
+ </description>
+ </method>
+ <method name="uri_decode">
+ <return type="String">
+ </return>
+ <description>
+ Decodes a string in URL encoded format. This is meant to decode parameters in a URL when receiving an HTTP request.
+ [codeblocks]
+ [gdscript]
+ print("https://example.org/?escaped=" + "Godot%20Engine%3A%27docs%27".uri_decode())
+ [/gdscript]
+ [csharp]
+ GD.Print("https://example.org/?escaped=" + "Godot%20Engine%3a%27Docs%27".URIDecode());
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
+ <method name="uri_encode">
+ <return type="String">
+ </return>
+ <description>
+ Encodes a string to URL friendly format. This is meant to encode parameters in a URL when sending an HTTP request.
+ [codeblocks]
+ [gdscript]
+ print("https://example.org/?escaped=" + "Godot Engine:'docs'".uri_encode())
+ [/gdscript]
+ [csharp]
+ GD.Print("https://example.org/?escaped=" + "Godot Engine:'docs'".URIEncode());
+ [/csharp]
+ [/codeblocks]
+ </description>
+ </method>
<method name="xml_escape">
<return type="String">
</return>
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index ba687357ec..52577e6102 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -204,12 +204,12 @@
<theme_item name="font_selected_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Font color of the currently selected tab.
</theme_item>
- <theme_item name="font_unselected_color" type="Color" default="Color( 0.69, 0.69, 0.69, 1 )">
- Font color of the other, unselected tabs.
- </theme_item>
<theme_item name="font_size" type="int">
Font size of the tab names.
</theme_item>
+ <theme_item name="font_unselected_color" type="Color" default="Color( 0.69, 0.69, 0.69, 1 )">
+ Font color of the other, unselected tabs.
+ </theme_item>
<theme_item name="icon_separation" type="int" default="4">
Space between tab's name and its icon.
</theme_item>
diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml
index 1c926ac36d..0c7b992cbf 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/Tabs.xml
@@ -365,12 +365,12 @@
<theme_item name="font_selected_color" type="Color" default="Color( 0.94, 0.94, 0.94, 1 )">
Font color of the currently selected tab.
</theme_item>
- <theme_item name="font_unselected_color" type="Color" default="Color( 0.69, 0.69, 0.69, 1 )">
- Font color of the other, unselected tabs.
- </theme_item>
<theme_item name="font_size" type="int">
Font size of the tab names.
</theme_item>
+ <theme_item name="font_unselected_color" type="Color" default="Color( 0.69, 0.69, 0.69, 1 )">
+ Font color of the other, unselected tabs.
+ </theme_item>
<theme_item name="hseparation" type="int" default="4">
The horizontal separation between the tabs.
</theme_item>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index 2b918b9db8..a12ef614e3 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -144,7 +144,7 @@
<argument index="1" name="ignore_half_ofs" type="bool" default="false">
</argument>
<description>
- Returns the global position corresponding to the given tilemap (grid-based) coordinates.
+ Returns the local position corresponding to the given tilemap (grid-based) coordinates.
Optionally, the tilemap's half offset can be ignored.
</description>
</method>
diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml
index e97c1e580c..fd157e5eb9 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -208,6 +208,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the metadata value that was set for the given column using [method set_metadata].
</description>
</method>
<method name="get_next">
@@ -268,6 +269,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns the value of a [constant CELL_MODE_RANGE] column.
</description>
</method>
<method name="get_range_config">
@@ -276,6 +278,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Returns a dictionary containing the range parameters for a given column. The keys are "min", "max", "step", and "expr".
</description>
</method>
<method name="get_structured_text_bidi_override" qualifiers="const">
@@ -300,6 +303,7 @@
<argument index="0" name="column" type="int">
</argument>
<description>
+ Gets the suffix string shown after the column value.
</description>
</method>
<method name="get_text" qualifiers="const">
@@ -606,6 +610,7 @@
<argument index="1" name="meta" type="Variant">
</argument>
<description>
+ Sets the metadata value for the given column, which can be retrieved later using [method get_metadata]. This can be used, for example, to store a reference to the original data.
</description>
</method>
<method name="set_opentype_feature">
@@ -629,6 +634,7 @@
<argument index="1" name="value" type="float">
</argument>
<description>
+ Sets the value of a [constant CELL_MODE_RANGE] column.
</description>
</method>
<method name="set_range_config">
@@ -645,6 +651,8 @@
<argument index="4" name="expr" type="bool" default="false">
</argument>
<description>
+ Sets the range of accepted values for a column. The column must be in the [constant CELL_MODE_RANGE] mode.
+ If [code]expr[/code] is [code]true[/code], the edit mode slider will use an exponential scale as with [member Range.exp_edit].
</description>
</method>
<method name="set_selectable">
@@ -686,6 +694,7 @@
<argument index="1" name="text" type="String">
</argument>
<description>
+ Sets a string to be shown after a column's value (for example, a unit abbreviation).
</description>
</method>
<method name="set_text">
@@ -696,6 +705,7 @@
<argument index="1" name="text" type="String">
</argument>
<description>
+ Sets the given column's text value.
</description>
</method>
<method name="set_text_align">
@@ -748,7 +758,7 @@
Cell contains a string.
</constant>
<constant name="CELL_MODE_CHECK" value="1" enum="TreeCellMode">
- Cell can be checked.
+ Cell contains a checkbox.
</constant>
<constant name="CELL_MODE_RANGE" value="2" enum="TreeCellMode">
Cell contains a range.
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index e66b8353a8..8120ae539e 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -240,6 +240,8 @@
</member>
<member name="sdf_scale" type="int" setter="set_sdf_scale" getter="get_sdf_scale" enum="Viewport.SDFScale" default="1">
</member>
+ <member name="shadow_atlas_16_bits" type="bool" setter="set_shadow_atlas_16_bits" getter="get_shadow_atlas_16_bits" default="true">
+ </member>
<member name="shadow_atlas_quad_0" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="2">
The subdivision amount of the first quadrant on the shadow atlas.
</member>
@@ -252,9 +254,9 @@
<member name="shadow_atlas_quad_3" type="int" setter="set_shadow_atlas_quadrant_subdiv" getter="get_shadow_atlas_quadrant_subdiv" enum="Viewport.ShadowAtlasQuadrantSubdiv" default="4">
The subdivision amount of the fourth quadrant on the shadow atlas.
</member>
- <member name="shadow_atlas_size" type="int" setter="set_shadow_atlas_size" getter="get_shadow_atlas_size" default="0">
+ <member name="shadow_atlas_size" type="int" setter="set_shadow_atlas_size" getter="get_shadow_atlas_size" default="2048">
The shadow atlas' resolution (used for omni and spot lights). The value will be rounded up to the nearest power of 2.
- [b]Note:[/b] If this is set to 0, shadows won't be visible. Since user-created viewports default to a value of 0, this value must be set above 0 manually.
+ [b]Note:[/b] If this is set to 0, shadows won't be visible.
</member>
<member name="snap_2d_transforms_to_pixel" type="bool" setter="set_snap_2d_transforms_to_pixel" getter="is_snap_2d_transforms_to_pixel_enabled" default="false">
</member>
@@ -409,6 +411,14 @@
</constant>
<constant name="DEBUG_DRAW_DISABLE_LOD" value="18" enum="DebugDraw">
</constant>
+ <constant name="DEBUG_DRAW_CLUSTER_OMNI_LIGHTS" value="19" enum="DebugDraw">
+ </constant>
+ <constant name="DEBUG_DRAW_CLUSTER_SPOT_LIGHTS" value="20" enum="DebugDraw">
+ </constant>
+ <constant name="DEBUG_DRAW_CLUSTER_DECALS" value="21" enum="DebugDraw">
+ </constant>
+ <constant name="DEBUG_DRAW_CLUSTER_REFLECTION_PROBES" value="22" enum="DebugDraw">
+ </constant>
<constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST" value="0" enum="DefaultCanvasItemTextureFilter">
The texture filter reads from the nearest pixel only. The simplest and fastest method of filtering, but the texture will look pixelized.
</constant>
diff --git a/doc/classes/VisualShaderNodeSDFRaymarch.xml b/doc/classes/VisualShaderNodeSDFRaymarch.xml
index d700761fdb..775f2814c2 100644
--- a/doc/classes/VisualShaderNodeSDFRaymarch.xml
+++ b/doc/classes/VisualShaderNodeSDFRaymarch.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeSDFRaymarch" inherits="VisualShaderNode" version="4.0">
<brief_description>
- SDF raymarching algorithm to be used within the visual shader graph.
+ SDF raymarching algorithm to be used within the visual shader graph.
</brief_description>
<description>
- Casts a ray against the screen SDF (signed-distance field) and returns the distance travelled.
+ Casts a ray against the screen SDF (signed-distance field) and returns the distance travelled.
</description>
<tutorials>
</tutorials>
diff --git a/drivers/alsa/audio_driver_alsa.cpp b/drivers/alsa/audio_driver_alsa.cpp
index 5b0d2233e0..ea0cba6c52 100644
--- a/drivers/alsa/audio_driver_alsa.cpp
+++ b/drivers/alsa/audio_driver_alsa.cpp
@@ -153,7 +153,7 @@ Error AudioDriverALSA::init() {
Error err = init_device();
if (err == OK) {
- thread = Thread::create(AudioDriverALSA::thread_func, this);
+ thread.start(AudioDriverALSA::thread_func, this);
}
return err;
@@ -291,16 +291,10 @@ void AudioDriverALSA::set_device(String device) {
}
void AudioDriverALSA::lock() {
- if (!thread) {
- return;
- }
mutex.lock();
}
void AudioDriverALSA::unlock() {
- if (!thread) {
- return;
- }
mutex.unlock();
}
@@ -312,13 +306,8 @@ void AudioDriverALSA::finish_device() {
}
void AudioDriverALSA::finish() {
- if (thread) {
- exit_thread = true;
- Thread::wait_to_finish(thread);
-
- memdelete(thread);
- thread = nullptr;
- }
+ exit_thread = true;
+ thread.wait_to_finish();
finish_device();
}
diff --git a/drivers/alsa/audio_driver_alsa.h b/drivers/alsa/audio_driver_alsa.h
index 7441229704..c0233f41e1 100644
--- a/drivers/alsa/audio_driver_alsa.h
+++ b/drivers/alsa/audio_driver_alsa.h
@@ -40,7 +40,7 @@
#include <alsa/asoundlib.h>
class AudioDriverALSA : public AudioDriver {
- Thread *thread = nullptr;
+ Thread thread;
Mutex mutex;
snd_pcm_t *pcm_handle = nullptr;
diff --git a/drivers/alsamidi/midi_driver_alsamidi.cpp b/drivers/alsamidi/midi_driver_alsamidi.cpp
index 2e1034fc66..245ea07730 100644
--- a/drivers/alsamidi/midi_driver_alsamidi.cpp
+++ b/drivers/alsamidi/midi_driver_alsamidi.cpp
@@ -150,19 +150,14 @@ Error MIDIDriverALSAMidi::open() {
snd_device_name_free_hint(hints);
exit_thread = false;
- thread = Thread::create(MIDIDriverALSAMidi::thread_func, this);
+ thread.start(MIDIDriverALSAMidi::thread_func, this);
return OK;
}
void MIDIDriverALSAMidi::close() {
- if (thread) {
- exit_thread = true;
- Thread::wait_to_finish(thread);
-
- memdelete(thread);
- thread = nullptr;
- }
+ exit_thread = true;
+ thread.wait_to_finish();
for (int i = 0; i < connected_inputs.size(); i++) {
snd_rawmidi_t *midi_in = connected_inputs[i];
@@ -198,8 +193,6 @@ PackedStringArray MIDIDriverALSAMidi::get_connected_inputs() {
}
MIDIDriverALSAMidi::MIDIDriverALSAMidi() {
- thread = nullptr;
-
exit_thread = false;
}
diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h
index 1ce0d397df..474f139bd6 100644
--- a/drivers/alsamidi/midi_driver_alsamidi.h
+++ b/drivers/alsamidi/midi_driver_alsamidi.h
@@ -42,7 +42,7 @@
#include <stdio.h>
class MIDIDriverALSAMidi : public MIDIDriver {
- Thread *thread;
+ Thread thread;
Mutex mutex;
Vector<snd_rawmidi_t *> connected_inputs;
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
index 440b7d7f53..a5092c8c5c 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp
@@ -287,7 +287,7 @@ Error AudioDriverPulseAudio::init() {
Error err = init_device();
if (err == OK) {
- thread = Thread::create(AudioDriverPulseAudio::thread_func, this);
+ thread.start(AudioDriverPulseAudio::thread_func, this);
}
return OK;
@@ -581,16 +581,10 @@ void AudioDriverPulseAudio::set_device(String device) {
}
void AudioDriverPulseAudio::lock() {
- if (!thread) {
- return;
- }
mutex.lock();
}
void AudioDriverPulseAudio::unlock() {
- if (!thread) {
- return;
- }
mutex.unlock();
}
@@ -603,12 +597,12 @@ void AudioDriverPulseAudio::finish_device() {
}
void AudioDriverPulseAudio::finish() {
- if (!thread) {
+ if (!thread.is_started()) {
return;
}
exit_thread = true;
- Thread::wait_to_finish(thread);
+ thread.wait_to_finish();
finish_device();
@@ -622,10 +616,6 @@ void AudioDriverPulseAudio::finish() {
pa_mainloop_free(pa_ml);
pa_ml = nullptr;
}
-
- memdelete(thread);
-
- thread = nullptr;
}
Error AudioDriverPulseAudio::capture_init_device() {
diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.h b/drivers/pulseaudio/audio_driver_pulseaudio.h
index 71ab2ef1c8..2ddf8d2592 100644
--- a/drivers/pulseaudio/audio_driver_pulseaudio.h
+++ b/drivers/pulseaudio/audio_driver_pulseaudio.h
@@ -40,7 +40,7 @@
#include <pulse/pulseaudio.h>
class AudioDriverPulseAudio : public AudioDriver {
- Thread *thread = nullptr;
+ Thread thread;
Mutex mutex;
pa_mainloop *pa_ml = nullptr;
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 5dc039afd9..eda929850c 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -232,7 +232,7 @@ static void _get_drives(List<String> *list) {
// Parse only file:// links
if (strncmp(string, "file://", 7) == 0) {
// Strip any unwanted edges on the strings and push_back if it's not a duplicate
- String fpath = String(string + 7).strip_edges().split_spaces()[0].percent_decode();
+ String fpath = String(string + 7).strip_edges().split_spaces()[0].uri_decode();
if (!list->find(fpath)) {
list->push_back(fpath);
}
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 36560eb736..b9bd773c2e 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -35,7 +35,6 @@
#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
-#include "core/os/thread_dummy.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
#include "drivers/unix/net_socket_posix.h"
@@ -63,6 +62,7 @@
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
+#include <time.h>
#include <unistd.h>
/// Clock Setup function (used by get_ticks_usec)
@@ -116,11 +116,10 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
}
void OS_Unix::initialize_core() {
-#ifdef NO_THREADS
- ThreadDummy::make_default();
-#else
- ThreadPosix::make_default();
+#if !defined(NO_THREADS)
+ init_thread_posix();
#endif
+
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index 5c7a546b29..19fab1d475 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -28,88 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "thread_posix.h"
-
#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
-#include "core/object/script_language.h"
-#include "core/os/memory.h"
-#include "core/templates/safe_refcount.h"
-
-#ifdef PTHREAD_BSD_SET_NAME
-#include <pthread_np.h>
-#endif
-
-static void _thread_id_key_destr_callback(void *p_value) {
- memdelete(static_cast<Thread::ID *>(p_value));
-}
-
-static pthread_key_t _create_thread_id_key() {
- pthread_key_t key;
- pthread_key_create(&key, &_thread_id_key_destr_callback);
- return key;
-}
-
-pthread_key_t ThreadPosix::thread_id_key = _create_thread_id_key();
-Thread::ID ThreadPosix::next_thread_id = 0;
-
-Thread::ID ThreadPosix::get_id() const {
- return id;
-}
-
-Thread *ThreadPosix::create_thread_posix() {
- return memnew(ThreadPosix);
-}
-
-void *ThreadPosix::thread_callback(void *userdata) {
- ThreadPosix *t = reinterpret_cast<ThreadPosix *>(userdata);
- t->id = atomic_increment(&next_thread_id);
- pthread_setspecific(thread_id_key, (void *)memnew(ID(t->id)));
-
- ScriptServer::thread_enter(); //scripts may need to attach a stack
-
- t->callback(t->user);
-
- ScriptServer::thread_exit();
-
- return nullptr;
-}
-
-Thread *ThreadPosix::create_func_posix(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
- ThreadPosix *tr = memnew(ThreadPosix);
- tr->callback = p_callback;
- tr->user = p_user;
- pthread_attr_init(&tr->pthread_attr);
- pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
- pthread_attr_setstacksize(&tr->pthread_attr, 256 * 1024);
-
- pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
-
- return tr;
-}
-
-Thread::ID ThreadPosix::get_thread_id_func_posix() {
- void *value = pthread_getspecific(thread_id_key);
-
- if (value) {
- return *static_cast<ID *>(value);
- }
-
- ID new_id = atomic_increment(&next_thread_id);
- pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id)));
- return new_id;
-}
-
-void ThreadPosix::wait_to_finish_func_posix(Thread *p_thread) {
- ThreadPosix *tp = static_cast<ThreadPosix *>(p_thread);
- ERR_FAIL_COND(!tp);
- ERR_FAIL_COND(tp->pthread == 0);
+#include "thread_posix.h"
- pthread_join(tp->pthread, nullptr);
- tp->pthread = 0;
-}
+#include "core/os/thread.h"
+#include "core/string/ustring.h"
-Error ThreadPosix::set_name_func_posix(const String &p_name) {
+static Error set_name(const String &p_name) {
#ifdef PTHREAD_NO_RENAME
return ERR_UNAVAILABLE;
@@ -137,20 +63,10 @@ Error ThreadPosix::set_name_func_posix(const String &p_name) {
return err == 0 ? OK : ERR_INVALID_PARAMETER;
#endif // PTHREAD_NO_RENAME
-};
-
-void ThreadPosix::make_default() {
- create_func = create_func_posix;
- get_thread_id_func = get_thread_id_func_posix;
- wait_to_finish_func = wait_to_finish_func_posix;
- set_name_func = set_name_func_posix;
-}
-
-ThreadPosix::ThreadPosix() {
- pthread = 0;
}
-ThreadPosix::~ThreadPosix() {
+void init_thread_posix() {
+ Thread::_set_platform_funcs(&set_name, nullptr);
}
#endif
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index fa2037e1a2..8b8a736bf0 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -31,42 +31,8 @@
#ifndef THREAD_POSIX_H
#define THREAD_POSIX_H
-#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
-
-#include "core/os/thread.h"
-#include <pthread.h>
-#include <sys/types.h>
-
-class ThreadPosix : public Thread {
- static pthread_key_t thread_id_key;
- static ID next_thread_id;
-
- pthread_t pthread;
- pthread_attr_t pthread_attr;
- ThreadCreateCallback callback;
- void *user;
- ID id;
-
- static Thread *create_thread_posix();
-
- static void *thread_callback(void *userdata);
-
- static Thread *create_func_posix(ThreadCreateCallback p_callback, void *, const Settings &);
- static ID get_thread_id_func_posix();
- static void wait_to_finish_func_posix(Thread *p_thread);
-
- static Error set_name_func_posix(const String &p_name);
-
- ThreadPosix();
-
-public:
- virtual ID get_id() const;
-
- static void make_default();
-
- ~ThreadPosix();
-};
-
+#if !defined(NO_THREADS)
+void init_thread_posix();
#endif
#endif
diff --git a/drivers/wasapi/audio_driver_wasapi.cpp b/drivers/wasapi/audio_driver_wasapi.cpp
index 7d5082d276..f2d541754f 100644
--- a/drivers/wasapi/audio_driver_wasapi.cpp
+++ b/drivers/wasapi/audio_driver_wasapi.cpp
@@ -397,7 +397,7 @@ Error AudioDriverWASAPI::init() {
exit_thread = false;
thread_exited = false;
- thread = Thread::create(thread_func, this);
+ thread.start(thread_func, this);
return OK;
}
@@ -767,13 +767,8 @@ void AudioDriverWASAPI::unlock() {
}
void AudioDriverWASAPI::finish() {
- if (thread) {
- exit_thread = true;
- Thread::wait_to_finish(thread);
-
- memdelete(thread);
- thread = nullptr;
- }
+ exit_thread = true;
+ thread.wait_to_finish();
finish_capture_device();
finish_render_device();
diff --git a/drivers/wasapi/audio_driver_wasapi.h b/drivers/wasapi/audio_driver_wasapi.h
index 2df07d16f7..b9b325f0fb 100644
--- a/drivers/wasapi/audio_driver_wasapi.h
+++ b/drivers/wasapi/audio_driver_wasapi.h
@@ -64,7 +64,7 @@ class AudioDriverWASAPI : public AudioDriver {
AudioDeviceWASAPI audio_output;
Mutex mutex;
- Thread *thread = nullptr;
+ Thread thread;
Vector<int32_t> samples_in;
diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp
deleted file mode 100644
index ec95c9523d..0000000000
--- a/drivers/windows/thread_windows.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*************************************************************************/
-/* thread_windows.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 "thread_windows.h"
-
-#if defined(WINDOWS_ENABLED) && !defined(UWP_ENABLED)
-
-#include "core/os/memory.h"
-
-Thread::ID ThreadWindows::get_id() const {
- return id;
-}
-
-Thread *ThreadWindows::create_thread_windows() {
- return memnew(ThreadWindows);
-}
-
-DWORD ThreadWindows::thread_callback(LPVOID userdata) {
- ThreadWindows *t = reinterpret_cast<ThreadWindows *>(userdata);
-
- ScriptServer::thread_enter(); //scripts may need to attach a stack
-
- t->id = (ID)GetCurrentThreadId(); // must implement
- t->callback(t->user);
- SetEvent(t->handle);
-
- ScriptServer::thread_exit();
-
- return 0;
-}
-
-Thread *ThreadWindows::create_func_windows(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
- ThreadWindows *tr = memnew(ThreadWindows);
- tr->callback = p_callback;
- tr->user = p_user;
- tr->handle = CreateEvent(nullptr, TRUE, FALSE, nullptr);
-
- QueueUserWorkItem(thread_callback, tr, WT_EXECUTELONGFUNCTION);
-
- return tr;
-}
-
-Thread::ID ThreadWindows::get_thread_id_func_windows() {
- return (ID)GetCurrentThreadId(); //must implement
-}
-
-void ThreadWindows::wait_to_finish_func_windows(Thread *p_thread) {
- ThreadWindows *tp = static_cast<ThreadWindows *>(p_thread);
- ERR_FAIL_COND(!tp);
- WaitForSingleObject(tp->handle, INFINITE);
- CloseHandle(tp->handle);
- //`memdelete(tp);
-}
-
-void ThreadWindows::make_default() {
- create_func = create_func_windows;
- get_thread_id_func = get_thread_id_func_windows;
- wait_to_finish_func = wait_to_finish_func_windows;
-}
-
-#endif
diff --git a/drivers/windows/thread_windows.h b/drivers/windows/thread_windows.h
deleted file mode 100644
index 3801bddc2c..0000000000
--- a/drivers/windows/thread_windows.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*************************************************************************/
-/* thread_windows.h */
-/*************************************************************************/
-/* 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. */
-/*************************************************************************/
-
-#ifndef THREAD_WINDOWS_H
-#define THREAD_WINDOWS_H
-
-#ifdef WINDOWS_ENABLED
-
-#include "core/object/script_language.h"
-#include "core/os/thread.h"
-
-#include <windows.h>
-
-class ThreadWindows : public Thread {
- ThreadCreateCallback callback;
- void *user;
- ID id;
- HANDLE handle = nullptr;
-
- static Thread *create_thread_windows();
-
- static DWORD WINAPI thread_callback(LPVOID userdata);
-
- static Thread *create_func_windows(ThreadCreateCallback p_callback, void *, const Settings &);
- static ID get_thread_id_func_windows();
- static void wait_to_finish_func_windows(Thread *p_thread);
-
- ThreadWindows() {}
-
-public:
- virtual ID get_id() const;
-
- static void make_default();
-
- ~ThreadWindows() {}
-};
-
-#endif
-
-#endif
diff --git a/drivers/xaudio2/audio_driver_xaudio2.cpp b/drivers/xaudio2/audio_driver_xaudio2.cpp
index 3b3c3481b6..1bb8da769b 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.cpp
+++ b/drivers/xaudio2/audio_driver_xaudio2.cpp
@@ -78,7 +78,7 @@ Error AudioDriverXAudio2::init() {
hr = xaudio->CreateSourceVoice(&source_voice, &wave_format, 0, XAUDIO2_MAX_FREQ_RATIO, &voice_callback);
ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_UNAVAILABLE, "Error creating XAudio2 source voice. Error code: " + itos(hr) + ".");
- thread = Thread::create(AudioDriverXAudio2::thread_func, this);
+ thread.start(AudioDriverXAudio2::thread_func, this);
return OK;
}
@@ -146,23 +146,16 @@ float AudioDriverXAudio2::get_latency() {
}
void AudioDriverXAudio2::lock() {
- if (!thread)
- return;
mutex.lock();
}
void AudioDriverXAudio2::unlock() {
- if (!thread)
- return;
mutex.unlock();
}
void AudioDriverXAudio2::finish() {
- if (!thread)
- return;
-
exit_thread = true;
- Thread::wait_to_finish(thread);
+ thread.wait_to_finish();
if (source_voice) {
source_voice->Stop(0);
@@ -179,9 +172,6 @@ void AudioDriverXAudio2::finish() {
}
mastering_voice->DestroyVoice();
-
- memdelete(thread);
- thread = nullptr;
}
AudioDriverXAudio2::AudioDriverXAudio2() {
diff --git a/drivers/xaudio2/audio_driver_xaudio2.h b/drivers/xaudio2/audio_driver_xaudio2.h
index e3c2d3a326..d3938a19d0 100644
--- a/drivers/xaudio2/audio_driver_xaudio2.h
+++ b/drivers/xaudio2/audio_driver_xaudio2.h
@@ -62,7 +62,7 @@ class AudioDriverXAudio2 : public AudioDriver {
void STDMETHODCALLTYPE OnVoiceError(void *pBufferContext, HRESULT Error) {}
};
- Thread *thread = nullptr;
+ Thread thread;
Mutex mutex;
int32_t *samples_in = nullptr;
diff --git a/editor/audio_stream_preview.cpp b/editor/audio_stream_preview.cpp
index 2e0c3491f7..8be8735f3e 100644
--- a/editor/audio_stream_preview.cpp
+++ b/editor/audio_stream_preview.cpp
@@ -197,7 +197,8 @@ Ref<AudioStreamPreview> AudioStreamPreviewGenerator::generate_preview(const Ref<
preview->preview->length = len_s;
if (preview->playback.is_valid()) {
- preview->thread = Thread::create(_preview_thread, preview);
+ preview->thread = memnew(Thread);
+ preview->thread->start(_preview_thread, preview);
}
return preview->preview;
@@ -218,7 +219,8 @@ void AudioStreamPreviewGenerator::_notification(int p_what) {
for (Map<ObjectID, Preview>::Element *E = previews.front(); E; E = E->next()) {
if (!E->get().generating) {
if (E->get().thread) {
- Thread::wait_to_finish(E->get().thread);
+ E->get().thread->wait_to_finish();
+ memdelete(E->get().thread);
E->get().thread = nullptr;
}
if (!ObjectDB::get_instance(E->key())) { //no longer in use, get rid of preview
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 1d3bd55ed3..336bf26607 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -273,16 +273,6 @@ EditorPlugin *EditorData::get_editor(Object *p_object) {
return nullptr;
}
-EditorPlugin *EditorData::get_subeditor(Object *p_object) {
- for (int i = editor_plugins.size() - 1; i > -1; i--) {
- if (!editor_plugins[i]->has_main_screen() && editor_plugins[i]->handles(p_object)) {
- return editor_plugins[i];
- }
- }
-
- return nullptr;
-}
-
Vector<EditorPlugin *> EditorData::get_subeditors(Object *p_object) {
Vector<EditorPlugin *> sub_plugins;
for (int i = editor_plugins.size() - 1; i > -1; i--) {
diff --git a/editor/editor_data.h b/editor/editor_data.h
index d5c8c2a713..f14a3fb4e0 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -144,7 +144,6 @@ private:
public:
EditorPlugin *get_editor(Object *p_object);
- EditorPlugin *get_subeditor(Object *p_object);
Vector<EditorPlugin *> get_subeditors(Object *p_object);
EditorPlugin *get_editor(String p_name);
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 76814ea378..4b68de26e7 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -595,7 +595,7 @@ void EditorFileSystem::scan() {
return;
}
- if (scanning || scanning_changes || thread) {
+ if (scanning || scanning_changes || thread.is_started()) {
return;
}
@@ -619,13 +619,13 @@ void EditorFileSystem::scan() {
_queue_update_script_classes();
first_scan = false;
} else {
- ERR_FAIL_COND(thread);
+ ERR_FAIL_COND(thread.is_started());
set_process(true);
Thread::Settings s;
scanning = true;
scan_total = 0;
s.priority = Thread::PRIORITY_LOW;
- thread = Thread::create(_thread_func, this, s);
+ thread.start(_thread_func, this, s);
//tree->hide();
//progress->show();
}
@@ -1046,7 +1046,7 @@ void EditorFileSystem::_thread_func_sources(void *_userdata) {
void EditorFileSystem::scan_changes() {
if (first_scan || // Prevent a premature changes scan from inhibiting the first full scan
- scanning || scanning_changes || thread) {
+ scanning || scanning_changes || thread.is_started()) {
scan_changes_pending = true;
set_process(true);
return;
@@ -1076,12 +1076,12 @@ void EditorFileSystem::scan_changes() {
scanning_changes_done = true;
emit_signal("sources_changed", sources_changed.size() > 0);
} else {
- ERR_FAIL_COND(thread_sources);
+ ERR_FAIL_COND(thread_sources.is_started());
set_process(true);
scan_total = 0;
Thread::Settings s;
s.priority = Thread::PRIORITY_LOW;
- thread_sources = Thread::create(_thread_func_sources, this, s);
+ thread_sources.start(_thread_func_sources, this, s);
}
}
@@ -1092,17 +1092,14 @@ void EditorFileSystem::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
- Thread *active_thread = thread ? thread : thread_sources;
- if (use_threads && active_thread) {
+ Thread &active_thread = thread.is_started() ? thread : thread_sources;
+ if (use_threads && active_thread.is_started()) {
//abort thread if in progress
abort_scan = true;
while (scanning) {
OS::get_singleton()->delay_usec(1000);
}
- Thread::wait_to_finish(active_thread);
- memdelete(active_thread);
- thread = nullptr;
- thread_sources = nullptr;
+ active_thread.wait_to_finish();
WARN_PRINT("Scan thread aborted...");
set_process(false);
}
@@ -1125,9 +1122,7 @@ void EditorFileSystem::_notification(int p_what) {
set_process(false);
- Thread::wait_to_finish(thread_sources);
- memdelete(thread_sources);
- thread_sources = nullptr;
+ thread_sources.wait_to_finish();
if (_update_scan_actions()) {
emit_signal("filesystem_changed");
}
@@ -1135,7 +1130,7 @@ void EditorFileSystem::_notification(int p_what) {
_queue_update_script_classes();
first_scan = false;
}
- } else if (!scanning && thread) {
+ } else if (!scanning && thread.is_started()) {
set_process(false);
if (filesystem) {
@@ -1143,9 +1138,7 @@ void EditorFileSystem::_notification(int p_what) {
}
filesystem = new_filesystem;
new_filesystem = nullptr;
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = nullptr;
+ thread.wait_to_finish();
_update_scan_actions();
emit_signal("filesystem_changed");
emit_signal("sources_changed", sources_changed.size() > 0);
@@ -2080,11 +2073,9 @@ EditorFileSystem::EditorFileSystem() {
filesystem = memnew(EditorFileSystemDirectory); //like, empty
filesystem->parent = nullptr;
- thread = nullptr;
scanning = false;
importing = false;
use_threads = true;
- thread_sources = nullptr;
new_filesystem = nullptr;
abort_scan = false;
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index c0e11a0402..fa0b89e667 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -127,7 +127,7 @@ class EditorFileSystem : public Node {
};
bool use_threads;
- Thread *thread;
+ Thread thread;
static void _thread_func(void *_userdata);
EditorFileSystemDirectory *new_filesystem;
@@ -189,7 +189,7 @@ class EditorFileSystem : public Node {
void _scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress);
- Thread *thread_sources;
+ Thread thread_sources;
bool scanning_changes;
bool scanning_changes_done;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 2cef6a6ede..040f1b1640 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -1858,6 +1858,7 @@ void EditorNode::push_item(Object *p_object, const String &p_property, bool p_in
node_dock->set_node(nullptr);
scene_tree_dock->set_selected(nullptr);
inspector_dock->update(nullptr);
+ _display_top_editors(false);
return;
}
@@ -5493,9 +5494,7 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
int prev_len = 0;
- eta.execute_output_thread = Thread::create(_execute_thread, &eta);
-
- ERR_FAIL_COND_V(!eta.execute_output_thread, 0);
+ eta.execute_output_thread.start(_execute_thread, &eta);
while (!eta.done) {
{
@@ -5510,8 +5509,7 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
OS::get_singleton()->delay_usec(1000);
}
- Thread::wait_to_finish(eta.execute_output_thread);
- memdelete(eta.execute_output_thread);
+ eta.execute_output_thread.wait_to_finish();
execute_outputs->add_text("\nExit Code: " + itos(eta.exitcode));
if (p_close_on_errors && eta.exitcode != 0) {
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 1da162dc9c..356ac0caac 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -108,7 +108,7 @@ public:
String path;
List<String> args;
String output;
- Thread *execute_output_thread = nullptr;
+ Thread execute_output_thread;
Mutex execute_output_mutex;
int exitcode = 0;
volatile bool done = false;
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 29a929d179..8056846f52 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -424,26 +424,23 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
}
void EditorResourcePreview::start() {
- ERR_FAIL_COND_MSG(thread, "Thread already started.");
- thread = Thread::create(_thread_func, this);
+ ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
+ thread.start(_thread_func, this);
}
void EditorResourcePreview::stop() {
- if (thread) {
+ if (thread.is_started()) {
exit = true;
preview_sem.post();
while (!exited) {
OS::get_singleton()->delay_usec(10000);
RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
}
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = nullptr;
+ thread.wait_to_finish();
}
}
EditorResourcePreview::EditorResourcePreview() {
- thread = nullptr;
singleton = this;
order = 0;
exit = false;
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index c119ccd99f..99c48967d8 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -70,7 +70,7 @@ class EditorResourcePreview : public Node {
Mutex preview_mutex;
Semaphore preview_sem;
- Thread *thread;
+ Thread thread;
volatile bool exit;
volatile bool exited;
diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp
index 02bbeb57c7..07edae833d 100644
--- a/editor/fileserver/editor_file_server.cpp
+++ b/editor/fileserver/editor_file_server.cpp
@@ -43,7 +43,7 @@ void EditorFileServer::_close_client(ClientData *cd) {
cd->connection->disconnect_from_host();
{
MutexLock lock(cd->efs->wait_mutex);
- cd->efs->to_wait.insert(cd->thread);
+ cd->efs->to_wait.insert(&cd->thread);
}
while (cd->files.size()) {
memdelete(cd->files.front()->get());
@@ -278,7 +278,7 @@ void EditorFileServer::_thread_start(void *s) {
cd->connection = self->server->take_connection();
cd->efs = self;
cd->quit = false;
- cd->thread = Thread::create(_subthread_start, cd);
+ cd->thread.start(_subthread_start, cd);
}
}
@@ -287,8 +287,7 @@ void EditorFileServer::_thread_start(void *s) {
Thread *w = self->to_wait.front()->get();
self->to_wait.erase(w);
self->wait_mutex.unlock();
- Thread::wait_to_finish(w);
- memdelete(w);
+ w->wait_to_finish();
self->wait_mutex.lock();
}
self->wait_mutex.unlock();
@@ -317,7 +316,7 @@ EditorFileServer::EditorFileServer() {
quit = false;
active = false;
cmd = CMD_NONE;
- thread = Thread::create(_thread_start, this);
+ thread.start(_thread_start, this);
EDITOR_DEF("filesystem/file_server/port", 6010);
EDITOR_DEF("filesystem/file_server/password", "");
@@ -325,6 +324,5 @@ EditorFileServer::EditorFileServer() {
EditorFileServer::~EditorFileServer() {
quit = true;
- Thread::wait_to_finish(thread);
- memdelete(thread);
+ thread.wait_to_finish();
}
diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h
index 267b129bda..e4c8327d76 100644
--- a/editor/fileserver/editor_file_server.h
+++ b/editor/fileserver/editor_file_server.h
@@ -47,7 +47,7 @@ class EditorFileServer : public Object {
};
struct ClientData {
- Thread *thread = nullptr;
+ Thread thread;
Ref<StreamPeerTCP> connection;
Map<int, FileAccess *> files;
EditorFileServer *efs = nullptr;
@@ -61,7 +61,7 @@ class EditorFileServer : public Object {
static void _subthread_start(void *s);
Mutex wait_mutex;
- Thread *thread;
+ Thread thread;
static void _thread_start(void *);
bool quit;
Command cmd;
diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp
index 63b614e436..e38034dd8c 100644
--- a/editor/import/collada.cpp
+++ b/editor/import/collada.cpp
@@ -289,7 +289,7 @@ void Collada::_parse_image(XMLParser &parser) {
String path = parser.get_attribute_value("source").strip_edges();
if (path.find("://") == -1 && path.is_rel_path()) {
// path is relative to file being loaded, so convert to a resource path
- image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path.percent_decode()));
+ image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path.uri_decode()));
}
} else {
while (parser.read() == OK) {
@@ -298,7 +298,7 @@ void Collada::_parse_image(XMLParser &parser) {
if (name == "init_from") {
parser.read();
- String path = parser.get_node_data().strip_edges().percent_decode();
+ String path = parser.get_node_data().strip_edges().uri_decode();
if (path.find("://") == -1 && path.is_rel_path()) {
// path is relative to file being loaded, so convert to a resource path
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 7c39175049..d726cd031e 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -900,7 +900,7 @@ void EditorAssetLibrary::_search(int p_page) {
}
if (filter->get_text() != String()) {
- args += "&filter=" + filter->get_text().http_escape();
+ args += "&filter=" + filter->get_text().uri_encode();
}
if (p_page > 0) {
diff --git a/main/main.cpp b/main/main.cpp
index f454829100..657a6ad822 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -265,27 +265,27 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print("\n");
OS::get_singleton()->print("General options:\n");
- OS::get_singleton()->print(" -h, --help Display this help message.\n");
- OS::get_singleton()->print(" --version Display the version string.\n");
- OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n");
- OS::get_singleton()->print(" --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
+ OS::get_singleton()->print(" -h, --help Display this help message.\n");
+ OS::get_singleton()->print(" --version Display the version string.\n");
+ OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n");
+ OS::get_singleton()->print(" --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Run options:\n");
#ifdef TOOLS_ENABLED
- OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n");
- OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n");
+ OS::get_singleton()->print(" -e, --editor Start the editor instead of running the scene.\n");
+ OS::get_singleton()->print(" -p, --project-manager Start the project manager, even if a project is auto-detected.\n");
#endif
- OS::get_singleton()->print(" -q, --quit Quit after the first iteration.\n");
- OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
- OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
- OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n");
- OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n");
- OS::get_singleton()->print(" --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n");
- OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n");
- OS::get_singleton()->print(" --remote-fs-password <password> Password for remote filesystem.\n");
-
- OS::get_singleton()->print(" --audio-driver <driver> Audio driver [");
+ OS::get_singleton()->print(" -q, --quit Quit after the first iteration.\n");
+ OS::get_singleton()->print(" -l, --language <locale> Use a specific locale (<locale> being a two-letter code).\n");
+ OS::get_singleton()->print(" --path <directory> Path to a project (<directory> must contain a 'project.godot' file).\n");
+ OS::get_singleton()->print(" -u, --upwards Scan folders upwards for project.godot file.\n");
+ OS::get_singleton()->print(" --main-pack <file> Path to a pack (.pck) file to load.\n");
+ OS::get_singleton()->print(" --render-thread <mode> Render thread mode ('unsafe', 'safe', 'separate').\n");
+ OS::get_singleton()->print(" --remote-fs <address> Remote filesystem (<host/IP>[:<port>] address).\n");
+ OS::get_singleton()->print(" --remote-fs-password <password> Password for remote filesystem.\n");
+
+ OS::get_singleton()->print(" --audio-driver <driver> Audio driver [");
for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
if (i > 0) {
OS::get_singleton()->print(", ");
@@ -294,7 +294,7 @@ void Main::print_help(const char *p_binary) {
}
OS::get_singleton()->print("].\n");
- OS::get_singleton()->print(" --display-driver <driver> Display driver (and rendering driver) [");
+ OS::get_singleton()->print(" --display-driver <driver> Display driver (and rendering driver) [");
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
if (i > 0) {
OS::get_singleton()->print(", ");
@@ -311,26 +311,26 @@ void Main::print_help(const char *p_binary) {
}
OS::get_singleton()->print("].\n");
- OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n");
+ OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n");
- OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping)\n");
+ OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping)\n");
OS::get_singleton()->print("\n");
#ifndef SERVER_ENABLED
OS::get_singleton()->print("Display options:\n");
- OS::get_singleton()->print(" -f, --fullscreen Request fullscreen mode.\n");
- OS::get_singleton()->print(" -m, --maximized Request a maximized window.\n");
- OS::get_singleton()->print(" -w, --windowed Request windowed mode.\n");
- OS::get_singleton()->print(" -t, --always-on-top Request an always-on-top window.\n");
- OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n");
- OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
- OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n");
- OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n");
- OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
- OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
- OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
- OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
+ OS::get_singleton()->print(" -f, --fullscreen Request fullscreen mode.\n");
+ OS::get_singleton()->print(" -m, --maximized Request a maximized window.\n");
+ OS::get_singleton()->print(" -w, --windowed Request windowed mode.\n");
+ OS::get_singleton()->print(" -t, --always-on-top Request an always-on-top window.\n");
+ OS::get_singleton()->print(" --resolution <W>x<H> Request window resolution.\n");
+ OS::get_singleton()->print(" --position <X>,<Y> Request window position.\n");
+ OS::get_singleton()->print(" --low-dpi Force low-DPI mode (macOS and Windows only).\n");
+ OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n");
+ OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
+ OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
+ OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
+ OS::get_singleton()->print(" --tablet-driver Tablet input driver (");
for (int i = 0; i < OS::get_singleton()->get_tablet_driver_count(); i++) {
if (i != 0)
OS::get_singleton()->print(", ");
@@ -341,43 +341,44 @@ void Main::print_help(const char *p_binary) {
#endif
OS::get_singleton()->print("Debug options:\n");
- OS::get_singleton()->print(" -d, --debug Debug (local stdout debugger).\n");
- OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
- OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n");
- OS::get_singleton()->print(" --vk-layers Enable Vulkan Validation layers for debugging.\n");
+ OS::get_singleton()->print(" -d, --debug Debug (local stdout debugger).\n");
+ OS::get_singleton()->print(" -b, --breakpoints Breakpoint list as source::line comma-separated pairs, no spaces (use %%20 instead).\n");
+ OS::get_singleton()->print(" --profiling Enable profiling in the script debugger.\n");
+ OS::get_singleton()->print(" --vk-layers Enable Vulkan Validation layers for debugging.\n");
#if DEBUG_ENABLED
- OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n");
+ OS::get_singleton()->print(" --gpu-abort Abort on GPU errors (usually validation layer errors), may help see the problem if your system freezes.\n");
#endif
- OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
+ OS::get_singleton()->print(" --remote-debug <uri> Remote debug (<protocol>://<host/IP>[:<port>], e.g. tcp://127.0.0.1:6007).\n");
#if defined(DEBUG_ENABLED) && !defined(SERVER_ENABLED)
- OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n");
- OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n");
+ OS::get_singleton()->print(" --debug-collisions Show collision shapes when running the scene.\n");
+ OS::get_singleton()->print(" --debug-navigation Show navigation polygons when running the scene.\n");
#endif
- OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n");
- OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
- OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
- OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
- OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
- OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n");
- OS::get_singleton()->print(" --profile-gpu Show a simple profile of the tasks that took more time during frame rendering.\n");
+ OS::get_singleton()->print(" --frame-delay <ms> Simulate high CPU load (delay each frame by <ms> milliseconds).\n");
+ OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
+ OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
+ OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
+ OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
+ OS::get_singleton()->print(" --print-fps Print the frames per second to the stdout.\n");
+ OS::get_singleton()->print(" --profile-gpu Show a simple profile of the tasks that took more time during frame rendering.\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Standalone tools:\n");
- OS::get_singleton()->print(" -s, --script <script> Run a script.\n");
- OS::get_singleton()->print(" --check-only Only parse for errors and quit (use with --script).\n");
+ OS::get_singleton()->print(" -s, --script <script> Run a script.\n");
+ OS::get_singleton()->print(" --check-only Only parse for errors and quit (use with --script).\n");
#ifdef TOOLS_ENABLED
- OS::get_singleton()->print(" --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg.\n");
- OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n");
- OS::get_singleton()->print(" --export-debug <preset> <path> Same as --export, but using the debug template.\n");
- OS::get_singleton()->print(" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n");
- OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n");
- OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
- OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
+ OS::get_singleton()->print(" --export <preset> <path> Export the project using the given preset and matching release template. The preset name should match one defined in export_presets.cfg.\n");
+ OS::get_singleton()->print(" <path> should be absolute or relative to the project directory, and include the filename for the binary (e.g. 'builds/game.exe'). The target directory should exist.\n");
+ OS::get_singleton()->print(" --export-debug <preset> <path> Same as --export, but using the debug template.\n");
+ OS::get_singleton()->print(" --export-pack <preset> <path> Same as --export, but only export the game pack for the given preset. The <path> extension determines whether it will be in PCK or ZIP format.\n");
+ OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n");
+ OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
+ OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
#ifdef DEBUG_METHODS_ENABLED
- OS::get_singleton()->print(" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n");
+ OS::get_singleton()->print(" --gdnative-generate-json-api <path> Generate JSON dump of the Godot API for GDNative bindings and save it on the file specified in <path>.\n");
+ OS::get_singleton()->print(" --gdnative-generate-json-builtin-api <path> Generate JSON dump of the Godot API of the builtin Variant types and utility functions for GDNative bindings and save it on the file specified in <path>.\n");
#endif
#ifdef TESTS_ENABLED
- OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n");
+ OS::get_singleton()->print(" --test [--help] Run unit tests. Use --test --help for more information.\n");
#endif
OS::get_singleton()->print("\n");
#endif
@@ -515,8 +516,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
MAIN_PRINT("Main: Initialize Globals");
- Thread::_main_thread_id = Thread::get_caller_id();
-
globals = memnew(ProjectSettings);
input_map = memnew(InputMap);
@@ -879,7 +878,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
auto_build_solutions = true;
editor = true;
#ifdef DEBUG_METHODS_ENABLED
- } else if (I->get() == "--gdnative-generate-json-api") {
+ } else if (I->get() == "--gdnative-generate-json-api" || I->get() == "--gdnative-generate-json-builtin-api") {
// Register as an editor instance to use low-end fallback if relevant.
editor = true;
@@ -1470,9 +1469,11 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
// Print engine name and version
print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
+#if !defined(NO_THREADS)
if (p_main_tid_override) {
- Thread::_main_thread_id = p_main_tid_override;
+ Thread::main_thread_id = p_main_tid_override;
}
+#endif
/* Determine text driver */
diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp
index 632682a15d..9144a781a0 100644
--- a/modules/bullet/bullet_physics_server.cpp
+++ b/modules/bullet/bullet_physics_server.cpp
@@ -625,14 +625,14 @@ uint32_t BulletPhysicsServer3D::body_get_user_flags(RID p_body) const {
return 0;
}
-void BulletPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, float p_value) {
+void BulletPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
body->set_param(p_param, p_value);
}
-float BulletPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const {
+real_t BulletPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0);
@@ -807,11 +807,11 @@ int BulletPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const {
return body->get_max_collisions_detection();
}
-void BulletPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) {
+void BulletPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) {
// Not supported by bullet and even Godot
}
-float BulletPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const {
+real_t BulletPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const {
// Not supported by bullet and even Godot
return 0.;
}
@@ -862,7 +862,7 @@ bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform &p_from
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes);
}
-int BulletPhysicsServer3D::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) {
+int BulletPhysicsServer3D::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, 0);
ERR_FAIL_COND_V(!body->get_space(), 0);
@@ -1221,7 +1221,7 @@ RID BulletPhysicsServer3D::joint_create_pin(RID p_body_A, const Vector3 &p_local
CreateThenReturnRID(joint_owner, joint);
}
-void BulletPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) {
+void BulletPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_PIN);
@@ -1229,7 +1229,7 @@ void BulletPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_par
pin_joint->set_param(p_param, p_value);
}
-float BulletPhysicsServer3D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
+real_t BulletPhysicsServer3D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0);
@@ -1309,7 +1309,7 @@ RID BulletPhysicsServer3D::joint_create_hinge_simple(RID p_body_A, const Vector3
CreateThenReturnRID(joint_owner, joint);
}
-void BulletPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) {
+void BulletPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_HINGE);
@@ -1317,7 +1317,7 @@ void BulletPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p
hinge_joint->set_param(p_param, p_value);
}
-float BulletPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
+real_t BulletPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0);
@@ -1361,7 +1361,7 @@ RID BulletPhysicsServer3D::joint_create_slider(RID p_body_A, const Transform &p_
CreateThenReturnRID(joint_owner, joint);
}
-void BulletPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) {
+void BulletPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER);
@@ -1369,7 +1369,7 @@ void BulletPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam
slider_joint->set_param(p_param, p_value);
}
-float BulletPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
+real_t BulletPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_SLIDER, 0);
@@ -1395,7 +1395,7 @@ RID BulletPhysicsServer3D::joint_create_cone_twist(RID p_body_A, const Transform
CreateThenReturnRID(joint_owner, joint);
}
-void BulletPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) {
+void BulletPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST);
@@ -1403,7 +1403,7 @@ void BulletPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJoi
coneTwist_joint->set_param(p_param, p_value);
}
-float BulletPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
+real_t BulletPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0.);
ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0.);
@@ -1431,7 +1431,7 @@ RID BulletPhysicsServer3D::joint_create_generic_6dof(RID p_body_A, const Transfo
CreateThenReturnRID(joint_owner, joint);
}
-void BulletPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value) {
+void BulletPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND(!joint);
ERR_FAIL_COND(joint->get_type() != JOINT_6DOF);
@@ -1439,7 +1439,7 @@ void BulletPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::A
generic_6dof_joint->set_param(p_axis, p_param, p_value);
}
-float BulletPhysicsServer3D::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) {
+real_t BulletPhysicsServer3D::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) {
JointBullet *joint = joint_owner.getornull(p_joint);
ERR_FAIL_COND_V(!joint, 0);
ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0);
@@ -1525,7 +1525,7 @@ void BulletPhysicsServer3D::init() {
BulletPhysicsDirectBodyState3D::initSingleton();
}
-void BulletPhysicsServer3D::step(float p_deltaTime) {
+void BulletPhysicsServer3D::step(real_t p_deltaTime) {
if (!active) {
return;
}
diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h
index b5dc84c8f5..f2740c9c75 100644
--- a/modules/bullet/bullet_physics_server.h
+++ b/modules/bullet/bullet_physics_server.h
@@ -207,8 +207,8 @@ public:
/// This is not supported by physics server
virtual uint32_t body_get_user_flags(RID p_body) const override;
- virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) override;
- virtual float body_get_param(RID p_body, BodyParameter p_param) const override;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) override;
+ virtual real_t body_get_param(RID p_body, BodyParameter p_param) const override;
virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) override;
virtual real_t body_get_kinematic_safe_margin(RID p_body) const override;
@@ -241,8 +241,8 @@ public:
virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
virtual int body_get_max_contacts_reported(RID p_body) const override;
- virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) override;
- virtual float body_get_contacts_reported_depth_threshold(RID p_body) const override;
+ virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) override;
+ virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const override;
virtual void body_set_omit_force_integration(RID p_body, bool p_omit) override;
virtual bool body_is_omitting_force_integration(RID p_body) const override;
@@ -256,7 +256,7 @@ public:
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
- virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) override;
+ virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
/* SOFT BODY API */
@@ -337,8 +337,8 @@ public:
virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) override;
- virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) override;
- virtual float pin_joint_get_param(RID p_joint, PinJointParam p_param) const override;
+ virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) override;
+ virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const override;
virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) override;
virtual Vector3 pin_joint_get_local_a(RID p_joint) const override;
@@ -349,8 +349,8 @@ public:
virtual RID joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) override;
virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) override;
- virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) override;
- virtual float hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const override;
+ virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) override;
+ virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const override;
virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) override;
virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const override;
@@ -358,20 +358,20 @@ public:
/// Reference frame is A
virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override;
- virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) override;
- virtual float slider_joint_get_param(RID p_joint, SliderJointParam p_param) const override;
+ virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) override;
+ virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const override;
/// Reference frame is A
virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override;
- virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) override;
- virtual float cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const override;
+ virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) override;
+ virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const override;
/// Reference frame is A
virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) override;
- virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value) override;
- virtual float generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) override;
+ virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) override;
+ virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) override;
virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) override;
virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) override;
@@ -393,7 +393,7 @@ public:
}
virtual void init() override;
- virtual void step(float p_deltaTime) override;
+ virtual void step(real_t p_deltaTime) override;
virtual void flush_queries() override;
virtual void finish() override;
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 4763098584..a5093afe9d 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -56,11 +56,11 @@ Vector3 BulletPhysicsDirectBodyState3D::get_total_gravity() const {
return gVec;
}
-float BulletPhysicsDirectBodyState3D::get_total_angular_damp() const {
+real_t BulletPhysicsDirectBodyState3D::get_total_angular_damp() const {
return body->btBody->getAngularDamping();
}
-float BulletPhysicsDirectBodyState3D::get_total_linear_damp() const {
+real_t BulletPhysicsDirectBodyState3D::get_total_linear_damp() const {
return body->btBody->getLinearDamping();
}
@@ -74,7 +74,7 @@ Basis BulletPhysicsDirectBodyState3D::get_principal_inertia_axes() const {
return Basis();
}
-float BulletPhysicsDirectBodyState3D::get_inverse_mass() const {
+real_t BulletPhysicsDirectBodyState3D::get_inverse_mass() const {
return body->btBody->getInvMass();
}
@@ -158,7 +158,7 @@ Vector3 BulletPhysicsDirectBodyState3D::get_contact_local_normal(int p_contact_i
return body->collisions[p_contact_idx].hitNormal;
}
-float BulletPhysicsDirectBodyState3D::get_contact_impulse(int p_contact_idx) const {
+real_t BulletPhysicsDirectBodyState3D::get_contact_impulse(int p_contact_idx) const {
return body->collisions[p_contact_idx].appliedImpulse;
}
@@ -412,7 +412,7 @@ void RigidBodyBullet::on_collision_checker_end() {
isTransformChanged = btBody->isActive() && !btBody->isStaticOrKinematicObject();
}
-bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) {
+bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const real_t &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) {
if (collisionsCount >= maxCollisionsDetection) {
return false;
}
@@ -710,12 +710,12 @@ bool RigidBodyBullet::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const {
}
void RigidBodyBullet::reload_axis_lock() {
- btBody->setLinearFactor(btVector3(float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_X)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Y)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Z))));
+ btBody->setLinearFactor(btVector3(btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_X)), btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Y)), btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Z))));
if (PhysicsServer3D::BODY_MODE_CHARACTER == mode) {
/// When character angular is always locked
btBody->setAngularFactor(btVector3(0., 0., 0.));
} else {
- btBody->setAngularFactor(btVector3(float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_X)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Y)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Z))));
+ btBody->setAngularFactor(btVector3(btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_X)), btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Y)), btScalar(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Z))));
}
}
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index fc3f2db796..57b80cf50c 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -89,13 +89,13 @@ private:
public:
virtual Vector3 get_total_gravity() const override;
- virtual float get_total_angular_damp() const override;
- virtual float get_total_linear_damp() const override;
+ virtual real_t get_total_angular_damp() const override;
+ virtual real_t get_total_linear_damp() const override;
virtual Vector3 get_center_of_mass() const override;
virtual Basis get_principal_inertia_axes() const override;
// get the mass
- virtual float get_inverse_mass() const override;
+ virtual real_t get_inverse_mass() const override;
// get density of this body space
virtual Vector3 get_inverse_inertia() const override;
// get density of this body space
@@ -124,7 +124,7 @@ public:
virtual Vector3 get_contact_local_position(int p_contact_idx) const override;
virtual Vector3 get_contact_local_normal(int p_contact_idx) const override;
- virtual float get_contact_impulse(int p_contact_idx) const override;
+ virtual real_t get_contact_impulse(int p_contact_idx) const override;
virtual int get_contact_local_shape(int p_contact_idx) const override;
virtual RID get_contact_collider(int p_contact_idx) const override;
@@ -150,7 +150,7 @@ public:
Vector3 hitLocalLocation;
Vector3 hitWorldLocation;
Vector3 hitNormal;
- float appliedImpulse;
+ real_t appliedImpulse;
};
struct ForceIntegrationCallback {
@@ -264,7 +264,7 @@ public:
}
bool can_add_collision() { return collisionsCount < maxCollisionsDetection; }
- bool add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index);
+ bool add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const real_t &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index);
bool was_colliding(RigidBodyBullet *p_other_object);
void set_activation_state(bool p_active);
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index cc2ec28a9e..82876ab77c 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -480,7 +480,11 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
Vector<real_t> l_heights;
Variant l_heights_v = d["heights"];
+#ifdef REAL_T_IS_DOUBLE
+ if (l_heights_v.get_type() == Variant::PACKED_FLOAT64_ARRAY) {
+#else
if (l_heights_v.get_type() == Variant::PACKED_FLOAT32_ARRAY) {
+#endif
// Ready-to-use heights can be passed
l_heights = l_heights_v;
@@ -503,7 +507,7 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
real_t *w = l_heights.ptrw();
const uint8_t *r = im_data.ptr();
- float *rp = (float *)r;
+ real_t *rp = (real_t *)r;
// At this point, `rp` could be used directly for Bullet, but I don't know how safe it would be.
for (int i = 0; i < l_heights.size(); ++i) {
@@ -511,7 +515,11 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
}
} else {
+#ifdef REAL_T_IS_DOUBLE
+ ERR_FAIL_MSG("Expected PackedFloat64Array or float Image.");
+#else
ERR_FAIL_MSG("Expected PackedFloat32Array or float Image.");
+#endif
}
ERR_FAIL_COND(l_width <= 0);
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index d7dd11d2a5..79a5fdb3d2 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -117,7 +117,7 @@ bool BulletPhysicsDirectSpaceState::intersect_ray(const Vector3 &p_from, const V
}
}
-int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0) {
return 0;
}
@@ -152,7 +152,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra
return btQuery.m_count;
}
-bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &r_closest_safe, float &r_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
+bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &r_closest_safe, real_t &r_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) {
r_closest_safe = 0.0f;
r_closest_unsafe = 0.0f;
btVector3 bt_motion;
@@ -214,7 +214,7 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
}
/// Returns the list of contacts pairs in this order: Local contact, other body contact
-bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
if (p_result_max <= 0) {
return false;
}
@@ -250,7 +250,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform &
return btQuery.m_count;
}
-bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
+bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) {
ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->getornull(p_shape);
ERR_FAIL_COND_V(!shape, false);
@@ -841,7 +841,7 @@ void SpaceBullet::check_body_collision() {
Vector3 collisionWorldPosition;
Vector3 collisionLocalPosition;
Vector3 normalOnB;
- float appliedImpulse = pt.m_appliedImpulse;
+ real_t appliedImpulse = pt.m_appliedImpulse;
B_TO_G(pt.m_normalWorldOnB, normalOnB);
// The pt.m_index only contains the shape index when more than one collision shape is used
@@ -1062,7 +1062,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f
return has_penetration;
}
-int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, float p_margin) {
+int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin) {
btTransform body_transform;
G_TO_B(p_transform, body_transform);
UNSCALE_BT_BASIS(body_transform);
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index 0f2482e551..1caa3c2a0c 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -78,11 +78,11 @@ public:
virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override;
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &r_closest_safe, float &r_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
+ virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &r_closest_safe, real_t &r_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) override;
/// Returns the list of contacts pairs in this order: Local contact, other body contact
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
+ virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override;
};
@@ -189,7 +189,7 @@ public:
real_t get_angular_damp() const { return angular_damp; }
bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes);
- int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, float p_margin);
+ int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin);
private:
void create_empty_world(bool p_create_soft_world);
diff --git a/modules/cvtt/image_compress_cvtt.cpp b/modules/cvtt/image_compress_cvtt.cpp
index 6661dbbb0b..43faa52218 100644
--- a/modules/cvtt/image_compress_cvtt.cpp
+++ b/modules/cvtt/image_compress_cvtt.cpp
@@ -267,12 +267,13 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::UsedChann
job_queue.num_tasks = static_cast<uint32_t>(tasks.size());
for (int i = 0; i < num_job_threads; i++) {
- threads_wb[i] = Thread::create(_digest_job_queue, &job_queue);
+ threads_wb[i] = memnew(Thread);
+ threads_wb[i]->start(_digest_job_queue, &job_queue);
}
_digest_job_queue(&job_queue);
for (int i = 0; i < num_job_threads; i++) {
- Thread::wait_to_finish(threads_wb[i]);
+ threads_wb[i]->wait_to_finish();
memdelete(threads_wb[i]);
}
}
diff --git a/modules/gdnative/android/android_gdn.cpp b/modules/gdnative/android/android_gdn.cpp
index a48e51a390..fe3b3e7e12 100644
--- a/modules/gdnative/android/android_gdn.cpp
+++ b/modules/gdnative/android/android_gdn.cpp
@@ -48,7 +48,7 @@ extern "C" {
JNIEnv *GDAPI godot_android_get_env() {
#ifdef __ANDROID__
- return ThreadAndroid::get_env();
+ return get_jni_env();
#else
return nullptr;
#endif
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index 6b46c9418a..2b824938f2 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -36,6 +36,7 @@
#include "core/core_constants.h"
#include "core/object/class_db.h"
#include "core/os/file_access.h"
+#include "core/string/string_builder.h"
#include "core/templates/pair.h"
// helper stuff
@@ -65,14 +66,14 @@ struct MethodAPI {
Map<int, Variant> default_arguments;
- int argument_count;
- bool has_varargs;
- bool is_editor;
- bool is_noscript;
- bool is_const;
- bool is_reverse;
- bool is_virtual;
- bool is_from_script;
+ int argument_count = 0;
+ bool has_varargs = false;
+ bool is_editor = false;
+ bool is_noscript = false;
+ bool is_const = false;
+ bool is_reverse = false;
+ bool is_virtual = false;
+ bool is_from_script = false;
};
struct PropertyAPI {
@@ -80,12 +81,14 @@ struct PropertyAPI {
String getter;
String setter;
String type;
- int index;
+ int index = 0;
};
struct ConstantAPI {
String constant_name;
- int constant_value;
+ int constant_value = 0;
+ Variant builtin_constant_value; // For builtin types;
+ String builtin_constant_type; // For builtin types;
};
struct SignalAPI {
@@ -100,23 +103,34 @@ struct EnumAPI {
List<Pair<int, String>> values;
};
+struct OperatorAPI { // For builtin types;
+ String name;
+ int oper = Variant::OP_MAX;
+ String other_type;
+ String return_type;
+};
+
struct ClassAPI {
String class_name;
String super_class_name;
- ClassDB::APIType api_type;
+ ClassDB::APIType api_type = ClassDB::API_NONE;
- bool is_singleton;
+ bool is_singleton = false;
String singleton_name;
- bool is_instanciable;
+ bool is_instantiable = false;
// @Unclear
- bool is_reference;
+ bool is_reference = false;
+ bool has_indexing = false; // For builtin types.
+ bool is_keyed = false; // For builtin types.
List<MethodAPI> methods;
+ List<MethodAPI> constructors; // For builtin types.
List<PropertyAPI> properties;
List<ConstantAPI> constants;
List<SignalAPI> signals_;
List<EnumAPI> enums;
+ List<OperatorAPI> operators; // For builtin types.
};
static String get_type_name(const PropertyInfo &info) {
@@ -180,7 +194,7 @@ List<ClassAPI> generate_c_api_classes() {
global_constants_api.api_type = ClassDB::API_CORE;
global_constants_api.is_singleton = true;
global_constants_api.singleton_name = "CoreConstants";
- global_constants_api.is_instanciable = false;
+ global_constants_api.is_instantiable = false;
const int constants_count = CoreConstants::get_global_constant_count();
for (int i = 0; i < constants_count; ++i) {
ConstantAPI constant_api;
@@ -195,6 +209,10 @@ List<ClassAPI> generate_c_api_classes() {
for (List<StringName>::Element *e = classes.front(); e != nullptr; e = e->next()) {
StringName class_name = e->get();
+ if (!ClassDB::is_class_exposed(class_name)) {
+ continue;
+ }
+
ClassAPI class_api;
class_api.api_type = ClassDB::get_api_type(e->get());
class_api.class_name = class_name;
@@ -209,7 +227,7 @@ List<ClassAPI> generate_c_api_classes() {
class_api.singleton_name = name;
}
}
- class_api.is_instanciable = !class_api.is_singleton && ClassDB::can_instance(class_name);
+ class_api.is_instantiable = !class_api.is_singleton && ClassDB::can_instance(class_name);
{
List<StringName> inheriters;
@@ -402,6 +420,191 @@ List<ClassAPI> generate_c_api_classes() {
}
/*
+ * Reads the builtin Variant API to a list
+ */
+List<ClassAPI> generate_c_builtin_api_types() {
+ List<ClassAPI> api;
+
+ // Special class for the utility methods.
+ {
+ ClassAPI utility_api;
+ utility_api.class_name = "Utilities";
+ utility_api.is_instantiable = false;
+
+ List<StringName> utility_functions;
+ Variant::get_utility_function_list(&utility_functions);
+ for (const List<StringName>::Element *E = utility_functions.front(); E; E = E->next()) {
+ const StringName &function_name = E->get();
+
+ MethodAPI function_api;
+ function_api.method_name = function_name;
+ function_api.has_varargs = Variant::is_utility_function_vararg(function_name);
+ function_api.argument_count = function_api.has_varargs ? 0 : Variant::get_utility_function_argument_count(function_name);
+ function_api.is_const = Variant::get_utility_function_type(function_name) == Variant::UTILITY_FUNC_TYPE_MATH;
+
+ for (int i = 0; i < function_api.argument_count; i++) {
+ function_api.argument_names.push_back(Variant::get_utility_function_argument_name(function_name, i));
+ Variant::Type arg_type = Variant::get_utility_function_argument_type(function_name, i);
+ function_api.argument_types.push_back(arg_type == Variant::NIL ? "Variant" : Variant::get_type_name(arg_type));
+ }
+
+ if (Variant::has_utility_function_return_value(function_name)) {
+ Variant::Type ret_type = Variant::get_utility_function_return_type(function_name);
+ function_api.return_type = ret_type == Variant::NIL ? "Variant" : Variant::get_type_name(ret_type);
+ } else {
+ function_api.return_type = "void";
+ }
+
+ utility_api.methods.push_back(function_api);
+ }
+
+ api.push_back(utility_api);
+ }
+
+ for (int t = 0; t < Variant::VARIANT_MAX; t++) {
+ Variant::Type type = (Variant::Type)t;
+
+ ClassAPI class_api;
+ class_api.class_name = Variant::get_type_name(type);
+ class_api.is_instantiable = true;
+ class_api.has_indexing = Variant::has_indexing(type);
+ class_api.is_keyed = Variant::is_keyed(type);
+ // Types that are passed by reference.
+ switch (type) {
+ case Variant::OBJECT:
+ case Variant::DICTIONARY:
+ case Variant::ARRAY:
+ case Variant::PACKED_BYTE_ARRAY:
+ case Variant::PACKED_INT32_ARRAY:
+ case Variant::PACKED_INT64_ARRAY:
+ case Variant::PACKED_FLOAT32_ARRAY:
+ case Variant::PACKED_FLOAT64_ARRAY:
+ case Variant::PACKED_STRING_ARRAY:
+ case Variant::PACKED_VECTOR2_ARRAY:
+ case Variant::PACKED_VECTOR3_ARRAY:
+ case Variant::PACKED_COLOR_ARRAY:
+ class_api.is_reference = true;
+ break;
+ default:
+ class_api.is_reference = false;
+ break;
+ }
+
+ // Methods.
+
+ List<StringName> methods;
+ Variant::get_builtin_method_list(type, &methods);
+ for (const List<StringName>::Element *E = methods.front(); E; E = E->next()) {
+ const StringName &method_name = E->get();
+
+ MethodAPI method_api;
+
+ method_api.method_name = method_name;
+ method_api.argument_count = Variant::get_builtin_method_argument_count(type, method_name);
+ method_api.has_varargs = Variant::is_builtin_method_vararg(type, method_name);
+ method_api.is_const = Variant::is_builtin_method_const(type, method_name);
+
+ for (int i = 0; i < method_api.argument_count; i++) {
+ method_api.argument_names.push_back(Variant::get_builtin_method_argument_name(type, method_name, i));
+ Variant::Type arg_type = Variant::get_builtin_method_argument_type(type, method_name, i);
+ method_api.argument_types.push_back(arg_type == Variant::NIL ? "Variant" : Variant::get_type_name(arg_type));
+ }
+
+ Vector<Variant> default_arguments = Variant::get_builtin_method_default_arguments(type, method_name);
+
+ int default_start = method_api.argument_names.size() - default_arguments.size();
+
+ for (int i = 0; i < default_arguments.size(); i++) {
+ method_api.default_arguments[default_start + i] = default_arguments[i];
+ }
+
+ if (Variant::has_builtin_method_return_value(type, method_name)) {
+ Variant::Type ret_type = Variant::get_builtin_method_return_type(type, method_name);
+ method_api.return_type = ret_type == Variant::NIL ? "Variant" : Variant::get_type_name(ret_type);
+ } else {
+ method_api.return_type = "void";
+ }
+
+ class_api.methods.push_back(method_api);
+ }
+
+ // Constructors.
+
+ for (int c = 0; c < Variant::get_constructor_count(type); c++) {
+ MethodAPI constructor_api;
+
+ constructor_api.method_name = Variant::get_type_name(type);
+ constructor_api.argument_count = Variant::get_constructor_argument_count(type, c);
+ constructor_api.return_type = Variant::get_type_name(type);
+
+ for (int i = 0; i < constructor_api.argument_count; i++) {
+ constructor_api.argument_names.push_back(Variant::get_constructor_argument_name(type, c, i));
+ Variant::Type arg_type = Variant::get_constructor_argument_type(type, c, i);
+ constructor_api.argument_types.push_back(arg_type == Variant::NIL ? "Variant" : Variant::get_type_name(arg_type));
+ }
+
+ class_api.constructors.push_back(constructor_api);
+ }
+
+ // Constants.
+
+ List<StringName> constants;
+ Variant::get_constants_for_type(type, &constants);
+ for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) {
+ const StringName &constant_name = E->get();
+ ConstantAPI constant_api;
+
+ constant_api.constant_name = constant_name;
+ constant_api.builtin_constant_value = Variant::get_constant_value(type, constant_name);
+ constant_api.builtin_constant_type = Variant::get_type_name(constant_api.builtin_constant_value.get_type());
+
+ class_api.constants.push_back(constant_api);
+ }
+
+ // Members.
+
+ List<StringName> members;
+ Variant::get_member_list(type, &members);
+ for (const List<StringName>::Element *E = members.front(); E; E = E->next()) {
+ const StringName &member_name = E->get();
+
+ PropertyAPI member_api;
+ member_api.name = member_name;
+ Variant::Type member_type = Variant::get_member_type(type, member_name);
+ member_api.type = member_type == Variant::NIL ? "Variant" : Variant::get_type_name(member_type);
+
+ class_api.properties.push_back(member_api);
+ }
+
+ // Operators.
+
+ for (int op = 0; op < Variant::OP_MAX; op++) {
+ Variant::Operator oper = (Variant::Operator)op;
+
+ for (int ot = 0; ot < Variant::VARIANT_MAX; ot++) {
+ Variant::Type other_type = (Variant::Type)ot;
+
+ if (!Variant::get_validated_operator_evaluator(oper, type, other_type)) {
+ continue;
+ }
+
+ OperatorAPI oper_api;
+ oper_api.name = Variant::get_operator_name(oper);
+ oper_api.oper = oper;
+ oper_api.other_type = Variant::get_type_name(other_type);
+ oper_api.return_type = Variant::get_type_name(Variant::get_operator_return_type(oper, type, other_type));
+
+ class_api.operators.push_back(oper_api);
+ }
+ }
+
+ api.push_back(class_api);
+ }
+
+ return api;
+}
+
+/*
* Generates the JSON source from the API in p_api
*/
static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
@@ -421,9 +624,8 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
source.push_back(String("\t\t\"api_type\": \"") + (api.api_type == ClassDB::API_CORE ? "core" : (api.api_type == ClassDB::API_EDITOR ? "tools" : "none")) + "\",\n");
source.push_back(String("\t\t\"singleton\": ") + (api.is_singleton ? "true" : "false") + ",\n");
source.push_back("\t\t\"singleton_name\": \"" + api.singleton_name + "\",\n");
- source.push_back(String("\t\t\"instanciable\": ") + (api.is_instanciable ? "true" : "false") + ",\n");
+ source.push_back(String("\t\t\"instantiable\": ") + (api.is_instantiable ? "true" : "false") + ",\n");
source.push_back(String("\t\t\"is_reference\": ") + (api.is_reference ? "true" : "false") + ",\n");
- // @Unclear
source.push_back("\t\t\"constants\": {\n");
for (List<ConstantAPI>::Element *e = api.constants.front(); e; e = e->next()) {
@@ -508,6 +710,164 @@ static List<String> generate_c_api_json(const List<ClassAPI> &p_api) {
return source;
}
+static int indent_level = 0;
+
+static void append_indented(StringBuilder &p_source, const String &p_text) {
+ for (int i = 0; i < indent_level; i++) {
+ p_source.append("\t");
+ }
+ p_source.append(p_text);
+ p_source.append("\n");
+}
+
+static void append_indented(StringBuilder &p_source, const char *p_text) {
+ for (int i = 0; i < indent_level; i++) {
+ p_source.append("\t");
+ }
+ p_source.append(p_text);
+ p_source.append("\n");
+}
+
+static void write_builtin_method(StringBuilder &p_source, const MethodAPI &p_method) {
+ append_indented(p_source, vformat(R"("name": "%s",)", p_method.method_name));
+ append_indented(p_source, vformat(R"("return_type": "%s",)", p_method.return_type));
+ append_indented(p_source, vformat(R"("is_const": %s,)", p_method.is_const ? "true" : "false"));
+ append_indented(p_source, vformat(R"("has_varargs": %s,)", p_method.has_varargs ? "true" : "false"));
+
+ append_indented(p_source, R"("arguments": [)");
+ indent_level++;
+ for (int i = 0; i < p_method.argument_count; i++) {
+ append_indented(p_source, "{");
+ indent_level++;
+
+ append_indented(p_source, vformat(R"("name": "%s",)", p_method.argument_names[i]));
+ append_indented(p_source, vformat(R"("type": "%s",)", p_method.argument_types[i]));
+ append_indented(p_source, vformat(R"("has_default_value": %s,)", p_method.default_arguments.has(i) ? "true" : "false"));
+ append_indented(p_source, vformat(R"("default_value": "%s")", p_method.default_arguments.has(i) ? p_method.default_arguments[i].operator String() : ""));
+
+ indent_level--;
+ append_indented(p_source, i < p_method.argument_count - 1 ? "}," : "}");
+ }
+ indent_level--;
+ append_indented(p_source, "]");
+}
+
+static List<String> generate_c_builtin_api_json(const List<ClassAPI> &p_api) {
+ StringBuilder source;
+
+ source.append("[\n");
+
+ indent_level = 1;
+
+ for (const List<ClassAPI>::Element *C = p_api.front(); C; C = C->next()) {
+ const ClassAPI &class_api = C->get();
+ append_indented(source, "{");
+ indent_level++;
+
+ append_indented(source, vformat(R"("name": "%s",)", class_api.class_name));
+ append_indented(source, vformat(R"("is_instantiable": %s,)", class_api.is_instantiable ? "true" : "false"));
+ append_indented(source, vformat(R"("is_reference": %s,)", class_api.is_reference ? "true" : "false"));
+ append_indented(source, vformat(R"("has_indexing": %s,)", class_api.has_indexing ? "true" : "false"));
+ append_indented(source, vformat(R"("is_keyed": %s,)", class_api.is_keyed ? "true" : "false"));
+
+ // Constructors.
+ append_indented(source, R"("constructors": [)");
+ indent_level++;
+ for (const List<MethodAPI>::Element *E = class_api.constructors.front(); E; E = E->next()) {
+ const MethodAPI &constructor = E->get();
+ append_indented(source, "{");
+ indent_level++;
+
+ write_builtin_method(source, constructor);
+
+ indent_level--;
+ append_indented(source, E->next() ? "}," : "}");
+ }
+ indent_level--;
+ append_indented(source, "],");
+
+ // Constants.
+ append_indented(source, R"("constants": [)");
+ indent_level++;
+ for (const List<ConstantAPI>::Element *E = class_api.constants.front(); E; E = E->next()) {
+ const ConstantAPI &constant = E->get();
+ append_indented(source, "{");
+ indent_level++;
+
+ append_indented(source, vformat(R"("name": "%s",)", constant.constant_name));
+ append_indented(source, vformat(R"("type": "%s",)", constant.builtin_constant_type));
+ append_indented(source, vformat(R"("value": "%s")", constant.builtin_constant_value.operator String()));
+
+ indent_level--;
+ append_indented(source, E->next() ? "}," : "}");
+ }
+ indent_level--;
+ append_indented(source, "],");
+
+ // Methods.
+ append_indented(source, R"("methods": [)");
+ indent_level++;
+ for (const List<MethodAPI>::Element *E = class_api.methods.front(); E; E = E->next()) {
+ const MethodAPI &method = E->get();
+ append_indented(source, "{");
+ indent_level++;
+
+ write_builtin_method(source, method);
+
+ indent_level--;
+ append_indented(source, E->next() ? "}," : "}");
+ }
+ indent_level--;
+ append_indented(source, "],");
+
+ // Members.
+ append_indented(source, R"("members": [)");
+ indent_level++;
+ for (const List<PropertyAPI>::Element *E = class_api.properties.front(); E; E = E->next()) {
+ const PropertyAPI &member = E->get();
+ append_indented(source, "{");
+ indent_level++;
+
+ append_indented(source, vformat(R"("name": "%s",)", member.name));
+ append_indented(source, vformat(R"("type": "%s")", member.type));
+
+ indent_level--;
+ append_indented(source, E->next() ? "}," : "}");
+ }
+ indent_level--;
+ append_indented(source, "],");
+
+ // Operators.
+ append_indented(source, R"("operators": [)");
+ indent_level++;
+ for (const List<OperatorAPI>::Element *E = class_api.operators.front(); E; E = E->next()) {
+ const OperatorAPI &oper = E->get();
+ append_indented(source, "{");
+ indent_level++;
+
+ append_indented(source, vformat(R"("name": "%s",)", oper.name));
+ append_indented(source, vformat(R"("operator": %d,)", oper.oper));
+ append_indented(source, vformat(R"("other_type": "%s",)", oper.other_type));
+ append_indented(source, vformat(R"("return_type": "%s")", oper.return_type));
+
+ indent_level--;
+ append_indented(source, E->next() ? "}," : "}");
+ }
+ indent_level--;
+ append_indented(source, "]");
+
+ indent_level--;
+ append_indented(source, C->next() ? "}," : "}");
+ }
+
+ indent_level--;
+ source.append("]\n");
+
+ List<String> result;
+ result.push_back(source.as_string());
+ return result;
+}
+
#endif
/*
@@ -526,3 +886,19 @@ Error generate_c_api(const String &p_path) {
return save_file(p_path, json_source);
#endif
}
+/*
+ * Saves the builtin Godot API to a JSON file located at
+ * p_path
+ */
+Error generate_c_builtin_api(const String &p_path) {
+#ifndef TOOLS_ENABLED
+ return ERR_BUG;
+#else
+
+ List<ClassAPI> api = generate_c_builtin_api_types();
+
+ List<String> json_source = generate_c_builtin_api_json(api);
+
+ return save_file(p_path, json_source);
+#endif
+}
diff --git a/modules/gdnative/nativescript/api_generator.h b/modules/gdnative/nativescript/api_generator.h
index a324ded4a9..611abb2a2d 100644
--- a/modules/gdnative/nativescript/api_generator.h
+++ b/modules/gdnative/nativescript/api_generator.h
@@ -35,5 +35,6 @@
#include "core/typedefs.h"
Error generate_c_api(const String &p_path);
+Error generate_c_builtin_api(const String &p_path);
#endif // API_GENERATOR_H
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index 944f4f052c..19cf1f980b 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -1257,6 +1257,15 @@ void NativeScriptLanguage::init() {
}
exit(0);
}
+
+ E = args.find("--gdnative-generate-json-builtin-api");
+
+ if (E && E->next()) {
+ if (generate_c_builtin_api(E->next()->get()) != OK) {
+ ERR_PRINT("Failed to generate C builtin API\n");
+ }
+ exit(0);
+ }
#endif
#ifdef TOOLS_ENABLED
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index aac9cb7fd7..12ed56a568 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -36,7 +36,6 @@
#include "editor/editor_node.h"
GDScriptLanguageServer::GDScriptLanguageServer() {
- thread = nullptr;
thread_running = false;
started = false;
@@ -87,9 +86,8 @@ void GDScriptLanguageServer::start() {
if (protocol.start(port, IP_Address("127.0.0.1")) == OK) {
EditorNode::get_log()->add_message("--- GDScript language server started ---", EditorLog::MSG_TYPE_EDITOR);
if (use_thread) {
- ERR_FAIL_COND(thread != nullptr);
thread_running = true;
- thread = Thread::create(GDScriptLanguageServer::thread_main, this);
+ thread.start(GDScriptLanguageServer::thread_main, this);
}
set_process_internal(!use_thread);
started = true;
@@ -98,11 +96,9 @@ void GDScriptLanguageServer::start() {
void GDScriptLanguageServer::stop() {
if (use_thread) {
- ERR_FAIL_COND(nullptr == thread);
+ ERR_FAIL_COND(!thread.is_started());
thread_running = false;
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = nullptr;
+ thread.wait_to_finish();
}
protocol.stop();
started = false;
diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h
index 218f42199e..7b7837a463 100644
--- a/modules/gdscript/language_server/gdscript_language_server.h
+++ b/modules/gdscript/language_server/gdscript_language_server.h
@@ -40,7 +40,7 @@ class GDScriptLanguageServer : public EditorPlugin {
GDScriptLanguageProtocol protocol;
- Thread *thread;
+ Thread thread;
bool thread_running;
bool started;
bool use_thread;
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 7b502f079b..69cad1a335 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -350,7 +350,7 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) {
String GDScriptWorkspace::get_file_path(const String &p_uri) const {
String path = p_uri;
path = path.replace(root_uri + "/", "res://");
- path = path.http_unescape();
+ path = path.uri_decode();
return path;
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
index 16f91a0925..ed25cdaa63 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
@@ -104,7 +104,7 @@ namespace GodotTools.Ides.Rider
if (line >= 0)
{
args.Add("--line");
- args.Add(line.ToString());
+ args.Add((line + 1).ToString()); // https://github.com/JetBrains/godot-support/issues/61
}
args.Add(scriptPath);
try
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index 0700f197ff..4dc182fb73 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -97,6 +97,36 @@ namespace Godot
return b;
}
+ /// <summary>
+ /// Converts a string containing a binary number into an integer.
+ /// Binary strings can either be prefixed with `0b` or not,
+ /// and they can also start with a `-` before the optional prefix.
+ /// </summary>
+ /// <param name="instance">The string to convert.</param>
+ /// <returns>The converted string.</returns>
+ public static int BinToInt(this string instance)
+ {
+ if (instance.Length == 0)
+ {
+ return 0;
+ }
+
+ int sign = 1;
+
+ if (instance[0] == '-')
+ {
+ sign = -1;
+ instance = instance.Substring(1);
+ }
+
+ if (instance.StartsWith("0b"))
+ {
+ instance = instance.Substring(2);
+ }
+
+ return sign * Convert.ToInt32(instance, 2);;
+ }
+
// <summary>
// Return the amount of substrings in string.
// </summary>
@@ -449,7 +479,7 @@ namespace Godot
/// <summary>
/// Returns a hexadecimal representation of this byte as a string.
/// </summary>
- /// <param name="bytes">The byte to encode.</param>
+ /// <param name="b">The byte to encode.</param>
/// <returns>The hexadecimal representation of this byte.</returns>
internal static string HexEncode(this byte b)
{
@@ -493,11 +523,20 @@ namespace Godot
return ret;
}
- // <summary>
- // Convert a string containing an hexadecimal number into an int.
- // </summary>
+ /// <summary>
+ /// Converts a string containing a hexadecimal number into an integer.
+ /// Hexadecimal strings can either be prefixed with `0x` or not,
+ /// and they can also start with a `-` before the optional prefix.
+ /// </summary>
+ /// <param name="instance">The string to convert.</param>
+ /// <returns>The converted string.</returns>
public static int HexToInt(this string instance)
{
+ if (instance.Length == 0)
+ {
+ return 0;
+ }
+
int sign = 1;
if (instance[0] == '-')
@@ -506,10 +545,12 @@ namespace Godot
instance = instance.Substring(1);
}
- if (!instance.StartsWith("0x"))
- return 0;
+ if (instance.StartsWith("0x"))
+ {
+ instance = instance.Substring(2);
+ }
- return sign * int.Parse(instance.Substring(2), NumberStyles.HexNumber);
+ return sign * int.Parse(instance, NumberStyles.HexNumber);
}
// <summary>
@@ -892,22 +933,6 @@ namespace Godot
}
// <summary>
- // Decode a percent-encoded string. See [method percent_encode].
- // </summary>
- public static string PercentDecode(this string instance)
- {
- return Uri.UnescapeDataString(instance);
- }
-
- // <summary>
- // Percent-encode a string. This is meant to encode parameters in a URL when sending a HTTP GET request and bodies of form-urlencoded POST request.
- // </summary>
- public static string PercentEncode(this string instance)
- {
- return Uri.EscapeDataString(instance);
- }
-
- // <summary>
// If the string is a path, this concatenates [code]file[/code] at the end of the string as a subpath. E.g. [code]"this/is".plus_file("path") == "this/is/path"[/code].
// </summary>
public static string PlusFile(this string instance, string file)
@@ -1169,6 +1194,33 @@ namespace Godot
return Encoding.UTF8.GetBytes(instance);
}
+ /// <summary>
+ /// Decodes a string in URL encoded format. This is meant to
+ /// decode parameters in a URL when receiving an HTTP request.
+ /// This mostly wraps around `System.Uri.UnescapeDataString()`,
+ /// but also handles `+`.
+ /// See <see cref="URIEncode"/> for encoding.
+ /// </summary>
+ /// <param name="instance">The string to decode.</param>
+ /// <returns>The unescaped string.</returns>
+ public static string URIDecode(this string instance)
+ {
+ return Uri.UnescapeDataString(instance.Replace("+", "%20"));
+ }
+
+ /// <summary>
+ /// Encodes a string to URL friendly format. This is meant to
+ /// encode parameters in a URL when sending an HTTP request.
+ /// This wraps around `System.Uri.EscapeDataString()`.
+ /// See <see cref="URIDecode"/> for decoding.
+ /// </summary>
+ /// <param name="instance">The string to encode.</param>
+ /// <returns>The escaped string.</returns>
+ public static string URIEncode(this string instance)
+ {
+ return Uri.EscapeDataString(instance);
+ }
+
// <summary>
// Return a copy of the string with special characters escaped using the XML standard.
// </summary>
diff --git a/modules/mono/mono_gd/support/android_support.cpp b/modules/mono/mono_gd/support/android_support.cpp
index 59e1385e7e..cba29d63cd 100644
--- a/modules/mono/mono_gd/support/android_support.cpp
+++ b/modules/mono/mono_gd/support/android_support.cpp
@@ -109,7 +109,7 @@ bool jni_exception_check(JNIEnv *p_env) {
String app_native_lib_dir_cache;
String determine_app_native_lib_dir() {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
ScopedLocalRef<jclass> activityThreadClass(env, env->FindClass("android/app/ActivityThread"));
jmethodID currentActivityThread = env->GetStaticMethodID(activityThreadClass, "currentActivityThread", "()Landroid/app/ActivityThread;");
@@ -253,7 +253,7 @@ int32_t get_build_version_sdk_int() {
// android.os.Build.VERSION.SDK_INT
if (build_version_sdk_int == 0) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jclass versionClass = env->FindClass("android/os/Build$VERSION");
ERR_FAIL_NULL_V(versionClass, 0);
@@ -281,7 +281,7 @@ MonoBoolean _gd_mono_init_cert_store() {
// return false;
// }
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
ScopedLocalRef<jclass> keyStoreClass(env, env->FindClass("java/security/KeyStore"));
@@ -322,7 +322,7 @@ MonoArray *_gd_mono_android_cert_store_lookup(MonoString *p_alias) {
return nullptr;
}
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
ScopedLocalRef<jstring> js_alias(env, env->NewStringUTF(alias_utf8));
mono_free(alias_utf8);
@@ -380,7 +380,7 @@ void cleanup() {
if (godot_dl_handle)
gd_mono_android_dlclose(godot_dl_handle, nullptr);
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
if (certStore) {
env->DeleteGlobalRef(certStore);
@@ -437,7 +437,7 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_up_state(const char
*r_is_up = 0;
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
ERR_FAIL_NULL_V(networkInterfaceClass, 0);
@@ -469,7 +469,7 @@ GD_PINVOKE_EXPORT mono_bool _monodroid_get_network_interface_supports_multicast(
*r_supports_multicast = 0;
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
ERR_FAIL_NULL_V(networkInterfaceClass, 0);
@@ -507,7 +507,7 @@ static void interop_get_active_network_dns_servers(char **r_dns_servers, int *dn
CRASH_COND(get_build_version_sdk_int() < 23);
#endif
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
GodotJavaWrapper *godot_java = ((OS_Android *)OS::get_singleton())->get_godot_java();
jobject activity = godot_java->get_activity();
@@ -648,7 +648,7 @@ GD_PINVOKE_EXPORT const char *_monodroid_timezone_get_default_id() {
//
// TimeZone.getDefault().getID()
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
ScopedLocalRef<jclass> timeZoneClass(env, env->FindClass("java/util/TimeZone"));
ERR_FAIL_NULL_V(timeZoneClass, nullptr);
diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp
index 1d75e46747..30a0ca3464 100644
--- a/modules/opensimplex/noise_texture.cpp
+++ b/modules/opensimplex/noise_texture.cpp
@@ -34,7 +34,6 @@
NoiseTexture::NoiseTexture() {
update_queued = false;
- noise_thread = nullptr;
regen_queued = false;
first_time = true;
@@ -52,10 +51,7 @@ NoiseTexture::~NoiseTexture() {
if (texture.is_valid()) {
RS::get_singleton()->free(texture);
}
- if (noise_thread) {
- Thread::wait_to_finish(noise_thread);
- memdelete(noise_thread);
- }
+ noise_thread.wait_to_finish();
}
void NoiseTexture::_bind_methods() {
@@ -109,11 +105,9 @@ void NoiseTexture::_set_texture_data(const Ref<Image> &p_image) {
void NoiseTexture::_thread_done(const Ref<Image> &p_image) {
_set_texture_data(p_image);
- Thread::wait_to_finish(noise_thread);
- memdelete(noise_thread);
- noise_thread = nullptr;
+ noise_thread.wait_to_finish();
if (regen_queued) {
- noise_thread = Thread::create(_thread_function, this);
+ noise_thread.start(_thread_function, this);
regen_queued = false;
}
}
@@ -165,8 +159,8 @@ void NoiseTexture::_update_texture() {
use_thread = false;
#endif
if (use_thread) {
- if (!noise_thread) {
- noise_thread = Thread::create(_thread_function, this);
+ if (!noise_thread.is_started()) {
+ noise_thread.start(_thread_function, this);
regen_queued = false;
} else {
regen_queued = true;
diff --git a/modules/opensimplex/noise_texture.h b/modules/opensimplex/noise_texture.h
index 9f6e2cbf43..170275bd2e 100644
--- a/modules/opensimplex/noise_texture.h
+++ b/modules/opensimplex/noise_texture.h
@@ -45,7 +45,7 @@ class NoiseTexture : public Texture2D {
private:
Ref<Image> data;
- Thread *noise_thread;
+ Thread noise_thread;
bool first_time;
bool update_queued;
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 243265769e..1026d58b85 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -140,9 +140,7 @@ void VideoStreamPlaybackTheora::clear() {
#ifdef THEORA_USE_THREAD_STREAMING
thread_exit = true;
thread_sem->post(); //just in case
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = nullptr;
+ thread.wait_to_finish();
ring_buffer.clear();
#endif
@@ -181,7 +179,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
int read = file->get_buffer(read_buffer.ptr(), to_read);
ring_buffer.write(read_buffer.ptr(), read);
- thread = Thread::create(_streaming_thread, this);
+ thread.start(_streaming_thread, this);
#endif
@@ -669,7 +667,6 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
ring_buffer.resize(rb_power);
read_buffer.resize(RB_SIZE_KB * 1024);
thread_sem = Semaphore::create();
- thread = nullptr;
thread_exit = false;
thread_eof = false;
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index d2036b5cb4..c315d682da 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -112,7 +112,7 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
Vector<uint8_t> read_buffer;
bool thread_eof;
Semaphore *thread_sem;
- Thread *thread;
+ Thread thread;
volatile bool thread_exit;
static void _streaming_thread(void *ud);
diff --git a/modules/webxr/doc_classes/WebXRInterface.xml b/modules/webxr/doc_classes/WebXRInterface.xml
index bddffd910e..2407d44496 100644
--- a/modules/webxr/doc_classes/WebXRInterface.xml
+++ b/modules/webxr/doc_classes/WebXRInterface.xml
@@ -10,75 +10,79 @@
Since WebXR is based on Javascript, it makes extensive use of callbacks, which means that [WebXRInterface] is forced to use signals, where other AR/VR interfaces would instead use functions that return a result immediately. This makes [WebXRInterface] quite a bit more complicated to intialize than other AR/VR interfaces.
Here's the minimum code required to start an immersive VR session:
[codeblock]
- var webxr_interface
- var vr_supported = false
+ extends Node3D
- func _ready():
- # We assume this node has a canvas layer with a button on it as a child.
- # This button is for the user to consent to entering immersive VR mode.
- $CanvasLayer/Button.connect("pressed", self, "_on_Button_pressed")
+ var webxr_interface
+ var vr_supported = false
- webxr_interface = XRServer.find_interface("WebXR")
- if webxr_interface:
- # WebXR uses a lot of asynchronous callbacks, so we connect to various
- # signals in order to receive them.
- webxr_interface.connect("session_supported", self, "_webxr_session_supported")
- webxr_interface.connect("session_started", self, "_webxr_session_started")
- webxr_interface.connect("session_ended", self, "_webxr_session_ended")
- webxr_interface.connect("session_failed", self, "_webxr_session_failed")
+ func _ready():
+ # We assume this node has a button as a child.
+ # This button is for the user to consent to entering immersive VR mode.
+ $Button.connect("pressed", self, "_on_Button_pressed")
- # This returns immediately - our _webxr_session_supported() method
- # (which we connected to the "session_supported" signal above) will
- # be called sometime later to let us know if it's supported or not.
- webxr_interface.is_session_supported("immersive-vr")
+ webxr_interface = XRServer.find_interface("WebXR")
+ if webxr_interface:
+ # WebXR uses a lot of asynchronous callbacks, so we connect to various
+ # signals in order to receive them.
+ webxr_interface.connect("session_supported", self, "_webxr_session_supported")
+ webxr_interface.connect("session_started", self, "_webxr_session_started")
+ webxr_interface.connect("session_ended", self, "_webxr_session_ended")
+ webxr_interface.connect("session_failed", self, "_webxr_session_failed")
- func _webxr_session_supported(session_mode, supported):
- if session_mode == 'immersive-vr':
- vr_supported = supported
+ # This returns immediately - our _webxr_session_supported() method
+ # (which we connected to the "session_supported" signal above) will
+ # be called sometime later to let us know if it's supported or not.
+ webxr_interface.is_session_supported("immersive-vr")
- func _on_Button_pressed():
- if not vr_supported:
- OS.alert("Your browser doesn't support VR")
- return
+ func _webxr_session_supported(session_mode, supported):
+ if session_mode == 'immersive-vr':
+ vr_supported = supported
- # We want an immersive VR session, as opposed to AR ('immersive-ar') or a
- # simple 3DoF viewer ('viewer').
- webxr_interface.session_mode = 'immersive-vr'
- # 'bounded-floor' is room scale, 'local-floor' is a standing or sitting
- # experience (it puts you 1.6m above the ground if you have 3DoF headset),
- # whereas as 'local' puts you down at the XROrigin.
- # This list means it'll first try to request 'bounded-floor', then
- # fallback on 'local-floor' and ultimately 'local', if nothing else is
- # supported.
- webxr_interface.requested_reference_space_types = 'bounded-floor, local-floor, local'
- # In order to use 'local-floor' or 'bounded-floor' we must also
- # mark the features as required or optional.
- webxr_interface.required_features = 'local-floor'
- webxr_interface.optional_features = 'bounded-floor'
+ func _on_Button_pressed():
+ if not vr_supported:
+ OS.alert("Your browser doesn't support VR")
+ return
- # This will return false if we're unable to even request the session,
- # however, it can still fail asynchronously later in the process, so we
- # only know if it's really succeeded or failed when our
- # _webxr_session_started() or _webxr_session_failed() methods are called.
- if not webxr_interface.initialize():
- OS.alert("Failed to initialize")
- return
+ # We want an immersive VR session, as opposed to AR ('immersive-ar') or a
+ # simple 3DoF viewer ('viewer').
+ webxr_interface.session_mode = 'immersive-vr'
+ # 'bounded-floor' is room scale, 'local-floor' is a standing or sitting
+ # experience (it puts you 1.6m above the ground if you have 3DoF headset),
+ # whereas as 'local' puts you down at the XROrigin.
+ # This list means it'll first try to request 'bounded-floor', then
+ # fallback on 'local-floor' and ultimately 'local', if nothing else is
+ # supported.
+ webxr_interface.requested_reference_space_types = 'bounded-floor, local-floor, local'
+ # In order to use 'local-floor' or 'bounded-floor' we must also
+ # mark the features as required or optional.
+ webxr_interface.required_features = 'local-floor'
+ webxr_interface.optional_features = 'bounded-floor'
- func _webxr_session_started():
- # This tells Godot to start rendering to the headset.
- get_viewport().xr = true
- # This will be the reference space type you ultimately got, out of the
- # types that you requested above. This is useful if you want the game to
- # work a little differently in 'bounded-floor' versus 'local-floor'.
- print ("Reference space type: " + webxr_interface.reference_space_type)
+ # This will return false if we're unable to even request the session,
+ # however, it can still fail asynchronously later in the process, so we
+ # only know if it's really succeeded or failed when our
+ # _webxr_session_started() or _webxr_session_failed() methods are called.
+ if not webxr_interface.initialize():
+ OS.alert("Failed to initialize")
+ return
- func _webxr_session_ended():
- # If the user exits immersive mode, then we tell Godot to render to the web
- # page again.
- get_viewport().xr = false
+ func _webxr_session_started():
+ $Button.visible = false
+ # This tells Godot to start rendering to the headset.
+ get_viewport().xr = true
+ # This will be the reference space type you ultimately got, out of the
+ # types that you requested above. This is useful if you want the game to
+ # work a little differently in 'bounded-floor' versus 'local-floor'.
+ print ("Reference space type: " + webxr_interface.reference_space_type)
- func _webxr_session_failed(message):
- OS.alert("Failed to initialize: " + message)
+ func _webxr_session_ended():
+ $Button.visible = true
+ # If the user exits immersive mode, then we tell Godot to render to the web
+ # page again.
+ get_viewport().xr = false
+
+ func _webxr_session_failed(message):
+ OS.alert("Failed to initialize: " + message)
[/codeblock]
There are several ways to handle "controller" input:
- Using [XRController3D] nodes and their [signal XRController3D.button_pressed] and [signal XRController3D.button_released] signals. This is how controllers are typically handled in AR/VR apps in Godot, however, this will only work with advanced VR controllers like the Oculus Touch or Index controllers, for example. The buttons codes are defined by [url=https://immersive-web.github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping]Section 3.3 of the WebXR Gamepads Module[/url].
diff --git a/modules/webxr/godot_webxr.h b/modules/webxr/godot_webxr.h
index 5e50ffde28..41a690f473 100644
--- a/modules/webxr/godot_webxr.h
+++ b/modules/webxr/godot_webxr.h
@@ -61,6 +61,7 @@ extern void godot_webxr_initialize(
GodotWebXRSimpleEventCallback p_on_simple_event);
extern void godot_webxr_uninitialize();
+extern int godot_webxr_get_view_count();
extern int *godot_webxr_get_render_targetsize();
extern float *godot_webxr_get_transform_for_eye(int p_eye);
extern float *godot_webxr_get_projection_for_eye(int p_eye);
diff --git a/modules/webxr/native/library_godot_webxr.js b/modules/webxr/native/library_godot_webxr.js
index 3041c16c79..8e9ef8a73c 100644
--- a/modules/webxr/native/library_godot_webxr.js
+++ b/modules/webxr/native/library_godot_webxr.js
@@ -380,6 +380,11 @@ const GodotWebXR = {
gl.deleteTexture(texture);
}
GodotWebXR.textures[i] = null;
+
+ const texture_id = GodotWebXR.texture_ids[i];
+ if (texture_id !== null) {
+ GL.textures[texture_id] = null;
+ }
GodotWebXR.texture_ids[i] = null;
}
@@ -394,6 +399,15 @@ const GodotWebXR = {
GodotWebXR.pauseResumeMainLoop();
},
+ godot_webxr_get_view_count__proxy: 'sync',
+ godot_webxr_get_view_count__sig: 'i',
+ godot_webxr_get_view_count: function () {
+ if (!GodotWebXR.session || !GodotWebXR.pose) {
+ return 0;
+ }
+ return GodotWebXR.pose.views.length;
+ },
+
godot_webxr_get_render_targetsize__proxy: 'sync',
godot_webxr_get_render_targetsize__sig: 'i',
godot_webxr_get_render_targetsize: function () {
@@ -451,7 +465,7 @@ const GodotWebXR = {
godot_webxr_get_external_texture_for_eye__proxy: 'sync',
godot_webxr_get_external_texture_for_eye__sig: 'ii',
godot_webxr_get_external_texture_for_eye: function (p_eye) {
- if (!GodotWebXR.session || !GodotWebXR.pose) {
+ if (!GodotWebXR.session) {
return 0;
}
@@ -460,6 +474,13 @@ const GodotWebXR = {
return GodotWebXR.texture_ids[view_index];
}
+ // Check pose separately and after returning the cached texture id,
+ // because we won't get a pose in some cases if we lose tracking, and
+ // we don't want to return 0 just because tracking was lost.
+ if (!GodotWebXR.pose) {
+ return 0;
+ }
+
const glLayer = GodotWebXR.session.renderState.baseLayer;
const view = GodotWebXR.pose.views[view_index];
const viewport = glLayer.getViewport(view);
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 6594553146..74789fc98e 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -78,6 +78,8 @@ void _emwebxr_on_session_failed(char *p_message) {
Ref<XRInterface> interface = xr_server->find_interface("WebXR");
ERR_FAIL_COND(interface.is_null());
+ interface->uninitialize();
+
String message = String(p_message);
interface->emit_signal("session_failed", message);
}
@@ -197,12 +199,11 @@ StringName WebXRInterfaceJS::get_name() const {
};
int WebXRInterfaceJS::get_capabilities() const {
- return XRInterface::XR_STEREO;
+ return XRInterface::XR_STEREO | XRInterface::XR_MONO;
};
bool WebXRInterfaceJS::is_stereo() {
- // @todo WebXR can be mono! So, how do we know? Count the views in the frame?
- return true;
+ return godot_webxr_get_view_count() == 2;
};
bool WebXRInterfaceJS::is_initialized() const {
@@ -225,6 +226,12 @@ bool WebXRInterfaceJS::initialize() {
// make this our primary interface
xr_server->set_primary_interface(this);
+ // Clear render_targetsize to make sure it gets reset to the new size.
+ // Clearing in uninitialize() doesn't work because a frame can still be
+ // rendered after it's called, which will fill render_targetsize again.
+ render_targetsize.width = 0;
+ render_targetsize.height = 0;
+
initialized = true;
godot_webxr_initialize(
@@ -278,22 +285,24 @@ Transform WebXRInterfaceJS::_js_matrix_to_transform(float *p_js_matrix) {
}
Size2 WebXRInterfaceJS::get_render_targetsize() {
- Size2 target_size;
+ if (render_targetsize.width != 0 && render_targetsize.height != 0) {
+ return render_targetsize;
+ }
int *js_size = godot_webxr_get_render_targetsize();
if (!initialized || js_size == nullptr) {
- // As a default, use half the window size.
- target_size = DisplayServer::get_singleton()->window_get_size();
- target_size.width /= 2.0;
- return target_size;
+ // As a temporary default (until WebXR is fully initialized), use half the window size.
+ Size2 temp = DisplayServer::get_singleton()->window_get_size();
+ temp.width /= 2.0;
+ return temp;
}
- target_size.width = js_size[0];
- target_size.height = js_size[1];
+ render_targetsize.width = js_size[0];
+ render_targetsize.height = js_size[1];
free(js_size);
- return target_size;
+ return render_targetsize;
};
Transform WebXRInterfaceJS::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h
index 93da9a6d12..49299b252f 100644
--- a/modules/webxr/webxr_interface_js.h
+++ b/modules/webxr/webxr_interface_js.h
@@ -47,7 +47,6 @@ class WebXRInterfaceJS : public WebXRInterface {
private:
bool initialized;
- // @todo Should these really use enums instead of strings?
String session_mode;
String required_features;
String optional_features;
@@ -55,6 +54,7 @@ private:
String reference_space_type;
bool controllers_state[2];
+ Size2 render_targetsize;
Transform _js_matrix_to_transform(float *p_js_matrix);
void _update_tracker(int p_controller_id);
diff --git a/platform/android/api/jni_singleton.h b/platform/android/api/jni_singleton.h
index 49c0104e67..965eaabf81 100644
--- a/platform/android/api/jni_singleton.h
+++ b/platform/android/api/jni_singleton.h
@@ -83,7 +83,7 @@ public:
v = (jvalue *)alloca(sizeof(jvalue) * p_argcount);
}
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
int res = env->PushLocalFrame(16);
diff --git a/platform/android/audio_driver_jandroid.cpp b/platform/android/audio_driver_jandroid.cpp
index 825132ac8c..ee28959adc 100644
--- a/platform/android/audio_driver_jandroid.cpp
+++ b/platform/android/audio_driver_jandroid.cpp
@@ -72,7 +72,7 @@ Error AudioDriverAndroid::init() {
// __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
int mix_rate = GLOBAL_GET("audio/mix_rate");
int latency = GLOBAL_GET("audio/output_latency");
@@ -98,7 +98,7 @@ void AudioDriverAndroid::start() {
}
void AudioDriverAndroid::setup(jobject p_io) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
io = p_io;
jclass c = env->GetObjectClass(io);
@@ -162,7 +162,7 @@ void AudioDriverAndroid::unlock() {
}
void AudioDriverAndroid::finish() {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(io, _quit);
if (audioBuffer) {
@@ -175,7 +175,7 @@ void AudioDriverAndroid::finish() {
}
void AudioDriverAndroid::set_pause(bool p_pause) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(io, _pause, p_pause);
}
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 78685991a8..f8ac29c738 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -47,7 +47,7 @@ DirAccess *DirAccessJAndroid::create_fs() {
Error DirAccessJAndroid::list_dir_begin() {
list_dir_end();
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring js = env->NewStringUTF(current_dir.utf8().get_data());
int res = env->CallIntMethod(io, _dir_open, js);
@@ -62,7 +62,7 @@ Error DirAccessJAndroid::list_dir_begin() {
String DirAccessJAndroid::get_next() {
ERR_FAIL_COND_V(id == 0, "");
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring str = (jstring)env->CallObjectMethod(io, _dir_next, id);
if (!str)
return "";
@@ -73,7 +73,7 @@ String DirAccessJAndroid::get_next() {
}
bool DirAccessJAndroid::current_is_dir() const {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
return env->CallBooleanMethod(io, _dir_is_dir, id);
}
@@ -86,7 +86,7 @@ void DirAccessJAndroid::list_dir_end() {
if (id == 0)
return;
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(io, _dir_close, id);
id = 0;
}
@@ -100,7 +100,7 @@ String DirAccessJAndroid::get_drive(int p_drive) {
}
Error DirAccessJAndroid::change_dir(String p_dir) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == ""))
return OK;
@@ -154,7 +154,7 @@ bool DirAccessJAndroid::file_exists(String p_file) {
}
bool DirAccessJAndroid::dir_exists(String p_dir) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
String sd;
@@ -207,7 +207,7 @@ size_t DirAccessJAndroid::get_space_left() {
}
void DirAccessJAndroid::setup(jobject p_io) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
io = p_io;
jclass c = env->GetObjectClass(io);
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 62720e8249..a963c5a741 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -269,7 +269,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
Vector<Device> devices;
volatile bool devices_changed;
Mutex device_lock;
- Thread *check_for_changes_thread;
+ Thread check_for_changes_thread;
volatile bool quit_request;
static void _check_for_changes_poll_thread(void *ud) {
@@ -2848,13 +2848,12 @@ public:
devices_changed = true;
plugins_changed = true;
quit_request = false;
- check_for_changes_thread = Thread::create(_check_for_changes_poll_thread, this);
+ check_for_changes_thread.start(_check_for_changes_poll_thread, this);
}
~EditorExportPlatformAndroid() {
quit_request = true;
- Thread::wait_to_finish(check_for_changes_thread);
- memdelete(check_for_changes_thread);
+ check_for_changes_thread.wait_to_finish();
}
};
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index 2b5ca530da..ab03599dc3 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -37,7 +37,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
if (!M)
return false;
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
MethodInfo *method = nullptr;
for (List<MethodInfo>::Element *E = M->get().front(); E; E = E->next()) {
@@ -964,7 +964,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
if (class_cache.has(p_class))
return class_cache[p_class];
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jclass bclass = env->FindClass(p_class.utf8().get_data());
ERR_FAIL_COND_V(!bclass, Ref<JavaClass>());
@@ -1148,7 +1148,7 @@ JavaClassWrapper *JavaClassWrapper::singleton = nullptr;
JavaClassWrapper::JavaClassWrapper(jobject p_activity) {
singleton = this;
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jclass activityClass = env->FindClass("android/app/Activity");
jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index 8f8275826d..4ee4427aa0 100644
--- a/platform/android/java_godot_io_wrapper.cpp
+++ b/platform/android/java_godot_io_wrapper.cpp
@@ -34,7 +34,7 @@
// JNIEnv is only valid within the thread it belongs to, in a multi threading environment
// we can't cache it.
// For GodotIO we call all access methods from our thread and we thus get a valid JNIEnv
-// from ThreadAndroid.
+// from get_jni_env().
GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instance) {
godot_io_instance = p_env->NewGlobalRef(p_godot_io_instance);
@@ -72,7 +72,7 @@ jobject GodotIOJavaWrapper::get_instance() {
Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
if (_open_URI) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring jStr = env->NewStringUTF(p_uri.utf8().get_data());
return env->CallIntMethod(godot_io_instance, _open_URI, jStr) ? ERR_CANT_OPEN : OK;
} else {
@@ -82,7 +82,7 @@ Error GodotIOJavaWrapper::open_uri(const String &p_uri) {
String GodotIOJavaWrapper::get_user_data_dir() {
if (_get_data_dir) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_data_dir);
return jstring_to_string(s, env);
} else {
@@ -92,7 +92,7 @@ String GodotIOJavaWrapper::get_user_data_dir() {
String GodotIOJavaWrapper::get_locale() {
if (_get_locale) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_locale);
return jstring_to_string(s, env);
} else {
@@ -102,7 +102,7 @@ String GodotIOJavaWrapper::get_locale() {
String GodotIOJavaWrapper::get_model() {
if (_get_model) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_model);
return jstring_to_string(s, env);
} else {
@@ -112,7 +112,7 @@ String GodotIOJavaWrapper::get_model() {
int GodotIOJavaWrapper::get_screen_dpi() {
if (_get_screen_DPI) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
return env->CallIntMethod(godot_io_instance, _get_screen_DPI);
} else {
return 160;
@@ -121,7 +121,7 @@ int GodotIOJavaWrapper::get_screen_dpi() {
void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) {
if (_screen_get_usable_rect) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jintArray returnArray = (jintArray)env->CallObjectMethod(godot_io_instance, _screen_get_usable_rect);
ERR_FAIL_COND(env->GetArrayLength(returnArray) != 4);
jint *arrayBody = env->GetIntArrayElements(returnArray, JNI_FALSE);
@@ -134,7 +134,7 @@ void GodotIOJavaWrapper::screen_get_usable_rect(int (&p_rect_xywh)[4]) {
String GodotIOJavaWrapper::get_unique_id() {
if (_get_unique_id) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_unique_id);
return jstring_to_string(s, env);
} else {
@@ -148,7 +148,7 @@ bool GodotIOJavaWrapper::has_vk() {
void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
if (_show_keyboard) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_multiline, p_max_input_length, p_cursor_start, p_cursor_end);
}
@@ -156,21 +156,21 @@ void GodotIOJavaWrapper::show_vk(const String &p_existing, bool p_multiline, int
void GodotIOJavaWrapper::hide_vk() {
if (_hide_keyboard) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(godot_io_instance, _hide_keyboard);
}
}
void GodotIOJavaWrapper::set_screen_orientation(int p_orient) {
if (_set_screen_orientation) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(godot_io_instance, _set_screen_orientation, p_orient);
}
}
int GodotIOJavaWrapper::get_screen_orientation() {
if (_get_screen_orientation) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
return env->CallIntMethod(godot_io_instance, _get_screen_orientation);
} else {
return 0;
@@ -179,7 +179,7 @@ int GodotIOJavaWrapper::get_screen_orientation() {
String GodotIOJavaWrapper::get_system_dir(int p_dir) {
if (_get_system_dir) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring s = (jstring)env->CallObjectMethod(godot_io_instance, _get_system_dir, p_dir);
return jstring_to_string(s, env);
} else {
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index e3a4ce63ef..bb22162879 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -87,7 +87,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
godot_java = new GodotJavaWrapper(env, activity, godot_instance);
godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env));
- ThreadAndroid::make_default(jvm);
+ init_thread_jandroid(jvm, env);
jobject amgr = env->NewGlobalRef(p_asset_manager);
@@ -119,7 +119,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline) {
- ThreadAndroid::setup_thread();
+ setup_android_thread();
const char **cmdline = nullptr;
jstring *j_cmdline = nullptr;
@@ -206,7 +206,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, jcl
return;
if (step == 0) {
- // Since Godot is initialized on the UI thread, _main_thread_id was set to that thread's id,
+ // Since Godot is initialized on the UI thread, main_thread_id was set to that thread's id,
// but for Godot purposes, the main thread is the one running the game loop
Main::setup2(Thread::get_caller_id());
++step;
@@ -382,7 +382,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_focusout(JNIEnv *env,
}
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_audio(JNIEnv *env, jclass clazz) {
- ThreadAndroid::setup_thread();
+ setup_android_thread();
AudioDriverAndroid::thread_func(env);
}
diff --git a/platform/android/java_godot_view_wrapper.cpp b/platform/android/java_godot_view_wrapper.cpp
index cb26c7b8c5..5b638300ef 100644
--- a/platform/android/java_godot_view_wrapper.cpp
+++ b/platform/android/java_godot_view_wrapper.cpp
@@ -33,7 +33,7 @@
#include "thread_jandroid.h"
GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
_godot_view = env->NewGlobalRef(godot_view);
@@ -47,20 +47,20 @@ GodotJavaViewWrapper::GodotJavaViewWrapper(jobject godot_view) {
void GodotJavaViewWrapper::request_pointer_capture() {
if (_request_pointer_capture != 0) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(_godot_view, _request_pointer_capture);
}
}
void GodotJavaViewWrapper::release_pointer_capture() {
if (_request_pointer_capture != 0) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(_godot_view, _release_pointer_capture);
}
}
GodotJavaViewWrapper::~GodotJavaViewWrapper() {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->DeleteGlobalRef(_godot_view);
env->DeleteGlobalRef(_cls);
}
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index c4e7f272d3..759980373a 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -33,7 +33,7 @@
// JNIEnv is only valid within the thread it belongs to, in a multi threading environment
// we can't cache it.
// For Godot we call most access methods from our thread and we thus get a valid JNIEnv
-// from ThreadAndroid. For one or two we expect to pass the environment
+// from get_jni_env(). For one or two we expect to pass the environment
// TODO we could probably create a base class for this...
@@ -91,7 +91,7 @@ jobject GodotJavaWrapper::get_activity() {
jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_class, JNIEnv *p_env) {
if (godot_class) {
if (p_env == nullptr)
- p_env = ThreadAndroid::get_env();
+ p_env = get_jni_env();
jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class);
return p_env->GetStaticObjectField(godot_class, fid);
@@ -102,7 +102,7 @@ jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_cl
jobject GodotJavaWrapper::get_class_loader() {
if (_get_class_loader) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
return env->CallObjectMethod(activity, _get_class_loader);
} else {
return nullptr;
@@ -113,7 +113,7 @@ GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() {
if (_godot_view != nullptr) {
return _godot_view;
}
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jmethodID godot_view_getter = env->GetMethodID(godot_class, "getRenderView", "()Lorg/godotengine/godot/GodotRenderView;");
_godot_view = new GodotJavaViewWrapper(env->CallObjectMethod(godot_instance, godot_view_getter));
return _godot_view;
@@ -122,7 +122,7 @@ GodotJavaViewWrapper *GodotJavaWrapper::get_godot_view() {
void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
if (_on_video_init)
if (p_env == nullptr)
- p_env = ThreadAndroid::get_env();
+ p_env = get_jni_env();
p_env->CallVoidMethod(godot_instance, _on_video_init);
}
@@ -130,7 +130,7 @@ void GodotJavaWrapper::on_video_init(JNIEnv *p_env) {
void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
if (_on_godot_main_loop_started) {
if (p_env == nullptr) {
- p_env = ThreadAndroid::get_env();
+ p_env = get_jni_env();
}
}
p_env->CallVoidMethod(godot_instance, _on_godot_main_loop_started);
@@ -139,7 +139,7 @@ void GodotJavaWrapper::on_godot_main_loop_started(JNIEnv *p_env) {
void GodotJavaWrapper::restart(JNIEnv *p_env) {
if (_restart)
if (p_env == nullptr)
- p_env = ThreadAndroid::get_env();
+ p_env = get_jni_env();
p_env->CallVoidMethod(godot_instance, _restart);
}
@@ -147,21 +147,21 @@ void GodotJavaWrapper::restart(JNIEnv *p_env) {
void GodotJavaWrapper::force_quit(JNIEnv *p_env) {
if (_finish)
if (p_env == nullptr)
- p_env = ThreadAndroid::get_env();
+ p_env = get_jni_env();
p_env->CallVoidMethod(godot_instance, _finish);
}
void GodotJavaWrapper::set_keep_screen_on(bool p_enabled) {
if (_set_keep_screen_on) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(godot_instance, _set_keep_screen_on, p_enabled);
}
}
void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
if (_alert) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring jStrMessage = env->NewStringUTF(p_message.utf8().get_data());
jstring jStrTitle = env->NewStringUTF(p_title.utf8().get_data());
env->CallVoidMethod(godot_instance, _alert, jStrMessage, jStrTitle);
@@ -169,7 +169,7 @@ void GodotJavaWrapper::alert(const String &p_message, const String &p_title) {
}
int GodotJavaWrapper::get_gles_version_code() {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
if (_get_GLES_version_code) {
return env->CallIntMethod(godot_instance, _get_GLES_version_code);
}
@@ -183,7 +183,7 @@ bool GodotJavaWrapper::has_get_clipboard() {
String GodotJavaWrapper::get_clipboard() {
if (_get_clipboard) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring s = (jstring)env->CallObjectMethod(godot_instance, _get_clipboard);
return jstring_to_string(s, env);
} else {
@@ -193,7 +193,7 @@ String GodotJavaWrapper::get_clipboard() {
String GodotJavaWrapper::get_input_fallback_mapping() {
if (_get_input_fallback_mapping) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping);
return jstring_to_string(fallback_mapping, env);
} else {
@@ -207,7 +207,7 @@ bool GodotJavaWrapper::has_set_clipboard() {
void GodotJavaWrapper::set_clipboard(const String &p_text) {
if (_set_clipboard) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring jStr = env->NewStringUTF(p_text.utf8().get_data());
env->CallVoidMethod(godot_instance, _set_clipboard, jStr);
}
@@ -215,7 +215,7 @@ void GodotJavaWrapper::set_clipboard(const String &p_text) {
bool GodotJavaWrapper::request_permission(const String &p_name) {
if (_request_permission) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jstring jStrName = env->NewStringUTF(p_name.utf8().get_data());
return env->CallBooleanMethod(godot_instance, _request_permission, jStrName);
} else {
@@ -225,7 +225,7 @@ bool GodotJavaWrapper::request_permission(const String &p_name) {
bool GodotJavaWrapper::request_permissions() {
if (_request_permissions) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
return env->CallBooleanMethod(godot_instance, _request_permissions);
} else {
return false;
@@ -235,7 +235,7 @@ bool GodotJavaWrapper::request_permissions() {
Vector<String> GodotJavaWrapper::get_granted_permissions() const {
Vector<String> permissions_list;
if (_get_granted_permissions) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
jobject permissions_object = env->CallObjectMethod(godot_instance, _get_granted_permissions);
jobjectArray *arr = reinterpret_cast<jobjectArray *>(&permissions_object);
@@ -253,14 +253,14 @@ Vector<String> GodotJavaWrapper::get_granted_permissions() const {
void GodotJavaWrapper::init_input_devices() {
if (_init_input_devices) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(godot_instance, _init_input_devices);
}
}
jobject GodotJavaWrapper::get_surface() {
if (_get_surface) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
return env->CallObjectMethod(godot_instance, _get_surface);
} else {
return nullptr;
@@ -269,7 +269,7 @@ jobject GodotJavaWrapper::get_surface() {
bool GodotJavaWrapper::is_activity_resumed() {
if (_is_activity_resumed) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
return env->CallBooleanMethod(godot_instance, _is_activity_resumed);
} else {
return false;
@@ -278,7 +278,7 @@ bool GodotJavaWrapper::is_activity_resumed() {
void GodotJavaWrapper::vibrate(int p_duration_ms) {
if (_vibrate) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(godot_instance, _vibrate, p_duration_ms);
}
}
diff --git a/platform/android/net_socket_android.cpp b/platform/android/net_socket_android.cpp
index ba7b3d3775..ddc2368793 100644
--- a/platform/android/net_socket_android.cpp
+++ b/platform/android/net_socket_android.cpp
@@ -38,7 +38,7 @@ jmethodID NetSocketAndroid::_multicast_lock_acquire = 0;
jmethodID NetSocketAndroid::_multicast_lock_release = 0;
void NetSocketAndroid::setup(jobject p_net_utils) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
net_utils = env->NewGlobalRef(p_net_utils);
@@ -51,14 +51,14 @@ void NetSocketAndroid::setup(jobject p_net_utils) {
void NetSocketAndroid::multicast_lock_acquire() {
if (_multicast_lock_acquire) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(net_utils, _multicast_lock_acquire);
}
}
void NetSocketAndroid::multicast_lock_release() {
if (_multicast_lock_release) {
- JNIEnv *env = ThreadAndroid::get_env();
+ JNIEnv *env = get_jni_env();
env->CallVoidMethod(net_utils, _multicast_lock_release);
}
}
diff --git a/platform/android/string_android.h b/platform/android/string_android.h
index 25c6f749d4..3721315d3f 100644
--- a/platform/android/string_android.h
+++ b/platform/android/string_android.h
@@ -37,14 +37,14 @@
/**
* Converts JNI jstring to Godot String.
* @param source Source JNI string. If null an empty string is returned.
- * @param env JNI environment instance. If null obtained by ThreadAndroid::get_env().
+ * @param env JNI environment instance. If null obtained by get_jni_env().
* @return Godot string instance.
*/
static inline String jstring_to_string(jstring source, JNIEnv *env = nullptr) {
String result;
if (source) {
if (!env) {
- env = ThreadAndroid::get_env();
+ env = get_jni_env();
}
const char *const source_utf8 = env->GetStringUTFChars(source, nullptr);
if (source_utf8) {
diff --git a/platform/android/thread_jandroid.cpp b/platform/android/thread_jandroid.cpp
index cb3527067f..afcc7294f2 100644
--- a/platform/android/thread_jandroid.cpp
+++ b/platform/android/thread_jandroid.cpp
@@ -30,116 +30,29 @@
#include "thread_jandroid.h"
-#include "core/object/script_language.h"
-#include "core/os/memory.h"
-#include "core/templates/safe_refcount.h"
+#include "core/os/thread.h"
-static void _thread_id_key_destr_callback(void *p_value) {
- memdelete(static_cast<Thread::ID *>(p_value));
-}
-
-static pthread_key_t _create_thread_id_key() {
- pthread_key_t key;
- pthread_key_create(&key, &_thread_id_key_destr_callback);
- return key;
-}
-
-pthread_key_t ThreadAndroid::thread_id_key = _create_thread_id_key();
-Thread::ID ThreadAndroid::next_thread_id = 0;
-
-Thread::ID ThreadAndroid::get_id() const {
- return id;
-}
-
-Thread *ThreadAndroid::create_thread_jandroid() {
- return memnew(ThreadAndroid);
-}
-
-void *ThreadAndroid::thread_callback(void *userdata) {
- ThreadAndroid *t = reinterpret_cast<ThreadAndroid *>(userdata);
- setup_thread();
- ScriptServer::thread_enter(); //scripts may need to attach a stack
- t->id = atomic_increment(&next_thread_id);
- pthread_setspecific(thread_id_key, (void *)memnew(ID(t->id)));
- t->callback(t->user);
- ScriptServer::thread_exit();
- return nullptr;
-}
-
-Thread *ThreadAndroid::create_func_jandroid(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
- ThreadAndroid *tr = memnew(ThreadAndroid);
- tr->callback = p_callback;
- tr->user = p_user;
- pthread_attr_init(&tr->pthread_attr);
- pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
-
- pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
-
- return tr;
-}
+static JavaVM *java_vm = nullptr;
+static thread_local JNIEnv *env = nullptr;
-Thread::ID ThreadAndroid::get_thread_id_func_jandroid() {
- void *value = pthread_getspecific(thread_id_key);
-
- if (value)
- return *static_cast<ID *>(value);
-
- ID new_id = atomic_increment(&next_thread_id);
- pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id)));
- return new_id;
-}
-
-void ThreadAndroid::wait_to_finish_func_jandroid(Thread *p_thread) {
- ThreadAndroid *tp = static_cast<ThreadAndroid *>(p_thread);
- ERR_FAIL_COND(!tp);
- ERR_FAIL_COND(tp->pthread == 0);
-
- pthread_join(tp->pthread, nullptr);
- tp->pthread = 0;
-}
-
-void ThreadAndroid::_thread_destroyed(void *value) {
- /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
- JNIEnv *env = (JNIEnv *)value;
- if (env != nullptr) {
- java_vm->DetachCurrentThread();
- pthread_setspecific(jvm_key, nullptr);
- }
-}
-
-pthread_key_t ThreadAndroid::jvm_key;
-JavaVM *ThreadAndroid::java_vm = nullptr;
-
-void ThreadAndroid::setup_thread() {
- if (pthread_getspecific(jvm_key))
- return; //already setup
- JNIEnv *env;
+static void init_thread() {
java_vm->AttachCurrentThread(&env, nullptr);
- pthread_setspecific(jvm_key, (void *)env);
}
-void ThreadAndroid::make_default(JavaVM *p_java_vm) {
- java_vm = p_java_vm;
- create_func = create_func_jandroid;
- get_thread_id_func = get_thread_id_func_jandroid;
- wait_to_finish_func = wait_to_finish_func_jandroid;
- pthread_key_create(&jvm_key, _thread_destroyed);
- setup_thread();
+static void term_thread() {
+ java_vm->DetachCurrentThread();
}
-JNIEnv *ThreadAndroid::get_env() {
- if (!pthread_getspecific(jvm_key)) {
- setup_thread();
- }
-
- JNIEnv *env = nullptr;
- java_vm->AttachCurrentThread(&env, nullptr);
- return env;
+void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env) {
+ java_vm = p_jvm;
+ env = p_env;
+ Thread::_set_platform_funcs(nullptr, nullptr, &init_thread, &term_thread);
}
-ThreadAndroid::ThreadAndroid() {
- pthread = 0;
+void setup_android_thread() {
+ init_thread();
}
-ThreadAndroid::~ThreadAndroid() {
+JNIEnv *get_jni_env() {
+ return env;
}
diff --git a/platform/android/thread_jandroid.h b/platform/android/thread_jandroid.h
index c37e2d740e..ff13ae911f 100644
--- a/platform/android/thread_jandroid.h
+++ b/platform/android/thread_jandroid.h
@@ -28,46 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef THREAD_POSIX_H
-#define THREAD_POSIX_H
+#ifndef THREAD_JANDROID_H
+#define THREAD_JANDROID_H
-#include "core/os/thread.h"
#include <jni.h>
-#include <pthread.h>
-#include <sys/types.h>
-class ThreadAndroid : public Thread {
- static pthread_key_t thread_id_key;
- static ID next_thread_id;
+void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env);
- pthread_t pthread;
- pthread_attr_t pthread_attr;
- ThreadCreateCallback callback;
- void *user;
- ID id;
-
- static Thread *create_thread_jandroid();
-
- static void *thread_callback(void *userdata);
-
- static Thread *create_func_jandroid(ThreadCreateCallback p_callback, void *, const Settings &);
- static ID get_thread_id_func_jandroid();
- static void wait_to_finish_func_jandroid(Thread *p_thread);
-
- static void _thread_destroyed(void *value);
- ThreadAndroid();
-
- static pthread_key_t jvm_key;
- static JavaVM *java_vm;
-
-public:
- virtual ID get_id() const;
-
- static void make_default(JavaVM *p_java_vm);
- static void setup_thread();
- static JNIEnv *get_env();
-
- ~ThreadAndroid();
-};
+void setup_android_thread();
+JNIEnv *get_jni_env();
#endif
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 2229ebd4ab..604ad4e04b 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -57,7 +57,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
// Plugins
volatile bool plugins_changed;
- Thread *check_for_changes_thread;
+ Thread check_for_changes_thread;
volatile bool quit_request;
Mutex plugins_lock;
Vector<PluginConfigIOS> plugins;
@@ -1940,13 +1940,12 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() {
plugins_changed = true;
quit_request = false;
- check_for_changes_thread = Thread::create(_check_for_changes_poll_thread, this);
+ check_for_changes_thread.start(_check_for_changes_poll_thread, this);
}
EditorExportPlatformIOS::~EditorExportPlatformIOS() {
quit_request = true;
- Thread::wait_to_finish(check_for_changes_thread);
- memdelete(check_for_changes_thread);
+ check_for_changes_thread.wait_to_finish();
}
void register_iphone_exporter() {
diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp
index 6395fdf721..f7cc9e6540 100644
--- a/platform/javascript/audio_driver_javascript.cpp
+++ b/platform/javascript/audio_driver_javascript.cpp
@@ -267,7 +267,7 @@ int AudioDriverJavaScript::WorkletNode::create(int p_buffer_size, int p_channels
void AudioDriverJavaScript::WorkletNode::start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) {
godot_audio_worklet_start(p_in_buf, p_in_buf_size, p_out_buf, p_out_buf_size, state);
- thread = Thread::create(_audio_thread_func, this);
+ thread.start(_audio_thread_func, this);
}
void AudioDriverJavaScript::WorkletNode::lock() {
@@ -280,8 +280,6 @@ void AudioDriverJavaScript::WorkletNode::unlock() {
void AudioDriverJavaScript::WorkletNode::finish() {
quit = true; // Ask thread to quit.
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = nullptr;
+ thread.wait_to_finish();
}
#endif
diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h
index d55ec261a4..393693640f 100644
--- a/platform/javascript/audio_driver_javascript.h
+++ b/platform/javascript/audio_driver_javascript.h
@@ -59,7 +59,7 @@ public:
STATE_MAX,
};
Mutex mutex;
- Thread *thread = nullptr;
+ Thread thread;
bool quit = false;
int32_t state[STATE_MAX] = { 0 };
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 76683da947..653d18f791 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -57,12 +57,11 @@ def get_flags():
def configure(env):
- if not isinstance(env["initial_memory"], int):
- try:
- env["initial_memory"] = int(env["initial_memory"])
- except:
- print("Initial memory must be a valid integer")
- sys.exit(255)
+ try:
+ env["initial_memory"] = int(env["initial_memory"])
+ except Exception:
+ print("Initial memory must be a valid integer")
+ sys.exit(255)
## Build type
if env["target"] == "release":
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index dd0938ee3e..f5d8a68994 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -214,7 +214,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
Ref<EditorHTTPServer> server;
bool server_quit = false;
Mutex server_lock;
- Thread *server_thread = nullptr;
+ Thread server_thread;
enum ExportMode {
EXPORT_MODE_NORMAL = 0,
@@ -682,7 +682,7 @@ void EditorExportPlatformJavaScript::_server_thread_poll(void *data) {
EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
server.instance();
- server_thread = Thread::create(_server_thread_poll, this);
+ server_thread.start(_server_thread_poll, this);
Ref<Image> img = memnew(Image(_javascript_logo));
logo.instance();
@@ -703,8 +703,7 @@ EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
EditorExportPlatformJavaScript::~EditorExportPlatformJavaScript() {
server->stop();
server_quit = true;
- Thread::wait_to_finish(server_thread);
- memdelete(server_thread);
+ server_thread.wait_to_finish();
}
void register_javascript_exporter() {
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 00b90923de..53baf17858 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -3360,7 +3360,7 @@ void DisplayServerX11::process_events() {
Vector<String> files = String((char *)p.data).split("\n", false);
for (int i = 0; i < files.size(); i++) {
- files.write[i] = files[i].replace("file://", "").http_unescape().strip_edges();
+ files.write[i] = files[i].replace("file://", "").uri_decode().strip_edges();
}
if (!windows[window_id].drop_files_callback.is_null()) {
@@ -4266,7 +4266,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
}
- events_thread = Thread::create(_poll_events_thread, this);
+ events_thread.start(_poll_events_thread, this);
_update_real_mouse_position(windows[MAIN_WINDOW_ID]);
@@ -4280,9 +4280,7 @@ DisplayServerX11::~DisplayServerX11() {
_clipboard_transfer_ownership(XInternAtom(x11_display, "CLIPBOARD", 0), x11_main_window);
events_thread_done = true;
- Thread::wait_to_finish(events_thread);
- memdelete(events_thread);
- events_thread = nullptr;
+ events_thread.wait_to_finish();
//destroy all windows
for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 7784ba82b5..906710f933 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -252,7 +252,7 @@ class DisplayServerX11 : public DisplayServer {
void _dispatch_input_event(const Ref<InputEvent> &p_event);
mutable Mutex events_mutex;
- Thread *events_thread = nullptr;
+ Thread events_thread;
bool events_thread_done = false;
LocalVector<XEvent> polled_events;
static void _poll_events_thread(void *ud);
diff --git a/platform/linuxbsd/joypad_linux.cpp b/platform/linuxbsd/joypad_linux.cpp
index 291ca49585..4e96e6d687 100644
--- a/platform/linuxbsd/joypad_linux.cpp
+++ b/platform/linuxbsd/joypad_linux.cpp
@@ -32,6 +32,7 @@
#include "joypad_linux.h"
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input.h>
@@ -73,13 +74,12 @@ void JoypadLinux::Joypad::reset() {
JoypadLinux::JoypadLinux(Input *in) {
exit_udev = false;
input = in;
- joy_thread = Thread::create(joy_thread_func, this);
+ joy_thread.start(joy_thread_func, this);
}
JoypadLinux::~JoypadLinux() {
exit_udev = true;
- Thread::wait_to_finish(joy_thread);
- memdelete(joy_thread);
+ joy_thread.wait_to_finish();
close_joypad();
}
@@ -183,13 +183,23 @@ void JoypadLinux::monitor_joypads() {
{
MutexLock lock(joy_mutex);
- for (int i = 0; i < 32; i++) {
+ DIR *input_directory;
+ input_directory = opendir("/dev/input");
+ if (input_directory) {
+ struct dirent *current;
char fname[64];
- sprintf(fname, "/dev/input/event%d", i);
- if (attached_devices.find(fname) == -1) {
- open_joypad(fname);
+
+ while ((current = readdir(input_directory)) != NULL) {
+ if (strncmp(current->d_name, "event", 5) != 0) {
+ continue;
+ }
+ sprintf(fname, "/dev/input/%.*s", 16, current->d_name);
+ if (attached_devices.find(fname) == -1) {
+ open_joypad(fname);
+ }
}
}
+ closedir(input_directory);
}
usleep(1000000); // 1s
}
diff --git a/platform/linuxbsd/joypad_linux.h b/platform/linuxbsd/joypad_linux.h
index 20d30b510c..bf343b7ceb 100644
--- a/platform/linuxbsd/joypad_linux.h
+++ b/platform/linuxbsd/joypad_linux.h
@@ -72,7 +72,7 @@ private:
bool exit_udev;
Mutex joy_mutex;
- Thread *joy_thread;
+ Thread joy_thread;
Input *input;
Joypad joypads[JOYPADS_MAX];
Vector<String> attached_devices;
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 44b3930d6c..09e1f9461c 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -410,7 +410,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
OS::Time time = OS::get_singleton()->get_time(false);
String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, date.month, date.day, time.hour, time.min);
timestamp = vformat("%s%02d", timestamp, time.sec); // vformat only supports up to 6 arguments.
- String trash_info = "[Trash Info]\nPath=" + p_path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
+ String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;
FileAccess *file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index f43c4ecdaf..8b60e55d2d 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -45,7 +45,6 @@
#include "servers/audio_server.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/rendering_server_wrap_mt.h"
-#include "thread_uwp.h"
#include <ppltasks.h>
#include <wrl.h>
@@ -130,8 +129,6 @@ void OS_UWP::initialize_core() {
//RedirectIOToConsole();
- ThreadUWP::make_default();
-
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
diff --git a/platform/uwp/thread_uwp.cpp b/platform/uwp/thread_uwp.cpp
deleted file mode 100644
index 364c414375..0000000000
--- a/platform/uwp/thread_uwp.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*************************************************************************/
-/* thread_uwp.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 "thread_uwp.h"
-
-#include "core/os/memory.h"
-
-Thread *ThreadUWP::create_func_uwp(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
- ThreadUWP *thread = memnew(ThreadUWP);
-
- std::thread new_thread(p_callback, p_user);
- std::swap(thread->thread, new_thread);
-
- return thread;
-};
-
-Thread::ID ThreadUWP::get_thread_id_func_uwp() {
- return std::hash<std::thread::id>()(std::this_thread::get_id());
-};
-
-void ThreadUWP::wait_to_finish_func_uwp(Thread *p_thread) {
- ThreadUWP *tp = static_cast<ThreadUWP *>(p_thread);
- tp->thread.join();
-};
-
-Thread::ID ThreadUWP::get_id() const {
- return std::hash<std::thread::id>()(thread.get_id());
-};
-
-void ThreadUWP::make_default() {
- create_func = create_func_uwp;
- get_thread_id_func = get_thread_id_func_uwp;
- wait_to_finish_func = wait_to_finish_func_uwp;
-};
diff --git a/platform/uwp/thread_uwp.h b/platform/uwp/thread_uwp.h
deleted file mode 100644
index 0bfc71d2e0..0000000000
--- a/platform/uwp/thread_uwp.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*************************************************************************/
-/* thread_uwp.h */
-/*************************************************************************/
-/* 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. */
-/*************************************************************************/
-
-#ifndef THREAD_UWP_H
-#define THREAD_UWP_H
-
-#ifdef UWP_ENABLED
-
-#include "core/os/thread.h"
-
-#include <thread>
-
-class ThreadUWP : public Thread {
- std::thread thread;
-
- static Thread *create_func_uwp(ThreadCreateCallback p_callback, void *, const Settings &);
- static ID get_thread_id_func_uwp();
- static void wait_to_finish_func_uwp(Thread *p_thread);
-
- ThreadUWP() {}
-
-public:
- virtual ID get_id() const;
-
- static void make_default();
-
- ~ThreadUWP() {}
-};
-
-#endif // UWP_ENABLED
-
-#endif // THREAD_UWP_H
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 3c38c715c1..fe007027da 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -39,7 +39,6 @@
#include "core/version_generated.gen.h"
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
-#include "drivers/windows/thread_windows.h"
#include "joypad_windows.h"
#include "lang_table.h"
#include "main/main.h"
@@ -176,8 +175,6 @@ void OS_Windows::initialize() {
//RedirectIOToConsole();
- ThreadWindows::make_default();
-
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index b7b1415091..e8cfa05a4b 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -170,18 +170,17 @@ void _bake_navigation_mesh(void *p_user_data) {
}
void NavigationRegion3D::bake_navigation_mesh() {
- ERR_FAIL_COND(bake_thread != nullptr);
+ ERR_FAIL_COND(bake_thread.is_started());
BakeThreadsArgs *args = memnew(BakeThreadsArgs);
args->nav_region = this;
- bake_thread = Thread::create(_bake_navigation_mesh, args);
- ERR_FAIL_COND(bake_thread == nullptr);
+ bake_thread.start(_bake_navigation_mesh, args);
}
void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_nav_mesh) {
set_navigation_mesh(p_nav_mesh);
- bake_thread = nullptr;
+ bake_thread.wait_to_finish();
emit_signal("bake_finished");
}
diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h
index a5b8c2cd5e..e966523b64 100644
--- a/scene/3d/navigation_region_3d.h
+++ b/scene/3d/navigation_region_3d.h
@@ -46,7 +46,7 @@ class NavigationRegion3D : public Node3D {
Navigation3D *navigation = nullptr;
Node *debug_view = nullptr;
- Thread *bake_thread = nullptr;
+ Thread bake_thread;
protected:
void _notification(int p_what);
diff --git a/scene/3d/visibility_notifier_3d.cpp b/scene/3d/visibility_notifier_3d.cpp
index 494709fe84..14c7659de4 100644
--- a/scene/3d/visibility_notifier_3d.cpp
+++ b/scene/3d/visibility_notifier_3d.cpp
@@ -80,13 +80,16 @@ AABB VisibilityNotifier3D::get_aabb() const {
void VisibilityNotifier3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_WORLD: {
- get_world_3d()->_register_notifier(this, get_global_transform().xform(aabb));
+ world = get_world_3d();
+ ERR_FAIL_COND(!world.is_valid());
+ world->_register_notifier(this, get_global_transform().xform(aabb));
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- get_world_3d()->_update_notifier(this, get_global_transform().xform(aabb));
+ world->_update_notifier(this, get_global_transform().xform(aabb));
} break;
case NOTIFICATION_EXIT_WORLD: {
- get_world_3d()->_remove_notifier(this);
+ ERR_FAIL_COND(!world.is_valid());
+ world->_remove_notifier(this);
} break;
}
}
diff --git a/scene/3d/visibility_notifier_3d.h b/scene/3d/visibility_notifier_3d.h
index 29552510b7..d566b7e40b 100644
--- a/scene/3d/visibility_notifier_3d.h
+++ b/scene/3d/visibility_notifier_3d.h
@@ -33,10 +33,12 @@
#include "scene/3d/node_3d.h"
+class World3D;
class Camera3D;
class VisibilityNotifier3D : public Node3D {
GDCLASS(VisibilityNotifier3D, Node3D);
+ Ref<World3D> world;
Set<Camera3D *> cameras;
AABB aabb;
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index ddcf07c8e9..4c6b85d78b 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -163,7 +163,7 @@ Error HTTPRequest::request_raw(const String &p_url, const Vector<String> &p_cust
thread_done = false;
thread_request_quit = false;
client->set_blocking_mode(true);
- thread = Thread::create(_thread_func, this);
+ thread.start(_thread_func, this);
} else {
client->set_blocking_mode(false);
err = _request();
@@ -209,9 +209,7 @@ void HTTPRequest::cancel_request() {
set_process_internal(false);
} else {
thread_request_quit = true;
- Thread::wait_to_finish(thread);
- memdelete(thread);
- thread = nullptr;
+ thread.wait_to_finish();
}
if (file) {
@@ -640,8 +638,6 @@ void HTTPRequest::_bind_methods() {
}
HTTPRequest::HTTPRequest() {
- thread = nullptr;
-
port = 80;
redirections = 0;
max_redirects = 8;
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 6f606296e4..9dbf561cd4 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -110,7 +110,7 @@ private:
volatile bool thread_done;
volatile bool thread_request_quit;
- Thread *thread;
+ Thread thread;
void _request_done(int p_status, int p_code, const PackedStringArray &p_headers, const PackedByteArray &p_data);
static void _thread_func(void *p_userdata);
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 242c3b8ec4..a0b65e9799 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -318,7 +318,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "CheckBox", control_font_color);
theme->set_color("font_pressed_color", "CheckBox", control_font_pressed_color);
theme->set_color("font_hover_color", "CheckBox", control_font_hover_color);
- theme->set_color("font_hover_color_pressed", "CheckBox", control_font_pressed_color);
+ theme->set_color("font_hover_pressed_color", "CheckBox", control_font_pressed_color);
theme->set_color("font_disabled_color", "CheckBox", control_font_disabled_color);
theme->set_constant("hseparation", "CheckBox", 4 * scale);
@@ -355,7 +355,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_color", "CheckButton", control_font_color);
theme->set_color("font_pressed_color", "CheckButton", control_font_pressed_color);
theme->set_color("font_hover_color", "CheckButton", control_font_hover_color);
- theme->set_color("font_hover_color_pressed", "CheckButton", control_font_pressed_color);
+ theme->set_color("font_hover_pressed_color", "CheckButton", control_font_pressed_color);
theme->set_color("font_disabled_color", "CheckButton", control_font_disabled_color);
theme->set_constant("hseparation", "CheckButton", 4 * scale);
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 12cadb9301..faddced155 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -48,7 +48,7 @@ Error AudioDriverDummy::init() {
samples_in = memnew_arr(int32_t, buffer_frames * channels);
- thread = Thread::create(AudioDriverDummy::thread_func, this);
+ thread.start(AudioDriverDummy::thread_func, this);
return OK;
};
@@ -86,31 +86,18 @@ AudioDriver::SpeakerMode AudioDriverDummy::get_speaker_mode() const {
};
void AudioDriverDummy::lock() {
- if (!thread) {
- return;
- }
mutex.lock();
};
void AudioDriverDummy::unlock() {
- if (!thread) {
- return;
- }
mutex.unlock();
};
void AudioDriverDummy::finish() {
- if (!thread) {
- return;
- }
-
exit_thread = true;
- Thread::wait_to_finish(thread);
+ thread.wait_to_finish();
if (samples_in) {
memdelete_arr(samples_in);
};
-
- memdelete(thread);
- thread = nullptr;
};
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 617ffb2c79..7d84e7ffc8 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -37,7 +37,7 @@
#include "core/os/thread.h"
class AudioDriverDummy : public AudioDriver {
- Thread *thread = nullptr;
+ Thread thread;
Mutex mutex;
int32_t *samples_in;
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index e8832c92a3..2015ede81f 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -118,7 +118,7 @@ void AudioEffectRecordInstance::init() {
#ifdef NO_THREADS
AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this);
#else
- io_thread = Thread::create(_thread_callback, this);
+ io_thread.start(_thread_callback, this);
#endif
}
@@ -126,9 +126,7 @@ void AudioEffectRecordInstance::finish() {
#ifdef NO_THREADS
AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this);
#else
- if (thread_active) {
- Thread::wait_to_finish(io_thread);
- }
+ io_thread.wait_to_finish();
#endif
}
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 14e646e29d..b97ec43946 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -48,7 +48,7 @@ class AudioEffectRecordInstance : public AudioEffectInstance {
Ref<AudioEffectRecord> base;
bool is_recording;
- Thread *io_thread;
+ Thread io_thread;
bool thread_active = false;
Vector<AudioFrame> ring_buffer;
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index 2939b4b99f..2db3961f41 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -61,7 +61,7 @@ private:
Variant metadata;
bool disabled;
bool one_way_collision;
- float one_way_collision_margin;
+ real_t one_way_collision_margin;
Shape() {
disabled = false;
one_way_collision = false;
@@ -153,7 +153,7 @@ public:
return shapes[p_idx].disabled;
}
- _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision, float p_margin) {
+ _FORCE_INLINE_ void set_shape_as_one_way_collision(int p_idx, bool p_one_way_collision, real_t p_margin) {
CRASH_BAD_INDEX(p_idx, shapes.size());
shapes.write[p_idx].one_way_collision = p_one_way_collision;
shapes.write[p_idx].one_way_collision_margin = p_margin;
@@ -163,7 +163,7 @@ public:
return shapes[p_idx].one_way_collision;
}
- _FORCE_INLINE_ float get_shape_one_way_collision_margin(int p_idx) const {
+ _FORCE_INLINE_ real_t get_shape_one_way_collision_margin(int p_idx) const {
CRASH_BAD_INDEX(p_idx, shapes.size());
return shapes[p_idx].one_way_collision_margin;
}
diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp
index c4e2489bef..14fcf1520a 100644
--- a/servers/physics_2d/physics_server_2d_sw.cpp
+++ b/servers/physics_2d/physics_server_2d_sw.cpp
@@ -667,7 +667,7 @@ void PhysicsServer2DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, boo
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
-void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin) {
+void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) {
Body2DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
@@ -958,7 +958,7 @@ bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from,
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
}
-int PhysicsServer2DSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) {
+int PhysicsServer2DSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
Body2DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h
index 3305c0bd3d..62ea30b3f6 100644
--- a/servers/physics_2d/physics_server_2d_sw.h
+++ b/servers/physics_2d/physics_server_2d_sw.h
@@ -191,7 +191,7 @@ public:
virtual void body_clear_shapes(RID p_body) override;
virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) override;
- virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin) override;
+ virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) override;
virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) override;
virtual ObjectID body_get_object_instance_id(RID p_body) const override;
@@ -248,7 +248,7 @@ public:
virtual void body_set_pickable(RID p_body, bool p_pickable) override;
virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
- virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) override;
+ virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) override;
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.cpp b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
index 15d875b3b7..897724fe6f 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.cpp
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.cpp
@@ -76,7 +76,7 @@ void PhysicsServer2DWrapMT::step(real_t p_step) {
}
void PhysicsServer2DWrapMT::sync() {
- if (thread) {
+ if (create_thread) {
if (first_frame) {
first_frame = false;
} else {
@@ -97,7 +97,7 @@ void PhysicsServer2DWrapMT::end_sync() {
void PhysicsServer2DWrapMT::init() {
if (create_thread) {
//OS::get_singleton()->release_rendering_thread();
- thread = Thread::create(_thread_callback, this);
+ thread.start(_thread_callback, this);
while (!step_thread_up) {
OS::get_singleton()->delay_usec(1000);
}
@@ -107,12 +107,9 @@ void PhysicsServer2DWrapMT::init() {
}
void PhysicsServer2DWrapMT::finish() {
- if (thread) {
+ if (thread.is_started()) {
command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit);
- Thread::wait_to_finish(thread);
- memdelete(thread);
-
- thread = nullptr;
+ thread.wait_to_finish();
} else {
physics_2d_server->finish();
}
@@ -135,7 +132,6 @@ PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool
command_queue(p_create_thread) {
physics_2d_server = p_contained;
create_thread = p_create_thread;
- thread = nullptr;
step_pending = 0;
step_thread_up = false;
diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h
index 9207081a51..fbc5b1eaa1 100644
--- a/servers/physics_2d/physics_server_2d_wrap_mt.h
+++ b/servers/physics_2d/physics_server_2d_wrap_mt.h
@@ -53,7 +53,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D {
Thread::ID server_thread;
Thread::ID main_thread;
volatile bool exit;
- Thread *thread;
+ Thread thread;
volatile bool step_thread_up;
bool create_thread;
@@ -189,7 +189,7 @@ public:
FUNC2RC(RID, body_get_shape, RID, int);
FUNC3(body_set_shape_disabled, RID, int, bool);
- FUNC4(body_set_shape_as_one_way_collision, RID, int, bool, float);
+ FUNC4(body_set_shape_as_one_way_collision, RID, int, bool, real_t);
FUNC2(body_remove_shape, RID, int);
FUNC1(body_clear_shapes, RID);
@@ -255,7 +255,7 @@ public:
return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes);
}
- int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) {
+ int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false);
return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin);
}
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 24c73314d8..6e7e802a8b 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -339,10 +339,10 @@ void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_suppor
}
bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const {
- float x = p_point.x;
- float y = p_point.y;
- float edge_x = half_extents.x;
- float edge_y = half_extents.y;
+ real_t x = p_point.x;
+ real_t y = p_point.y;
+ real_t edge_x = half_extents.x;
+ real_t edge_y = half_extents.y;
return (x >= -edge_x) && (x < edge_x) && (y >= -edge_y) && (y < edge_y);
}
@@ -590,7 +590,11 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2
}
void ConvexPolygonShape2DSW::set_data(const Variant &p_data) {
+#ifdef REAL_T_IS_DOUBLE
+ ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT64_ARRAY);
+#else
ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT32_ARRAY);
+#endif
if (points) {
memdelete_arr(points);
@@ -829,7 +833,11 @@ int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) {
}
void ConcavePolygonShape2DSW::set_data(const Variant &p_data) {
+#ifdef REAL_T_IS_DOUBLE
+ ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT64_ARRAY);
+#else
ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT32_ARRAY);
+#endif
Rect2 aabb;
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 068bc7fc0a..41537f7170 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -644,7 +644,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
recover_motion += (b - a) / cbk.amount;
- float depth = a.distance_to(b);
+ real_t depth = a.distance_to(b);
if (depth > result.collision_depth) {
result.collision_depth = depth;
result.collision_point = b;
@@ -739,7 +739,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
- float separation_margin = MIN(p_margin, MAX(0.0, p_motion.length() - CMP_EPSILON)); //don't separate by more than the intended motion
+ real_t separation_margin = MIN(p_margin, MAX(0.0, p_motion.length() - CMP_EPSILON)); //don't separate by more than the intended motion
Transform2D body_transform = p_from;
@@ -793,7 +793,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
- float owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
+ real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx);
cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work
cbk.invalid_by_dir = 0;
@@ -804,7 +804,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
Vector2 motion = lv * PhysicsDirectBodyState2DSW::singleton->step;
- float motion_len = motion.length();
+ real_t motion_len = motion.length();
motion.normalize();
cbk.valid_depth += motion_len * MAX(motion.dot(-cbk.valid_dir), 0.0);
}
diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h
index 41578778f6..8e21003a5f 100644
--- a/servers/physics_3d/body_3d_sw.h
+++ b/servers/physics_3d/body_3d_sw.h
@@ -426,7 +426,7 @@ public:
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
return body->contacts[p_contact_idx].local_normal;
}
- virtual float get_contact_impulse(int p_contact_idx) const override {
+ virtual real_t get_contact_impulse(int p_contact_idx) const override {
return 0.0f; // Only implemented for bullet
}
virtual int get_contact_local_shape(int p_contact_idx) const override {
diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp
index 274de8411c..b554a23bf2 100644
--- a/servers/physics_3d/physics_server_3d_sw.cpp
+++ b/servers/physics_3d/physics_server_3d_sw.cpp
@@ -874,7 +874,7 @@ bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform &p_from, co
return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, body->get_kinematic_margin(), r_result, p_exclude_raycast_shapes);
}
-int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) {
+int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin) {
Body3DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, false);
ERR_FAIL_COND_V(!body->get_space(), false);
diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h
index 9b6b113677..c48db81d97 100644
--- a/servers/physics_3d/physics_server_3d_sw.h
+++ b/servers/physics_3d/physics_server_3d_sw.h
@@ -235,7 +235,7 @@ public:
virtual bool body_is_ray_pickable(RID p_body) const override;
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) override;
- virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) override;
+ virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) override;
// this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) override;
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index f2adcc1072..9c37060bea 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -261,7 +261,7 @@ bool SphereShape3DSW::intersect_point(const Vector3 &p_point) const {
Vector3 SphereShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
Vector3 p = p_point;
- float l = p.length();
+ real_t l = p.length();
if (l < radius) {
return p_point;
}
@@ -429,7 +429,7 @@ Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
}
//check segments
- float min_distance = 1e20;
+ real_t min_distance = 1e20;
Vector3 closest_vertex = half_extents * p_point.sign();
Vector3 s[2] = {
closest_vertex,
@@ -442,7 +442,7 @@ Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const {
Vector3 closest_edge = Geometry3D::get_closest_point_to_segment(p_point, s);
- float d = p_point.distance_to(closest_edge);
+ real_t d = p_point.distance_to(closest_edge);
if (d < min_distance) {
min_point = closest_edge;
min_distance = d;
@@ -839,7 +839,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con
return p_point;
}
- float min_distance = 1e20;
+ real_t min_distance = 1e20;
Vector3 min_point;
//check edges
@@ -852,7 +852,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con
};
Vector3 closest = Geometry3D::get_closest_point_to_segment(p_point, s);
- float d = closest.distance_to(p_point);
+ real_t d = closest.distance_to(p_point);
if (d < min_distance) {
min_distance = d;
min_point = closest;
diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp
index 6cc7ad2676..547717c73c 100644
--- a/servers/physics_3d/space_3d_sw.cpp
+++ b/servers/physics_3d/space_3d_sw.cpp
@@ -476,7 +476,7 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob
ERR_FAIL_COND_V(obj->get_space() != space, Vector3());
- float min_distance = 1e20;
+ real_t min_distance = 1e20;
Vector3 min_point;
bool shapes_found = false;
@@ -492,7 +492,7 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob
Vector3 point = shape->get_closest_point_to(shape_xform.affine_inverse().xform(p_point));
point = shape_xform.xform(point);
- float dist = point.distance_to(p_point);
+ real_t dist = point.distance_to(p_point);
if (dist < min_distance) {
min_distance = dist;
min_point = point;
@@ -651,7 +651,7 @@ int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_tra
recover_motion += (b - a) / cbk.amount;
- float depth = a.distance_to(b);
+ real_t depth = a.distance_to(b);
if (depth > result.collision_depth) {
result.collision_depth = depth;
result.collision_point = b;
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index a6f64f5848..7c36229e9f 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -42,7 +42,7 @@ void PhysicsDirectBodyState2D::integrate_forces() {
real_t av = get_angular_velocity();
- float damp = 1.0 - step * get_total_linear_damp();
+ real_t damp = 1.0 - step * get_total_linear_damp();
if (damp < 0) { // reached zero in the given time
damp = 0;
@@ -168,11 +168,11 @@ Vector2 PhysicsShapeQueryParameters2D::get_motion() const {
return motion;
}
-void PhysicsShapeQueryParameters2D::set_margin(float p_margin) {
+void PhysicsShapeQueryParameters2D::set_margin(real_t p_margin) {
margin = p_margin;
}
-float PhysicsShapeQueryParameters2D::get_margin() const {
+real_t PhysicsShapeQueryParameters2D::get_margin() const {
return margin;
}
@@ -311,7 +311,7 @@ Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryPar
Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
- float closest_safe, closest_unsafe;
+ real_t closest_safe, closest_unsafe;
bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
if (!res) {
return Array();
@@ -517,7 +517,7 @@ PhysicsTestMotionResult2D::PhysicsTestMotionResult2D() {
///////////////////////////////////////
-bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref<PhysicsTestMotionResult2D> &p_result) {
+bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, const Ref<PhysicsTestMotionResult2D> &p_result) {
MotionResult *r = nullptr;
if (p_result.is_valid()) {
r = p_result->get_result_ptr();
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index dd38855199..710eecfdec 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -45,10 +45,10 @@ protected:
public:
virtual Vector2 get_total_gravity() const = 0; // get gravity vector working on this body space/area
- virtual float get_total_linear_damp() const = 0; // get density of this body space/area
- virtual float get_total_angular_damp() const = 0; // get density of this body space/area
+ virtual real_t get_total_linear_damp() const = 0; // get density of this body space/area
+ virtual real_t get_total_angular_damp() const = 0; // get density of this body space/area
- virtual float get_inverse_mass() const = 0; // get the mass
+ virtual real_t get_inverse_mass() const = 0; // get the mass
virtual real_t get_inverse_inertia() const = 0; // get density of this body space
virtual void set_linear_velocity(const Vector2 &p_velocity) = 0;
@@ -103,7 +103,7 @@ class PhysicsShapeQueryParameters2D : public Reference {
RID shape;
Transform2D transform;
Vector2 motion;
- float margin;
+ real_t margin;
Set<RID> exclude;
uint32_t collision_mask;
@@ -125,8 +125,8 @@ public:
void set_motion(const Vector2 &p_motion);
Vector2 get_motion() const;
- void set_margin(float p_margin);
- float get_margin() const;
+ void set_margin(real_t p_margin);
+ real_t get_margin() const;
void set_collision_mask(int p_collision_mask);
int get_collision_mask() const;
@@ -182,11 +182,11 @@ public:
virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0;
- virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
- virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
- virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
struct ShapeRestInfo {
Vector2 point;
@@ -198,7 +198,7 @@ public:
Variant metadata;
};
- virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
PhysicsDirectSpaceState2D();
};
@@ -230,7 +230,7 @@ class PhysicsServer2D : public Object {
static PhysicsServer2D *singleton;
- virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>());
+ virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>());
protected:
static void _bind_methods();
@@ -393,7 +393,7 @@ public:
virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const = 0;
virtual void body_set_shape_disabled(RID p_body, int p_shape, bool p_disabled) = 0;
- virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled, float p_margin = 0) = 0;
+ virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled, real_t p_margin = 0) = 0;
virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0;
virtual void body_clear_shapes(RID p_body) = 0;
@@ -431,8 +431,8 @@ public:
BODY_PARAM_MAX,
};
- virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0;
- virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) = 0;
+ virtual real_t body_get_param(RID p_body, BodyParameter p_param) const = 0;
//state
enum BodyState {
@@ -450,15 +450,15 @@ public:
virtual void body_set_applied_force(RID p_body, const Vector2 &p_force) = 0;
virtual Vector2 body_get_applied_force(RID p_body) const = 0;
- virtual void body_set_applied_torque(RID p_body, float p_torque) = 0;
- virtual float body_get_applied_torque(RID p_body) const = 0;
+ virtual void body_set_applied_torque(RID p_body, real_t p_torque) = 0;
+ virtual real_t body_get_applied_torque(RID p_body) const = 0;
virtual void body_add_central_force(RID p_body, const Vector2 &p_force) = 0;
virtual void body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0;
- virtual void body_add_torque(RID p_body, float p_torque) = 0;
+ virtual void body_add_torque(RID p_body, real_t p_torque) = 0;
virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) = 0;
- virtual void body_apply_torque_impulse(RID p_body, float p_torque) = 0;
+ virtual void body_apply_torque_impulse(RID p_body, real_t p_torque) = 0;
virtual void body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) = 0;
virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) = 0;
@@ -471,8 +471,8 @@ public:
virtual int body_get_max_contacts_reported(RID p_body) const = 0;
//missing remove
- virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) = 0;
- virtual float body_get_contacts_reported_depth_threshold(RID p_body) const = 0;
+ virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) = 0;
+ virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const = 0;
virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
@@ -506,10 +506,10 @@ public:
}
};
- virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
+ virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
struct SeparationResult {
- float collision_depth;
+ real_t collision_depth;
Vector2 collision_point;
Vector2 collision_normal;
Vector2 collider_velocity;
@@ -520,7 +520,7 @@ public:
Variant collider_metadata;
};
- virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0;
+ virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) = 0;
/* JOINT API */
@@ -576,7 +576,7 @@ public:
virtual void set_active(bool p_active) = 0;
virtual void init() = 0;
- virtual void step(float p_step) = 0;
+ virtual void step(real_t p_step) = 0;
virtual void sync() = 0;
virtual void flush_queries() = 0;
virtual void end_sync() = 0;
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index 27ebe32e50..a4dc80b0a6 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -42,13 +42,13 @@ void PhysicsDirectBodyState3D::integrate_forces() {
Vector3 av = get_angular_velocity();
- float linear_damp = 1.0 - step * get_total_linear_damp();
+ real_t linear_damp = 1.0 - step * get_total_linear_damp();
if (linear_damp < 0) { // reached zero in the given time
linear_damp = 0;
}
- float angular_damp = 1.0 - step * get_total_angular_damp();
+ real_t angular_damp = 1.0 - step * get_total_angular_damp();
if (angular_damp < 0) { // reached zero in the given time
angular_damp = 0;
@@ -128,7 +128,7 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform");
}
PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {}
@@ -164,11 +164,11 @@ Transform PhysicsShapeQueryParameters3D::get_transform() const {
return transform;
}
-void PhysicsShapeQueryParameters3D::set_margin(float p_margin) {
+void PhysicsShapeQueryParameters3D::set_margin(real_t p_margin) {
margin = p_margin;
}
-float PhysicsShapeQueryParameters3D::get_margin() const {
+real_t PhysicsShapeQueryParameters3D::get_margin() const {
return margin;
}
@@ -303,7 +303,7 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar
Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, const Vector3 &p_motion) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
- float closest_safe = 1.0f, closest_unsafe = 1.0f;
+ real_t closest_safe = 1.0f, closest_unsafe = 1.0f;
bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas);
if (!res) {
return Array();
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 303825f37c..1349e0e033 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -44,12 +44,12 @@ protected:
public:
virtual Vector3 get_total_gravity() const = 0;
- virtual float get_total_angular_damp() const = 0;
- virtual float get_total_linear_damp() const = 0;
+ virtual real_t get_total_angular_damp() const = 0;
+ virtual real_t get_total_linear_damp() const = 0;
virtual Vector3 get_center_of_mass() const = 0;
virtual Basis get_principal_inertia_axes() const = 0;
- virtual float get_inverse_mass() const = 0; // get the mass
+ virtual real_t get_inverse_mass() const = 0; // get the mass
virtual Vector3 get_inverse_inertia() const = 0; // get density of this body space
virtual Basis get_inverse_inertia_tensor() const = 0; // get density of this body space
@@ -76,7 +76,7 @@ public:
virtual Vector3 get_contact_local_position(int p_contact_idx) const = 0;
virtual Vector3 get_contact_local_normal(int p_contact_idx) const = 0;
- virtual float get_contact_impulse(int p_contact_idx) const = 0;
+ virtual real_t get_contact_impulse(int p_contact_idx) const = 0;
virtual int get_contact_local_shape(int p_contact_idx) const = 0;
virtual RID get_contact_collider(int p_contact_idx) const = 0;
@@ -103,7 +103,7 @@ class PhysicsShapeQueryParameters3D : public Reference {
RES shape_ref;
RID shape;
Transform transform;
- float margin;
+ real_t margin;
Set<RID> exclude;
uint32_t collision_mask;
@@ -122,8 +122,8 @@ public:
void set_transform(const Transform &p_transform);
Transform get_transform() const;
- void set_margin(float p_margin);
- float get_margin() const;
+ void set_margin(real_t p_margin);
+ real_t get_margin() const;
void set_collision_mask(int p_collision_mask);
int get_collision_mask() const;
@@ -174,7 +174,7 @@ public:
virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0;
- virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
struct ShapeRestInfo {
Vector3 point;
@@ -185,11 +185,11 @@ public:
Vector3 linear_velocity; //velocity at contact point
};
- virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0;
+ virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = nullptr) = 0;
- virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
- virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
+ virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0;
virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0;
@@ -404,8 +404,8 @@ public:
BODY_PARAM_MAX,
};
- virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0;
- virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value) = 0;
+ virtual real_t body_get_param(RID p_body, BodyParameter p_param) const = 0;
virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0;
virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0;
@@ -459,8 +459,8 @@ public:
virtual int body_get_max_contacts_reported(RID p_body) const = 0;
//missing remove
- virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) = 0;
- virtual float body_get_contacts_reported_depth_threshold(RID p_body) const = 0;
+ virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) = 0;
+ virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const = 0;
virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
@@ -495,7 +495,7 @@ public:
virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = nullptr, bool p_exclude_raycast_shapes = true) = 0;
struct SeparationResult {
- float collision_depth;
+ real_t collision_depth;
Vector3 collision_point;
Vector3 collision_normal;
Vector3 collider_velocity;
@@ -506,7 +506,7 @@ public:
Variant collider_metadata;
};
- virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0;
+ virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, real_t p_margin = 0.001) = 0;
/* SOFT BODY */
@@ -601,8 +601,8 @@ public:
PIN_JOINT_IMPULSE_CLAMP
};
- virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) = 0;
- virtual float pin_joint_get_param(RID p_joint, PinJointParam p_param) const = 0;
+ virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) = 0;
+ virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const = 0;
virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) = 0;
virtual Vector3 pin_joint_get_local_a(RID p_joint) const = 0;
@@ -631,8 +631,8 @@ public:
virtual RID joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0;
virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0;
- virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) = 0;
- virtual float hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const = 0;
+ virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) = 0;
+ virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const = 0;
virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) = 0;
virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const = 0;
@@ -667,8 +667,8 @@ public:
virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
- virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) = 0;
- virtual float slider_joint_get_param(RID p_joint, SliderJointParam p_param) const = 0;
+ virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) = 0;
+ virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const = 0;
enum ConeTwistJointParam {
CONE_TWIST_JOINT_SWING_SPAN,
@@ -681,8 +681,8 @@ public:
virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
- virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) = 0;
- virtual float cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const = 0;
+ virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) = 0;
+ virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const = 0;
enum G6DOFJointAxisParam {
G6DOF_JOINT_LINEAR_LOWER_LIMIT,
@@ -722,8 +722,8 @@ public:
virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A
- virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, float p_value) = 0;
- virtual float generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) = 0;
+ virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value) = 0;
+ virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) = 0;
virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) = 0;
virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) = 0;
@@ -741,7 +741,7 @@ public:
virtual void set_active(bool p_active) = 0;
virtual void init() = 0;
- virtual void step(float p_step) = 0;
+ virtual void step(real_t p_step) = 0;
virtual void flush_queries() = 0;
virtual void finish() = 0;
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 67f9246b5b..70497bcdb3 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -288,7 +288,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("uniform_set_is_valid", "uniform_set"), &RenderingDevice::uniform_set_is_valid);
ClassDB::bind_method(D_METHOD("buffer_update", "buffer", "offset", "size_bytes", "data", "post_barrier"), &RenderingDevice::_buffer_update, DEFVAL(BARRIER_MASK_ALL));
- ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::_buffer_update, DEFVAL(BARRIER_MASK_ALL));
+ ClassDB::bind_method(D_METHOD("buffer_clear", "buffer", "offset", "size_bytes", "post_barrier"), &RenderingDevice::buffer_clear, DEFVAL(BARRIER_MASK_ALL));
ClassDB::bind_method(D_METHOD("buffer_get_data", "buffer"), &RenderingDevice::buffer_get_data);
ClassDB::bind_method(D_METHOD("render_pipeline_create", "shader", "framebuffer_format", "vertex_format", "primitive", "rasterization_state", "multisample_state", "stencil_state", "color_blend_state", "dynamic_state_flags"), &RenderingDevice::_render_pipeline_create, DEFVAL(0));
@@ -346,7 +346,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_local_device"), &RenderingDevice::create_local_device);
- ClassDB::bind_method(D_METHOD("set_resource_name"), &RenderingDevice::set_resource_name);
+ ClassDB::bind_method(D_METHOD("set_resource_name", "id", "name"), &RenderingDevice::set_resource_name);
ClassDB::bind_method(D_METHOD("draw_command_begin_label", "name", "color"), &RenderingDevice::draw_command_begin_label);
ClassDB::bind_method(D_METHOD("draw_command_insert_label", "name", "color"), &RenderingDevice::draw_command_insert_label);
diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp
index 3572c4dc78..9b8d35e5b3 100644
--- a/servers/rendering/rendering_server_wrap_mt.cpp
+++ b/servers/rendering/rendering_server_wrap_mt.cpp
@@ -97,7 +97,7 @@ void RenderingServerWrapMT::init() {
print_verbose("RenderingServerWrapMT: Creating render thread");
DisplayServer::get_singleton()->release_rendering_thread();
if (create_thread) {
- thread = Thread::create(_thread_callback, this);
+ thread.start(_thread_callback, this);
print_verbose("RenderingServerWrapMT: Starting render thread");
}
while (!draw_thread_up) {
@@ -136,12 +136,9 @@ void RenderingServerWrapMT::finish() {
canvas_light_occluder_free_cached_ids();
canvas_occluder_polygon_free_cached_ids();
- if (thread) {
+ if (create_thread) {
command_queue.push(this, &RenderingServerWrapMT::thread_exit);
- Thread::wait_to_finish(thread);
- memdelete(thread);
-
- thread = nullptr;
+ thread.wait_to_finish();
} else {
rendering_server->finish();
}
@@ -160,7 +157,6 @@ RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool
rendering_server = p_contained;
create_thread = p_create_thread;
- thread = nullptr;
draw_pending = 0;
draw_thread_up = false;
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h
index 2f76577474..f8e73654a0 100644
--- a/servers/rendering/rendering_server_wrap_mt.h
+++ b/servers/rendering/rendering_server_wrap_mt.h
@@ -46,7 +46,7 @@ class RenderingServerWrapMT : public RenderingServer {
Thread::ID server_thread;
volatile bool exit;
- Thread *thread;
+ Thread thread;
volatile bool draw_thread_up;
bool create_thread;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 2fa3355d2f..e6415c0258 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -643,7 +643,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
}
if (hexa_found) {
- tk.constant = (double)str.hex_to_int(true);
+ tk.constant = (double)str.hex_to_int();
} else {
tk.constant = str.to_float();
}
diff --git a/tests/test_command_queue.h b/tests/test_command_queue.h
index 2f0b75760d..b4fa63ad2b 100644
--- a/tests/test_command_queue.h
+++ b/tests/test_command_queue.h
@@ -122,8 +122,8 @@ public:
int message_count_to_read = 0;
bool exit_threads = false;
- Thread *reader_thread = nullptr;
- Thread *writer_thread = nullptr;
+ Thread reader_thread;
+ Thread writer_thread;
int func1_count = 0;
@@ -221,20 +221,16 @@ public:
}
void init_threads() {
- reader_thread = Thread::create(&SharedThreadState::static_reader_thread_loop, this);
- writer_thread = Thread::create(&SharedThreadState::static_writer_thread_loop, this);
+ reader_thread.start(&SharedThreadState::static_reader_thread_loop, this);
+ writer_thread.start(&SharedThreadState::static_writer_thread_loop, this);
}
void destroy_threads() {
exit_threads = true;
reader_threadwork.main_start_work();
writer_threadwork.main_start_work();
- Thread::wait_to_finish(reader_thread);
- memdelete(reader_thread);
- reader_thread = nullptr;
- Thread::wait_to_finish(writer_thread);
- memdelete(writer_thread);
- writer_thread = nullptr;
+ reader_thread.wait_to_finish();
+ writer_thread.wait_to_finish();
}
};
diff --git a/tests/test_object.h b/tests/test_object.h
index 7f310fc096..142d76553d 100644
--- a/tests/test_object.h
+++ b/tests/test_object.h
@@ -31,12 +31,103 @@
#ifndef TEST_OBJECT_H
#define TEST_OBJECT_H
+#include "core/core_string_names.h"
#include "core/object/object.h"
#include "thirdparty/doctest/doctest.h"
+// Declared in global namespace because of GDCLASS macro warning (Windows):
+// "Unqualified friend declaration referring to type outside of the nearest enclosing namespace
+// is a Microsoft extension; add a nested name specifier".
+class _TestDerivedObject : public Object {
+ GDCLASS(_TestDerivedObject, Object);
+
+ int property_value;
+
+protected:
+ static void _bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_property", "property"), &_TestDerivedObject::set_property);
+ ClassDB::bind_method(D_METHOD("get_property"), &_TestDerivedObject::get_property);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "property"), "set_property", "get_property");
+ }
+
+public:
+ void set_property(int value) { property_value = value; }
+ int get_property() const { return property_value; }
+};
+
namespace TestObject {
+class _MockScriptInstance : public ScriptInstance {
+ StringName property_name = "NO_NAME";
+ Variant property_value;
+
+public:
+ bool set(const StringName &p_name, const Variant &p_value) override {
+ property_name = p_name;
+ property_value = p_value;
+ return true;
+ }
+ bool get(const StringName &p_name, Variant &r_ret) const override {
+ if (property_name == p_name) {
+ r_ret = property_value;
+ return true;
+ }
+ return false;
+ }
+ void get_property_list(List<PropertyInfo> *p_properties) const override {
+ }
+ Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const override {
+ return Variant::PACKED_FLOAT32_ARRAY;
+ }
+ void get_method_list(List<MethodInfo> *p_list) const override {
+ }
+ bool has_method(const StringName &p_method) const override {
+ return false;
+ }
+ Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override {
+ return Variant();
+ }
+ void notification(int p_notification) override {
+ }
+ Ref<Script> get_script() const override {
+ return Ref<Script>();
+ }
+ Vector<ScriptNetData> get_rpc_methods() const override {
+ return Vector<ScriptNetData>();
+ }
+ uint16_t get_rpc_method_id(const StringName &p_method) const override {
+ return 0;
+ }
+ StringName get_rpc_method(uint16_t p_id) const override {
+ return StringName();
+ }
+ MultiplayerAPI::RPCMode get_rpc_mode_by_id(uint16_t p_id) const override {
+ return MultiplayerAPI::RPC_MODE_PUPPET;
+ }
+ MultiplayerAPI::RPCMode get_rpc_mode(const StringName &p_method) const override {
+ return MultiplayerAPI::RPC_MODE_PUPPET;
+ }
+ Vector<ScriptNetData> get_rset_properties() const override {
+ return Vector<ScriptNetData>();
+ }
+ uint16_t get_rset_property_id(const StringName &p_variable) const override {
+ return 0;
+ }
+ StringName get_rset_property(uint16_t p_id) const override {
+ return StringName();
+ }
+ MultiplayerAPI::RPCMode get_rset_mode_by_id(uint16_t p_id) const override {
+ return MultiplayerAPI::RPC_MODE_PUPPET;
+ }
+ MultiplayerAPI::RPCMode get_rset_mode(const StringName &p_variable) const override {
+ return MultiplayerAPI::RPC_MODE_PUPPET;
+ }
+ ScriptLanguage *get_language() override {
+ return nullptr;
+ }
+};
+
TEST_CASE("[Object] Core getters") {
Object object;
@@ -55,6 +146,15 @@ TEST_CASE("[Object] Core getters") {
CHECK_MESSAGE(
object.get_save_class() == "Object",
"The returned save class should match the expected value.");
+
+ List<String> inheritance_list;
+ object.get_inheritance_list_static(&inheritance_list);
+ CHECK_MESSAGE(
+ inheritance_list.size() == 1,
+ "The inheritance list should consist of Object only");
+ CHECK_MESSAGE(
+ inheritance_list[0] == "Object",
+ "The inheritance list should consist of Object only");
}
TEST_CASE("[Object] Metadata") {
@@ -87,6 +187,119 @@ TEST_CASE("[Object] Metadata") {
meta_list2.size() == 0,
"The metadata list should contain 0 items after removing all metadata items.");
}
+
+TEST_CASE("[Object] Construction") {
+ Object object;
+
+ CHECK_MESSAGE(
+ !object.is_reference(),
+ "Object is not a Reference.");
+
+ Object *p_db = ObjectDB::get_instance(object.get_instance_id());
+ CHECK_MESSAGE(
+ p_db == &object,
+ "The database pointer returned by the object id should reference same object.");
+}
+
+TEST_CASE("[Object] Script instance property setter") {
+ Object object;
+ _MockScriptInstance *script_instance = memnew(_MockScriptInstance);
+ object.set_script_instance(script_instance);
+
+ bool valid = false;
+ object.set("some_name", 100, &valid);
+ CHECK(valid);
+ Variant actual_value;
+ CHECK_MESSAGE(
+ script_instance->get("some_name", actual_value),
+ "The assigned script instance should successfully retrieve value by name.");
+ CHECK_MESSAGE(
+ actual_value == Variant(100),
+ "The returned value should equal the one which was set by the object.");
+}
+
+TEST_CASE("[Object] Script instance property getter") {
+ Object object;
+ _MockScriptInstance *script_instance = memnew(_MockScriptInstance);
+ script_instance->set("some_name", 100); // Make sure script instance has the property
+ object.set_script_instance(script_instance);
+
+ bool valid = false;
+ const Variant &actual_value = object.get("some_name", &valid);
+ CHECK(valid);
+ CHECK_MESSAGE(
+ actual_value == Variant(100),
+ "The returned value should equal the one which was set by the script instance.");
+}
+
+TEST_CASE("[Object] Built-in property setter") {
+ ClassDB::register_class<_TestDerivedObject>();
+ _TestDerivedObject derived_object;
+
+ bool valid = false;
+ derived_object.set("property", 100, &valid);
+ CHECK(valid);
+ CHECK_MESSAGE(
+ derived_object.get_property() == 100,
+ "The property value should equal the one which was set with built-in setter.");
+}
+
+TEST_CASE("[Object] Built-in property getter") {
+ ClassDB::register_class<_TestDerivedObject>();
+ _TestDerivedObject derived_object;
+ derived_object.set_property(100);
+
+ bool valid = false;
+ const Variant &actual_value = derived_object.get("property", &valid);
+ CHECK(valid);
+ CHECK_MESSAGE(
+ actual_value == Variant(100),
+ "The returned value should equal the one which was set with built-in setter.");
+}
+
+TEST_CASE("[Object] Script property setter") {
+ Object object;
+ Variant script;
+
+ bool valid = false;
+ object.set(CoreStringNames::get_singleton()->_script, script, &valid);
+ CHECK(valid);
+ CHECK_MESSAGE(
+ object.get_script() == script,
+ "The object script should be equal to the assigned one.");
+}
+
+TEST_CASE("[Object] Script property getter") {
+ Object object;
+ Variant script;
+ object.set_script(script);
+
+ bool valid = false;
+ const Variant &actual_value = object.get(CoreStringNames::get_singleton()->_script, &valid);
+ CHECK(valid);
+ CHECK_MESSAGE(
+ actual_value == script,
+ "The returned value should be equal to the assigned script.");
+}
+
+TEST_CASE("[Object] Absent name setter") {
+ Object object;
+
+ bool valid = true;
+ object.set("absent_name", 100, &valid);
+ CHECK(!valid);
+}
+
+TEST_CASE("[Object] Absent name getter") {
+ Object object;
+
+ bool valid = true;
+ const Variant &actual_value = object.get("absent_name", &valid);
+ CHECK(!valid);
+ CHECK_MESSAGE(
+ actual_value == Variant(),
+ "The returned value should equal nil variant.");
+}
} // namespace TestObject
#endif // TEST_OBJECT_H
diff --git a/tests/test_physics_3d.cpp b/tests/test_physics_3d.cpp
index a11140cfc3..f991fd7c86 100644
--- a/tests/test_physics_3d.cpp
+++ b/tests/test_physics_3d.cpp
@@ -59,7 +59,7 @@ class TestPhysics3DMainLoop : public MainLoop {
RID character;
- float ofs_x, ofs_y;
+ real_t ofs_x, ofs_y;
Point2 joy_direction;
@@ -115,7 +115,7 @@ protected:
return b;
}
- void configure_body(RID p_body, float p_mass, float p_friction, float p_bounce) {
+ void configure_body(RID p_body, real_t p_mass, real_t p_friction, real_t p_bounce) {
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_MASS, p_mass);
ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_FRICTION, p_friction);
@@ -211,8 +211,8 @@ protected:
vs->instance_set_transform(triins, tritrans);
}
- void make_grid(int p_width, int p_height, float p_cellsize, float p_cellheight, const Transform &p_xform = Transform()) {
- Vector<Vector<float>> grid;
+ void make_grid(int p_width, int p_height, real_t p_cellsize, real_t p_cellheight, const Transform &p_xform = Transform()) {
+ Vector<Vector<real_t>> grid;
grid.resize(p_width);
@@ -253,8 +253,8 @@ public:
}
if (mm.is_valid() && mm->get_button_mask() & 1) {
- float y = -mm->get_relative().y / 20.0;
- float x = mm->get_relative().x / 20.0;
+ real_t y = -mm->get_relative().y / 20.0;
+ real_t x = mm->get_relative().x / 20.0;
if (mover.is_valid()) {
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
@@ -312,7 +312,7 @@ public:
}
virtual bool physics_process(float p_time) override {
if (mover.is_valid()) {
- static float joy_speed = 10;
+ static real_t joy_speed = 10;
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
Transform t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM);
t.origin += Vector3(joy_speed * joy_direction.x * p_time, -joy_speed * joy_direction.y * p_time, 0);
diff --git a/tests/test_string.h b/tests/test_string.h
index 17a2df190d..cc3152203e 100644
--- a/tests/test_string.h
+++ b/tests/test_string.h
@@ -266,7 +266,7 @@ TEST_CASE("[String] Operator []") {
a[6] = 'C';
CHECK(a == "Sugar Cane");
CHECK(a[1] == 'u');
- CHECK(a.ord_at(1) == 'u');
+ CHECK(a.unicode_at(1) == 'u');
}
TEST_CASE("[String] Case function test") {
@@ -370,12 +370,9 @@ TEST_CASE("[String] String to integer") {
TEST_CASE("[String] Hex to integer") {
static const char *nums[4] = { "0xFFAE", "22", "0", "AADDAD" };
static const int64_t num[4] = { 0xFFAE, 0x22, 0, 0xAADDAD };
- static const bool wo_prefix[4] = { false, true, true, true };
- static const bool w_prefix[4] = { true, false, true, false };
for (int i = 0; i < 4; i++) {
- CHECK((String(nums[i]).hex_to_int(true) == num[i]) == w_prefix[i]);
- CHECK((String(nums[i]).hex_to_int(false) == num[i]) == wo_prefix[i]);
+ CHECK(String(nums[i]).hex_to_int() == num[i]);
}
}
@@ -1155,20 +1152,12 @@ TEST_CASE("[String] hash") {
CHECK(a.hash64() != c.hash64());
}
-TEST_CASE("[String] http_escape/unescape") {
+TEST_CASE("[String] uri_encode/unescape") {
String s = "Godot Engine:'docs'";
String t = "Godot%20Engine%3A%27docs%27";
- CHECK(s.http_escape() == t);
- CHECK(t.http_unescape() == s);
-}
-
-TEST_CASE("[String] percent_encode/decode") { // Note: is it redundant? Seems to be same as http_escape/unescape but in lower case.
- String s = "Godot Engine:'docs'";
- String t = "Godot%20Engine%3a%27docs%27";
-
- CHECK(s.percent_encode() == t);
- CHECK(t.percent_decode() == s);
+ CHECK(s.uri_encode() == t);
+ CHECK(t.uri_decode() == s);
}
TEST_CASE("[String] xml_escape/unescape") {