summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/SCsub5
-rw-r--r--modules/arkit/arkit_interface.h18
-rw-r--r--modules/arkit/arkit_interface.mm56
-rw-r--r--modules/arkit/register_types.cpp2
-rw-r--r--modules/bullet/SCsub3
-rw-r--r--modules/bullet/config.py11
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsDirectBodyState3D.xml13
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsServer3D.xml13
-rw-r--r--modules/bullet/rigid_body_bullet.cpp44
-rw-r--r--modules/bullet/rigid_body_bullet.h2
-rw-r--r--modules/bullet/space_bullet.cpp10
-rw-r--r--modules/bullet/space_bullet.h6
-rw-r--r--modules/csg/csg.cpp2
-rw-r--r--modules/csg/csg_gizmos.cpp24
-rw-r--r--modules/csg/csg_gizmos.h6
-rw-r--r--modules/csg/csg_shape.cpp24
-rw-r--r--modules/dds/texture_loader_dds.cpp2
-rw-r--r--modules/dds/texture_loader_dds.h2
-rw-r--r--modules/etc/texture_loader_pkm.cpp2
-rw-r--r--modules/etc/texture_loader_pkm.h2
-rw-r--r--modules/gdnative/SCsub2
-rw-r--r--modules/gdnative/config.py2
-rw-r--r--modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml15
-rw-r--r--modules/gdnative/doc_classes/GDNativeLibrary.xml2
-rw-r--r--modules/gdnative/doc_classes/XRInterfaceGDNative.xml15
-rw-r--r--modules/gdnative/gdnative.cpp2
-rw-r--r--modules/gdnative/gdnative.h2
-rw-r--r--modules/gdnative/gdnative/color.cpp4
-rw-r--r--modules/gdnative/gdnative/vector2.cpp4
-rw-r--r--modules/gdnative/gdnative/vector3.cpp4
-rw-r--r--modules/gdnative/gdnative_api.json34
-rw-r--r--modules/gdnative/gdnative_builders.py6
-rw-r--r--modules/gdnative/include/gdnative/color.h2
-rw-r--r--modules/gdnative/include/gdnative/vector2.h2
-rw-r--r--modules/gdnative/include/gdnative/vector3.h2
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h4
-rw-r--r--modules/gdnative/include/xr/godot_xr.h (renamed from modules/gdnative/include/arvr/godot_arvr.h)37
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp9
-rw-r--r--modules/gdnative/nativescript/nativescript.h4
-rw-r--r--modules/gdnative/pluginscript/pluginscript_loader.cpp2
-rw-r--r--modules/gdnative/pluginscript/pluginscript_loader.h2
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp7
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.h2
-rw-r--r--modules/gdnative/register_types.cpp6
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp2
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.h2
-rw-r--r--modules/gdnative/xr/SCsub (renamed from modules/gdnative/arvr/SCsub)0
-rw-r--r--modules/gdnative/xr/config.py (renamed from modules/gdnative/arvr/config.py)0
-rw-r--r--modules/gdnative/xr/register_types.cpp (renamed from modules/gdnative/arvr/register_types.cpp)9
-rw-r--r--modules/gdnative/xr/register_types.h (renamed from modules/gdnative/arvr/register_types.h)10
-rw-r--r--modules/gdnative/xr/xr_interface_gdnative.cpp (renamed from modules/gdnative/arvr/arvr_interface_gdnative.cpp)185
-rw-r--r--modules/gdnative/xr/xr_interface_gdnative.h (renamed from modules/gdnative/arvr/arvr_interface_gdnative.h)34
-rw-r--r--modules/gdscript/config.py1
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptNativeClass.xml19
-rw-r--r--modules/gdscript/gdscript.cpp39
-rw-r--r--modules/gdscript/gdscript.h4
-rw-r--r--modules/gdscript/gdscript_editor.cpp27
-rw-r--r--modules/gdscript/gdscript_function.cpp43
-rw-r--r--modules/gdscript/gdscript_function.h6
-rw-r--r--modules/gdscript/gdscript_functions.cpp9
-rw-r--r--modules/gdscript/gdscript_parser.cpp107
-rw-r--r--modules/gdscript/gdscript_parser.h1
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp24
-rw-r--r--modules/gdscript/gdscript_tokenizer.h1
-rw-r--r--modules/gdscript/language_server/lsp.hpp6
-rw-r--r--modules/gridmap/grid_map.cpp14
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp14
-rw-r--r--modules/mobile_vr/doc_classes/MobileVRInterface.xml8
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp49
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h14
-rw-r--r--modules/mobile_vr/register_types.cpp2
-rw-r--r--modules/mono/build_scripts/godot_tools_build.py8
-rw-r--r--modules/mono/build_scripts/solution_builder.py114
-rw-r--r--modules/mono/config.py1
-rw-r--r--modules/mono/csharp_script.cpp16
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs27
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs5
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs62
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs12
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/BuildTab.cs10
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs54
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs36
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj34
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs2
-rw-r--r--modules/mono/editor/bindings_generator.cpp16
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp10
-rw-r--r--modules/mono/editor/godotsharp_export.cpp18
-rw-r--r--modules/mono/editor/godotsharp_export.h4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs28
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs38
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs31
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs178
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs18
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs6
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs18
-rw-r--r--modules/mono/godotsharp_dirs.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp17
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp13
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.cpp32
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h23
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp34
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h13
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp107
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp307
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h9
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp5
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp60
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h17
-rw-r--r--modules/mono/utils/string_utils.cpp10
-rw-r--r--modules/opensimplex/noise_texture.cpp11
-rw-r--r--modules/pvr/texture_loader_pvr.cpp2
-rw-r--r--modules/pvr/texture_loader_pvr.h2
-rw-r--r--modules/theora/video_stream_theora.cpp2
-rw-r--r--modules/theora/video_stream_theora.h2
-rw-r--r--modules/tinyexr/SCsub3
-rw-r--r--modules/upnp/upnp.cpp7
-rw-r--r--modules/upnp/upnp_device.cpp22
-rw-r--r--modules/visual_script/visual_script.cpp24
-rw-r--r--modules/visual_script/visual_script.h2
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp6
-rw-r--r--modules/visual_script/visual_script_editor.cpp51
-rw-r--r--modules/visual_script/visual_script_flow_control.cpp2
-rw-r--r--modules/visual_script/visual_script_nodes.cpp13
-rw-r--r--modules/webm/video_stream_webm.cpp2
-rw-r--r--modules/webm/video_stream_webm.h2
-rw-r--r--modules/xatlas_unwrap/register_types.cpp138
133 files changed, 1468 insertions, 1301 deletions
diff --git a/modules/SCsub b/modules/SCsub
index 1671b398e5..fb46c5f877 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -11,6 +11,7 @@ Export("env_modules")
# Header with MODULE_*_ENABLED defines.
env.CommandNoCache("modules_enabled.gen.h", Value(env.module_list), modules_builders.generate_modules_enabled)
+vs_sources = []
# libmodule_<name>.a for each active module.
for module in env.module_list:
env.modules_sources = []
@@ -23,6 +24,8 @@ for module in env.module_list:
lib = env_modules.add_library("module_%s" % module, env.modules_sources)
env.Prepend(LIBS=[lib])
+ if env["vsproj"]:
+ vs_sources += env.modules_sources
# libmodules.a with only register_module_types.
# Must be last so that all libmodule_<name>.a libraries are on the right side
@@ -31,3 +34,5 @@ env.modules_sources = []
env_modules.add_source_files(env.modules_sources, "register_module_types.gen.cpp")
lib = env_modules.add_library("modules", env.modules_sources)
env.Prepend(LIBS=[lib])
+if env["vsproj"]:
+ env.modules_sources += vs_sources
diff --git a/modules/arkit/arkit_interface.h b/modules/arkit/arkit_interface.h
index 4f8f726816..1044f3cf6f 100644
--- a/modules/arkit/arkit_interface.h
+++ b/modules/arkit/arkit_interface.h
@@ -31,9 +31,9 @@
#ifndef ARKIT_INTERFACE_H
#define ARKIT_INTERFACE_H
-#include "servers/arvr/arvr_interface.h"
-#include "servers/arvr/arvr_positional_tracker.h"
#include "servers/camera/camera_feed.h"
+#include "servers/xr/xr_interface.h"
+#include "servers/xr/xr_positional_tracker.h"
/**
@author Bastiaan Olij <mux213@gmail.com>
@@ -44,8 +44,8 @@
// forward declaration for some needed objects
class ARKitShader;
-class ARKitInterface : public ARVRInterface {
- GDCLASS(ARKitInterface, ARVRInterface);
+class ARKitInterface : public XRInterface {
+ GDCLASS(ARKitInterface, XRInterface);
private:
bool initialized;
@@ -65,7 +65,7 @@ private:
Vector<uint8_t> img_data[2];
struct anchor_map {
- ARVRPositionalTracker *tracker;
+ XRPositionalTracker *tracker;
unsigned char uuid[16];
};
@@ -73,7 +73,7 @@ private:
unsigned int num_anchors;
unsigned int max_anchors;
anchor_map *anchors;
- ARVRPositionalTracker *get_anchor_for_uuid(const unsigned char *p_uuid);
+ XRPositionalTracker *get_anchor_for_uuid(const unsigned char *p_uuid);
void remove_anchor_for_uuid(const unsigned char *p_uuid);
void remove_all_anchors();
@@ -108,9 +108,9 @@ public:
virtual Size2 get_render_targetsize();
virtual bool is_stereo();
- virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
- virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
- virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
+ virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform);
+ virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+ virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
virtual void process();
diff --git a/modules/arkit/arkit_interface.mm b/modules/arkit/arkit_interface.mm
index 031e1e115e..7de824815a 100644
--- a/modules/arkit/arkit_interface.mm
+++ b/modules/arkit/arkit_interface.mm
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "core/input/input_filter.h"
+#include "core/input/input.h"
#include "core/os/os.h"
#include "scene/resources/surface_tool.h"
#include "servers/rendering/rendering_server_globals.h"
@@ -158,7 +158,7 @@ StringName ARKitInterface::get_name() const {
}
int ARKitInterface::get_capabilities() const {
- return ARKitInterface::ARVR_MONO + ARKitInterface::ARVR_AR;
+ return ARKitInterface::XR_MONO + ARKitInterface::XR_AR;
}
Array ARKitInterface::raycast(Vector2 p_screen_coord) {
@@ -218,8 +218,8 @@ bool ARKitInterface::is_initialized() const {
}
bool ARKitInterface::initialize() {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL_V(arvr_server, false);
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, false);
if (!initialized) {
print_line("initializing ARKit");
@@ -244,7 +244,7 @@ bool ARKitInterface::initialize() {
transform = Transform();
// make this our primary interface
- arvr_server->set_primary_interface(this);
+ xr_server->set_primary_interface(this);
// make sure we have our feed setup
if (feed.is_null()) {
@@ -270,10 +270,10 @@ bool ARKitInterface::initialize() {
void ARKitInterface::uninitialize() {
if (initialized) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- if (arvr_server != NULL) {
+ XRServer *xr_server = XRServer::get_singleton();
+ if (xr_server != NULL) {
// no longer our primary interface
- arvr_server->clear_primary_interface_if(this);
+ xr_server->clear_primary_interface_if(this);
}
if (feed.is_valid()) {
@@ -303,22 +303,22 @@ Size2 ARKitInterface::get_render_targetsize() {
return target_size;
}
-Transform ARKitInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) {
+Transform ARKitInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
_THREAD_SAFE_METHOD_
Transform transform_for_eye;
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL_V(arvr_server, transform_for_eye);
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, transform_for_eye);
if (initialized) {
- float world_scale = arvr_server->get_world_scale();
+ float world_scale = xr_server->get_world_scale();
// just scale our origin point of our transform, note that we really shouldn't be using world_scale in ARKit but....
transform_for_eye = transform;
transform_for_eye.origin *= world_scale;
- transform_for_eye = p_cam_transform * arvr_server->get_reference_frame() * transform_for_eye;
+ transform_for_eye = p_cam_transform * xr_server->get_reference_frame() * transform_for_eye;
} else {
// huh? well just return what we got....
transform_for_eye = p_cam_transform;
@@ -327,7 +327,7 @@ Transform ARKitInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const
return transform_for_eye;
}
-CameraMatrix ARKitInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+CameraMatrix ARKitInterface::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
// Remember our near and far, it will be used in process when we obtain our projection from our ARKit session.
z_near = p_z_near;
z_far = p_z_far;
@@ -335,7 +335,7 @@ CameraMatrix ARKitInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, r
return projection;
}
-void ARKitInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
+void ARKitInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
_THREAD_SAFE_METHOD_
// We must have a valid render target
@@ -356,7 +356,7 @@ void ARKitInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_targ
VSG::rasterizer->blit_render_target_to_screen(p_render_target, screen_rect, 0);
}
-ARVRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *p_uuid) {
+XRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *p_uuid) {
if (anchors == NULL) {
num_anchors = 0;
max_anchors = 10;
@@ -377,8 +377,8 @@ ARVRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *
ERR_FAIL_NULL_V(anchors, NULL);
}
- ARVRPositionalTracker *new_tracker = memnew(ARVRPositionalTracker);
- new_tracker->set_type(ARVRServer::TRACKER_ANCHOR);
+ XRPositionalTracker *new_tracker = memnew(XRPositionalTracker);
+ new_tracker->set_type(XRServer::TRACKER_ANCHOR);
char tracker_name[256];
sprintf(tracker_name, "Anchor %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", p_uuid[0], p_uuid[1], p_uuid[2], p_uuid[3], p_uuid[4], p_uuid[5], p_uuid[6], p_uuid[7], p_uuid[8], p_uuid[9], p_uuid[10], p_uuid[11], p_uuid[12], p_uuid[13], p_uuid[14], p_uuid[15]);
@@ -388,7 +388,7 @@ ARVRPositionalTracker *ARKitInterface::get_anchor_for_uuid(const unsigned char *
new_tracker->set_name(name);
// add our tracker
- ARVRServer::get_singleton()->add_tracker(new_tracker);
+ XRServer::get_singleton()->add_tracker(new_tracker);
anchors[num_anchors].tracker = new_tracker;
memcpy(anchors[num_anchors].uuid, p_uuid, 16);
num_anchors++;
@@ -401,7 +401,7 @@ void ARKitInterface::remove_anchor_for_uuid(const unsigned char *p_uuid) {
for (unsigned int i = 0; i < num_anchors; i++) {
if (memcmp(anchors[i].uuid, p_uuid, 16) == 0) {
// remove our tracker
- ARVRServer::get_singleton()->remove_tracker(anchors[i].tracker);
+ XRServer::get_singleton()->remove_tracker(anchors[i].tracker);
memdelete(anchors[i].tracker);
// bring remaining forward
@@ -421,7 +421,7 @@ void ARKitInterface::remove_all_anchors() {
if (anchors != NULL) {
for (unsigned int i = 0; i < num_anchors; i++) {
// remove our tracker
- ARVRServer::get_singleton()->remove_tracker(anchors[i].tracker);
+ XRServer::get_singleton()->remove_tracker(anchors[i].tracker);
memdelete(anchors[i].tracker);
};
@@ -582,16 +582,16 @@ void ARKitInterface::process() {
// strangely enough we have to states, rolling them up into one
if (camera.trackingState == ARTrackingStateNotAvailable) {
// no tracking, would be good if we black out the screen or something...
- tracking_state = ARVRInterface::ARVR_NOT_TRACKING;
+ tracking_state = XRInterface::XR_NOT_TRACKING;
} else {
if (camera.trackingState == ARTrackingStateNormal) {
- tracking_state = ARVRInterface::ARVR_NORMAL_TRACKING;
+ tracking_state = XRInterface::XR_NORMAL_TRACKING;
} else if (camera.trackingStateReason == ARTrackingStateReasonExcessiveMotion) {
- tracking_state = ARVRInterface::ARVR_EXCESSIVE_MOTION;
+ tracking_state = XRInterface::XR_EXCESSIVE_MOTION;
} else if (camera.trackingStateReason == ARTrackingStateReasonInsufficientFeatures) {
- tracking_state = ARVRInterface::ARVR_INSUFFICIENT_FEATURES;
+ tracking_state = XRInterface::XR_INSUFFICIENT_FEATURES;
} else {
- tracking_state = ARVRInterface::ARVR_UNKNOWN_TRACKING;
+ tracking_state = XRInterface::XR_UNKNOWN_TRACKING;
}
// copy our current frame transform
@@ -665,7 +665,7 @@ void ARKitInterface::_add_or_update_anchor(void *p_anchor) {
unsigned char uuid[16];
[anchor.identifier getUUIDBytes:uuid];
- ARVRPositionalTracker *tracker = get_anchor_for_uuid(uuid);
+ XRPositionalTracker *tracker = get_anchor_for_uuid(uuid);
if (tracker != NULL) {
// lets update our mesh! (using Arjens code as is for now)
// we should also probably limit how often we do this...
@@ -695,7 +695,7 @@ void ARKitInterface::_add_or_update_anchor(void *p_anchor) {
}
// Note, this also contains a scale factor which gives us an idea of the size of the anchor
- // We may extract that in our ARVRAnchor class
+ // We may extract that in our XRAnchor class
Basis b;
matrix_float4x4 m44 = anchor.transform;
b.elements[0].x = m44.columns[0][0];
diff --git a/modules/arkit/register_types.cpp b/modules/arkit/register_types.cpp
index c78b35529b..91069ab364 100644
--- a/modules/arkit/register_types.cpp
+++ b/modules/arkit/register_types.cpp
@@ -37,7 +37,7 @@ void register_arkit_types() {
Ref<ARKitInterface> arkit_interface;
arkit_interface.instance();
- ARVRServer::get_singleton()->add_interface(arkit_interface);
+ XRServer::get_singleton()->add_interface(arkit_interface);
}
void unregister_arkit_types() {
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
index 692c749886..b853ebfc63 100644
--- a/modules/bullet/SCsub
+++ b/modules/bullet/SCsub
@@ -175,6 +175,7 @@ if env["builtin_bullet"]:
"BulletSoftBody/btDeformableContactProjection.cpp",
"BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp",
"BulletSoftBody/btDeformableContactConstraint.cpp",
+ "BulletSoftBody/poly34.cpp",
# clew
"clew/clew.c",
# LinearMath
@@ -203,6 +204,8 @@ if env["builtin_bullet"]:
# if env['target'] == "debug" or env['target'] == "release_debug":
# env_bullet.Append(CPPDEFINES=['BT_DEBUG'])
+ env_bullet.Append(CPPDEFINES=["BT_USE_OLD_DAMPING_METHOD"])
+
env_thirdparty = env_bullet.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
diff --git a/modules/bullet/config.py b/modules/bullet/config.py
index e8ca273f61..d22f9454ed 100644
--- a/modules/bullet/config.py
+++ b/modules/bullet/config.py
@@ -4,14 +4,3 @@ def can_build(env, platform):
def configure(env):
pass
-
-
-def get_doc_classes():
- return [
- "BulletPhysicsDirectBodyState3D",
- "BulletPhysicsServer3D",
- ]
-
-
-def get_doc_path():
- return "doc_classes"
diff --git a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState3D.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState3D.xml
deleted file mode 100644
index 1c0181bd9c..0000000000
--- a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState3D.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BulletPhysicsDirectBodyState3D" inherits="PhysicsDirectBodyState3D" version="4.0">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/modules/bullet/doc_classes/BulletPhysicsServer3D.xml b/modules/bullet/doc_classes/BulletPhysicsServer3D.xml
deleted file mode 100644
index b20595b4f6..0000000000
--- a/modules/bullet/doc_classes/BulletPhysicsServer3D.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BulletPhysicsServer3D" inherits="PhysicsServer3D" version="4.0">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index fc4e1d57de..e393396713 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -138,8 +138,8 @@ void BulletPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impul
body->apply_torque_impulse(p_impulse);
}
-void BulletPhysicsDirectBodyState3D::set_sleep_state(bool p_enable) {
- body->set_activation_state(p_enable);
+void BulletPhysicsDirectBodyState3D::set_sleep_state(bool p_sleep) {
+ body->set_activation_state(!p_sleep);
}
bool BulletPhysicsDirectBodyState3D::is_sleeping() const {
@@ -503,15 +503,18 @@ void RigidBodyBullet::set_param(PhysicsServer3D::BodyParameter p_param, real_t p
}
case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP:
linearDamp = p_value;
- btBody->setDamping(linearDamp, angularDamp);
+ // Mark for updating total linear damping.
+ scratch_space_override_modificator();
break;
case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP:
angularDamp = p_value;
- btBody->setDamping(linearDamp, angularDamp);
+ // Mark for updating total angular damping.
+ scratch_space_override_modificator();
break;
case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE:
gravity_scale = p_value;
- /// The Bullet gravity will be is set by reload_space_override_modificator
+ // The Bullet gravity will be is set by reload_space_override_modificator.
+ // Mark for updating total gravity scale.
scratch_space_override_modificator();
break;
default:
@@ -902,21 +905,20 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) {
}
void RigidBodyBullet::reload_space_override_modificator() {
-
// Make sure that kinematic bodies have their total gravity calculated
if (!is_active() && PhysicsServer3D::BODY_MODE_KINEMATIC != mode)
return;
- Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude());
- real_t newLinearDamp(linearDamp);
- real_t newAngularDamp(angularDamp);
+ Vector3 newGravity(0.0, 0.0, 0.0);
+ real_t newLinearDamp = MAX(0.0, linearDamp);
+ real_t newAngularDamp = MAX(0.0, angularDamp);
AreaBullet *currentArea;
// Variable used to calculate new gravity for gravity point areas, it is pointed by currentGravity pointer
Vector3 support_gravity(0, 0, 0);
- int countCombined(0);
- for (int i = areaWhereIamCount - 1; 0 <= i; --i) {
+ bool stopped = false;
+ for (int i = areaWhereIamCount - 1; (0 <= i) && !stopped; --i) {
currentArea = areasWhereIam[i];
@@ -965,7 +967,6 @@ void RigidBodyBullet::reload_space_override_modificator() {
newGravity += support_gravity;
newLinearDamp += currentArea->get_spOv_linearDamp();
newAngularDamp += currentArea->get_spOv_angularDamp();
- ++countCombined;
break;
case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE:
/// This area adds its gravity/damp values to whatever has been calculated
@@ -974,32 +975,31 @@ void RigidBodyBullet::reload_space_override_modificator() {
newGravity += support_gravity;
newLinearDamp += currentArea->get_spOv_linearDamp();
newAngularDamp += currentArea->get_spOv_angularDamp();
- ++countCombined;
- goto endAreasCycle;
+ stopped = true;
+ break;
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE:
/// This area replaces any gravity/damp, even the default one, and
/// stops taking into account the rest of the areas.
newGravity = support_gravity;
newLinearDamp = currentArea->get_spOv_linearDamp();
newAngularDamp = currentArea->get_spOv_angularDamp();
- countCombined = 1;
- goto endAreasCycle;
+ stopped = true;
+ break;
case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE:
/// This area replaces any gravity/damp calculated so far, but keeps
/// calculating the rest of the areas, down to the default one.
newGravity = support_gravity;
newLinearDamp = currentArea->get_spOv_linearDamp();
newAngularDamp = currentArea->get_spOv_angularDamp();
- countCombined = 1;
break;
}
}
-endAreasCycle:
- if (1 < countCombined) {
- newGravity /= countCombined;
- newLinearDamp /= countCombined;
- newAngularDamp /= countCombined;
+ // Add default gravity and damping from space.
+ if (!stopped) {
+ newGravity += space->get_gravity_direction() * space->get_gravity_magnitude();
+ newLinearDamp += space->get_linear_damp();
+ newAngularDamp += space->get_angular_damp();
}
btVector3 newBtGravity;
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 95491b1e62..420b5cc443 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -117,7 +117,7 @@ public:
virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse);
virtual void apply_torque_impulse(const Vector3 &p_impulse);
- virtual void set_sleep_state(bool p_enable);
+ virtual void set_sleep_state(bool p_sleep);
virtual bool is_sleeping() const;
virtual int get_contact_count() const;
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index 1659664ff9..d49e635fd5 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -342,6 +342,8 @@ SpaceBullet::SpaceBullet() :
godotFilterCallback(nullptr),
gravityDirection(0, -1, 0),
gravityMagnitude(10),
+ linear_damp(0.0),
+ angular_damp(0.0),
contactDebugCount(0),
delta_time(0.) {
@@ -379,8 +381,11 @@ void SpaceBullet::set_param(PhysicsServer3D::AreaParameter p_param, const Varian
update_gravity();
break;
case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP:
+ linear_damp = p_value;
+ break;
case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP:
- break; // No damp
+ angular_damp = p_value;
+ break;
case PhysicsServer3D::AREA_PARAM_PRIORITY:
// Priority is always 0, the lower
break;
@@ -401,8 +406,9 @@ Variant SpaceBullet::get_param(PhysicsServer3D::AreaParameter p_param) {
case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR:
return gravityDirection;
case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP:
+ return linear_damp;
case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP:
- return 0; // No damp
+ return angular_damp;
case PhysicsServer3D::AREA_PARAM_PRIORITY:
return 0; // Priority is always 0, the lower
case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT:
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index f9a8c063fd..3d4a2aeceb 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -108,6 +108,9 @@ class SpaceBullet : public RIDBullet {
Vector3 gravityDirection;
real_t gravityMagnitude;
+ real_t linear_damp;
+ real_t angular_damp;
+
Vector<AreaBullet *> areas;
Vector<Vector3> contactDebug;
@@ -177,6 +180,9 @@ public:
void update_gravity();
+ real_t get_linear_damp() const { return linear_damp; }
+ 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);
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 3f61e2852f..6714db76bb 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -50,7 +50,7 @@ inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2],
float distance = (p_interpolation_point - p_segement_points[0]).length();
float fraction = distance / segment_length;
- return p_uvs[0].linear_interpolate(p_uvs[1], fraction);
+ return p_uvs[0].lerp(p_uvs[1], fraction);
}
inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const Vector2 p_uvs[3], const Vector2 &p_interpolation_point) {
diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp
index 4b27eea019..fa176cb94e 100644
--- a/modules/csg/csg_gizmos.cpp
+++ b/modules/csg/csg_gizmos.cpp
@@ -32,7 +32,7 @@
///////////
-CSGShapeNode3DGizmoPlugin::CSGShapeNode3DGizmoPlugin() {
+CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() {
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/csg", Color(0.0, 0.4, 1, 0.15));
create_material("shape_union_material", gizmo_color);
@@ -49,7 +49,7 @@ CSGShapeNode3DGizmoPlugin::CSGShapeNode3DGizmoPlugin() {
create_handle_material("handles");
}
-String CSGShapeNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
@@ -76,7 +76,7 @@ String CSGShapeNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_giz
return "";
}
-Variant CSGShapeNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
@@ -110,7 +110,7 @@ Variant CSGShapeNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo,
return Variant();
}
-void CSGShapeNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
@@ -207,7 +207,7 @@ void CSGShapeNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx
s->set_outer_radius(d);
}
}
-void CSGShapeNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
@@ -299,23 +299,23 @@ void CSGShapeNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_
ur->commit_action();
}
}
-bool CSGShapeNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+bool CSGShape3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
return Object::cast_to<CSGSphere3D>(p_spatial) || Object::cast_to<CSGBox3D>(p_spatial) || Object::cast_to<CSGCylinder3D>(p_spatial) || Object::cast_to<CSGTorus3D>(p_spatial) || Object::cast_to<CSGMesh3D>(p_spatial) || Object::cast_to<CSGPolygon3D>(p_spatial);
}
-String CSGShapeNode3DGizmoPlugin::get_name() const {
- return "CSGShapes";
+String CSGShape3DGizmoPlugin::get_name() const {
+ return "CSGShape3D";
}
-int CSGShapeNode3DGizmoPlugin::get_priority() const {
+int CSGShape3DGizmoPlugin::get_priority() const {
return -1;
}
-bool CSGShapeNode3DGizmoPlugin::is_selectable_when_hidden() const {
+bool CSGShape3DGizmoPlugin::is_selectable_when_hidden() const {
return true;
}
-void CSGShapeNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
@@ -419,6 +419,6 @@ void CSGShapeNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
EditorPluginCSG::EditorPluginCSG(EditorNode *p_editor) {
- Ref<CSGShapeNode3DGizmoPlugin> gizmo_plugin = Ref<CSGShapeNode3DGizmoPlugin>(memnew(CSGShapeNode3DGizmoPlugin));
+ Ref<CSGShape3DGizmoPlugin> gizmo_plugin = Ref<CSGShape3DGizmoPlugin>(memnew(CSGShape3DGizmoPlugin));
Node3DEditor::get_singleton()->add_gizmo_plugin(gizmo_plugin);
}
diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h
index 90a059b31c..7763989b2a 100644
--- a/modules/csg/csg_gizmos.h
+++ b/modules/csg/csg_gizmos.h
@@ -35,9 +35,9 @@
#include "editor/editor_plugin.h"
#include "editor/node_3d_editor_gizmos.h"
-class CSGShapeNode3DGizmoPlugin : public EditorNode3DGizmoPlugin {
+class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
- GDCLASS(CSGShapeNode3DGizmoPlugin, EditorNode3DGizmoPlugin);
+ GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
public:
bool has_gizmo(Node3D *p_spatial);
@@ -51,7 +51,7 @@ public:
void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point);
void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel);
- CSGShapeNode3DGizmoPlugin();
+ CSGShape3DGizmoPlugin();
};
class EditorPluginCSG : public EditorPlugin {
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 5557da3014..550a919d0d 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -46,7 +46,7 @@ void CSGShape3D::set_use_collision(bool p_enable) {
root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
- PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space());
+ PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space());
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
set_collision_layer(collision_layer);
set_collision_mask(collision_mask);
@@ -296,20 +296,18 @@ void CSGShape3D::_update_shape() {
int mat = n->faces[i].material;
ERR_CONTINUE(mat < -1 || mat >= face_count.size());
int idx = mat == -1 ? face_count.size() - 1 : mat;
- if (n->faces[i].smooth) {
- Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
+ Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
- for (int j = 0; j < 3; j++) {
- Vector3 v = n->faces[i].vertices[j];
- Vector3 add;
- if (vec_map.lookup(v, add)) {
- add += p.normal;
- } else {
- add = p.normal;
- }
- vec_map.set(v, add);
+ for (int j = 0; j < 3; j++) {
+ Vector3 v = n->faces[i].vertices[j];
+ Vector3 add;
+ if (vec_map.lookup(v, add)) {
+ add += p.normal;
+ } else {
+ add = p.normal;
}
+ vec_map.set(v, add);
}
face_count.write[idx]++;
@@ -509,7 +507,7 @@ void CSGShape3D::_notification(int p_what) {
root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC);
PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid());
- PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space());
+ PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world_3d()->get_space());
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id());
set_collision_layer(collision_layer);
set_collision_mask(collision_mask);
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index ae21156b8b..294d594135 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -94,7 +94,7 @@ static const DDSFormatInfo dds_format_info[DDS_MAX] = {
{ "GRAYSCALE_ALPHA", false, false, 1, 2, Image::FORMAT_LA8 }
};
-RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
if (r_error)
*r_error = ERR_CANT_OPEN;
diff --git a/modules/dds/texture_loader_dds.h b/modules/dds/texture_loader_dds.h
index 5b89f16277..ef08967df7 100644
--- a/modules/dds/texture_loader_dds.h
+++ b/modules/dds/texture_loader_dds.h
@@ -36,7 +36,7 @@
class ResourceFormatDDS : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/etc/texture_loader_pkm.cpp b/modules/etc/texture_loader_pkm.cpp
index ad0cc91c96..bfb2098dff 100644
--- a/modules/etc/texture_loader_pkm.cpp
+++ b/modules/etc/texture_loader_pkm.cpp
@@ -42,7 +42,7 @@ struct ETC1Header {
uint16_t origHeight;
};
-RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatPKM::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
if (r_error)
*r_error = ERR_CANT_OPEN;
diff --git a/modules/etc/texture_loader_pkm.h b/modules/etc/texture_loader_pkm.h
index 989e203994..6507e0bdec 100644
--- a/modules/etc/texture_loader_pkm.h
+++ b/modules/etc/texture_loader_pkm.h
@@ -36,7 +36,7 @@
class ResourceFormatPKM : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub
index a788175b07..cab05549d2 100644
--- a/modules/gdnative/SCsub
+++ b/modules/gdnative/SCsub
@@ -17,7 +17,7 @@ env_gdnative.Prepend(CPPPATH=["#modules/gdnative/include/"])
Export("env_gdnative")
SConscript("net/SCsub")
-SConscript("arvr/SCsub")
+SConscript("xr/SCsub")
SConscript("pluginscript/SCsub")
SConscript("videodecoder/SCsub")
diff --git a/modules/gdnative/config.py b/modules/gdnative/config.py
index 37e25a46d4..4b997e4bfe 100644
--- a/modules/gdnative/config.py
+++ b/modules/gdnative/config.py
@@ -9,7 +9,7 @@ def configure(env):
def get_doc_classes():
return [
"@NativeScript",
- "ARVRInterfaceGDNative",
+ "XRInterfaceGDNative",
"GDNative",
"GDNativeLibrary",
"MultiplayerPeerGDNative",
diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
deleted file mode 100644
index e8405b64a3..0000000000
--- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" version="4.0">
- <brief_description>
- GDNative wrapper for an ARVR interface.
- </brief_description>
- <description>
- This is a wrapper class for GDNative implementations of the ARVR interface. To use a GDNative ARVR interface, simply instantiate this object and set your GDNative library containing the ARVR interface implementation.
- </description>
- <tutorials>
- </tutorials>
- <methods>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml
index 601e132d42..1aab864102 100644
--- a/modules/gdnative/doc_classes/GDNativeLibrary.xml
+++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml
@@ -4,7 +4,7 @@
An external library containing functions or script classes to use in Godot.
</brief_description>
<description>
- A GDNative library can implement [NativeScript]s, global functions to call with the [GDNative] class, or low-level engine extensions through interfaces such as [ARVRInterfaceGDNative]. The library must be compiled for each platform and architecture that the project will run on.
+ A GDNative library can implement [NativeScript]s, global functions to call with the [GDNative] class, or low-level engine extensions through interfaces such as [XRInterfaceGDNative]. The library must be compiled for each platform and architecture that the project will run on.
</description>
<tutorials>
<link>https://docs.godotengine.org/en/latest/tutorials/plugins/gdnative/gdnative-c-example.html</link>
diff --git a/modules/gdnative/doc_classes/XRInterfaceGDNative.xml b/modules/gdnative/doc_classes/XRInterfaceGDNative.xml
new file mode 100644
index 0000000000..13de815793
--- /dev/null
+++ b/modules/gdnative/doc_classes/XRInterfaceGDNative.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="XRInterfaceGDNative" inherits="XRInterface" version="4.0">
+ <brief_description>
+ GDNative wrapper for an XR interface.
+ </brief_description>
+ <description>
+ This is a wrapper class for GDNative implementations of the XR interface. To use a GDNative XR interface, simply instantiate this object and set your GDNative library containing the XR interface implementation.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index d3426044ec..a131e3a78f 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -493,7 +493,7 @@ Error GDNative::get_symbol(StringName p_procedure_name, void *&r_handle, bool p_
return result;
}
-RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES GDNativeLibraryResourceLoader::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
Ref<GDNativeLibrary> lib;
lib.instance();
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index 9ef9c706d1..6d26c2141d 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -166,7 +166,7 @@ public:
class GDNativeLibraryResourceLoader : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp
index 914d5b03f4..68c83e05a6 100644
--- a/modules/gdnative/gdnative/color.cpp
+++ b/modules/gdnative/gdnative/color.cpp
@@ -155,11 +155,11 @@ godot_color GDAPI godot_color_contrasted(const godot_color *p_self) {
return dest;
}
-godot_color GDAPI godot_color_linear_interpolate(const godot_color *p_self, const godot_color *p_b, const godot_real p_t) {
+godot_color GDAPI godot_color_lerp(const godot_color *p_self, const godot_color *p_b, const godot_real p_t) {
godot_color dest;
const Color *self = (const Color *)p_self;
const Color *b = (const Color *)p_b;
- *((Color *)&dest) = self->linear_interpolate(*b, p_t);
+ *((Color *)&dest) = self->lerp(*b, p_t);
return dest;
}
diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index e9e2a8edf8..dc273e7951 100644
--- a/modules/gdnative/gdnative/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -109,11 +109,11 @@ godot_real GDAPI godot_vector2_angle_to_point(const godot_vector2 *p_self, const
return self->angle_to_point(*to);
}
-godot_vector2 GDAPI godot_vector2_linear_interpolate(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t) {
+godot_vector2 GDAPI godot_vector2_lerp(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t) {
godot_vector2 dest;
const Vector2 *self = (const Vector2 *)p_self;
const Vector2 *b = (const Vector2 *)p_b;
- *((Vector2 *)&dest) = self->linear_interpolate(*b, p_t);
+ *((Vector2 *)&dest) = self->lerp(*b, p_t);
return dest;
}
diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index e34a9370a5..bb27ad5a00 100644
--- a/modules/gdnative/gdnative/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -106,11 +106,11 @@ godot_vector3 GDAPI godot_vector3_rotated(const godot_vector3 *p_self, const god
return dest;
}
-godot_vector3 GDAPI godot_vector3_linear_interpolate(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t) {
+godot_vector3 GDAPI godot_vector3_lerp(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t) {
godot_vector3 dest;
const Vector3 *self = (const Vector3 *)p_self;
const Vector3 *b = (const Vector3 *)p_b;
- *((Vector3 *)&dest) = self->linear_interpolate(*b, p_t);
+ *((Vector3 *)&dest) = self->lerp(*b, p_t);
return dest;
}
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index e1d6c0c867..d5ab62dc61 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -586,7 +586,7 @@
]
},
{
- "name": "godot_color_linear_interpolate",
+ "name": "godot_color_lerp",
"return_type": "godot_color",
"arguments": [
["const godot_color *", "p_self"],
@@ -710,7 +710,7 @@
]
},
{
- "name": "godot_vector2_linear_interpolate",
+ "name": "godot_vector2_lerp",
"return_type": "godot_vector2",
"arguments": [
["const godot_vector2 *", "p_self"],
@@ -1449,7 +1449,7 @@
]
},
{
- "name": "godot_vector3_linear_interpolate",
+ "name": "godot_vector3_lerp",
"return_type": "godot_vector3",
"arguments": [
["const godot_vector3 *", "p_self"],
@@ -5935,8 +5935,8 @@
]
},
{
- "name": "arvr",
- "type": "ARVR",
+ "name": "xr",
+ "type": "XR",
"version": {
"major": 1,
"minor": 1
@@ -5944,24 +5944,24 @@
"next": null,
"api": [
{
- "name": "godot_arvr_register_interface",
+ "name": "godot_xr_register_interface",
"return_type": "void",
"arguments": [
- ["const godot_arvr_interface_gdnative *", "p_interface"]
+ ["const godot_xr_interface_gdnative *", "p_interface"]
]
},
{
- "name": "godot_arvr_get_worldscale",
+ "name": "godot_xr_get_worldscale",
"return_type": "godot_real",
"arguments": []
},
{
- "name": "godot_arvr_get_reference_frame",
+ "name": "godot_xr_get_reference_frame",
"return_type": "godot_transform",
"arguments": []
},
{
- "name": "godot_arvr_blit",
+ "name": "godot_xr_blit",
"return_type": "void",
"arguments": [
["godot_int", "p_eye"],
@@ -5970,14 +5970,14 @@
]
},
{
- "name": "godot_arvr_get_texid",
+ "name": "godot_xr_get_texid",
"return_type": "godot_int",
"arguments": [
["godot_rid *", "p_render_target"]
]
},
{
- "name": "godot_arvr_add_controller",
+ "name": "godot_xr_add_controller",
"return_type": "godot_int",
"arguments": [
["char *", "p_device_name"],
@@ -5987,14 +5987,14 @@
]
},
{
- "name": "godot_arvr_remove_controller",
+ "name": "godot_xr_remove_controller",
"return_type": "void",
"arguments": [
["godot_int", "p_controller_id"]
]
},
{
- "name": "godot_arvr_set_controller_transform",
+ "name": "godot_xr_set_controller_transform",
"return_type": "void",
"arguments": [
["godot_int", "p_controller_id"],
@@ -6004,7 +6004,7 @@
]
},
{
- "name": "godot_arvr_set_controller_button",
+ "name": "godot_xr_set_controller_button",
"return_type": "void",
"arguments": [
["godot_int", "p_controller_id"],
@@ -6013,7 +6013,7 @@
]
},
{
- "name": "godot_arvr_set_controller_axis",
+ "name": "godot_xr_set_controller_axis",
"return_type": "void",
"arguments": [
["godot_int", "p_controller_id"],
@@ -6023,7 +6023,7 @@
]
},
{
- "name": "godot_arvr_get_controller_rumble",
+ "name": "godot_xr_get_controller_rumble",
"return_type": "godot_real",
"arguments": [
["godot_int", "p_controller_id"]
diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py
index d0094fb869..620935795f 100644
--- a/modules/gdnative/gdnative_builders.py
+++ b/modules/gdnative/gdnative_builders.py
@@ -19,7 +19,7 @@ def _build_gdnative_api_struct_header(api):
"",
"#include <gdnative/gdnative.h>",
"#include <android/godot_android.h>",
- "#include <arvr/godot_arvr.h>",
+ "#include <xr/godot_xr.h>",
"#include <nativescript/godot_nativescript.h>",
"#include <net/godot_net.h>",
"#include <pluginscript/godot_pluginscript.h>",
@@ -163,7 +163,7 @@ def _build_gdnative_api_struct_source(api):
"\t{" + str(ext["version"]["major"]) + ", " + str(ext["version"]["minor"]) + "},",
"\t"
+ (
- "NULL"
+ "nullptr"
if not ext["next"]
else ("(const godot_gdnative_api_struct *)&" + get_extension_struct_instance_name(name, ext["next"]))
)
@@ -191,7 +191,7 @@ def _build_gdnative_api_struct_source(api):
"\t{" + str(core["version"]["major"]) + ", " + str(core["version"]["minor"]) + "},",
"\t"
+ (
- "NULL"
+ "nullptr"
if not core["next"]
else (
"(const godot_gdnative_api_struct *)& api_{0}_{1}".format(
diff --git a/modules/gdnative/include/gdnative/color.h b/modules/gdnative/include/gdnative/color.h
index 47c01dbb20..e7737bf8e1 100644
--- a/modules/gdnative/include/gdnative/color.h
+++ b/modules/gdnative/include/gdnative/color.h
@@ -95,7 +95,7 @@ godot_color GDAPI godot_color_inverted(const godot_color *p_self);
godot_color GDAPI godot_color_contrasted(const godot_color *p_self);
-godot_color GDAPI godot_color_linear_interpolate(const godot_color *p_self, const godot_color *p_b, const godot_real p_t);
+godot_color GDAPI godot_color_lerp(const godot_color *p_self, const godot_color *p_b, const godot_real p_t);
godot_color GDAPI godot_color_blend(const godot_color *p_self, const godot_color *p_over);
diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index 15a1a6063b..c11e23a586 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -81,7 +81,7 @@ godot_real GDAPI godot_vector2_angle_to(const godot_vector2 *p_self, const godot
godot_real GDAPI godot_vector2_angle_to_point(const godot_vector2 *p_self, const godot_vector2 *p_to);
-godot_vector2 GDAPI godot_vector2_linear_interpolate(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t);
+godot_vector2 GDAPI godot_vector2_lerp(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t);
godot_vector2 GDAPI godot_vector2_cubic_interpolate(const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_vector2 *p_pre_a, const godot_vector2 *p_post_b, const godot_real p_t);
diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index 1b344590ea..8ebf15b724 100644
--- a/modules/gdnative/include/gdnative/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -86,7 +86,7 @@ godot_vector3 GDAPI godot_vector3_snapped(const godot_vector3 *p_self, const god
godot_vector3 GDAPI godot_vector3_rotated(const godot_vector3 *p_self, const godot_vector3 *p_axis, const godot_real p_phi);
-godot_vector3 GDAPI godot_vector3_linear_interpolate(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t);
+godot_vector3 GDAPI godot_vector3_lerp(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t);
godot_vector3 GDAPI godot_vector3_cubic_interpolate(const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_vector3 *p_pre_a, const godot_vector3 *p_post_b, const godot_real p_t);
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index 1b131c8cf0..0fb5180103 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -54,7 +54,6 @@ typedef enum {
GODOT_PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
GODOT_PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease)
GODOT_PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer)
- GODOT_PROPERTY_HINT_SPRITE_FRAME, // FIXME: Obsolete: drop whenever we can break compat
GODOT_PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer)
GODOT_PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
GODOT_PROPERTY_HINT_LAYERS_2D_RENDER,
@@ -96,8 +95,7 @@ typedef enum {
GODOT_PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings
GODOT_PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor
GODOT_PROPERTY_USAGE_CATEGORY = 256,
- GODOT_PROPERTY_USAGE_STORE_IF_NONZERO = 512, // FIXME: Obsolete: drop whenever we can break compat
- GODOT_PROPERTY_USAGE_STORE_IF_NONONE = 1024, // FIXME: Obsolete: drop whenever we can break compat
+ GODOT_PROPERTY_USAGE_SUBGROUP = 512,
GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/xr/godot_xr.h
index aaef31a855..22f7f021c4 100644
--- a/modules/gdnative/include/arvr/godot_arvr.h
+++ b/modules/gdnative/include/xr/godot_xr.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* godot_arvr.h */
+/* godot_xr.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_NATIVEARVR_H
-#define GODOT_NATIVEARVR_H
+#ifndef GODOT_NATIVEXR_H
+#define GODOT_NATIVEXR_H
#include <gdnative/gdnative.h>
@@ -61,32 +61,31 @@ typedef struct {
void (*fill_projection_for_eye)(void *, godot_real *, godot_int, godot_real, godot_real, godot_real);
void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *);
void (*process)(void *);
- // only in 1.1 onwards
godot_int (*get_external_texture_for_eye)(void *, godot_int);
void (*notification)(void *, godot_int);
godot_int (*get_camera_feed_id)(void *);
-} godot_arvr_interface_gdnative;
+} godot_xr_interface_gdnative;
-void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface);
+void GDAPI godot_xr_register_interface(const godot_xr_interface_gdnative *p_interface);
-// helper functions to access ARVRServer data
-godot_real GDAPI godot_arvr_get_worldscale();
-godot_transform GDAPI godot_arvr_get_reference_frame();
+// helper functions to access XRServer data
+godot_real GDAPI godot_xr_get_worldscale();
+godot_transform GDAPI godot_xr_get_reference_frame();
// helper functions for rendering
-void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect);
-godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target);
+void GDAPI godot_xr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect);
+godot_int GDAPI godot_xr_get_texid(godot_rid *p_render_target);
-// helper functions for updating ARVR controllers
-godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
-void GDAPI godot_arvr_remove_controller(godot_int p_controller_id);
-void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
-void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed);
-void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative);
-godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id);
+// helper functions for updating XR controllers
+godot_int GDAPI godot_xr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
+void GDAPI godot_xr_remove_controller(godot_int p_controller_id);
+void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position);
+void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed);
+void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative);
+godot_real GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id);
#ifdef __cplusplus
}
#endif
-#endif /* !GODOT_NATIVEARVR_H */
+#endif /* !GODOT_NATIVEXR_H */
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index bf458c15ee..ed3ec44bf7 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -111,6 +111,13 @@ void NativeScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder)
#endif
+bool NativeScript::inherits_script(const Ref<Script> &p_script) const {
+#ifndef _MSC_VER
+#warning inheritance needs to be implemented in NativeScript
+#endif
+ return false;
+}
+
void NativeScript::set_class_name(String p_class_name) {
class_name = p_class_name;
}
@@ -1931,7 +1938,7 @@ void NativeReloadNode::_notification(int p_what) {
#endif
}
-RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
return ResourceFormatLoaderText::singleton->load(p_path, p_original_path, r_error);
}
diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h
index 75bbb42664..7e7598e06c 100644
--- a/modules/gdnative/nativescript/nativescript.h
+++ b/modules/gdnative/nativescript/nativescript.h
@@ -133,6 +133,8 @@ protected:
public:
inline NativeScriptDesc *get_script_desc() const;
+ bool inherits_script(const Ref<Script> &p_script) const;
+
void set_class_name(String p_class_name);
String get_class_name() const;
@@ -406,7 +408,7 @@ public:
class ResourceFormatLoaderNativeScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/pluginscript/pluginscript_loader.cpp b/modules/gdnative/pluginscript/pluginscript_loader.cpp
index 3fb22b3f8d..64582cc517 100644
--- a/modules/gdnative/pluginscript/pluginscript_loader.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_loader.cpp
@@ -39,7 +39,7 @@ ResourceFormatLoaderPluginScript::ResourceFormatLoaderPluginScript(PluginScriptL
_language = language;
}
-RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatLoaderPluginScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
if (r_error)
*r_error = ERR_FILE_CANT_OPEN;
diff --git a/modules/gdnative/pluginscript/pluginscript_loader.h b/modules/gdnative/pluginscript/pluginscript_loader.h
index c929be53bd..e47754490a 100644
--- a/modules/gdnative/pluginscript/pluginscript_loader.h
+++ b/modules/gdnative/pluginscript/pluginscript_loader.h
@@ -44,7 +44,7 @@ class ResourceFormatLoaderPluginScript : public ResourceFormatLoader {
public:
ResourceFormatLoaderPluginScript(PluginScriptLanguage *language);
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
index a4c84dc0ca..6b303c8716 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -140,6 +140,13 @@ bool PluginScript::can_instance() const {
return can;
}
+bool PluginScript::inherits_script(const Ref<Script> &p_script) const {
+#ifndef _MSC_VER
+#warning inheritance needs to be implemented in PluginScript
+#endif
+ return false;
+}
+
Ref<Script> PluginScript::get_base_script() const {
if (_ref_base_parent.is_valid()) {
return Ref<PluginScript>(_ref_base_parent);
diff --git a/modules/gdnative/pluginscript/pluginscript_script.h b/modules/gdnative/pluginscript/pluginscript_script.h
index 5c93ae38f5..70b9ca980b 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.h
+++ b/modules/gdnative/pluginscript/pluginscript_script.h
@@ -72,6 +72,8 @@ private:
protected:
static void _bind_methods();
+ bool inherits_script(const Ref<Script> &p_script) const;
+
PluginScriptInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, Callable::CallError &r_error);
Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 397a020689..67a286ee2e 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -34,11 +34,11 @@
#include "gdnative.h"
-#include "arvr/register_types.h"
#include "nativescript/register_types.h"
#include "net/register_types.h"
#include "pluginscript/register_types.h"
#include "videodecoder/register_types.h"
+#include "xr/register_types.h"
#include "core/engine.h"
#include "core/io/resource_loader.h"
@@ -240,7 +240,7 @@ void register_gdnative_types() {
GDNativeCallRegistry::singleton->register_native_call_type("standard_varcall", cb_standard_varcall);
register_net_types();
- register_arvr_types();
+ register_xr_types();
register_nativescript_types();
register_pluginscript_types();
register_videodecoder_types();
@@ -305,7 +305,7 @@ void unregister_gdnative_types() {
unregister_videodecoder_types();
unregister_pluginscript_types();
unregister_nativescript_types();
- unregister_arvr_types();
+ unregister_xr_types();
unregister_net_types();
memdelete(GDNativeCallRegistry::singleton);
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
index fa9f6be5c1..f7d87595af 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
@@ -373,7 +373,7 @@ void VideoStreamGDNative::set_audio_track(int p_track) {
/* --- NOTE ResourceFormatLoaderVideoStreamGDNative starts here. ----- */
-RES ResourceFormatLoaderVideoStreamGDNative::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatLoaderVideoStreamGDNative::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
if (r_error) {
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h
index fbc0d4016f..092e10a0f5 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.h
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.h
@@ -199,7 +199,7 @@ public:
class ResourceFormatLoaderVideoStreamGDNative : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdnative/arvr/SCsub b/modules/gdnative/xr/SCsub
index 0b2db3b504..0b2db3b504 100644
--- a/modules/gdnative/arvr/SCsub
+++ b/modules/gdnative/xr/SCsub
diff --git a/modules/gdnative/arvr/config.py b/modules/gdnative/xr/config.py
index d22f9454ed..d22f9454ed 100644
--- a/modules/gdnative/arvr/config.py
+++ b/modules/gdnative/xr/config.py
diff --git a/modules/gdnative/arvr/register_types.cpp b/modules/gdnative/xr/register_types.cpp
index 0f6e2bca1a..da3a7dc4b8 100644
--- a/modules/gdnative/arvr/register_types.cpp
+++ b/modules/gdnative/xr/register_types.cpp
@@ -29,11 +29,12 @@
/*************************************************************************/
#include "register_types.h"
-#include "arvr_interface_gdnative.h"
+#include "xr_interface_gdnative.h"
-void register_arvr_types() {
- ClassDB::register_class<ARVRInterfaceGDNative>();
+void register_xr_types() {
+ ClassDB::register_class<XRInterfaceGDNative>();
+ ClassDB::add_compatibility_class("ARVRInterfaceGDNative", "XRInterfaceGDNative");
}
-void unregister_arvr_types() {
+void unregister_xr_types() {
}
diff --git a/modules/gdnative/arvr/register_types.h b/modules/gdnative/xr/register_types.h
index b0de6f7c14..2501d28651 100644
--- a/modules/gdnative/arvr/register_types.h
+++ b/modules/gdnative/xr/register_types.h
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ARVR_REGISTER_TYPES_H
-#define ARVR_REGISTER_TYPES_H
+#ifndef XR_REGISTER_TYPES_H
+#define XR_REGISTER_TYPES_H
-void register_arvr_types();
-void unregister_arvr_types();
+void register_xr_types();
+void unregister_xr_types();
-#endif // ARVR_REGISTER_TYPES_H
+#endif // XR_REGISTER_TYPES_H
diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/xr/xr_interface_gdnative.cpp
index f14691027a..d65089a123 100644
--- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp
+++ b/modules/gdnative/xr/xr_interface_gdnative.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* arvr_interface_gdnative.cpp */
+/* xr_interface_gdnative.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,17 +28,17 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "arvr_interface_gdnative.h"
-#include "core/input/input_filter.h"
-#include "servers/arvr/arvr_positional_tracker.h"
+#include "xr_interface_gdnative.h"
+#include "core/input/input.h"
#include "servers/rendering/rendering_server_globals.h"
+#include "servers/xr/xr_positional_tracker.h"
-void ARVRInterfaceGDNative::_bind_methods() {
+void XRInterfaceGDNative::_bind_methods() {
ADD_PROPERTY_DEFAULT("interface_is_initialized", false);
ADD_PROPERTY_DEFAULT("ar_is_anchor_detection_enabled", false);
}
-ARVRInterfaceGDNative::ARVRInterfaceGDNative() {
+XRInterfaceGDNative::XRInterfaceGDNative() {
print_verbose("Construct gdnative interface\n");
// we won't have our data pointer until our library gets set
@@ -47,7 +47,7 @@ ARVRInterfaceGDNative::ARVRInterfaceGDNative() {
interface = nullptr;
}
-ARVRInterfaceGDNative::~ARVRInterfaceGDNative() {
+XRInterfaceGDNative::~XRInterfaceGDNative() {
print_verbose("Destruct gdnative interface\n");
if (interface != nullptr && is_initialized()) {
@@ -58,7 +58,7 @@ ARVRInterfaceGDNative::~ARVRInterfaceGDNative() {
cleanup();
}
-void ARVRInterfaceGDNative::cleanup() {
+void XRInterfaceGDNative::cleanup() {
if (interface != nullptr) {
interface->destructor(data);
data = nullptr;
@@ -66,7 +66,7 @@ void ARVRInterfaceGDNative::cleanup() {
}
}
-void ARVRInterfaceGDNative::set_interface(const godot_arvr_interface_gdnative *p_interface) {
+void XRInterfaceGDNative::set_interface(const godot_xr_interface_gdnative *p_interface) {
// this should only be called once, just being paranoid..
if (interface) {
cleanup();
@@ -79,7 +79,7 @@ void ARVRInterfaceGDNative::set_interface(const godot_arvr_interface_gdnative *p
data = interface->constructor((godot_object *)this);
}
-StringName ARVRInterfaceGDNative::get_name() const {
+StringName XRInterfaceGDNative::get_name() const {
ERR_FAIL_COND_V(interface == nullptr, StringName());
@@ -92,7 +92,7 @@ StringName ARVRInterfaceGDNative::get_name() const {
return name;
}
-int ARVRInterfaceGDNative::get_capabilities() const {
+int XRInterfaceGDNative::get_capabilities() const {
int capabilities;
ERR_FAIL_COND_V(interface == nullptr, 0); // 0 = None
@@ -102,32 +102,28 @@ int ARVRInterfaceGDNative::get_capabilities() const {
return capabilities;
}
-bool ARVRInterfaceGDNative::get_anchor_detection_is_enabled() const {
+bool XRInterfaceGDNative::get_anchor_detection_is_enabled() const {
ERR_FAIL_COND_V(interface == nullptr, false);
return interface->get_anchor_detection_is_enabled(data);
}
-void ARVRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) {
+void XRInterfaceGDNative::set_anchor_detection_is_enabled(bool p_enable) {
ERR_FAIL_COND(interface == nullptr);
interface->set_anchor_detection_is_enabled(data, p_enable);
}
-int ARVRInterfaceGDNative::get_camera_feed_id() {
+int XRInterfaceGDNative::get_camera_feed_id() {
ERR_FAIL_COND_V(interface == nullptr, 0);
- if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) {
- return (unsigned int)interface->get_camera_feed_id(data);
- } else {
- return 0;
- }
+ return (unsigned int)interface->get_camera_feed_id(data);
}
-bool ARVRInterfaceGDNative::is_stereo() {
+bool XRInterfaceGDNative::is_stereo() {
bool stereo;
ERR_FAIL_COND_V(interface == nullptr, false);
@@ -137,14 +133,14 @@ bool ARVRInterfaceGDNative::is_stereo() {
return stereo;
}
-bool ARVRInterfaceGDNative::is_initialized() const {
+bool XRInterfaceGDNative::is_initialized() const {
ERR_FAIL_COND_V(interface == nullptr, false);
return interface->is_initialized(data);
}
-bool ARVRInterfaceGDNative::initialize() {
+bool XRInterfaceGDNative::initialize() {
ERR_FAIL_COND_V(interface == nullptr, false);
bool initialized = interface->initialize(data);
@@ -152,28 +148,28 @@ bool ARVRInterfaceGDNative::initialize() {
if (initialized) {
// if we successfully initialize our interface and we don't have a primary interface yet, this becomes our primary interface
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- if ((arvr_server != nullptr) && (arvr_server->get_primary_interface() == nullptr)) {
- arvr_server->set_primary_interface(this);
+ XRServer *xr_server = XRServer::get_singleton();
+ if ((xr_server != nullptr) && (xr_server->get_primary_interface() == nullptr)) {
+ xr_server->set_primary_interface(this);
};
};
return initialized;
}
-void ARVRInterfaceGDNative::uninitialize() {
+void XRInterfaceGDNative::uninitialize() {
ERR_FAIL_COND(interface == nullptr);
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- if (arvr_server != nullptr) {
+ XRServer *xr_server = XRServer::get_singleton();
+ if (xr_server != nullptr) {
// Whatever happens, make sure this is no longer our primary interface
- arvr_server->clear_primary_interface_if(this);
+ xr_server->clear_primary_interface_if(this);
}
interface->uninitialize(data);
}
-Size2 ARVRInterfaceGDNative::get_render_targetsize() {
+Size2 XRInterfaceGDNative::get_render_targetsize() {
ERR_FAIL_COND_V(interface == nullptr, Size2());
@@ -183,7 +179,7 @@ Size2 ARVRInterfaceGDNative::get_render_targetsize() {
return *vec;
}
-Transform ARVRInterfaceGDNative::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) {
+Transform XRInterfaceGDNative::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
Transform *ret;
ERR_FAIL_COND_V(interface == nullptr, Transform());
@@ -195,7 +191,7 @@ Transform ARVRInterfaceGDNative::get_transform_for_eye(ARVRInterface::Eyes p_eye
return *ret;
}
-CameraMatrix ARVRInterfaceGDNative::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+CameraMatrix XRInterfaceGDNative::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
CameraMatrix cm;
ERR_FAIL_COND_V(interface == nullptr, CameraMatrix());
@@ -205,37 +201,30 @@ CameraMatrix ARVRInterfaceGDNative::get_projection_for_eye(ARVRInterface::Eyes p
return cm;
}
-unsigned int ARVRInterfaceGDNative::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) {
+unsigned int XRInterfaceGDNative::get_external_texture_for_eye(XRInterface::Eyes p_eye) {
ERR_FAIL_COND_V(interface == nullptr, 0);
- if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) {
- return (unsigned int)interface->get_external_texture_for_eye(data, (godot_int)p_eye);
- } else {
- return 0;
- }
+ return (unsigned int)interface->get_external_texture_for_eye(data, (godot_int)p_eye);
}
-void ARVRInterfaceGDNative::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
+void XRInterfaceGDNative::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
ERR_FAIL_COND(interface == nullptr);
interface->commit_for_eye(data, (godot_int)p_eye, (godot_rid *)&p_render_target, (godot_rect2 *)&p_screen_rect);
}
-void ARVRInterfaceGDNative::process() {
+void XRInterfaceGDNative::process() {
ERR_FAIL_COND(interface == nullptr);
interface->process(data);
}
-void ARVRInterfaceGDNative::notification(int p_what) {
+void XRInterfaceGDNative::notification(int p_what) {
ERR_FAIL_COND(interface == nullptr);
- // this is only available in interfaces that implement 1.1 or later
- if ((interface->version.major > 1) || ((interface->version.major == 1) && (interface->version.minor > 0))) {
- interface->notification(data, p_what);
- }
+ interface->notification(data, p_what);
}
/////////////////////////////////////////////////////////////////////////////////////
@@ -243,30 +232,30 @@ void ARVRInterfaceGDNative::notification(int p_what) {
extern "C" {
-void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface) {
- // If our major version is 0 or bigger then 10, we're likely looking at our constructor pointer from an older plugin
- ERR_FAIL_COND_MSG((p_interface->version.major == 0) || (p_interface->version.major > 10), "GDNative ARVR interfaces build for Godot 3.0 are not supported.");
+void GDAPI godot_xr_register_interface(const godot_xr_interface_gdnative *p_interface) {
+ // Must be on a version 4 plugin
+ ERR_FAIL_COND_MSG(p_interface->version.major < 4, "GDNative XR interfaces build for Godot 3.x are not supported.");
- Ref<ARVRInterfaceGDNative> new_interface;
+ Ref<XRInterfaceGDNative> new_interface;
new_interface.instance();
- new_interface->set_interface((const godot_arvr_interface_gdnative *)p_interface);
- ARVRServer::get_singleton()->add_interface(new_interface);
+ new_interface->set_interface((const godot_xr_interface_gdnative *)p_interface);
+ XRServer::get_singleton()->add_interface(new_interface);
}
-godot_real GDAPI godot_arvr_get_worldscale() {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL_V(arvr_server, 1.0);
+godot_real GDAPI godot_xr_get_worldscale() {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, 1.0);
- return arvr_server->get_world_scale();
+ return xr_server->get_world_scale();
}
-godot_transform GDAPI godot_arvr_get_reference_frame() {
+godot_transform GDAPI godot_xr_get_reference_frame() {
godot_transform reference_frame;
Transform *reference_frame_ptr = (Transform *)&reference_frame;
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- if (arvr_server != nullptr) {
- *reference_frame_ptr = arvr_server->get_reference_frame();
+ XRServer *xr_server = XRServer::get_singleton();
+ if (xr_server != nullptr) {
+ *reference_frame_ptr = xr_server->get_reference_frame();
} else {
godot_transform_new_identity(&reference_frame);
}
@@ -274,17 +263,17 @@ godot_transform GDAPI godot_arvr_get_reference_frame() {
return reference_frame;
}
-void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect) {
+void GDAPI godot_xr_blit(godot_int p_eye, godot_rid *p_render_target, godot_rect2 *p_rect) {
// blits out our texture as is, handy for preview display of one of the eyes that is already rendered with lens distortion on an external HMD
- ARVRInterface::Eyes eye = (ARVRInterface::Eyes)p_eye;
+ XRInterface::Eyes eye = (XRInterface::Eyes)p_eye;
#if 0
RID *render_target = (RID *)p_render_target;
#endif
Rect2 screen_rect = *(Rect2 *)p_rect;
- if (eye == ARVRInterface::EYE_LEFT) {
+ if (eye == XRInterface::EYE_LEFT) {
screen_rect.size.x /= 2.0;
- } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ } else if (p_eye == XRInterface::EYE_RIGHT) {
screen_rect.size.x /= 2.0;
screen_rect.position.x += screen_rect.size.x;
}
@@ -296,7 +285,7 @@ void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_re
#endif
}
-godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target) {
+godot_int GDAPI godot_xr_get_texid(godot_rid *p_render_target) {
// In order to send off our textures to display on our hardware we need the opengl texture ID instead of the render target RID
// This is a handy function to expose that.
#if 0
@@ -313,20 +302,20 @@ godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target) {
return texid;
}
-godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL_V(arvr_server, 0);
+godot_int GDAPI godot_xr_add_controller(char *p_device_name, godot_int p_hand, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, 0);
- InputFilter *input = InputFilter::get_singleton();
+ Input *input = Input::get_singleton();
ERR_FAIL_NULL_V(input, 0);
- ARVRPositionalTracker *new_tracker = memnew(ARVRPositionalTracker);
+ XRPositionalTracker *new_tracker = memnew(XRPositionalTracker);
new_tracker->set_name(p_device_name);
- new_tracker->set_type(ARVRServer::TRACKER_CONTROLLER);
+ new_tracker->set_type(XRServer::TRACKER_CONTROLLER);
if (p_hand == 1) {
- new_tracker->set_hand(ARVRPositionalTracker::TRACKER_LEFT_HAND);
+ new_tracker->set_hand(XRPositionalTracker::TRACKER_LEFT_HAND);
} else if (p_hand == 2) {
- new_tracker->set_hand(ARVRPositionalTracker::TRACKER_RIGHT_HAND);
+ new_tracker->set_hand(XRPositionalTracker::TRACKER_RIGHT_HAND);
}
// also register as joystick...
@@ -346,20 +335,20 @@ godot_int GDAPI godot_arvr_add_controller(char *p_device_name, godot_int p_hand,
}
// add our tracker to our server and remember its pointer
- arvr_server->add_tracker(new_tracker);
+ xr_server->add_tracker(new_tracker);
// note, this ID is only unique within controllers!
return new_tracker->get_tracker_id();
}
-void GDAPI godot_arvr_remove_controller(godot_int p_controller_id) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL(arvr_server);
+void GDAPI godot_xr_remove_controller(godot_int p_controller_id) {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL(xr_server);
- InputFilter *input = InputFilter::get_singleton();
+ Input *input = Input::get_singleton();
ERR_FAIL_NULL(input);
- ARVRPositionalTracker *remove_tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ XRPositionalTracker *remove_tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
if (remove_tracker != nullptr) {
// unset our joystick if applicable
int joyid = remove_tracker->get_joy_id();
@@ -369,16 +358,16 @@ void GDAPI godot_arvr_remove_controller(godot_int p_controller_id) {
}
// remove our tracker from our server
- arvr_server->remove_tracker(remove_tracker);
+ xr_server->remove_tracker(remove_tracker);
memdelete(remove_tracker);
}
}
-void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL(arvr_server);
+void GDAPI godot_xr_set_controller_transform(godot_int p_controller_id, godot_transform *p_transform, godot_bool p_tracks_orientation, godot_bool p_tracks_position) {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL(xr_server);
- ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
if (tracker != nullptr) {
Transform *transform = (Transform *)p_transform;
if (p_tracks_orientation) {
@@ -390,14 +379,14 @@ void GDAPI godot_arvr_set_controller_transform(godot_int p_controller_id, godot_
}
}
-void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL(arvr_server);
+void GDAPI godot_xr_set_controller_button(godot_int p_controller_id, godot_int p_button, godot_bool p_is_pressed) {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL(xr_server);
- InputFilter *input = InputFilter::get_singleton();
+ Input *input = Input::get_singleton();
ERR_FAIL_NULL(input);
- ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
if (tracker != nullptr) {
int joyid = tracker->get_joy_id();
if (joyid != -1) {
@@ -406,18 +395,18 @@ void GDAPI godot_arvr_set_controller_button(godot_int p_controller_id, godot_int
}
}
-void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL(arvr_server);
+void GDAPI godot_xr_set_controller_axis(godot_int p_controller_id, godot_int p_axis, godot_real p_value, godot_bool p_can_be_negative) {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL(xr_server);
- InputFilter *input = InputFilter::get_singleton();
+ Input *input = Input::get_singleton();
ERR_FAIL_NULL(input);
- ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
if (tracker != nullptr) {
int joyid = tracker->get_joy_id();
if (joyid != -1) {
- InputFilter::JoyAxis jx;
+ Input::JoyAxis jx;
jx.min = p_can_be_negative ? -1 : 0;
jx.value = p_value;
input->joy_axis(joyid, p_axis, jx);
@@ -425,11 +414,11 @@ void GDAPI godot_arvr_set_controller_axis(godot_int p_controller_id, godot_int p
}
}
-godot_real GDAPI godot_arvr_get_controller_rumble(godot_int p_controller_id) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL_V(arvr_server, 0.0);
+godot_real GDAPI godot_xr_get_controller_rumble(godot_int p_controller_id) {
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, 0.0);
- ARVRPositionalTracker *tracker = arvr_server->find_by_type_and_id(ARVRServer::TRACKER_CONTROLLER, p_controller_id);
+ XRPositionalTracker *tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id);
if (tracker != nullptr) {
return tracker->get_rumble();
}
diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.h b/modules/gdnative/xr/xr_interface_gdnative.h
index e38eb435c6..64f1282a7e 100644
--- a/modules/gdnative/arvr/arvr_interface_gdnative.h
+++ b/modules/gdnative/xr/xr_interface_gdnative.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* arvr_interface_gdnative.h */
+/* xr_interface_gdnative.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef ARVR_INTERFACE_GDNATIVE_H
-#define ARVR_INTERFACE_GDNATIVE_H
+#ifndef XR_INTERFACE_GDNATIVE_H
+#define XR_INTERFACE_GDNATIVE_H
#include "modules/gdnative/gdnative.h"
-#include "servers/arvr/arvr_interface.h"
+#include "servers/xr/xr_interface.h"
/**
@authors Hinsbart & Karroffel & Mux213
@@ -40,23 +40,23 @@
This subclass of our AR/VR interface forms a bridge to GDNative.
*/
-class ARVRInterfaceGDNative : public ARVRInterface {
- GDCLASS(ARVRInterfaceGDNative, ARVRInterface);
+class XRInterfaceGDNative : public XRInterface {
+ GDCLASS(XRInterfaceGDNative, XRInterface);
void cleanup();
protected:
- const godot_arvr_interface_gdnative *interface;
+ const godot_xr_interface_gdnative *interface;
void *data;
static void _bind_methods();
public:
/** general interface information **/
- ARVRInterfaceGDNative();
- ~ARVRInterfaceGDNative();
+ XRInterfaceGDNative();
+ ~XRInterfaceGDNative();
- void set_interface(const godot_arvr_interface_gdnative *p_interface);
+ void set_interface(const godot_xr_interface_gdnative *p_interface);
virtual StringName get_name() const;
virtual int get_capabilities() const;
@@ -73,19 +73,19 @@ public:
/** rendering and internal **/
virtual Size2 get_render_targetsize();
virtual bool is_stereo();
- virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
+ virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform);
// we expose a Vector<float> version of this function to GDNative
- Vector<float> _get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+ Vector<float> _get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
- // and a CameraMatrix version to ARVRServer
- virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+ // and a CameraMatrix version to XRServer
+ virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
- virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye);
- virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
+ virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye);
+ virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
virtual void process();
virtual void notification(int p_what);
};
-#endif // ARVR_INTERFACE_GDNATIVE_H
+#endif // XR_INTERFACE_GDNATIVE_H
diff --git a/modules/gdscript/config.py b/modules/gdscript/config.py
index 185a10bcb2..6fc227e7f5 100644
--- a/modules/gdscript/config.py
+++ b/modules/gdscript/config.py
@@ -11,7 +11,6 @@ def get_doc_classes():
"@GDScript",
"GDScript",
"GDScriptFunctionState",
- "GDScriptNativeClass",
]
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 9324691df5..be159b6407 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -568,7 +568,7 @@
<description>
Linearly interpolates between two values by a normalized value. This is the opposite of [method inverse_lerp].
If the [code]from[/code] and [code]to[/code] arguments are of type [int] or [float], the return value is a [float].
- If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]linear_interpolate[/code] method).
+ If both are of the same vector type ([Vector2], [Vector3] or [Color]), the return value will be of the same type ([code]lerp[/code] then calls the vector type's [code]lerp[/code] method).
[codeblock]
lerp(0, 4, 0.75) # Returns 3.0
lerp(Vector2(1, 5), Vector2(3, 2), 0.5) # Returns Vector2(2, 3.5)
diff --git a/modules/gdscript/doc_classes/GDScriptNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
deleted file mode 100644
index 0a8982de8e..0000000000
--- a/modules/gdscript/doc_classes/GDScriptNativeClass.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScriptNativeClass" inherits="Reference" version="4.0">
- <brief_description>
- </brief_description>
- <description>
- </description>
- <tutorials>
- </tutorials>
- <methods>
- <method name="new">
- <return type="Variant">
- </return>
- <description>
- </description>
- </method>
- </methods>
- <constants>
- </constants>
-</class>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 9a4fa5cc86..06ab9e226d 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -103,15 +103,14 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
instance->owner->set_script_instance(instance);
/* STEP 2, INITIALIZE AND CONSTRUCT */
-
{
MutexLock lock(GDScriptLanguage::singleton->lock);
-
instances.insert(instance->owner);
}
-
+ if (p_argcount < 0) {
+ return instance;
+ }
initializer->call(instance, p_args, p_argcount, r_error);
-
if (r_error.error != Callable::CallError::CALL_OK) {
instance->script = Ref<GDScript>();
instance->owner->set_script_instance(nullptr);
@@ -119,10 +118,8 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
MutexLock lock(GDScriptLanguage::singleton->lock);
instances.erase(p_owner);
}
-
- ERR_FAIL_COND_V(r_error.error != Callable::CallError::CALL_OK, nullptr); //error constructing
+ ERR_FAIL_V_MSG(nullptr, "Error constructing a GDScriptInstance.");
}
-
//@TODO make thread safe
return instance;
}
@@ -638,12 +635,12 @@ uint16_t GDScript::get_rpc_method_id(const StringName &p_method) const {
}
StringName GDScript::get_rpc_method(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), StringName());
+ if (p_rpc_method_id >= rpc_functions.size()) return StringName();
return rpc_functions[p_rpc_method_id].name;
}
MultiplayerAPI::RPCMode GDScript::get_rpc_mode_by_id(const uint16_t p_rpc_method_id) const {
- ERR_FAIL_COND_V(p_rpc_method_id >= rpc_functions.size(), MultiplayerAPI::RPC_MODE_DISABLED);
+ if (p_rpc_method_id >= rpc_functions.size()) return MultiplayerAPI::RPC_MODE_DISABLED;
return rpc_functions[p_rpc_method_id].mode;
}
@@ -665,12 +662,12 @@ uint16_t GDScript::get_rset_property_id(const StringName &p_variable) const {
}
StringName GDScript::get_rset_property(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), StringName());
+ if (p_rset_member_id >= rpc_variables.size()) return StringName();
return rpc_variables[p_rset_member_id].name;
}
MultiplayerAPI::RPCMode GDScript::get_rset_mode_by_id(const uint16_t p_rset_member_id) const {
- ERR_FAIL_COND_V(p_rset_member_id >= rpc_variables.size(), MultiplayerAPI::RPC_MODE_DISABLED);
+ if (p_rset_member_id >= rpc_variables.size()) return MultiplayerAPI::RPC_MODE_DISABLED;
return rpc_variables[p_rset_member_id].mode;
}
@@ -895,6 +892,24 @@ Ref<GDScript> GDScript::get_base() const {
return base;
}
+bool GDScript::inherits_script(const Ref<Script> &p_script) const {
+ Ref<GDScript> gd = p_script;
+ if (gd.is_null()) {
+ return false;
+ }
+
+ const GDScript *s = this;
+
+ while (s) {
+ if (s == p_script.ptr()) {
+ return true;
+ }
+ s = s->_base;
+ }
+
+ return false;
+}
+
bool GDScript::has_script_signal(const StringName &p_signal) const {
if (_signals.has(p_signal))
return true;
@@ -2257,7 +2272,7 @@ Ref<GDScript> GDScriptLanguage::get_orphan_subclass(const String &p_qualified_na
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
if (r_error)
*r_error = ERR_FILE_CANT_OPEN;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 2c5876372b..5fdc25669f 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -151,6 +151,8 @@ protected:
public:
virtual bool is_valid() const { return valid; }
+ bool inherits_script(const Ref<Script> &p_script) const;
+
const Map<StringName, Ref<GDScript>> &get_subclasses() const { return subclasses; }
const Map<StringName, Variant> &get_constants() const { return constants; }
const Set<StringName> &get_members() const { return members; }
@@ -545,7 +547,7 @@ public:
class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 1e3cbd661e..ab3228d076 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1427,6 +1427,7 @@ static bool _guess_identifier_type_from_base(GDScriptCompletionContext &p_contex
// Variable used in the same expression
return false;
}
+
if (_guess_expression_type(p_context, m.expression, r_type)) {
return true;
}
@@ -2057,7 +2058,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<PropertyInfo> pinfo;
ClassDB::get_property_list(type, &pinfo);
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) {
+ if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP | PROPERTY_USAGE_CATEGORY)) {
continue;
}
if (E->get().name.find("/") != -1) {
@@ -2098,7 +2099,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (!p_only_functions) {
List<PropertyInfo> members;
- p_base.value.get_property_list(&members);
+ tmp.get_property_list(&members);
for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
if (String(E->get().name).find("/") == -1) {
@@ -2150,7 +2151,7 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
}
const GDScriptParser::ClassNode *clss = p_context._class;
- bool _static = !p_context.function || p_context.function->_static;
+ bool _static = p_context.function && p_context.function->_static;
while (clss) {
GDScriptCompletionContext c = p_context;
@@ -2236,6 +2237,8 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
+#define IS_METHOD_SIGNAL(m_method) (m_method == "connect" || m_method == "disconnect" || m_method == "is_connected" || m_method == "emit_signal")
+
while (base_type.has_type) {
switch (base_type.kind) {
case GDScriptParser::DataType::CLASS: {
@@ -2252,7 +2255,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
}
}
- if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
+ if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
option.insert_text = quote_style + option.display + quote_style;
@@ -2265,7 +2268,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
case GDScriptParser::DataType::GDSCRIPT: {
Ref<GDScript> gds = base_type.script_type;
if (gds.is_valid()) {
- if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
+ if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) {
List<MethodInfo> signals;
gds->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
@@ -2327,7 +2330,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
}
}
- if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
+ if (IS_METHOD_SIGNAL(p_method) && p_argidx == 0) {
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
@@ -2336,6 +2339,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
r_result.insert(option.display, option);
}
}
+#undef IS_METHOD_SIGNAL
if (ClassDB::is_parent_class(class_name, "Node") && (p_method == "get_node" || p_method == "has_node") && p_argidx == 0) {
// Get autoloads
@@ -3487,6 +3491,17 @@ Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symbol
return OK;
}
} break;
+ case GDScriptParser::COMPLETION_TYPE_HINT: {
+
+ GDScriptParser::DataType base_type = context._class->base_type;
+ base_type.has_type = true;
+ base_type.kind = GDScriptParser::DataType::CLASS;
+ base_type.class_type = const_cast<GDScriptParser::ClassNode *>(context._class);
+
+ if (_lookup_symbol_from_base(base_type, p_symbol, false, r_result) == OK) {
+ return OK;
+ }
+ } break;
default: {
}
}
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index ca4d6f6de9..44640411bb 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -294,11 +294,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
line = p_state->line;
ip = p_state->ip;
alloca_size = p_state->stack.size();
- script = p_state->script.ptr();
- p_instance = p_state->instance;
+ script = static_cast<GDScript *>(ObjectDB::get_instance(p_state->script_id));
+ p_instance = p_state->instance_id.is_valid() ? static_cast<GDScriptInstance *>(ObjectDB::get_instance(p_state->instance_id)->get_script_instance()) : nullptr;
defarg = p_state->defarg;
self = p_state->self;
- //stack[p_state->result_pos]=p_state->result; //assign stack with result
} else {
@@ -337,15 +336,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (!argument_types[i].is_type(*p_args[i], true)) {
- if (argument_types[i].is_type(Variant(), true)) {
- memnew_placement(&stack[i], Variant);
- continue;
- } else {
- r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_err.argument = i;
- r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
- return Variant();
- }
+ r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_err.argument = i;
+ r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
+ return Variant();
}
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
Variant arg = Variant::construct(argument_types[i].builtin_type, &p_args[i], 1, r_err);
@@ -1285,13 +1279,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->state.stack_size = _stack_size;
gdfs->state.self = self;
gdfs->state.alloca_size = alloca_size;
- gdfs->state.script = Ref<GDScript>(_script);
gdfs->state.ip = ip + ipofs;
gdfs->state.line = line;
+ gdfs->state.script_id = script->get_instance_id();
+#ifdef DEBUG_ENABLED
+ gdfs->state.script_path = _script->get_path();
+#endif
gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : ObjectID();
- //gdfs->state.result_pos=ip+ipofs-1;
gdfs->state.defarg = defarg;
- gdfs->state.instance = p_instance;
gdfs->function = this;
retvalue = gdfs;
@@ -1838,9 +1833,14 @@ bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
return false;
if (p_extended_check) {
- //class instance gone?
- if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id))
+ // Class instance gone? (Otherwise script is valid for sure, because the instance has a ref to the script)
+ if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) {
+ return false;
+ }
+ // Script gone? (Static method, so there's no instance whose ref to the script can ensure it's valid)
+ if (!ObjectDB::get_instance(state.script_id)) {
return false;
+ }
}
return true;
@@ -1851,7 +1851,14 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
ERR_FAIL_COND_V(!function, Variant());
if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) {
#ifdef DEBUG_ENABLED
- ERR_FAIL_V_MSG(Variant(), "Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script->get_path() + ":" + itos(state.line));
+ ERR_FAIL_V_MSG(Variant(), "Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script_path + ":" + itos(state.line));
+#else
+ return Variant();
+#endif
+ }
+ if (!ObjectDB::get_instance(state.script_id)) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_V_MSG(Variant(), "Resumed function '" + String(function->get_name()) + "()' after yield, but script is gone. At script: " + state.script_path + ":" + itos(state.line));
#else
return Variant();
#endif
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index acfc0a95b4..9d8e23d994 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -293,13 +293,15 @@ private:
public:
struct CallState {
+ ObjectID script_id;
+#ifdef DEBUG_ENABLED
+ String script_path;
+#endif
ObjectID instance_id;
- GDScriptInstance *instance;
Vector<uint8_t> stack;
int stack_size;
Variant self;
uint32_t alloca_size;
- Ref<GDScript> script;
int ip;
int line;
int defarg;
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 9154d6eb89..0199af642f 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -362,13 +362,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
const double t = (double)*p_args[2];
switch (p_args[0]->get_type() == p_args[1]->get_type() ? p_args[0]->get_type() : Variant::FLOAT) {
case Variant::VECTOR2: {
- r_ret = ((Vector2)*p_args[0]).linear_interpolate((Vector2)*p_args[1], t);
+ r_ret = ((Vector2)*p_args[0]).lerp((Vector2)*p_args[1], t);
} break;
case Variant::VECTOR3: {
- r_ret = (p_args[0]->operator Vector3()).linear_interpolate(p_args[1]->operator Vector3(), t);
+ r_ret = (p_args[0]->operator Vector3()).lerp(p_args[1]->operator Vector3(), t);
} break;
case Variant::COLOR: {
- r_ret = ((Color)*p_args[0]).linear_interpolate((Color)*p_args[1], t);
+ r_ret = ((Color)*p_args[0]).lerp((Color)*p_args[1], t);
} break;
default: {
VALIDATE_ARG_NUM(0);
@@ -1197,8 +1197,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
return;
}
}
-
- r_ret = gdscr->_new(nullptr, 0, r_error);
+ r_ret = gdscr->_new(nullptr, -1 /*skip initializer*/, r_error);
GDScriptInstance *ins = static_cast<GDScriptInstance *>(static_cast<Object *>(r_ret)->get_script_instance());
Ref<GDScript> gd_ref = ins->get_script();
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index d02786bf41..c875846fcc 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -746,6 +746,13 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (tokenizer->get_token() == GDScriptTokenizer::TK_CURSOR) {
_make_completable_call(0);
completion_node = op;
+
+ if (op->arguments[0]->type == GDScriptParser::Node::Type::TYPE_BUILT_IN_FUNCTION) {
+ BuiltInFunctionNode *bn = static_cast<BuiltInFunctionNode *>(op->arguments[0]);
+ if (bn->function == GDScriptFunctions::Function::RESOURCE_LOAD) {
+ completion_type = COMPLETION_RESOURCE_PATH;
+ }
+ }
}
if (!replaced) {
if (!_parse_arguments(op, op->arguments, p_static, true, p_parsing_constant))
@@ -827,6 +834,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
//check from singletons
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = GDScriptLanguage::get_singleton()->get_named_globals_map()[identifier];
+ constant->datatype = _type_from_variant(constant->value);
expr = constant;
bfn = true;
}
@@ -837,6 +845,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (scr.is_valid() && scr->is_valid()) {
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = scr;
+ constant->datatype = _type_from_variant(constant->value);
expr = constant;
bfn = true;
}
@@ -852,6 +861,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (parent_constants.has(identifier)) {
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = parent_constants[identifier];
+ constant->datatype = _type_from_variant(constant->value);
expr = constant;
bfn = true;
}
@@ -2022,6 +2032,38 @@ GDScriptParser::Node *GDScriptParser::_parse_and_reduce_expression(Node *p_paren
return expr;
}
+bool GDScriptParser::_reduce_export_var_type(Variant &p_value, int p_line) {
+
+ if (p_value.get_type() == Variant::ARRAY) {
+ Array arr = p_value;
+ for (int i = 0; i < arr.size(); i++) {
+ if (!_reduce_export_var_type(arr[i], p_line)) return false;
+ }
+ return true;
+ }
+
+ if (p_value.get_type() == Variant::DICTIONARY) {
+ Dictionary dict = p_value;
+ for (int i = 0; i < dict.size(); i++) {
+ Variant value = dict.get_value_at_index(i);
+ if (!_reduce_export_var_type(value, p_line)) return false;
+ }
+ return true;
+ }
+
+ // validate type
+ DataType type = _type_from_variant(p_value);
+ if (type.kind == DataType::BUILTIN) {
+ return true;
+ } else if (type.kind == DataType::NATIVE) {
+ if (ClassDB::is_parent_class(type.native_type, "Resource")) {
+ return true;
+ }
+ }
+ _set_error("Invalid export type. Only built-in and native resource types can be exported.", p_line);
+ return false;
+}
+
bool GDScriptParser::_recover_from_completion() {
if (!completion_found) {
@@ -2386,6 +2428,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m
// a bind always matches
ConstantNode *true_value = alloc_node<ConstantNode>();
true_value->value = Variant(true);
+ true_value->datatype = _type_from_variant(true_value->value);
p_resulting_node = true_value;
} break;
case PatternNode::PT_ARRAY: {
@@ -2432,6 +2475,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m
// size
ConstantNode *length = alloc_node<ConstantNode>();
length->value = Variant(open_ended ? p_pattern->array.size() - 1 : p_pattern->array.size());
+ length->datatype = _type_from_variant(length->value);
OperatorNode *call = alloc_node<OperatorNode>();
call->op = OperatorNode::OP_CALL;
@@ -2465,6 +2509,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m
ConstantNode *index = alloc_node<ConstantNode>();
index->value = Variant(i);
+ index->datatype = _type_from_variant(index->value);
OperatorNode *indexed_value = alloc_node<OperatorNode>();
indexed_value->op = OperatorNode::OP_INDEX;
@@ -2525,6 +2570,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m
// size
ConstantNode *length = alloc_node<ConstantNode>();
length->value = Variant(open_ended ? p_pattern->dictionary.size() - 1 : p_pattern->dictionary.size());
+ length->datatype = _type_from_variant(length->value);
OperatorNode *call = alloc_node<OperatorNode>();
call->op = OperatorNode::OP_CALL;
@@ -2601,6 +2647,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m
// simply generate a `true`
ConstantNode *true_value = alloc_node<ConstantNode>();
true_value->value = Variant(true);
+ true_value->datatype = _type_from_variant(true_value->value);
p_resulting_node = true_value;
} break;
default: {
@@ -2683,6 +2730,7 @@ void GDScriptParser::_transform_match_statment(MatchNode *p_match_statement) {
LocalVarNode *local_var = branch->body->variables[e->key()];
local_var->assign = e->value();
local_var->set_datatype(local_var->assign->get_datatype());
+ local_var->assignments++;
IdentifierNode *id2 = alloc_node<IdentifierNode>();
id2->name = local_var->name;
@@ -2786,6 +2834,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
}
+ _mark_line_as_safe(line);
NewLineNode *nl2 = alloc_node<NewLineNode>();
nl2->line = line;
p_block->statements.push_back(nl2);
@@ -3299,6 +3348,8 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
return;
}
+ int assert_line = tokenizer->get_token_line();
+
tokenizer->advance();
Vector<Node *> args;
@@ -3308,25 +3359,27 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
}
if (args.empty() || args.size() > 2) {
- _set_error("Wrong number of arguments, expected 1 or 2");
+ _set_error("Wrong number of arguments, expected 1 or 2", assert_line);
return;
}
AssertNode *an = alloc_node<AssertNode>();
an->condition = _reduce_expression(args[0], p_static);
+ an->line = assert_line;
if (args.size() == 2) {
an->message = _reduce_expression(args[1], p_static);
} else {
ConstantNode *message_node = alloc_node<ConstantNode>();
message_node->value = String();
+ message_node->datatype = _type_from_variant(message_node->value);
an->message = message_node;
}
p_block->statements.push_back(an);
if (!_end_statement()) {
- _set_error("Expected end of statement after \"assert\".");
+ _set_error("Expected end of statement after \"assert\".", assert_line);
return;
}
} break;
@@ -3674,6 +3727,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("A constant named \"" + String(name) + "\" already exists in the outer class scope (at line" + itos(outer_class->constant_expressions[name].expression->line) + ").");
return;
}
+ for (int i = 0; i < outer_class->variables.size(); i++) {
+ if (outer_class->variables[i].identifier == name) {
+ _set_error("A variable named \"" + String(name) + "\" already exists in the outer class scope (at line " + itos(outer_class->variables[i].line) + ").");
+ return;
+ }
+ }
outer_class = outer_class->owner;
}
@@ -3975,7 +4034,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (!_enter_indent_block(block)) {
- _set_error("Indented block expected.");
+ _set_error(vformat("Indented block expected after declaration of \"%s\" function.", function->name));
return;
}
@@ -4864,6 +4923,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_set_error("Can't accept a null constant expression for inferring export type.");
return;
}
+
+ if (!_reduce_export_var_type(cn->value, member.line)) return;
+
member._export.type = cn->value.get_type();
member._export.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
if (cn->value.get_type() == Variant::OBJECT) {
@@ -6232,11 +6294,13 @@ GDScriptParser::Node *GDScriptParser::_get_default_value_for_type(const DataType
ConstantNode *c = alloc_node<ConstantNode>();
Callable::CallError err;
c->value = Variant::construct(p_type.builtin_type, nullptr, 0, err);
+ c->datatype = _type_from_variant(c->value);
result = c;
}
} else {
ConstantNode *c = alloc_node<ConstantNode>();
c->value = Variant();
+ c->datatype = _type_from_variant(c->value);
result = c;
}
@@ -6565,6 +6629,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
node_type = _reduce_identifier_type(&base_type, member_id->name, op->line, true);
#ifdef DEBUG_ENABLED
if (!node_type.has_type) {
+ _mark_line_as_unsafe(op->line);
_add_warning(GDScriptWarning::UNSAFE_PROPERTY_ACCESS, op->line, member_id->name.operator String(), base_type.to_string());
}
#endif // DEBUG_ENABLED
@@ -7368,6 +7433,8 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
}
}
+#define IS_USAGE_MEMBER(m_usage) (!(m_usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP | PROPERTY_USAGE_CATEGORY)))
+
// Check other script types
while (scr.is_valid()) {
Map<StringName, Variant> constants;
@@ -7380,7 +7447,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
List<PropertyInfo> properties;
scr->get_script_property_list(&properties);
for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().name == p_member) {
+ if (E->get().name == p_member && IS_USAGE_MEMBER(E->get().usage)) {
r_member_type = _type_from_property(E->get());
return true;
}
@@ -7422,7 +7489,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
List<PropertyInfo> properties;
ClassDB::get_property_list(native, &properties);
for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().name == p_member) {
+ if (E->get().name == p_member && IS_USAGE_MEMBER(E->get().usage)) {
// Check if a getter exists
StringName getter_name = ClassDB::get_property_getter(native, p_member);
if (getter_name != StringName()) {
@@ -7462,7 +7529,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
List<PropertyInfo> properties;
ClassDB::get_property_list(native, &properties);
for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().name == p_member) {
+ if (E->get().name == p_member && IS_USAGE_MEMBER(E->get().usage)) {
// Check if a getter exists
StringName getter_name = ClassDB::get_property_getter(native, p_member);
if (getter_name != StringName()) {
@@ -7484,6 +7551,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
}
}
}
+#undef IS_USAGE_MEMBER
return false;
}
@@ -7507,6 +7575,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
}
if (_get_member_type(base_type, p_identifier, member_type)) {
+ if (!p_base_type && current_function && current_function->_static) {
+ _set_error("Can't access member variable (\"" + p_identifier.operator String() + "\") from a static function.", p_line);
+ return DataType();
+ }
return member_type;
}
@@ -8064,10 +8136,15 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
Node *statement = E->get();
switch (statement->type) {
case Node::TYPE_NEWLINE:
- case Node::TYPE_BREAKPOINT:
- case Node::TYPE_ASSERT: {
+ case Node::TYPE_BREAKPOINT: {
// Nothing to do
} break;
+ case Node::TYPE_ASSERT: {
+ AssertNode *an = static_cast<AssertNode *>(statement);
+ _mark_line_as_safe(an->line);
+ _reduce_node_type(an->condition);
+ _reduce_node_type(an->message);
+ } break;
case Node::TYPE_LOCAL_VAR: {
LocalVarNode *lv = static_cast<LocalVarNode *>(statement);
lv->datatype = _resolve_type(lv->datatype, lv->line);
@@ -8111,6 +8188,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
ConstantNode *tgt_type = alloc_node<ConstantNode>();
tgt_type->line = lv->line;
tgt_type->value = (int)lv->datatype.builtin_type;
+ tgt_type->datatype = _type_from_variant(tgt_type->value);
OperatorNode *convert_call = alloc_node<OperatorNode>();
convert_call->line = lv->line;
@@ -8246,6 +8324,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
ConstantNode *tgt_type = alloc_node<ConstantNode>();
tgt_type->line = op->line;
tgt_type->value = (int)lh_type.builtin_type;
+ tgt_type->datatype = _type_from_variant(tgt_type->value);
OperatorNode *convert_call = alloc_node<OperatorNode>();
convert_call->line = op->line;
@@ -8500,7 +8579,13 @@ Error GDScriptParser::_parse(const String &p_base_path) {
_set_error("Parse error: " + tokenizer->get_token_error());
}
- if (error_set && !for_completion) {
+ bool for_completion_error_set = false;
+ if (error_set && for_completion) {
+ for_completion_error_set = true;
+ error_set = false;
+ }
+
+ if (error_set) {
return ERR_PARSE_ERROR;
}
@@ -8530,6 +8615,10 @@ Error GDScriptParser::_parse(const String &p_base_path) {
// Resolve the function blocks
_check_class_blocks_types(main_class);
+ if (for_completion_error_set) {
+ error_set = true;
+ }
+
if (error_set) {
return ERR_PARSE_ERROR;
}
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index eca5f83f7a..f254352423 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -613,6 +613,7 @@ private:
Node *_parse_expression(Node *p_parent, bool p_static, bool p_allow_assign = false, bool p_parsing_constant = false);
Node *_reduce_expression(Node *p_node, bool p_to_const = false);
Node *_parse_and_reduce_expression(Node *p_parent, bool p_static, bool p_reduce_const = false, bool p_allow_assign = false);
+ bool _reduce_export_var_type(Variant &p_value, int p_line = 0);
PatternNode *_parse_pattern(bool p_static);
void _parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode *> &p_branches, bool p_static);
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index d42ca52731..76f42ead5f 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -803,19 +803,16 @@ void GDScriptTokenizerText::_advance() {
switch (next) {
- case 'a': res = 7; break;
- case 'b': res = 8; break;
- case 't': res = 9; break;
- case 'n': res = 10; break;
- case 'v': res = 11; break;
- case 'f': res = 12; break;
- case 'r': res = 13; break;
+ case 'a': res = '\a'; break;
+ case 'b': res = '\b'; break;
+ case 't': res = '\t'; break;
+ case 'n': res = '\n'; break;
+ case 'v': res = '\v'; break;
+ case 'f': res = '\f'; break;
+ case 'r': res = '\r'; break;
case '\'': res = '\''; break;
case '\"': res = '\"'; break;
case '\\': res = '\\'; break;
- case '/':
- res = '/';
- break; //wtf
case 'u': {
// hex number
@@ -847,6 +844,10 @@ void GDScriptTokenizerText::_advance() {
i += 3;
} break;
+ case '\n': {
+ line++;
+ column = 1;
+ } break;
default: {
_make_error("Invalid escape sequence");
@@ -854,7 +855,8 @@ void GDScriptTokenizerText::_advance() {
} break;
}
- str += res;
+ if (next != '\n')
+ str += res;
} else {
if (CharType(GETCHAR(i)) == '\n') {
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 1b432ae8c1..180ec3c77e 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -32,6 +32,7 @@
#define GDSCRIPT_TOKENIZER_H
#include "core/pair.h"
+#include "core/set.h"
#include "core/string_name.h"
#include "core/ustring.h"
#include "core/variant.h"
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index 914c9742e1..124fcbfed8 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -156,7 +156,7 @@ struct LocationLink {
* Used as the underlined span for mouse interaction. Defaults to the word range at
* the mouse position.
*/
- Range *originSelectionRange = NULL;
+ Range *originSelectionRange = nullptr;
/**
* The target resource identifier of this link.
@@ -1686,8 +1686,8 @@ struct InitializeResult {
struct GodotNativeClassInfo {
String name;
- const DocData::ClassDoc *class_doc = NULL;
- const ClassDB::ClassInfo *class_info = NULL;
+ const DocData::ClassDoc *class_doc = nullptr;
+ const ClassDB::ClassInfo *class_info = nullptr;
Dictionary to_json() {
Dictionary dict;
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index df7c2f397f..0dbefbb39f 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -80,7 +80,7 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) {
RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id());
if (is_inside_tree()) {
- RS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario());
+ RS::get_singleton()->instance_set_scenario(bm.instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(bm.instance, get_global_transform());
}
baked_meshes.push_back(bm);
@@ -536,7 +536,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
RS::get_singleton()->instance_set_base(instance, mm);
if (is_inside_tree()) {
- RS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario());
+ RS::get_singleton()->instance_set_scenario(instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(instance, get_global_transform());
}
@@ -577,15 +577,15 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
ERR_FAIL_COND(!octant_map.has(p_key));
Octant &g = *octant_map[p_key];
PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform());
- PhysicsServer3D::get_singleton()->body_set_space(g.static_body, get_world()->get_space());
+ PhysicsServer3D::get_singleton()->body_set_space(g.static_body, get_world_3d()->get_space());
if (g.collision_debug_instance.is_valid()) {
- RS::get_singleton()->instance_set_scenario(g.collision_debug_instance, get_world()->get_scenario());
+ RS::get_singleton()->instance_set_scenario(g.collision_debug_instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform());
}
for (int i = 0; i < g.multimesh_instances.size(); i++) {
- RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, get_world()->get_scenario());
+ RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform());
}
@@ -684,7 +684,7 @@ void GridMap::_notification(int p_what) {
}
for (int i = 0; i < baked_meshes.size(); i++) {
- RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world()->get_scenario());
+ RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform());
}
@@ -1054,7 +1054,7 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe
RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid());
RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id());
if (is_inside_tree()) {
- RS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario());
+ RS::get_singleton()->instance_set_scenario(bm.instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(bm.instance, get_global_transform());
}
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index eb8feb5bc7..9abbac6a0b 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "grid_map_editor_plugin.h"
-#include "core/input/input_filter.h"
+#include "core/input/input.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/plugins/node_3d_editor_plugin.h"
@@ -556,7 +556,7 @@ void GridMapEditor::_set_clipboard_data() {
item.cell_item = itm;
item.grid_offset = Vector3(i, j, k) - selection.begin;
item.orientation = node->get_cell_item_orientation(i, j, k);
- item.instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario());
+ item.instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world_3d()->get_scenario());
clipboard_items.push_back(item);
}
@@ -1083,12 +1083,12 @@ void GridMapEditor::_notification(int p_what) {
for (int i = 0; i < 3; i++) {
grid[i] = RS::get_singleton()->mesh_create();
- grid_instance[i] = RS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario());
- selection_level_instance[i] = RenderingServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario());
+ grid_instance[i] = RS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world_3d()->get_scenario());
+ selection_level_instance[i] = RenderingServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world_3d()->get_scenario());
}
- selection_instance = RenderingServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario());
- paste_instance = RenderingServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario());
+ selection_instance = RenderingServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world_3d()->get_scenario());
+ paste_instance = RenderingServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world_3d()->get_scenario());
_update_selection_transform();
_update_paste_indicator();
@@ -1168,7 +1168,7 @@ void GridMapEditor::_update_cursor_instance() {
Ref<Mesh> mesh = node->get_mesh_library()->get_item_mesh(selected_palette);
if (!mesh.is_null() && mesh->get_rid().is_valid()) {
- cursor_instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario());
+ cursor_instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world_3d()->get_scenario());
RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform);
}
}
diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
index 7552abe61d..120535bd41 100644
--- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml
+++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MobileVRInterface" inherits="ARVRInterface" version="4.0">
+<class name="MobileVRInterface" inherits="XRInterface" version="4.0">
<brief_description>
Generic mobile VR implementation.
</brief_description>
@@ -8,9 +8,9 @@
Note that even though there is no positional tracking, the camera will assume the headset is at a height of 1.85 meters. You can change this by setting [member eye_height].
You can initialise this interface as follows:
[codeblock]
- var interface = ARVRServer.find_interface("Native mobile")
+ var interface = XRServer.find_interface("Native mobile")
if interface and interface.initialize():
- get_viewport().arvr = true
+ get_viewport().xr = true
[/codeblock]
</description>
<tutorials>
@@ -25,7 +25,7 @@
The width of the display in centimeters.
</member>
<member name="eye_height" type="float" setter="set_eye_height" getter="get_eye_height" default="1.85">
- The height at which the camera is placed in relation to the ground (i.e. [ARVROrigin] node).
+ The height at which the camera is placed in relation to the ground (i.e. [XROrigin3D] node).
</member>
<member name="iod" type="float" setter="set_iod" getter="get_iod" default="6.0">
The interocular distance, also known as the interpupillary distance. The distance between the pupils of the left and right eye.
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index 6b5a70435d..48276c0d3d 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -29,7 +29,8 @@
/*************************************************************************/
#include "mobile_vr_interface.h"
-#include "core/input/input_filter.h"
+
+#include "core/input/input.h"
#include "core/os/os.h"
#include "servers/display_server.h"
#include "servers/rendering/rendering_server_globals.h"
@@ -39,7 +40,7 @@ StringName MobileVRInterface::get_name() const {
};
int MobileVRInterface::get_capabilities() const {
- return ARVRInterface::ARVR_STEREO;
+ return XRInterface::XR_STEREO;
};
Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) {
@@ -118,7 +119,7 @@ void MobileVRInterface::set_position_from_sensors() {
float delta_time = (double)ticks_elapsed / 1000000.0;
// few things we need
- InputFilter *input = InputFilter::get_singleton();
+ Input *input = Input::get_singleton();
Vector3 down(0.0, -1.0, 0.0); // Down is Y negative
Vector3 north(0.0, 0.0, 1.0); // North is Z positive
@@ -165,7 +166,7 @@ void MobileVRInterface::set_position_from_sensors() {
rotate.rotate(orientation.get_axis(2), gyro.z * delta_time);
orientation = rotate * orientation;
- tracking_state = ARVRInterface::ARVR_NORMAL_TRACKING;
+ tracking_state = XRInterface::XR_NORMAL_TRACKING;
};
///@TODO improve this, the magnetometer is very fidgity sometimes flipping the axis for no apparent reason (probably a bug on my part)
@@ -177,7 +178,7 @@ void MobileVRInterface::set_position_from_sensors() {
transform_quat = transform_quat.slerp(acc_mag_quat, 0.1);
orientation = Basis(transform_quat);
- tracking_state = ARVRInterface::ARVR_NORMAL_TRACKING;
+ tracking_state = XRInterface::XR_NORMAL_TRACKING;
} else if (has_grav) {
// use gravity vector to make sure down is down...
// transform gravity into our world space
@@ -297,8 +298,8 @@ bool MobileVRInterface::is_initialized() const {
};
bool MobileVRInterface::initialize() {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL_V(arvr_server, false);
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, false);
if (!initialized) {
// reset our sensor data and orientation
@@ -314,7 +315,7 @@ bool MobileVRInterface::initialize() {
orientation = Basis();
// make this our primary interface
- arvr_server->set_primary_interface(this);
+ xr_server->set_primary_interface(this);
last_ticks = OS::get_singleton()->get_ticks_usec();
@@ -326,10 +327,10 @@ bool MobileVRInterface::initialize() {
void MobileVRInterface::uninitialize() {
if (initialized) {
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- if (arvr_server != nullptr) {
+ XRServer *xr_server = XRServer::get_singleton();
+ if (xr_server != nullptr) {
// no longer our primary interface
- arvr_server->clear_primary_interface_if(this);
+ xr_server->clear_primary_interface_if(this);
}
initialized = false;
@@ -348,22 +349,22 @@ Size2 MobileVRInterface::get_render_targetsize() {
return target_size;
};
-Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) {
+Transform MobileVRInterface::get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform) {
_THREAD_SAFE_METHOD_
Transform transform_for_eye;
- ARVRServer *arvr_server = ARVRServer::get_singleton();
- ERR_FAIL_NULL_V(arvr_server, transform_for_eye);
+ XRServer *xr_server = XRServer::get_singleton();
+ ERR_FAIL_NULL_V(xr_server, transform_for_eye);
if (initialized) {
- float world_scale = arvr_server->get_world_scale();
+ float world_scale = xr_server->get_world_scale();
// we don't need to check for the existence of our HMD, doesn't effect our values...
// note * 0.01 to convert cm to m and * 0.5 as we're moving half in each direction...
- if (p_eye == ARVRInterface::EYE_LEFT) {
+ if (p_eye == XRInterface::EYE_LEFT) {
transform_for_eye.origin.x = -(intraocular_dist * 0.01 * 0.5 * world_scale);
- } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ } else if (p_eye == XRInterface::EYE_RIGHT) {
transform_for_eye.origin.x = intraocular_dist * 0.01 * 0.5 * world_scale;
} else {
// for mono we don't reposition, we want our center position.
@@ -374,7 +375,7 @@ Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, co
hmd_transform.basis = orientation;
hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0);
- transform_for_eye = p_cam_transform * (arvr_server->get_reference_frame()) * hmd_transform * transform_for_eye;
+ transform_for_eye = p_cam_transform * (xr_server->get_reference_frame()) * hmd_transform * transform_for_eye;
} else {
// huh? well just return what we got....
transform_for_eye = p_cam_transform;
@@ -383,12 +384,12 @@ Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, co
return transform_for_eye;
};
-CameraMatrix MobileVRInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+CameraMatrix MobileVRInterface::get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
_THREAD_SAFE_METHOD_
CameraMatrix eye;
- if (p_eye == ARVRInterface::EYE_MONO) {
+ if (p_eye == XRInterface::EYE_MONO) {
///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real cameras properties
// which probably means implementing a specific class for iOS and Android. For now this is purely here as an example.
// Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface
@@ -396,13 +397,13 @@ CameraMatrix MobileVRInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye
// This will make more sense when we implement ARkit on iOS (probably a separate interface).
eye.set_perspective(60.0, p_aspect, p_z_near, p_z_far, false);
} else {
- eye.set_for_hmd(p_eye == ARVRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far);
+ eye.set_for_hmd(p_eye == XRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far);
};
return eye;
};
-void MobileVRInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
+void MobileVRInterface::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
_THREAD_SAFE_METHOD_
// We must have a valid render target
@@ -417,9 +418,9 @@ void MobileVRInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_t
// we output half a screen
dest.size.x *= 0.5;
- if (p_eye == ARVRInterface::EYE_LEFT) {
+ if (p_eye == XRInterface::EYE_LEFT) {
eye_center.x = ((-intraocular_dist / 2.0) + (display_width / 4.0)) / (display_width / 2.0);
- } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ } else if (p_eye == XRInterface::EYE_RIGHT) {
dest.position.x = dest.size.x;
eye_center.x = ((intraocular_dist / 2.0) - (display_width / 4.0)) / (display_width / 2.0);
}
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index c762c9b799..3a9ed1314a 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -31,8 +31,8 @@
#ifndef MOBILE_VR_INTERFACE_H
#define MOBILE_VR_INTERFACE_H
-#include "servers/arvr/arvr_interface.h"
-#include "servers/arvr/arvr_positional_tracker.h"
+#include "servers/xr/xr_interface.h"
+#include "servers/xr/xr_positional_tracker.h"
/**
@author Bastiaan Olij <mux213@gmail.com>
@@ -47,8 +47,8 @@
more advanced interfaces.
*/
-class MobileVRInterface : public ARVRInterface {
- GDCLASS(MobileVRInterface, ARVRInterface);
+class MobileVRInterface : public XRInterface {
+ GDCLASS(MobileVRInterface, XRInterface);
private:
bool initialized;
@@ -137,9 +137,9 @@ public:
virtual Size2 get_render_targetsize();
virtual bool is_stereo();
- virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
- virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
- virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
+ virtual Transform get_transform_for_eye(XRInterface::Eyes p_eye, const Transform &p_cam_transform);
+ virtual CameraMatrix get_projection_for_eye(XRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+ virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
virtual void process();
virtual void notification(int p_what);
diff --git a/modules/mobile_vr/register_types.cpp b/modules/mobile_vr/register_types.cpp
index faf6c3b151..75638d47c4 100644
--- a/modules/mobile_vr/register_types.cpp
+++ b/modules/mobile_vr/register_types.cpp
@@ -37,7 +37,7 @@ void register_mobile_vr_types() {
Ref<MobileVRInterface> mobile_vr;
mobile_vr.instance();
- ARVRServer::get_singleton()->add_interface(mobile_vr);
+ XRServer::get_singleton()->add_interface(mobile_vr);
}
void unregister_mobile_vr_types() {
diff --git a/modules/mono/build_scripts/godot_tools_build.py b/modules/mono/build_scripts/godot_tools_build.py
index cffacf2577..8e77f3bb44 100644
--- a/modules/mono/build_scripts/godot_tools_build.py
+++ b/modules/mono/build_scripts/godot_tools_build.py
@@ -13,13 +13,9 @@ def build_godot_tools(source, target, env):
solution_path = os.path.join(module_dir, "editor/GodotTools/GodotTools.sln")
build_config = "Debug" if env["target"] == "debug" else "Release"
- # Custom build target to make sure output is always copied to the data dir.
- extra_build_args = ["/Target:Build;GodotTools:BuildAlwaysCopyToDataDir"]
+ from .solution_builder import build_solution
- from .solution_builder import build_solution, nuget_restore
-
- nuget_restore(env, solution_path)
- build_solution(env, solution_path, build_config, extra_build_args)
+ build_solution(env, solution_path, build_config, restore=True)
# No need to copy targets. The GodotTools csproj takes care of copying them.
diff --git a/modules/mono/build_scripts/solution_builder.py b/modules/mono/build_scripts/solution_builder.py
index db6b4ff7aa..e8ddb7114e 100644
--- a/modules/mono/build_scripts/solution_builder.py
+++ b/modules/mono/build_scripts/solution_builder.py
@@ -4,91 +4,19 @@ import os
verbose = False
-def find_nuget_unix():
- import os
-
- if "NUGET_PATH" in os.environ:
- hint_path = os.environ["NUGET_PATH"]
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
- hint_path = os.path.join(hint_path, "nuget")
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
-
- import os.path
- import sys
-
- hint_dirs = ["/opt/novell/mono/bin"]
- if sys.platform == "darwin":
- hint_dirs = [
- "/Library/Frameworks/Mono.framework/Versions/Current/bin",
- "/usr/local/var/homebrew/linked/mono/bin",
- ] + hint_dirs
-
- for hint_dir in hint_dirs:
- hint_path = os.path.join(hint_dir, "nuget")
- if os.path.isfile(hint_path):
- return hint_path
- elif os.path.isfile(hint_path + ".exe"):
- return hint_path + ".exe"
-
- for hint_dir in os.environ["PATH"].split(os.pathsep):
- hint_dir = hint_dir.strip('"')
- hint_path = os.path.join(hint_dir, "nuget")
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
- if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
- return hint_path + ".exe"
-
- return None
-
-
-def find_nuget_windows(env):
- import os
-
- if "NUGET_PATH" in os.environ:
- hint_path = os.environ["NUGET_PATH"]
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
- hint_path = os.path.join(hint_path, "nuget.exe")
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
-
- from .mono_reg_utils import find_mono_root_dir
-
- mono_root = env["mono_prefix"] or find_mono_root_dir(env["bits"])
-
- if mono_root:
- mono_bin_dir = os.path.join(mono_root, "bin")
- nuget_mono = os.path.join(mono_bin_dir, "nuget.bat")
-
- if os.path.isfile(nuget_mono):
- return nuget_mono
-
- # Standalone NuGet
-
- for hint_dir in os.environ["PATH"].split(os.pathsep):
- hint_dir = hint_dir.strip('"')
- hint_path = os.path.join(hint_dir, "nuget.exe")
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
-
- return None
-
-
def find_msbuild_unix(filename):
import os.path
import sys
- hint_dirs = ["/opt/novell/mono/bin"]
+ hint_dirs = []
if sys.platform == "darwin":
- hint_dirs = [
+ hint_dirs[:0] = [
"/Library/Frameworks/Mono.framework/Versions/Current/bin",
"/usr/local/var/homebrew/linked/mono/bin",
- ] + hint_dirs
+ ]
for hint_dir in hint_dirs:
- hint_path = os.path.join(hint_dir, filename)
+ hint_path = os.path.join(hint_dir, "msbuild")
if os.path.isfile(hint_path):
return hint_path
elif os.path.isfile(hint_path + ".exe"):
@@ -96,7 +24,7 @@ def find_msbuild_unix(filename):
for hint_dir in os.environ["PATH"].split(os.pathsep):
hint_dir = hint_dir.strip('"')
- hint_path = os.path.join(hint_dir, filename)
+ hint_path = os.path.join(hint_dir, "msbuild")
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
return hint_path
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
@@ -162,18 +90,11 @@ def nuget_restore(env, *args):
global verbose
verbose = env["verbose"]
- # Find NuGet
- nuget_path = find_nuget_windows(env) if os.name == "nt" else find_nuget_unix()
- if nuget_path is None:
- raise RuntimeError("Cannot find NuGet executable")
-
- print("NuGet path: " + nuget_path)
-
# Do NuGet restore
run_command(nuget_path, ["restore"] + list(args), name="nuget restore")
-def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
+def build_solution(env, solution_path, build_config, extra_msbuild_args=[], restore=False):
global verbose
verbose = env["verbose"]
@@ -193,28 +114,17 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
else:
msbuild_path = find_msbuild_unix("msbuild")
if msbuild_path is None:
- xbuild_fallback = env["xbuild_fallback"]
-
- if xbuild_fallback and os.name == "nt":
- print("Option 'xbuild_fallback' not supported on Windows")
- xbuild_fallback = False
-
- if xbuild_fallback:
- print("Cannot find MSBuild executable, trying with xbuild")
- print("Warning: xbuild is deprecated")
-
- msbuild_path = find_msbuild_unix("xbuild")
-
- if msbuild_path is None:
- raise RuntimeError("Cannot find xbuild executable")
- else:
- raise RuntimeError("Cannot find MSBuild executable")
+ raise RuntimeError("Cannot find MSBuild executable")
print("MSBuild path: " + msbuild_path)
# Build solution
- msbuild_args = [solution_path, "/p:Configuration=" + build_config]
+ targets = ["Build"]
+ if restore:
+ targets.insert(0, "Restore")
+
+ msbuild_args = [solution_path, "/t:%s" % ",".join(targets), "/p:Configuration=" + build_config]
msbuild_args += extra_msbuild_args
run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild")
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 106ca6e028..d41f3755b5 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -35,7 +35,6 @@ def configure(env):
"copy_mono_root", "Make a copy of the mono installation directory to bundle with the editor", False
)
)
- envvars.Add(BoolVariable("xbuild_fallback", "If MSBuild is not found, fallback to xbuild", False))
# TODO: It would be great if this could be detected automatically instead
envvars.Add(
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 0b5d3c8dbc..6c1c8b87ef 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -850,7 +850,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
to_reload.push_back(script);
if (script->get_path().empty()) {
- script->tied_class_name_for_reload = script->script_class->get_name();
+ script->tied_class_name_for_reload = script->script_class->get_name_for_lookup();
script->tied_class_namespace_for_reload = script->script_class->get_namespace();
}
@@ -3536,6 +3536,18 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
}
}
+bool CSharpScript::inherits_script(const Ref<Script> &p_script) const {
+ Ref<CSharpScript> cs = p_script;
+ if (cs.is_null()) {
+ return false;
+ }
+
+#ifndef _MSC_VER
+#warning TODO: Implement CSharpScript::inherits_script and other relevant changes after GH-38063.
+#endif
+ return false;
+}
+
Ref<Script> CSharpScript::get_base_script() const {
// TODO search in metadata file once we have it, not important any way?
@@ -3673,7 +3685,7 @@ CSharpScript::~CSharpScript() {
/*************** RESOURCE ***************/
-RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
if (r_error)
*r_error = ERR_FILE_CANT_OPEN;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 29c33b50bb..05e2857538 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -194,6 +194,8 @@ public:
virtual bool is_tool() const { return tool; }
virtual bool is_valid() const { return valid; }
+ bool inherits_script(const Ref<Script> &p_script) const;
+
virtual Ref<Script> get_base_script() const;
virtual ScriptLanguage *get_language() const;
@@ -530,7 +532,7 @@ public:
class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs b/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs
new file mode 100644
index 0000000000..85760a3705
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs
@@ -0,0 +1,27 @@
+using System.IO;
+
+namespace GodotTools.Core
+{
+ public static class FileUtils
+ {
+ public static void SaveBackupCopy(string filePath)
+ {
+ string backupPathBase = filePath + ".old";
+ string backupPath = backupPathBase;
+
+ const int maxAttempts = 5;
+ int attempt = 1;
+
+ while (File.Exists(backupPath) && attempt <= maxAttempts)
+ {
+ backupPath = backupPathBase + "." + (attempt);
+ attempt++;
+ }
+
+ if (attempt > maxAttempts + 1)
+ return;
+
+ File.Copy(filePath, backupPath, overwrite: true);
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
index 2c35ef540a..c9ea7d3a2c 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
@@ -31,6 +31,7 @@
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="FileUtils.cs" />
<Compile Include="ProcessExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StringExtensions.cs" />
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
index 9afd9adeb1..6f318aab4a 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
@@ -153,7 +153,12 @@ EndProject";
var result = regex.Replace(input,m => dict[m.Value]);
if (result != input)
+ {
+ // Save a copy of the solution before replacing it
+ FileUtils.SaveBackupCopy(slnPath);
+
File.WriteAllText(slnPath, result);
+ }
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
index 1776b46e6a..f2ebef1a7d 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
@@ -9,8 +9,28 @@ using Microsoft.Build.Construction;
namespace GodotTools.ProjectEditor
{
+ public sealed class MSBuildProject
+ {
+ public ProjectRootElement Root { get; }
+
+ public bool HasUnsavedChanges { get; set; }
+
+ public void Save() => Root.Save();
+
+ public MSBuildProject(ProjectRootElement root)
+ {
+ Root = root;
+ }
+ }
+
public static class ProjectUtils
{
+ public static MSBuildProject Open(string path)
+ {
+ var root = ProjectRootElement.Open(path);
+ return root != null ? new MSBuildProject(root) : null;
+ }
+
public static void AddItemToProjectChecked(string projectPath, string itemType, string include)
{
var dir = Directory.GetParent(projectPath).FullName;
@@ -43,7 +63,6 @@ namespace GodotTools.ProjectEditor
public static void RemoveItemFromProjectChecked(string projectPath, string itemType, string include)
{
- var dir = Directory.GetParent(projectPath).FullName;
var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
@@ -150,12 +169,9 @@ namespace GodotTools.ProjectEditor
}
/// Simple function to make sure the Api assembly references are configured correctly
- public static void FixApiHintPath(string projectPath)
+ public static void FixApiHintPath(MSBuildProject project)
{
- var root = ProjectRootElement.Open(projectPath);
- Debug.Assert(root != null);
-
- bool dirty = false;
+ var root = project.Root;
void AddPropertyIfNotPresent(string name, string condition, string value)
{
@@ -170,7 +186,7 @@ namespace GodotTools.ProjectEditor
}
root.AddProperty(name, value).Condition = " " + condition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
AddPropertyIfNotPresent(name: "ApiConfiguration",
@@ -212,7 +228,7 @@ namespace GodotTools.ProjectEditor
}
referenceWithHintPath.AddMetadata("HintPath", hintPath);
- dirty = true;
+ project.HasUnsavedChanges = true;
return;
}
@@ -221,14 +237,14 @@ namespace GodotTools.ProjectEditor
{
// Found a Reference item without a HintPath
referenceWithoutHintPath.AddMetadata("HintPath", hintPath);
- dirty = true;
+ project.HasUnsavedChanges = true;
return;
}
}
// Found no Reference item at all. Add it.
root.AddItem("Reference", referenceName).Condition = " " + condition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
const string coreProjectName = "GodotSharp";
@@ -242,17 +258,11 @@ namespace GodotTools.ProjectEditor
SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath);
SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath);
-
- if (dirty)
- root.Save();
}
- public static void MigrateFromOldConfigNames(string projectPath)
+ public static void MigrateFromOldConfigNames(MSBuildProject project)
{
- var root = ProjectRootElement.Open(projectPath);
- Debug.Assert(root != null);
-
- bool dirty = false;
+ var root = project.Root;
bool hasGodotProjectGeneratorVersion = false;
bool foundOldConfiguration = false;
@@ -267,7 +277,7 @@ namespace GodotTools.ProjectEditor
{
configItem.Value = "Debug";
foundOldConfiguration = true;
- dirty = true;
+ project.HasUnsavedChanges = true;
}
}
@@ -275,7 +285,7 @@ namespace GodotTools.ProjectEditor
{
root.PropertyGroups.First(g => g.Condition == string.Empty)?
.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
- dirty = true;
+ project.HasUnsavedChanges = true;
}
if (!foundOldConfiguration)
@@ -301,7 +311,7 @@ namespace GodotTools.ProjectEditor
foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition.Trim() == oldCondition))
{
propertyGroup.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
foreach (var propertyGroup in root.PropertyGroups)
@@ -309,14 +319,14 @@ namespace GodotTools.ProjectEditor
foreach (var prop in propertyGroup.Properties.Where(p => p.Condition.Trim() == oldCondition))
{
prop.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
}
foreach (var itemGroup in root.ItemGroups.Where(g => g.Condition.Trim() == oldCondition))
{
itemGroup.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
foreach (var itemGroup in root.ItemGroups)
@@ -324,7 +334,7 @@ namespace GodotTools.ProjectEditor
foreach (var item in itemGroup.Items.Where(item => item.Condition.Trim() == oldCondition))
{
item.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
}
}
@@ -340,10 +350,6 @@ namespace GodotTools.ProjectEditor
MigrateConfigurationConditions("Release", "ExportRelease");
MigrateConfigurationConditions("Tools", "Debug"); // Must be last
}
-
-
- if (dirty)
- root.Save();
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs b/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs
index e4c8759802..3cf495f025 100644
--- a/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/BottomPanel.cs
@@ -205,9 +205,9 @@ namespace GodotTools
if (what == EditorSettings.NotificationEditorSettingsChanged)
{
var editorBaseControl = editorInterface.GetBaseControl();
- panelTabs.AddStyleboxOverride("panel", editorBaseControl.GetStylebox("DebuggerPanel", "EditorStyles"));
- panelTabs.AddStyleboxOverride("tab_fg", editorBaseControl.GetStylebox("DebuggerTabFG", "EditorStyles"));
- panelTabs.AddStyleboxOverride("tab_bg", editorBaseControl.GetStylebox("DebuggerTabBG", "EditorStyles"));
+ panelTabs.AddThemeStyleboxOverride("panel", editorBaseControl.GetThemeStylebox("DebuggerPanel", "EditorStyles"));
+ panelTabs.AddThemeStyleboxOverride("tab_fg", editorBaseControl.GetThemeStylebox("DebuggerTabFG", "EditorStyles"));
+ panelTabs.AddThemeStyleboxOverride("tab_bg", editorBaseControl.GetThemeStylebox("DebuggerTabBG", "EditorStyles"));
}
}
@@ -258,9 +258,9 @@ namespace GodotTools
RectMinSize = new Vector2(0, 228) * EditorScale,
SizeFlagsVertical = (int)SizeFlags.ExpandFill
};
- panelTabs.AddStyleboxOverride("panel", editorBaseControl.GetStylebox("DebuggerPanel", "EditorStyles"));
- panelTabs.AddStyleboxOverride("tab_fg", editorBaseControl.GetStylebox("DebuggerTabFG", "EditorStyles"));
- panelTabs.AddStyleboxOverride("tab_bg", editorBaseControl.GetStylebox("DebuggerTabBG", "EditorStyles"));
+ panelTabs.AddThemeStyleboxOverride("panel", editorBaseControl.GetThemeStylebox("DebuggerPanel", "EditorStyles"));
+ panelTabs.AddThemeStyleboxOverride("tab_fg", editorBaseControl.GetThemeStylebox("DebuggerTabFG", "EditorStyles"));
+ panelTabs.AddThemeStyleboxOverride("tab_bg", editorBaseControl.GetThemeStylebox("DebuggerTabBG", "EditorStyles"));
AddChild(panelTabs);
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs
index b2459b69ad..938c3d8be1 100644
--- a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs
@@ -46,12 +46,12 @@ namespace GodotTools
get
{
if (!BuildExited)
- return GetIcon("Stop", "EditorIcons");
+ return GetThemeIcon("Stop", "EditorIcons");
if (BuildResult == BuildResults.Error)
- return GetIcon("StatusError", "EditorIcons");
+ return GetThemeIcon("StatusError", "EditorIcons");
- return GetIcon("StatusSuccess", "EditorIcons");
+ return GetThemeIcon("StatusSuccess", "EditorIcons");
}
}
@@ -145,8 +145,8 @@ namespace GodotTools
{
issuesList.Clear();
- using (var warningIcon = GetIcon("Warning", "EditorIcons"))
- using (var errorIcon = GetIcon("Error", "EditorIcons"))
+ using (var warningIcon = GetThemeIcon("Warning", "EditorIcons"))
+ using (var errorIcon = GetThemeIcon("Error", "EditorIcons"))
{
for (int i = 0; i < issues.Count; i++)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index d782d4e61b..2ceb4888a2 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -168,13 +168,13 @@ namespace GodotTools.Export
// Add dependency assemblies
- var dependencies = new Godot.Collections.Dictionary<string, string>();
+ var assemblies = new Godot.Collections.Dictionary<string, string>();
string projectDllName = GodotSharpEditor.ProjectAssemblyName;
string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
- dependencies[projectDllName] = projectDllSrcPath;
+ assemblies[projectDllName] = projectDllSrcPath;
if (platform == OS.Platforms.Android)
{
@@ -184,15 +184,15 @@ namespace GodotTools.Export
if (!File.Exists(monoAndroidAssemblyPath))
throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath);
- dependencies["Mono.Android"] = monoAndroidAssemblyPath;
+ assemblies["Mono.Android"] = monoAndroidAssemblyPath;
}
string bclDir = DeterminePlatformBclDir(platform);
- var initialDependencies = dependencies.Duplicate();
- internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, bclDir, dependencies);
+ var initialAssemblies = assemblies.Duplicate();
+ internal_GetExportedAssemblyDependencies(initialAssemblies, buildConfig, bclDir, assemblies);
- AddI18NAssemblies(dependencies, bclDir);
+ AddI18NAssemblies(assemblies, bclDir);
string outputDataDir = null;
@@ -211,20 +211,32 @@ namespace GodotTools.Export
Directory.CreateDirectory(outputDataGameAssembliesDir);
}
- foreach (var dependency in dependencies)
+ foreach (var assembly in assemblies)
{
- string dependSrcPath = dependency.Value;
-
- if (assembliesInsidePck)
- {
- string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile());
- AddFile(dependSrcPath, dependDstPath);
- }
- else
+ void AddToAssembliesDir(string fileSrcPath)
{
- string dependDstPath = Path.Combine(outputDataDir, "Assemblies", dependSrcPath.GetFile());
- File.Copy(dependSrcPath, dependDstPath);
+ if (assembliesInsidePck)
+ {
+ string fileDstPath = Path.Combine(resAssembliesDir, fileSrcPath.GetFile());
+ AddFile(fileSrcPath, fileDstPath);
+ }
+ else
+ {
+ Debug.Assert(outputDataDir != null);
+ string fileDstPath = Path.Combine(outputDataDir, "Assemblies", fileSrcPath.GetFile());
+ File.Copy(fileSrcPath, fileDstPath);
+ }
}
+
+ string assemblySrcPath = assembly.Value;
+
+ string assemblyPathWithoutExtension = Path.ChangeExtension(assemblySrcPath, null);
+ string pdbSrcPath = assemblyPathWithoutExtension + ".pdb";
+
+ AddToAssembliesDir(assemblySrcPath);
+
+ if (File.Exists(pdbSrcPath))
+ AddToAssembliesDir(pdbSrcPath);
}
// AOT compilation
@@ -254,7 +266,7 @@ namespace GodotTools.Export
ToolchainPath = aotToolchainPath
};
- AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, dependencies);
+ AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, assemblies);
}
}
@@ -366,7 +378,7 @@ namespace GodotTools.Export
if (PlatformRequiresCustomBcl(platform))
throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}");
- platformBclDir = typeof(object).Assembly.Location; // Use the one we're running on
+ platformBclDir = typeof(object).Assembly.Location.GetBaseDir(); // Use the one we're running on
}
}
@@ -425,7 +437,7 @@ namespace GodotTools.Export
}
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialDependencies,
- string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencies);
+ private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialAssemblies,
+ string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencyAssemblies);
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index afe7670165..c070cb16d9 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -1,4 +1,5 @@
using Godot;
+using GodotTools.Core;
using GodotTools.Export;
using GodotTools.Utils;
using System;
@@ -128,7 +129,7 @@ namespace GodotTools
{
bool showOnStart = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
aboutDialogCheckBox.Pressed = showOnStart;
- aboutDialog.PopupCenteredMinsize();
+ aboutDialog.PopupCentered();
}
private void _MenuOptionPressed(int id)
@@ -166,10 +167,10 @@ namespace GodotTools
bool showInfoDialog = (bool)editorSettings.GetSetting("mono/editor/show_info_on_start");
if (showInfoDialog)
{
- aboutDialog.PopupExclusive = true;
+ aboutDialog.Exclusive = true;
_ShowAboutDialog();
// Once shown a first time, it can be seen again via the Mono menu - it doesn't have to be exclusive from that time on.
- aboutDialog.PopupExclusive = false;
+ aboutDialog.Exclusive = false;
}
var fileSystemDock = GetEditorInterface().GetFileSystemDock();
@@ -212,9 +213,9 @@ namespace GodotTools
public void ShowErrorDialog(string message, string title = "Error")
{
- errorDialog.WindowTitle = title;
+ errorDialog.Title = title;
errorDialog.DialogText = message;
- errorDialog.PopupCenteredMinsize();
+ errorDialog.PopupCentered();
}
private static string _vsCodePath = string.Empty;
@@ -383,7 +384,6 @@ namespace GodotTools
menuPopup = new PopupMenu();
menuPopup.Hide();
- menuPopup.SetAsToplevel(true);
AddToolSubmenuItem("Mono", menuPopup);
@@ -392,7 +392,7 @@ namespace GodotTools
menuPopup.AddItem("About C# support".TTR(), (int)MenuOptions.AboutCSharp);
aboutDialog = new AcceptDialog();
editorBaseControl.AddChild(aboutDialog);
- aboutDialog.WindowTitle = "Important: C# support is not feature-complete";
+ aboutDialog.Title = "Important: C# support is not feature-complete";
// We don't use DialogText as the default AcceptDialog Label doesn't play well with the TextureRect and CheckBox
// we'll add. Instead we add containers and a new autowrapped Label inside.
@@ -406,7 +406,7 @@ namespace GodotTools
aboutVBox.AddChild(aboutHBox);
var aboutIcon = new TextureRect();
- aboutIcon.Texture = aboutIcon.GetIcon("NodeWarning", "EditorIcons");
+ aboutIcon.Texture = aboutIcon.GetThemeIcon("NodeWarning", "EditorIcons");
aboutHBox.AddChild(aboutIcon);
var aboutLabel = new Label();
@@ -443,13 +443,27 @@ namespace GodotTools
{
// Migrate solution from old configuration names to: Debug, ExportDebug and ExportRelease
DotNetSolution.MigrateFromOldConfigNames(GodotSharpDirs.ProjectSlnPath);
+
+ var msbuildProject = ProjectUtils.Open(GodotSharpDirs.ProjectCsProjPath)
+ ?? throw new Exception("Cannot open C# project");
+
+ // NOTE: The order in which changes are made to the project is important
+
// Migrate csproj from old configuration names to: Debug, ExportDebug and ExportRelease
- ProjectUtils.MigrateFromOldConfigNames(GodotSharpDirs.ProjectCsProjPath);
+ ProjectUtils.MigrateFromOldConfigNames(msbuildProject);
- // Apply the other fixes after configurations are migrated
+ // Apply the other fixes only after configurations have been migrated
// Make sure the existing project has Api assembly references configured correctly
- ProjectUtils.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath);
+ ProjectUtils.FixApiHintPath(msbuildProject);
+
+ if (msbuildProject.HasUnsavedChanges)
+ {
+ // Save a copy of the project before replacing it
+ FileUtils.SaveBackupCopy(GodotSharpDirs.ProjectCsProjPath);
+
+ msbuildProject.Save();
+ }
}
catch (Exception e)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index ac9379adf8..e1570d6465 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -8,16 +8,21 @@
<RootNamespace>GodotTools</RootNamespace>
<AssemblyName>GodotTools</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
- <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
- <DataDirToolsOutputPath>$(GodotSourceRootPath)/bin/GodotSharp/Tools</DataDirToolsOutputPath>
- <GodotApiConfiguration>Debug</GodotApiConfiguration>
<LangVersion>7</LangVersion>
+ <GodotApiConfiguration>Debug</GodotApiConfiguration> <!-- The Godot editor uses the Debug Godot API assemblies -->
+ <GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
+ <GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
+ <GodotApiAssembliesDir>$(GodotOutputDataDir)/Api/$(GodotApiConfiguration)</GodotApiAssembliesDir>
+ </PropertyGroup>
+ <PropertyGroup Condition=" Exists('$(GodotApiAssembliesDir)/GodotSharp.dll') ">
+ <!-- The project is part of the Godot source tree -->
+ <!-- Use the Godot source tree output folder instead of '$(ProjectDir)/bin' -->
+ <OutputPath>$(GodotOutputDataDir)/Tools</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
- <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -25,7 +30,6 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
@@ -41,11 +45,11 @@
</Reference>
<Reference Include="System" />
<Reference Include="GodotSharp">
- <HintPath>$(GodotSourceRootPath)/bin/GodotSharp/Api/$(GodotApiConfiguration)/GodotSharp.dll</HintPath>
+ <HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="GodotSharpEditor">
- <HintPath>$(GodotSourceRootPath)/bin/GodotSharp/Api/$(GodotApiConfiguration)/GodotSharpEditor.dll</HintPath>
+ <HintPath>$(GodotApiAssembliesDir)/GodotSharpEditor.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
@@ -103,21 +107,5 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
- <Target Name="CopyToDataDir" AfterTargets="Build">
- <ItemGroup>
- <GodotToolsCopy Include="$(OutputPath)\GodotTools*.dll" />
- <GodotToolsCopy Include="$(OutputPath)\Newtonsoft.Json.dll" />
- <GodotToolsCopy Include="$(OutputPath)\DotNet.Glob.dll" />
- </ItemGroup>
- <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
- <GodotToolsCopy Include="$(OutputPath)\GodotTools*.pdb" />
- </ItemGroup>
- <Copy SourceFiles="@(GodotToolsCopy)" DestinationFolder="$(DataDirToolsOutputPath)" ContinueOnError="false" />
- </Target>
- <Target Name="BuildAlwaysCopyToDataDir">
- <!-- Custom target run by SCons to make sure the CopyToDataDir target is always executed, without having to use DisableFastUpToDateCheck -->
- <CallTarget Targets="Build" />
- <CallTarget Targets="CopyToDataDir" />
- </Target>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
diff --git a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
index 1d19fab706..ae05710f4f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
@@ -10,7 +10,7 @@ namespace GodotTools
public override void _Notification(int what)
{
- if (what == MainLoop.NotificationWmFocusIn)
+ if (what == Node.NotificationWmFocusIn)
{
RestartTimer();
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 6cd10a94f9..bdf9cf965f 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -566,8 +566,12 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
code_tag = true;
pos = brk_end + 1;
tag_stack.push_front(tag);
+ } else if (tag == "kbd") {
+ // keyboard combinations are not supported in xml comments
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
} else if (tag == "center") {
- // center is alignment not supported in xml comments
+ // center alignment is not supported in xml comments
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "br") {
@@ -1406,7 +1410,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
const TypeInterface *current_type = &p_itype;
while (!setter && current_type->base_name != StringName()) {
OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name);
- ERR_FAIL_COND_V(!base_match, ERR_BUG);
+ ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'.");
current_type = &base_match.get();
setter = current_type->find_method_by_name(p_iprop.setter);
}
@@ -1417,7 +1421,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
current_type = &p_itype;
while (!getter && current_type->base_name != StringName()) {
OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name);
- ERR_FAIL_COND_V(!base_match, ERR_BUG);
+ ERR_FAIL_COND_V_MSG(!base_match, ERR_BUG, "Type not found '" + current_type->base_name + "'. Inherited by '" + current_type->name + "'.");
current_type = &base_match.get();
getter = current_type->find_method_by_name(p_iprop.getter);
}
@@ -1631,7 +1635,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method
{
if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
- p_output.append(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static IntPtr ");
+ p_output.append(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static readonly IntPtr ");
p_output.append(method_bind_field);
p_output.append(" = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
p_output.append(p_imethod.name);
@@ -2187,7 +2191,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
}
p_output.append(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
- p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
+ p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "nullptr");
p_output.append(", total_length, vcall_error);\n");
if (!ret_void) {
@@ -2383,7 +2387,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
const PropertyInfo &property = E->get();
- if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_CATEGORY)
+ if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY)
continue;
PropertyInterface iprop;
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index 283d4beb8e..c3e7e67ae9 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -231,14 +231,14 @@ int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObje
return err;
}
-uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_dependencies,
- MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_dependencies) {
- Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_dependencies);
+uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
+ MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) {
+ Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies);
String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config);
String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir);
- Dictionary dependencies = GDMonoMarshal::mono_object_to_variant(r_dependencies);
+ Dictionary assembly_dependencies = GDMonoMarshal::mono_object_to_variant(r_assembly_dependencies);
- return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, dependencies);
+ return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, assembly_dependencies);
}
MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) {
diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp
index 324013e5e2..4126da16be 100644
--- a/modules/mono/editor/godotsharp_export.cpp
+++ b/modules/mono/editor/godotsharp_export.cpp
@@ -50,13 +50,13 @@ String get_assemblyref_name(MonoImage *p_image, int index) {
return String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME]));
}
-Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies) {
+Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_assembly_dependencies) {
MonoImage *image = p_assembly->get_image();
for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) {
String ref_name = get_assemblyref_name(image, i);
- if (r_dependencies.has(ref_name))
+ if (r_assembly_dependencies.has(ref_name))
continue;
GDMonoAssembly *ref_assembly = nullptr;
@@ -93,17 +93,17 @@ Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String>
ERR_FAIL_COND_V_MSG(!ref_assembly, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
// Use the path we got from the search. Don't try to get the path from the loaded assembly as we can't trust it will be from the selected BCL dir.
- r_dependencies[ref_name] = path;
+ r_assembly_dependencies[ref_name] = path;
- Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies);
+ Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_assembly_dependencies);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'.");
}
return OK;
}
-Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
- const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_dependencies) {
+Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
+ const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_assembly_dependencies) {
MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport");
ERR_FAIL_NULL_V(export_domain, FAILED);
_GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain);
@@ -113,16 +113,16 @@ Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencie
Vector<String> search_dirs;
GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir);
- for (const Variant *key = p_initial_dependencies.next(); key; key = p_initial_dependencies.next(key)) {
+ for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) {
String assembly_name = *key;
- String assembly_path = p_initial_dependencies[*key];
+ String assembly_path = p_initial_assemblies[*key];
GDMonoAssembly *assembly = nullptr;
bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true);
ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'.");
- Error err = get_assembly_dependencies(assembly, search_dirs, r_dependencies);
+ Error err = get_assembly_dependencies(assembly, search_dirs, r_assembly_dependencies);
if (err != OK)
return err;
}
diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h
index 36138f81b7..9ab57755de 100644
--- a/modules/mono/editor/godotsharp_export.h
+++ b/modules/mono/editor/godotsharp_export.h
@@ -41,8 +41,8 @@ namespace GodotSharpExport {
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies);
-Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
- const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_dependencies);
+Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
+ const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_assembly_dependencies);
} // namespace GodotSharpExport
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index aba1065498..a963810d63 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -15,10 +15,7 @@ namespace Godot.Collections
public override bool IsInvalid
{
- get
- {
- return handle == IntPtr.Zero;
- }
+ get { return handle == IntPtr.Zero; }
}
protected override bool ReleaseHandle()
@@ -43,7 +40,8 @@ namespace Godot.Collections
if (collection == null)
throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
- MarshalUtils.EnumerableToArray(collection, GetPtr());
+ foreach (object element in collection)
+ Add(element);
}
internal Array(ArraySafeHandle handle)
@@ -272,14 +270,8 @@ namespace Godot.Collections
public T this[int index]
{
- get
- {
- return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass);
- }
- set
- {
- objectArray[index] = value;
- }
+ get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); }
+ set { objectArray[index] = value; }
}
public int IndexOf(T item)
@@ -301,18 +293,12 @@ namespace Godot.Collections
public int Count
{
- get
- {
- return objectArray.Count;
- }
+ get { return objectArray.Count; }
}
public bool IsReadOnly
{
- get
- {
- return objectArray.IsReadOnly;
- }
+ get { return objectArray.IsReadOnly; }
}
public void Add(T item)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
index 1d1a49945f..6030b72a44 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
@@ -306,16 +306,26 @@ namespace Godot
return res;
}
- public Color LinearInterpolate(Color c, float t)
- {
- var res = this;
-
- res.r += t * (c.r - r);
- res.g += t * (c.g - g);
- res.b += t * (c.b - b);
- res.a += t * (c.a - a);
+ public Color Lerp(Color to, float weight)
+ {
+ return new Color
+ (
+ Mathf.Lerp(r, to.r, weight),
+ Mathf.Lerp(g, to.g, weight),
+ Mathf.Lerp(b, to.b, weight),
+ Mathf.Lerp(a, to.a, weight)
+ );
+ }
- return res;
+ public Color Lerp(Color to, Color weight)
+ {
+ return new Color
+ (
+ Mathf.Lerp(r, to.r, weight.r),
+ Mathf.Lerp(g, to.g, weight.g),
+ Mathf.Lerp(b, to.b, weight.b),
+ Mathf.Lerp(a, to.a, weight.a)
+ );
}
public uint ToAbgr32()
@@ -410,7 +420,7 @@ namespace Godot
return txt;
}
- // Constructors
+ // Constructors
public Color(float r, float g, float b, float a = 1.0f)
{
this.r = r;
@@ -419,6 +429,14 @@ namespace Godot
this.a = a;
}
+ public Color(Color c, float a = 1.0f)
+ {
+ r = c.r;
+ g = c.g;
+ b = c.b;
+ this.a = a;
+ }
+
public Color(uint rgba)
{
a = (rgba & 0xFF) / 255.0f;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
index d72109de92..213fc181c1 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs
@@ -15,10 +15,7 @@ namespace Godot.Collections
public override bool IsInvalid
{
- get
- {
- return handle == IntPtr.Zero;
- }
+ get { return handle == IntPtr.Zero; }
}
protected override bool ReleaseHandle()
@@ -45,7 +42,8 @@ namespace Godot.Collections
if (dictionary == null)
throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
- MarshalUtils.IDictionaryToDictionary(dictionary, GetPtr());
+ foreach (DictionaryEntry entry in dictionary)
+ Add(entry.Key, entry.Value);
}
internal Dictionary(DictionarySafeHandle handle)
@@ -330,14 +328,8 @@ namespace Godot.Collections
public TValue this[TKey key]
{
- get
- {
- return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass);
- }
- set
- {
- objectDict[key] = value;
- }
+ get { return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); }
+ set { objectDict[key] = value; }
}
public ICollection<TKey> Keys
@@ -385,18 +377,12 @@ namespace Godot.Collections
public int Count
{
- get
- {
- return objectDict.Count;
- }
+ get { return objectDict.Count; }
}
public bool IsReadOnly
{
- get
- {
- return objectDict.IsReadOnly;
- }
+ get { return objectDict.IsReadOnly; }
}
public void Add(KeyValuePair<TKey, TValue> item)
@@ -440,7 +426,8 @@ namespace Godot.Collections
public bool Remove(KeyValuePair<TKey, TValue> item)
{
- return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value); ;
+ return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
+ ;
}
// IEnumerable<KeyValuePair<TKey, TValue>>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
index a1d63a62ef..c59d083080 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
@@ -16,10 +16,8 @@ namespace Godot
/// <exception cref="System.InvalidOperationException">
/// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
/// </exception>
- static bool TypeIsGenericArray(Type type)
- {
- return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>);
- }
+ static bool TypeIsGenericArray(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>);
/// <summary>
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
@@ -28,10 +26,20 @@ namespace Godot
/// <exception cref="System.InvalidOperationException">
/// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
/// </exception>
- static bool TypeIsGenericDictionary(Type type)
- {
- return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
- }
+ static bool TypeIsGenericDictionary(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
+
+ static bool TypeIsSystemGenericList(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>);
+
+ static bool TypeIsSystemGenericDictionary(Type type) =>
+ type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.Dictionary<,>);
+
+ static bool TypeIsGenericIEnumerable(Type type) => type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
+
+ static bool TypeIsGenericICollection(Type type) => type.GetGenericTypeDefinition() == typeof(ICollection<>);
+
+ static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>);
static void ArrayGetElementType(Type arrayType, out Type elementType)
{
@@ -45,105 +53,6 @@ namespace Godot
valueType = genericArgs[1];
}
- static bool GenericIEnumerableIsAssignableFromType(Type type)
- {
- if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
- return true;
-
- foreach (var interfaceType in type.GetInterfaces())
- {
- if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
- return true;
- }
-
- Type baseType = type.BaseType;
-
- if (baseType == null)
- return false;
-
- return GenericIEnumerableIsAssignableFromType(baseType);
- }
-
- static bool GenericIDictionaryIsAssignableFromType(Type type)
- {
- if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>))
- return true;
-
- foreach (var interfaceType in type.GetInterfaces())
- {
- if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
- return true;
- }
-
- Type baseType = type.BaseType;
-
- if (baseType == null)
- return false;
-
- return GenericIDictionaryIsAssignableFromType(baseType);
- }
-
- static bool GenericIEnumerableIsAssignableFromType(Type type, out Type elementType)
- {
- if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
- {
- elementType = type.GetGenericArguments()[0];
- return true;
- }
-
- foreach (var interfaceType in type.GetInterfaces())
- {
- if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
- {
- elementType = interfaceType.GetGenericArguments()[0];
- return true;
- }
- }
-
- Type baseType = type.BaseType;
-
- if (baseType == null)
- {
- elementType = null;
- return false;
- }
-
- return GenericIEnumerableIsAssignableFromType(baseType, out elementType);
- }
-
- static bool GenericIDictionaryIsAssignableFromType(Type type, out Type keyType, out Type valueType)
- {
- if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>))
- {
- var genericArgs = type.GetGenericArguments();
- keyType = genericArgs[0];
- valueType = genericArgs[1];
- return true;
- }
-
- foreach (var interfaceType in type.GetInterfaces())
- {
- if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
- {
- var genericArgs = interfaceType.GetGenericArguments();
- keyType = genericArgs[0];
- valueType = genericArgs[1];
- return true;
- }
- }
-
- Type baseType = type.BaseType;
-
- if (baseType == null)
- {
- keyType = null;
- valueType = null;
- return false;
- }
-
- return GenericIDictionaryIsAssignableFromType(baseType, out keyType, out valueType);
- }
-
static Type MakeGenericArrayType(Type elemType)
{
return typeof(Godot.Collections.Array<>).MakeGenericType(elemType);
@@ -153,60 +62,5 @@ namespace Godot
{
return typeof(Godot.Collections.Dictionary<,>).MakeGenericType(keyType, valueType);
}
-
- // TODO Add support for IEnumerable<T> and IDictionary<TKey, TValue>
- // TODO: EnumerableToArray and IDictionaryToDictionary can be optimized
-
- internal static void EnumerableToArray(IEnumerable enumerable, IntPtr godotArrayPtr)
- {
- if (enumerable is ICollection collection)
- {
- int count = collection.Count;
-
- object[] tempArray = new object[count];
- collection.CopyTo(tempArray, 0);
-
- for (int i = 0; i < count; i++)
- {
- Array.godot_icall_Array_Add(godotArrayPtr, tempArray[i]);
- }
- }
- else
- {
- foreach (object element in enumerable)
- {
- Array.godot_icall_Array_Add(godotArrayPtr, element);
- }
- }
- }
-
- internal static void IDictionaryToDictionary(IDictionary dictionary, IntPtr godotDictionaryPtr)
- {
- foreach (DictionaryEntry entry in dictionary)
- {
- Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value);
- }
- }
-
- internal static void GenericIDictionaryToDictionary(object dictionary, IntPtr godotDictionaryPtr)
- {
-#if DEBUG
- if (!GenericIDictionaryIsAssignableFromType(dictionary.GetType()))
- throw new InvalidOperationException("The type does not implement IDictionary<,>");
-#endif
-
- // TODO: Can we optimize this?
-
- var keys = ((IEnumerable)dictionary.GetType().GetProperty("Keys").GetValue(dictionary)).GetEnumerator();
- var values = ((IEnumerable)dictionary.GetType().GetProperty("Values").GetValue(dictionary)).GetEnumerator();
-
- while (keys.MoveNext() && values.MoveNext())
- {
- object key = keys.Current;
- object value = values.Current;
-
- Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, key, value);
- }
- }
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index 91e614dc7b..1098ffe4e5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -127,7 +127,7 @@ namespace Godot
{
var g = this;
- g.GrowIndividual(Margin.Left == margin ? by : 0,
+ g = g.GrowIndividual(Margin.Left == margin ? by : 0,
Margin.Top == margin ? by : 0,
Margin.Right == margin ? by : 0,
Margin.Bottom == margin ? by : 0);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
index bc2cad8713..c0b236c524 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs
@@ -122,7 +122,7 @@ namespace Godot
{
var g = this;
- g.GrowIndividual(Margin.Left == margin ? by : 0,
+ g = g.GrowIndividual(Margin.Left == margin ? by : 0,
Margin.Top == margin ? by : 0,
Margin.Right == margin ? by : 0,
Margin.Bottom == margin ? by : 0);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index 099eacd7dd..41b4e9367f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -12,7 +12,7 @@ namespace Godot
{
private static int GetSliceCount(this string instance, string splitter)
{
- if (instance.Empty() || splitter.Empty())
+ if (string.IsNullOrEmpty(instance) || string.IsNullOrEmpty(splitter))
return 0;
int pos = 0;
@@ -29,7 +29,7 @@ namespace Godot
private static string GetSliceCharacter(this string instance, char splitter, int slice)
{
- if (!instance.Empty() && slice >= 0)
+ if (!string.IsNullOrEmpty(instance) && slice >= 0)
{
int i = 0;
int prev = 0;
@@ -237,10 +237,10 @@ namespace Godot
// </summary>
public static int CompareTo(this string instance, string to, bool caseSensitive = true)
{
- if (instance.Empty())
- return to.Empty() ? 0 : -1;
+ if (string.IsNullOrEmpty(instance))
+ return string.IsNullOrEmpty(to) ? 0 : -1;
- if (to.Empty())
+ if (string.IsNullOrEmpty(to))
return 1;
int instanceIndex = 0;
@@ -287,14 +287,6 @@ namespace Godot
}
// <summary>
- // Return true if the string is empty.
- // </summary>
- public static bool Empty(this string instance)
- {
- return string.IsNullOrEmpty(instance);
- }
-
- // <summary>
// Return true if the strings ends with the given string.
// </summary>
public static bool EndsWith(this string instance, string text)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs
index aa8815d1aa..6a58b90561 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform.cs
@@ -104,8 +104,8 @@ namespace Godot
Vector3 destinationLocation = transform.origin;
var interpolated = new Transform();
- interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.LinearInterpolate(destinationScale, c));
- interpolated.origin = sourceLocation.LinearInterpolate(destinationLocation, c);
+ interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.Lerp(destinationScale, c));
+ interpolated.origin = sourceLocation.Lerp(destinationLocation, c);
return interpolated;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index e72a44809a..3ae96d4922 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -172,7 +172,7 @@ namespace Godot
if (dot > 0.9995f)
{
// Linearly interpolate to avoid numerical precision issues
- v = v1.LinearInterpolate(v2, c).Normalized();
+ v = v1.Lerp(v2, c).Normalized();
}
else
{
@@ -186,8 +186,8 @@ namespace Godot
Vector2 p2 = m.origin;
// Construct matrix
- var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.LinearInterpolate(p2, c));
- Vector2 scale = s1.LinearInterpolate(s2, c);
+ var res = new Transform2D(Mathf.Atan2(v.y, v.x), p1.Lerp(p2, c));
+ Vector2 scale = s1.Lerp(s2, c);
res.x *= scale;
res.y *= scale;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index f7b13198f8..7e4804f9fd 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -186,14 +186,22 @@ namespace Godot
return x * x + y * y;
}
- public Vector2 LinearInterpolate(Vector2 b, real_t t)
+ public Vector2 Lerp(Vector2 to, real_t weight)
{
- var res = this;
-
- res.x += t * (b.x - x);
- res.y += t * (b.y - y);
+ return new Vector2
+ (
+ Mathf.Lerp(x, to.x, weight),
+ Mathf.Lerp(y, to.y, weight)
+ );
+ }
- return res;
+ public Vector2 Lerp(Vector2 to, Vector2 weight)
+ {
+ return new Vector2
+ (
+ Mathf.Lerp(x, to.x, weight.x),
+ Mathf.Lerp(y, to.y, weight.y)
+ );
}
public Vector2 MoveToward(Vector2 to, real_t delta)
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index a43836e985..b26e17ecba 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -184,13 +184,23 @@ namespace Godot
return x2 + y2 + z2;
}
- public Vector3 LinearInterpolate(Vector3 b, real_t t)
+ public Vector3 Lerp(Vector3 to, real_t weight)
{
return new Vector3
(
- x + t * (b.x - x),
- y + t * (b.y - y),
- z + t * (b.z - z)
+ Mathf.Lerp(x, to.x, weight),
+ Mathf.Lerp(y, to.y, weight),
+ Mathf.Lerp(z, to.z, weight)
+ );
+ }
+
+ public Vector3 Lerp(Vector3 to, Vector3 weight)
+ {
+ return new Vector3
+ (
+ Mathf.Lerp(x, to.x, weight.x),
+ Mathf.Lerp(y, to.y, weight.y),
+ Mathf.Lerp(z, to.z, weight.z)
);
}
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index fe8b925257..d596163926 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -40,7 +40,7 @@
#endif
#ifdef ANDROID_ENABLED
-#include "mono_gd/support/mono-support.h"
+#include "mono_gd/support/android_support.h"
#endif
#include "mono_gd/gd_mono.h"
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 306a1997ab..3298c5da4c 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -129,12 +129,8 @@ void gd_mono_profiler_init() {
}
}
-#if defined(DEBUG_ENABLED)
-
void gd_mono_debug_init() {
- mono_debug_init(MONO_DEBUG_FORMAT_MONO);
-
CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
#ifdef TOOLS_ENABLED
@@ -159,6 +155,10 @@ void gd_mono_debug_init() {
return; // Exported games don't use the project settings to setup the debugger agent
#endif
+ // Debugging enabled
+
+ mono_debug_init(MONO_DEBUG_FORMAT_MONO);
+
// --debugger-agent=help
const char *options[] = {
"--soft-breakpoints",
@@ -167,7 +167,6 @@ void gd_mono_debug_init() {
mono_jit_parse_options(2, (char **)options);
}
-#endif // defined(DEBUG_ENABLED)
#endif // !defined(JAVASCRIPT_ENABLED)
#if defined(JAVASCRIPT_ENABLED)
@@ -175,6 +174,7 @@ MonoDomain *gd_initialize_mono_runtime() {
const char *vfs_prefix = "managed";
int enable_debugging = 0;
+ // TODO: Provide a way to enable debugging on WASM release builds.
#ifdef DEBUG_ENABLED
enable_debugging = 1;
#endif
@@ -185,9 +185,7 @@ MonoDomain *gd_initialize_mono_runtime() {
}
#else
MonoDomain *gd_initialize_mono_runtime() {
-#ifdef DEBUG_ENABLED
gd_mono_debug_init();
-#endif
#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED)
// I don't know whether this actually matters or not
@@ -1389,7 +1387,10 @@ bool _GodotSharp::is_runtime_initialized() {
void _GodotSharp::_reload_assemblies(bool p_soft_reload) {
#ifdef GD_MONO_HOT_RELOAD
- CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload);
+ // This method may be called more than once with `call_deferred`, so we need to check
+ // again if reloading is needed to avoid reloading multiple times unnecessarily.
+ if (CSharpLanguage::get_singleton()->is_assembly_reloading_needed())
+ CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload);
#endif
}
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 8439769d84..0f211eebc6 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -277,12 +277,25 @@ no_pdb:
#endif
+ bool need_manual_load_hook = mono_image_get_assembly(image) != nullptr; // Re-using an existing image with an assembly loaded
+
status = MONO_IMAGE_OK;
MonoAssembly *assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, p_refonly);
ERR_FAIL_COND_V_MSG(status != MONO_IMAGE_OK || !assembly, nullptr, "Failed to load assembly for image");
+ if (need_manual_load_hook) {
+ // For some reason if an assembly survived domain reloading (maybe because it's referenced somewhere else),
+ // the mono internal search hook don't detect it, yet mono_image_open_from_data_with_name re-uses the image
+ // and assembly, and mono_assembly_load_from_full doesn't call the load hook. We need to call it manually.
+ String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly)));
+ bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");
+ GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name);
+ if (!loaded_asm)
+ assembly_load_hook(assembly, nullptr);
+ }
+
// Decrement refcount which was previously incremented by mono_image_open_from_data_with_name
mono_image_close(image);
diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp
index 40cc41122b..5ddf18d544 100644
--- a/modules/mono/mono_gd/gd_mono_cache.cpp
+++ b/modules/mono/mono_gd/gd_mono_cache.cpp
@@ -84,6 +84,7 @@ void CachedData::clear_corlib_cache() {
class_IntPtr = nullptr;
class_System_Collections_IEnumerable = nullptr;
+ class_System_Collections_ICollection = nullptr;
class_System_Collections_IDictionary = nullptr;
#ifdef DEBUG_ENABLED
@@ -171,22 +172,18 @@ void CachedData::clear_godot_api_cache() {
methodthunk_MarshalUtils_TypeIsGenericArray.nullify();
methodthunk_MarshalUtils_TypeIsGenericDictionary.nullify();
+ methodthunk_MarshalUtils_TypeIsSystemGenericList.nullify();
+ methodthunk_MarshalUtils_TypeIsSystemGenericDictionary.nullify();
+ methodthunk_MarshalUtils_TypeIsGenericIEnumerable.nullify();
+ methodthunk_MarshalUtils_TypeIsGenericICollection.nullify();
+ methodthunk_MarshalUtils_TypeIsGenericIDictionary.nullify();
methodthunk_MarshalUtils_ArrayGetElementType.nullify();
methodthunk_MarshalUtils_DictionaryGetKeyValueTypes.nullify();
- methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType.nullify();
- methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType.nullify();
- methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info.nullify();
- methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info.nullify();
-
methodthunk_MarshalUtils_MakeGenericArrayType.nullify();
methodthunk_MarshalUtils_MakeGenericDictionaryType.nullify();
- methodthunk_MarshalUtils_EnumerableToArray.nullify();
- methodthunk_MarshalUtils_IDictionaryToDictionary.nullify();
- methodthunk_MarshalUtils_GenericIDictionaryToDictionary.nullify();
-
// End of MarshalUtils methods
task_scheduler_handle = Ref<MonoGCHandleRef>();
@@ -213,6 +210,7 @@ void update_corlib_cache() {
CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
CACHE_CLASS_AND_CHECK(System_Collections_IEnumerable, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IEnumerable"));
+ CACHE_CLASS_AND_CHECK(System_Collections_ICollection, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "ICollection"));
CACHE_CLASS_AND_CHECK(System_Collections_IDictionary, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IDictionary"));
#ifdef DEBUG_ENABLED
@@ -251,7 +249,7 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(GodotResource, GODOT_API_CLASS(Resource));
CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
- CACHE_CLASS_AND_CHECK(Node3D, GODOT_API_CLASS(Node3Dshou));
+ CACHE_CLASS_AND_CHECK(Node3D, GODOT_API_CLASS(Node3D));
CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
CACHE_CLASS_AND_CHECK(Callable, GODOT_API_CLASS(Callable));
CACHE_CLASS_AND_CHECK(SignalInfo, GODOT_API_CLASS(SignalInfo));
@@ -297,22 +295,18 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericArray", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericDictionary", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsSystemGenericList, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsSystemGenericList", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsSystemGenericDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsSystemGenericDictionary", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIEnumerable, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIEnumerable", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericICollection, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericICollection", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIDictionary", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, GODOT_API_CLASS(MarshalUtils)->get_method("ArrayGetElementType", 2));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, GODOT_API_CLASS(MarshalUtils)->get_method("DictionaryGetKeyValueTypes", 3));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIEnumerableIsAssignableFromType", 1));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIDictionaryIsAssignableFromType", 1));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIEnumerableIsAssignableFromType", 2));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIDictionaryIsAssignableFromType", 3));
-
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, GODOT_API_CLASS(MarshalUtils)->get_method("MakeGenericArrayType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, GODOT_API_CLASS(MarshalUtils)->get_method("MakeGenericDictionaryType", 2));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, EnumerableToArray, GODOT_API_CLASS(MarshalUtils)->get_method("EnumerableToArray", 2));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IDictionaryToDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("IDictionaryToDictionary", 2));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryToDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("GenericIDictionaryToDictionary", 2));
-
// End of MarshalUtils methods
#ifdef DEBUG_ENABLED
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 21c8ed4efe..3cf2bd6ce5 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -58,6 +58,7 @@ struct CachedData {
GDMonoClass *class_IntPtr; // System.IntPtr
GDMonoClass *class_System_Collections_IEnumerable;
+ GDMonoClass *class_System_Collections_ICollection;
GDMonoClass *class_System_Collections_IDictionary;
#ifdef DEBUG_ENABLED
@@ -141,22 +142,18 @@ struct CachedData {
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericArray;
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericDictionary;
+ GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsSystemGenericList;
+ GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsSystemGenericDictionary;
+ GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIEnumerable;
+ GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericICollection;
+ GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIDictionary;
GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **> methodthunk_MarshalUtils_ArrayGetElementType;
GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **, MonoReflectionType **> methodthunk_MarshalUtils_DictionaryGetKeyValueTypes;
- GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType;
- GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType;
- GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *, MonoReflectionType **> methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info;
- GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *, MonoReflectionType **, MonoReflectionType **> methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info;
-
GDMonoMethodThunkR<MonoReflectionType *, MonoReflectionType *> methodthunk_MarshalUtils_MakeGenericArrayType;
GDMonoMethodThunkR<MonoReflectionType *, MonoReflectionType *, MonoReflectionType *> methodthunk_MarshalUtils_MakeGenericDictionaryType;
- GDMonoMethodThunk<MonoObject *, Array *> methodthunk_MarshalUtils_EnumerableToArray;
- GDMonoMethodThunk<MonoObject *, Dictionary *> methodthunk_MarshalUtils_IDictionaryToDictionary;
- GDMonoMethodThunk<MonoObject *, Dictionary *> methodthunk_MarshalUtils_GenericIDictionaryToDictionary;
-
// End of MarshalUtils methods
Ref<MonoGCHandleRef> task_scheduler_handle;
@@ -186,14 +183,6 @@ inline void clear_godot_api_cache() {
cached_data.clear_godot_api_cache();
}
-_FORCE_INLINE_ bool tools_godot_api_check() {
-#ifdef TOOLS_ENABLED
- return cached_data.godot_api_cache_updated;
-#else
- return true; // Assume it's updated if this was called, otherwise it's a bug
-#endif
-}
-
} // namespace GDMonoCache
#define CACHED_CLASS(m_class) (GDMonoCache::cached_data.class_##m_class)
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index ede4203e35..9dabb4ec4c 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -31,6 +31,7 @@
#include "gd_mono_class.h"
#include <mono/metadata/attrdefs.h>
+#include <mono/metadata/debug-helpers.h>
#include "gd_mono_assembly.h"
#include "gd_mono_cache.h"
@@ -55,7 +56,11 @@ String GDMonoClass::get_full_name() const {
return get_full_name(mono_class);
}
-MonoType *GDMonoClass::get_mono_type() {
+String GDMonoClass::get_type_desc() const {
+ return GDMonoUtils::get_type_desc(get_mono_type());
+}
+
+MonoType *GDMonoClass::get_mono_type() const {
// Careful, you cannot compare two MonoType*.
// There is mono_metadata_type_equal, how is this different from comparing two MonoClass*?
return get_mono_type(mono_class);
@@ -74,12 +79,26 @@ bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
return mono_class_is_assignable_from(mono_class, p_from->mono_class);
}
-GDMonoClass *GDMonoClass::get_parent_class() {
+StringName GDMonoClass::get_namespace() const {
+ GDMonoClass *nesting_class = get_nesting_class();
+ if (!nesting_class)
+ return namespace_name;
+ return nesting_class->get_namespace();
+}
+
+String GDMonoClass::get_name_for_lookup() const {
+ GDMonoClass *nesting_class = get_nesting_class();
+ if (!nesting_class)
+ return class_name;
+ return nesting_class->get_name_for_lookup() + "/" + class_name;
+}
+
+GDMonoClass *GDMonoClass::get_parent_class() const {
MonoClass *parent_mono_class = mono_class_get_parent(mono_class);
return parent_mono_class ? GDMono::get_singleton()->get_class(parent_mono_class) : nullptr;
}
-GDMonoClass *GDMonoClass::get_nesting_class() {
+GDMonoClass *GDMonoClass::get_nesting_class() const {
MonoClass *nesting_type = mono_class_get_nesting_type(mono_class);
return nesting_type ? GDMono::get_singleton()->get_class(nesting_type) : nullptr;
}
@@ -264,6 +283,12 @@ bool GDMonoClass::implements_interface(GDMonoClass *p_interface) {
return mono_class_implements_interface(mono_class, p_interface->get_mono_ptr());
}
+bool GDMonoClass::has_public_parameterless_ctor() {
+
+ GDMonoMethod *ctor = get_method(".ctor", 0);
+ return ctor && ctor->get_visibility() == IMonoClassMember::PUBLIC;
+}
+
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) {
MethodKey key = MethodKey(p_name, p_params_count);
@@ -328,6 +353,9 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo
MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class);
mono_method_desc_free(desc);
+ if (!method)
+ return nullptr;
+
ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, nullptr);
return get_method(method);
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index 0c9a8cdafe..44b146b87c 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -31,8 +31,6 @@
#ifndef GD_MONO_CLASS_H
#define GD_MONO_CLASS_H
-#include <mono/metadata/debug-helpers.h>
-
#include "core/map.h"
#include "core/ustring.h"
@@ -107,21 +105,23 @@ public:
static MonoType *get_mono_type(MonoClass *p_mono_class);
String get_full_name() const;
- MonoType *get_mono_type();
+ String get_type_desc() const;
+ MonoType *get_mono_type() const;
uint32_t get_flags() const;
bool is_static() const;
bool is_assignable_from(GDMonoClass *p_from) const;
- _FORCE_INLINE_ StringName get_namespace() const { return namespace_name; }
+ StringName get_namespace() const;
_FORCE_INLINE_ StringName get_name() const { return class_name; }
+ String get_name_for_lookup() const;
_FORCE_INLINE_ MonoClass *get_mono_ptr() const { return mono_class; }
_FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; }
- GDMonoClass *get_parent_class();
- GDMonoClass *get_nesting_class();
+ GDMonoClass *get_parent_class() const;
+ GDMonoClass *get_nesting_class() const;
#ifdef TOOLS_ENABLED
Vector<MonoClassField *> get_enum_fields();
@@ -137,6 +137,7 @@ public:
void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base);
bool implements_interface(GDMonoClass *p_interface);
+ bool has_public_parameterless_ctor();
GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0);
GDMonoMethod *get_method(MonoMethod *p_raw_method);
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 3f4e5fe5ac..e76cb84d43 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -322,6 +322,13 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
+ GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) {
+ MonoArray *managed = GDMonoMarshal::Array_to_mono_array(p_value.operator ::Array(), array_type_class);
+ mono_field_set_value(p_object, mono_field, managed);
+ break;
+ }
+
ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type.");
} break;
@@ -353,56 +360,22 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
- if (CACHED_CLASS(Dictionary) == type_class) {
+ // Godot.Collections.Dictionary or IDictionary
+ if (CACHED_CLASS(Dictionary) == type_class || type_class == CACHED_CLASS(System_Collections_IDictionary)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
mono_field_set_value(p_object, mono_field, managed);
break;
}
- if (CACHED_CLASS(Array) == type_class) {
+ // Godot.Collections.Array or ICollection or IEnumerable
+ if (CACHED_CLASS(Array) == type_class ||
+ type_class == CACHED_CLASS(System_Collections_ICollection) ||
+ type_class == CACHED_CLASS(System_Collections_IEnumerable)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
mono_field_set_value(p_object, mono_field, managed);
break;
}
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type());
-
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(),
- GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype));
- mono_field_set_value(p_object, mono_field, managed);
- break;
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
- mono_field_set_value(p_object, mono_field, managed);
- break;
- }
-
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(),
- GDMonoUtils::Marshal::make_generic_array_type(elem_reftype));
- mono_field_set_value(p_object, mono_field, managed);
- break;
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
- if (GDMonoCache::tools_godot_api_check()) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
- mono_field_set_value(p_object, mono_field, managed);
- break;
- } else {
- MonoObject *managed = (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_value.operator Array());
- mono_field_set_value(p_object, mono_field, managed);
- break;
- }
- }
-
ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + type_class->get_name() + "'.");
} break;
@@ -535,52 +508,62 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
case MONO_TYPE_GENERICINST: {
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type.type_class->get_mono_type());
+ // Godot.Collections.Dictionary<TKey, TValue>
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), type.type_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
+ // Godot.Collections.Array<T>
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), type.type_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(),
- GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype));
+ // System.Collections.Generic.Dictionary<TKey, TValue>
+ if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) {
+ MonoReflectionType *key_reftype = nullptr;
+ MonoReflectionType *value_reftype = nullptr;
+ GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
+ MonoObject *managed = GDMonoMarshal::Dictionary_to_system_generic_dict(p_value.operator Dictionary(),
+ type.type_class, key_reftype, value_reftype);
mono_field_set_value(p_object, mono_field, managed);
break;
}
- if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
+ // System.Collections.Generic.List<T>
+ if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) {
+ MonoReflectionType *elem_reftype = nullptr;
+ GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
+ MonoObject *managed = GDMonoMarshal::Array_to_system_generic_list(p_value.operator Array(),
+ type.type_class, elem_reftype);
mono_field_set_value(p_object, mono_field, managed);
break;
}
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(),
- GDMonoUtils::Marshal::make_generic_array_type(elem_reftype));
+ // IDictionary<TKey, TValue>
+ if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) {
+ MonoReflectionType *key_reftype;
+ MonoReflectionType *value_reftype;
+ GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
+ GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype);
+
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), godot_dict_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
- if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
- if (GDMonoCache::tools_godot_api_check()) {
- MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
- mono_field_set_value(p_object, mono_field, managed);
- break;
- } else {
- MonoObject *managed = (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_value.operator Array());
- mono_field_set_value(p_object, mono_field, managed);
- break;
- }
+ // ICollection<T> or IEnumerable<T>
+ if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) {
+ MonoReflectionType *elem_reftype;
+ GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
+ GDMonoClass *godot_array_class = GDMonoUtils::Marshal::make_generic_array_type(elem_reftype);
+
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), godot_array_class);
+ mono_field_set_value(p_object, mono_field, managed);
+ break;
}
} break;
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 1878038f44..91ee07388b 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -154,6 +154,10 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
if (array_type->eklass == CACHED_CLASS_RAW(Color))
return Variant::PACKED_COLOR_ARRAY;
+
+ GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class))
+ return Variant::ARRAY;
} break;
case MONO_TYPE_CLASS: {
@@ -184,23 +188,14 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
return Variant::ARRAY;
}
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type());
-
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) {
- return Variant::DICTIONARY;
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ // IDictionary
+ if (p_type.type_class == CACHED_CLASS(System_Collections_IDictionary)) {
return Variant::DICTIONARY;
}
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) {
- return Variant::ARRAY;
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ // ICollection or IEnumerable
+ if (p_type.type_class == CACHED_CLASS(System_Collections_ICollection) ||
+ p_type.type_class == CACHED_CLASS(System_Collections_IEnumerable)) {
return Variant::ARRAY;
}
} break;
@@ -214,27 +209,33 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
case MONO_TYPE_GENERICINST: {
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
+ // Godot.Collections.Dictionary<TKey, TValue>
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
return Variant::DICTIONARY;
}
+ // Godot.Collections.Array<T>
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
return Variant::ARRAY;
}
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype))
- return Variant::DICTIONARY;
-
- if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ // System.Collections.Generic.Dictionary<TKey, TValue>
+ if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) {
return Variant::DICTIONARY;
}
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype))
+ // System.Collections.Generic.List<T>
+ if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) {
return Variant::ARRAY;
+ }
- if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ // IDictionary<TKey, TValue>
+ if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) {
+ return Variant::DICTIONARY;
+ }
+
+ // ICollection<T> or IEnumerable<T>
+ if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) {
return Variant::ARRAY;
}
} break;
@@ -252,10 +253,20 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_
bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type) {
switch (p_array_type.type_encoding) {
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY: {
+ MonoArrayType *array_type = mono_type_get_array_type(p_array_type.type_class->get_mono_type());
+ GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
+ r_elem_type = ManagedType::from_class(array_type_class);
+ return true;
+ } break;
case MONO_TYPE_GENERICINST: {
MonoReflectionType *array_reftype = mono_type_get_object(mono_domain_get(), p_array_type.type_class->get_mono_type());
- if (GDMonoUtils::Marshal::type_is_generic_array(array_reftype)) {
+ if (GDMonoUtils::Marshal::type_is_generic_array(array_reftype) ||
+ GDMonoUtils::Marshal::type_is_system_generic_list(array_reftype) ||
+ GDMonoUtils::Marshal::type_is_generic_icollection(array_reftype) ||
+ GDMonoUtils::Marshal::type_is_generic_ienumerable(array_reftype)) {
MonoReflectionType *elem_reftype;
GDMonoUtils::Marshal::array_get_element_type(array_reftype, &elem_reftype);
@@ -263,12 +274,6 @@ bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_
r_elem_type = ManagedType::from_reftype(elem_reftype);
return true;
}
-
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(array_reftype, &elem_reftype)) {
- r_elem_type = ManagedType::from_reftype(elem_reftype);
- return true;
- }
} break;
default: {
} break;
@@ -282,7 +287,9 @@ bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, Ma
case MONO_TYPE_GENERICINST: {
MonoReflectionType *dict_reftype = mono_type_get_object(mono_domain_get(), p_dictionary_type.type_class->get_mono_type());
- if (GDMonoUtils::Marshal::type_is_generic_dictionary(dict_reftype)) {
+ if (GDMonoUtils::Marshal::type_is_generic_dictionary(dict_reftype) ||
+ GDMonoUtils::Marshal::type_is_system_generic_dictionary(dict_reftype) ||
+ GDMonoUtils::Marshal::type_is_generic_idictionary(dict_reftype)) {
MonoReflectionType *key_reftype;
MonoReflectionType *value_reftype;
@@ -292,13 +299,6 @@ bool try_get_dictionary_key_value_types(const ManagedType &p_dictionary_type, Ma
r_value_type = ManagedType::from_reftype(value_reftype);
return true;
}
-
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(dict_reftype, &key_reftype, &value_reftype)) {
- r_key_type = ManagedType::from_reftype(key_reftype);
- r_value_type = ManagedType::from_reftype(value_reftype);
- return true;
- }
} break;
default: {
} break;
@@ -577,6 +577,10 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
if (array_type->eklass == CACHED_CLASS_RAW(Color))
return (MonoObject *)PackedColorArray_to_mono_array(p_var->operator PackedColorArray());
+ GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class))
+ return (MonoObject *)Array_to_mono_array(p_var->operator Array(), array_type_class);
+
ERR_FAIL_V_MSG(nullptr, "Attempted to convert Variant to a managed array of unmarshallable element type.");
} break;
@@ -600,41 +604,17 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
return GDMonoUtils::create_managed_from(p_var->operator RID());
}
- if (CACHED_CLASS(Dictionary) == type_class) {
+ // Godot.Collections.Dictionary or IDictionary
+ if (CACHED_CLASS(Dictionary) == type_class || CACHED_CLASS(System_Collections_IDictionary) == type_class) {
return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
}
- if (CACHED_CLASS(Array) == type_class) {
+ // Godot.Collections.Array or ICollection or IEnumerable
+ if (CACHED_CLASS(Array) == type_class ||
+ CACHED_CLASS(System_Collections_ICollection) == type_class ||
+ CACHED_CLASS(System_Collections_IEnumerable) == type_class) {
return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
}
-
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type());
-
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) {
- return GDMonoUtils::create_managed_from(p_var->operator Dictionary(),
- GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype));
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
- return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
- }
-
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) {
- return GDMonoUtils::create_managed_from(p_var->operator Array(),
- GDMonoUtils::Marshal::make_generic_array_type(elem_reftype));
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
- if (GDMonoCache::tools_godot_api_check()) {
- return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
- } else {
- return (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_var->operator Array());
- }
- }
} break;
case MONO_TYPE_OBJECT: {
// Variant
@@ -755,38 +735,48 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
case MONO_TYPE_GENERICINST: {
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
+ // Godot.Collections.Dictionary<TKey, TValue>
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), p_type.type_class);
}
+ // Godot.Collections.Array<T>
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
return GDMonoUtils::create_managed_from(p_var->operator Array(), p_type.type_class);
}
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- MonoReflectionType *key_reftype, *value_reftype;
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) {
- return GDMonoUtils::create_managed_from(p_var->operator Dictionary(),
- GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype));
+ // System.Collections.Generic.Dictionary<TKey, TValue>
+ if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) {
+ MonoReflectionType *key_reftype = nullptr;
+ MonoReflectionType *value_reftype = nullptr;
+ GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
+ return Dictionary_to_system_generic_dict(p_var->operator Dictionary(), p_type.type_class, key_reftype, value_reftype);
}
- if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
- return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
+ // System.Collections.Generic.List<T>
+ if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) {
+ MonoReflectionType *elem_reftype = nullptr;
+ GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
+ return Array_to_system_generic_list(p_var->operator Array(), p_type.type_class, elem_reftype);
}
- MonoReflectionType *elem_reftype;
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) {
- return GDMonoUtils::create_managed_from(p_var->operator Array(),
- GDMonoUtils::Marshal::make_generic_array_type(elem_reftype));
+ // IDictionary<TKey, TValue>
+ if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) {
+ MonoReflectionType *key_reftype;
+ MonoReflectionType *value_reftype;
+ GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
+ GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype);
+
+ return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), godot_dict_class);
}
- if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
- if (GDMonoCache::tools_godot_api_check()) {
- return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
- } else {
- return (MonoObject *)GDMonoMarshal::Array_to_mono_array(p_var->operator Array());
- }
+ // ICollection<T> or IEnumerable<T>
+ if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) {
+ MonoReflectionType *elem_reftype;
+ GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
+ GDMonoClass *godot_array_class = GDMonoUtils::Marshal::make_generic_array_type(elem_reftype);
+
+ return GDMonoUtils::create_managed_from(p_var->operator Array(), godot_array_class);
}
} break;
} break;
@@ -922,6 +912,10 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
if (array_type->eklass == CACHED_CLASS_RAW(Color))
return mono_array_to_PackedColorArray((MonoArray *)p_obj);
+ GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class))
+ return mono_array_to_Array((MonoArray *)p_obj);
+
if (p_fail_with_err) {
ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant.");
} else {
@@ -957,44 +951,27 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
return ptr ? Variant(*ptr) : Variant();
}
- if (CACHED_CLASS(Array) == type_class) {
+ // Godot.Collections.Dictionary
+ if (CACHED_CLASS(Dictionary) == type_class) {
MonoException *exc = nullptr;
- Array *ptr = CACHED_METHOD_THUNK(Array, GetPtr).invoke(p_obj, &exc);
+ Dictionary *ptr = CACHED_METHOD_THUNK(Dictionary, GetPtr).invoke(p_obj, &exc);
UNHANDLED_EXCEPTION(exc);
return ptr ? Variant(*ptr) : Variant();
}
- if (CACHED_CLASS(Dictionary) == type_class) {
+ // Godot.Collections.Array
+ if (CACHED_CLASS(Array) == type_class) {
MonoException *exc = nullptr;
- Dictionary *ptr = CACHED_METHOD_THUNK(Dictionary, GetPtr).invoke(p_obj, &exc);
+ Array *ptr = CACHED_METHOD_THUNK(Array, GetPtr).invoke(p_obj, &exc);
UNHANDLED_EXCEPTION(exc);
return ptr ? Variant(*ptr) : Variant();
}
-
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type_class->get_mono_type());
-
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) {
- return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj);
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
- return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj);
- }
-
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) {
- return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
- }
-
- if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
- return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
- }
} break;
case MONO_TYPE_GENERICINST: {
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
+ // Godot.Collections.Dictionary<TKey, TValue>
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
MonoException *exc = nullptr;
MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
@@ -1002,6 +979,7 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
return *unbox<Dictionary *>(ret);
}
+ // Godot.Collections.Array<T>
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
MonoException *exc = nullptr;
MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
@@ -1009,22 +987,19 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type
return *unbox<Array *>(ret);
}
- // The order in which we check the following interfaces is very important (dictionaries and generics first)
-
- if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) {
- return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj);
- }
-
- if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
- return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj);
+ // System.Collections.Generic.Dictionary<TKey, TValue>
+ if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) {
+ MonoReflectionType *key_reftype = nullptr;
+ MonoReflectionType *value_reftype = nullptr;
+ GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
+ return system_generic_dict_to_Dictionary(p_obj, p_type.type_class, key_reftype, value_reftype);
}
- if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) {
- return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
- }
-
- if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
- return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
+ // System.Collections.Generic.List<T>
+ if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) {
+ MonoReflectionType *elem_reftype = nullptr;
+ GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
+ return system_generic_list_to_Array(p_obj, p_type.type_class, elem_reftype);
}
} break;
}
@@ -1081,6 +1056,80 @@ String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) {
}
}
+MonoObject *Dictionary_to_system_generic_dict(const Dictionary &p_dict, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) {
+ String ctor_desc = ":.ctor(System.Collections.Generic.IDictionary`2<" + GDMonoUtils::get_type_desc(p_key_reftype) +
+ ", " + GDMonoUtils::get_type_desc(p_value_reftype) + ">)";
+ GDMonoMethod *ctor = p_class->get_method_with_desc(ctor_desc, true);
+ CRASH_COND(ctor == nullptr);
+
+ MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
+ ERR_FAIL_NULL_V(mono_object, nullptr);
+
+ GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(p_key_reftype, p_value_reftype);
+ MonoObject *godot_dict = GDMonoUtils::create_managed_from(p_dict, godot_dict_class);
+
+ void *ctor_args[1] = { godot_dict };
+
+ MonoException *exc = nullptr;
+ ctor->invoke_raw(mono_object, ctor_args, &exc);
+ UNHANDLED_EXCEPTION(exc);
+
+ return mono_object;
+}
+
+Dictionary system_generic_dict_to_Dictionary(MonoObject *p_obj, [[maybe_unused]] GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) {
+ GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(p_key_reftype, p_value_reftype);
+ String ctor_desc = ":.ctor(System.Collections.Generic.IDictionary`2<" + GDMonoUtils::get_type_desc(p_key_reftype) +
+ ", " + GDMonoUtils::get_type_desc(p_value_reftype) + ">)";
+ GDMonoMethod *godot_dict_ctor = godot_dict_class->get_method_with_desc(ctor_desc, true);
+ CRASH_COND(godot_dict_ctor == nullptr);
+
+ MonoObject *godot_dict = mono_object_new(mono_domain_get(), godot_dict_class->get_mono_ptr());
+ ERR_FAIL_NULL_V(godot_dict, Dictionary());
+
+ void *ctor_args[1] = { p_obj };
+
+ MonoException *exc = nullptr;
+ godot_dict_ctor->invoke_raw(godot_dict, ctor_args, &exc);
+ UNHANDLED_EXCEPTION(exc);
+
+ exc = nullptr;
+ MonoObject *ret = godot_dict_class->get_method("GetPtr")->invoke(godot_dict, &exc);
+ UNHANDLED_EXCEPTION(exc);
+
+ return *unbox<Dictionary *>(ret);
+}
+
+MonoObject *Array_to_system_generic_list(const Array &p_array, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype) {
+ GDMonoClass *elem_class = ManagedType::from_reftype(p_elem_reftype).type_class;
+
+ String ctor_desc = ":.ctor(System.Collections.Generic.IEnumerable`1<" + elem_class->get_type_desc() + ">)";
+ GDMonoMethod *ctor = p_class->get_method_with_desc(ctor_desc, true);
+ CRASH_COND(ctor == nullptr);
+
+ MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
+ ERR_FAIL_NULL_V(mono_object, nullptr);
+
+ void *ctor_args[1] = { Array_to_mono_array(p_array, elem_class) };
+
+ MonoException *exc = nullptr;
+ ctor->invoke_raw(mono_object, ctor_args, &exc);
+ UNHANDLED_EXCEPTION(exc);
+
+ return mono_object;
+}
+
+Array system_generic_list_to_Array(MonoObject *p_obj, GDMonoClass *p_class, [[maybe_unused]] MonoReflectionType *p_elem_reftype) {
+ GDMonoMethod *to_array = p_class->get_method("ToArray", 0);
+ CRASH_COND(to_array == nullptr);
+
+ MonoException *exc = nullptr;
+ MonoArray *mono_array = (MonoArray *)to_array->invoke_raw(p_obj, nullptr, &exc);
+ UNHANDLED_EXCEPTION(exc);
+
+ return mono_array_to_Array(mono_array);
+}
+
MonoArray *Array_to_mono_array(const Array &p_array) {
int length = p_array.size();
MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), length);
@@ -1093,6 +1142,18 @@ MonoArray *Array_to_mono_array(const Array &p_array) {
return ret;
}
+MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class) {
+ int length = p_array.size();
+ MonoArray *ret = mono_array_new(mono_domain_get(), p_array_type_class->get_mono_ptr(), length);
+
+ for (int i = 0; i < length; i++) {
+ MonoObject *boxed = variant_to_mono_object(p_array[i]);
+ mono_array_setref(ret, i, boxed);
+ }
+
+ return ret;
+}
+
Array mono_array_to_Array(MonoArray *p_array) {
Array ret;
if (!p_array)
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 8b405291a7..f2d887e6d6 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -123,9 +123,18 @@ Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_ty
/// If the MonoObject* cannot be converted to Variant, then 'ToString()' is called instead.
String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc);
+// System.Collections.Generic
+
+MonoObject *Dictionary_to_system_generic_dict(const Dictionary &p_dict, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype);
+Dictionary system_generic_dict_to_Dictionary(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype);
+
+MonoObject *Array_to_system_generic_list(const Array &p_array, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype);
+Array system_generic_list_to_Array(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype);
+
// Array
MonoArray *Array_to_mono_array(const Array &p_array);
+MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class);
Array mono_array_to_Array(MonoArray *p_array);
// PackedInt32Array
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
index c8cc5247c6..432aa74a6f 100644
--- a/modules/mono/mono_gd/gd_mono_method.cpp
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -30,13 +30,14 @@
#include "gd_mono_method.h"
+#include <mono/metadata/attrdefs.h>
+#include <mono/metadata/debug-helpers.h>
+
#include "gd_mono_cache.h"
#include "gd_mono_class.h"
#include "gd_mono_marshal.h"
#include "gd_mono_utils.h"
-#include <mono/metadata/attrdefs.h>
-
void GDMonoMethod::_update_signature() {
// Apparently MonoMethodSignature needs not to be freed.
// mono_method_signature caches the result, we don't need to cache it ourselves.
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 00119ced88..f9d492dabb 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -30,6 +30,7 @@
#include "gd_mono_utils.h"
+#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/exception.h>
#include "core/debugger/engine_debugger.h"
@@ -358,6 +359,14 @@ MonoDomain *create_domain(const String &p_friendly_name) {
return domain;
}
+String get_type_desc(MonoType *p_type) {
+ return mono_type_full_name(p_type);
+}
+
+String get_type_desc(MonoReflectionType *p_reftype) {
+ return get_type_desc(mono_reflection_type_get_type(p_reftype));
+}
+
String get_exception_name_and_message(MonoException *p_exc) {
String res;
@@ -584,75 +593,56 @@ bool type_is_generic_dictionary(MonoReflectionType *p_reftype) {
return (bool)res;
}
-void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) {
- MonoException *exc = nullptr;
- CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType).invoke(p_array_reftype, r_elem_reftype, &exc);
- UNHANDLED_EXCEPTION(exc);
-}
-
-void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
- MonoException *exc = nullptr;
- CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes).invoke(p_dict_reftype, r_key_reftype, r_value_reftype, &exc);
- UNHANDLED_EXCEPTION(exc);
-}
-
-bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) {
+bool type_is_system_generic_list(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
MonoException *exc = nullptr;
- MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType).invoke(p_reftype, &exc);
+ MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsSystemGenericList).invoke(p_reftype, &exc);
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
-bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) {
+bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
MonoException *exc = nullptr;
- MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType).invoke(p_reftype, &exc);
+ MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsSystemGenericDictionary).invoke(p_reftype, &exc);
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
-bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) {
+bool type_is_generic_ienumerable(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
MonoException *exc = nullptr;
- MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info).invoke(p_reftype, r_elem_reftype, &exc);
+ MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericIEnumerable).invoke(p_reftype, &exc);
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
-bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
+bool type_is_generic_icollection(MonoReflectionType *p_reftype) {
NO_GLUE_RET(false);
MonoException *exc = nullptr;
- MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info).invoke(p_reftype, r_key_reftype, r_value_reftype, &exc);
+ MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericICollection).invoke(p_reftype, &exc);
UNHANDLED_EXCEPTION(exc);
return (bool)res;
}
-Array enumerable_to_array(MonoObject *p_enumerable) {
- NO_GLUE_RET(Array());
- Array result;
+bool type_is_generic_idictionary(MonoReflectionType *p_reftype) {
+ NO_GLUE_RET(false);
MonoException *exc = nullptr;
- CACHED_METHOD_THUNK(MarshalUtils, EnumerableToArray).invoke(p_enumerable, &result, &exc);
+ MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericIDictionary).invoke(p_reftype, &exc);
UNHANDLED_EXCEPTION(exc);
- return result;
+ return (bool)res;
}
-Dictionary idictionary_to_dictionary(MonoObject *p_idictionary) {
- NO_GLUE_RET(Dictionary());
- Dictionary result;
+void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) {
MonoException *exc = nullptr;
- CACHED_METHOD_THUNK(MarshalUtils, IDictionaryToDictionary).invoke(p_idictionary, &result, &exc);
+ CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType).invoke(p_array_reftype, r_elem_reftype, &exc);
UNHANDLED_EXCEPTION(exc);
- return result;
}
-Dictionary generic_idictionary_to_dictionary(MonoObject *p_generic_idictionary) {
- NO_GLUE_RET(Dictionary());
- Dictionary result;
+void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
MonoException *exc = nullptr;
- CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryToDictionary).invoke(p_generic_idictionary, &result, &exc);
+ CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes).invoke(p_dict_reftype, r_key_reftype, r_value_reftype, &exc);
UNHANDLED_EXCEPTION(exc);
- return result;
}
GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index b850e1be9b..e3011ade5d 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -52,22 +52,18 @@ namespace Marshal {
bool type_is_generic_array(MonoReflectionType *p_reftype);
bool type_is_generic_dictionary(MonoReflectionType *p_reftype);
+bool type_is_system_generic_list(MonoReflectionType *p_reftype);
+bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype);
+bool type_is_generic_ienumerable(MonoReflectionType *p_reftype);
+bool type_is_generic_icollection(MonoReflectionType *p_reftype);
+bool type_is_generic_idictionary(MonoReflectionType *p_reftype);
void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype);
void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype);
-bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype);
-bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype);
-bool generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype);
-bool generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype);
-
GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype);
GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype);
-Array enumerable_to_array(MonoObject *p_enumerable);
-Dictionary idictionary_to_dictionary(MonoObject *p_idictionary);
-Dictionary generic_idictionary_to_dictionary(MonoObject *p_generic_idictionary);
-
} // namespace Marshal
_FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash) {
@@ -115,6 +111,9 @@ MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class);
MonoDomain *create_domain(const String &p_friendly_name);
+String get_type_desc(MonoType *p_type);
+String get_type_desc(MonoReflectionType *p_reftype);
+
String get_exception_name_and_message(MonoException *p_exc);
void set_exception_message(MonoException *p_exc, String message);
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index 907811355f..67b264d803 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -196,16 +196,6 @@ String str_format(const char *p_format, ...) {
return res;
}
-// va_copy was defined in the C99, but not in C++ standards before C++11.
-// When you compile C++ without --std=c++<XX> option, compilers still define
-// va_copy, otherwise you have to use the internal version (__va_copy).
-#if !defined(va_copy)
-#if defined(__GNUC__)
-#define va_copy(d, s) __va_copy((d), (s))
-#else
-#define va_copy(d, s) ((d) = (s))
-#endif
-#endif
#if defined(MINGW_ENABLED) || defined(_MSC_VER) && _MSC_VER < 1900
#define gd_vsnprintf(m_buffer, m_count, m_format, m_args_copy) vsnprintf_s(m_buffer, m_count, _TRUNCATE, m_format, m_args_copy)
diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp
index ec67030a65..2018f90e9f 100644
--- a/modules/opensimplex/noise_texture.cpp
+++ b/modules/opensimplex/noise_texture.cpp
@@ -137,14 +137,19 @@ void NoiseTexture::_queue_update() {
Ref<Image> NoiseTexture::_generate_texture() {
- if (noise.is_null()) return Ref<Image>();
+ // Prevent memdelete due to unref() on other thread.
+ Ref<OpenSimplexNoise> ref_noise = noise;
+
+ if (ref_noise.is_null()) {
+ return Ref<Image>();
+ }
Ref<Image> image;
if (seamless) {
- image = noise->get_seamless_image(size.x);
+ image = ref_noise->get_seamless_image(size.x);
} else {
- image = noise->get_image(size.x, size.y);
+ image = ref_noise->get_image(size.x, size.y);
}
if (as_normalmap) {
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
index 10d4d71f5e..a8e8a9a2f1 100644
--- a/modules/pvr/texture_loader_pvr.cpp
+++ b/modules/pvr/texture_loader_pvr.cpp
@@ -51,7 +51,7 @@ enum PVRFLags {
};
-RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
if (r_error)
*r_error = ERR_CANT_OPEN;
diff --git a/modules/pvr/texture_loader_pvr.h b/modules/pvr/texture_loader_pvr.h
index 642323db35..07ef129689 100644
--- a/modules/pvr/texture_loader_pvr.h
+++ b/modules/pvr/texture_loader_pvr.h
@@ -36,7 +36,7 @@
class ResourceFormatPVR : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index e5fb6f996d..b9f276fb12 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -725,7 +725,7 @@ void VideoStreamTheora::_bind_methods() {
////////////
-RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index cd7bff7adb..f98368ed8b 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -187,7 +187,7 @@ public:
class ResourceFormatLoaderTheora : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/tinyexr/SCsub b/modules/tinyexr/SCsub
index e7fd44fabd..84b3b4015b 100644
--- a/modules/tinyexr/SCsub
+++ b/modules/tinyexr/SCsub
@@ -15,6 +15,9 @@ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_tinyexr.Prepend(CPPPATH=[thirdparty_dir])
+# Enable threaded loading with C++11.
+env_tinyexr.Append(CPPDEFINES=["TINYEXR_USE_THREAD"])
+
env_thirdparty = env_tinyexr.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp
index 856f4188aa..988bf3017d 100644
--- a/modules/upnp/upnp.cpp
+++ b/modules/upnp/upnp.cpp
@@ -44,9 +44,8 @@ bool UPNP::is_common_device(const String &dev) const {
}
int UPNP::discover(int timeout, int ttl, const String &device_filter) {
- ERR_FAIL_COND_V(timeout < 0, UPNP_RESULT_INVALID_PARAM);
- ERR_FAIL_COND_V(ttl < 0, UPNP_RESULT_INVALID_PARAM);
- ERR_FAIL_COND_V(ttl > 255, UPNP_RESULT_INVALID_PARAM);
+ ERR_FAIL_COND_V_MSG(timeout < 0, UPNP_RESULT_INVALID_PARAM, "The response's wait time can't be negative.");
+ ERR_FAIL_COND_V_MSG(ttl < 0 || ttl > 255, UPNP_RESULT_INVALID_PARAM, "The time-to-live must be set between 0 and 255 (inclusive).");
devices.clear();
@@ -264,7 +263,7 @@ void UPNP::clear_devices() {
}
Ref<UPNPDevice> UPNP::get_gateway() const {
- ERR_FAIL_COND_V(devices.size() < 1, nullptr);
+ ERR_FAIL_COND_V_MSG(devices.size() < 1, nullptr, "Couldn't find any UPNPDevices.");
for (int i = 0; i < devices.size(); i++) {
Ref<UPNPDevice> dev = get_device(i);
diff --git a/modules/upnp/upnp_device.cpp b/modules/upnp/upnp_device.cpp
index c21826d14d..40eb6106a0 100644
--- a/modules/upnp/upnp_device.cpp
+++ b/modules/upnp/upnp_device.cpp
@@ -35,7 +35,7 @@
#include <miniupnpc/upnpcommands.h>
String UPNPDevice::query_external_address() const {
- ERR_FAIL_COND_V(!is_valid_gateway(), "");
+ ERR_FAIL_COND_V_MSG(!is_valid_gateway(), "", "The Internet Gateway Device must be valid.");
char addr[16];
int i = UPNP_GetExternalIPAddress(
@@ -43,17 +43,17 @@ String UPNPDevice::query_external_address() const {
igd_service_type.utf8().get_data(),
(char *)&addr);
- ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, "");
+ ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, "", "Couldn't get external IP address.");
return String(addr);
}
int UPNPDevice::add_port_mapping(int port, int port_internal, String desc, String proto, int duration) const {
- ERR_FAIL_COND_V(!is_valid_gateway(), UPNP::UPNP_RESULT_INVALID_GATEWAY);
- ERR_FAIL_COND_V(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT);
- ERR_FAIL_COND_V(port_internal < 0 || port_internal > 65535, UPNP::UPNP_RESULT_INVALID_PORT); // Needs to allow 0 because 0 signifies "use external port as internal port"
- ERR_FAIL_COND_V(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL);
- ERR_FAIL_COND_V(duration < 0, UPNP::UPNP_RESULT_INVALID_DURATION);
+ ERR_FAIL_COND_V_MSG(!is_valid_gateway(), UPNP::UPNP_RESULT_INVALID_GATEWAY, "The Internet Gateway Device must be valid.");
+ ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive).");
+ ERR_FAIL_COND_V_MSG(port_internal < 0 || port_internal > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 0 and 65535 (inclusive)."); // Needs to allow 0 because 0 signifies "use external port as internal port"
+ ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP.");
+ ERR_FAIL_COND_V_MSG(duration < 0, UPNP::UPNP_RESULT_INVALID_DURATION, "The port mapping's lease duration can't be negative.");
if (port_internal < 1) {
port_internal = port;
@@ -70,14 +70,14 @@ int UPNPDevice::add_port_mapping(int port, int port_internal, String desc, Strin
nullptr, // Remote host, always nullptr as IGDs don't support it
duration > 0 ? itos(duration).utf8().get_data() : nullptr);
- ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i));
+ ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i), "Couldn't add port mapping.");
return UPNP::UPNP_RESULT_SUCCESS;
}
int UPNPDevice::delete_port_mapping(int port, String proto) const {
- ERR_FAIL_COND_V(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT);
- ERR_FAIL_COND_V(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL);
+ ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive).");
+ ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP.");
int i = UPNP_DeletePortMapping(
igd_control_url.utf8().get_data(),
@@ -87,7 +87,7 @@ int UPNPDevice::delete_port_mapping(int port, String proto) const {
nullptr // Remote host, always nullptr as IGDs don't support it
);
- ERR_FAIL_COND_V(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i));
+ ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNP::upnp_result(i), "Couldn't delete port mapping.");
return UPNP::UPNP_RESULT_SUCCESS;
}
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index b52dfe1733..fe1d82f977 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -727,6 +727,26 @@ void VisualScript::rename_variable(const StringName &p_name, const StringName &p
variables[p_new_name] = variables[p_name];
variables.erase(p_name);
+
+ List<StringName> funcs;
+ get_function_list(&funcs);
+ for (List<StringName>::Element *F = funcs.front(); F; F = F->next()) { // loop through all the functions
+ List<int> ids;
+ get_node_list(F->get(), &ids);
+ for (List<int>::Element *E = ids.front(); E; E = E->next()) {
+ Ref<VisualScriptVariableGet> nodeget = get_node(F->get(), E->get());
+ if (nodeget.is_valid()) {
+ if (nodeget->get_variable() == p_name)
+ nodeget->set_variable(p_new_name);
+ } else {
+ Ref<VisualScriptVariableSet> nodeset = get_node(F->get(), E->get());
+ if (nodeset.is_valid()) {
+ if (nodeset->get_variable() == p_name)
+ nodeset->set_variable(p_new_name);
+ }
+ }
+ }
+ }
}
void VisualScript::add_custom_signal(const StringName &p_name) {
@@ -1440,6 +1460,10 @@ VisualScript::VisualScript() {
is_tool_script = false;
}
+bool VisualScript::inherits_script(const Ref<Script> &p_script) const {
+ return this == p_script.ptr(); //there is no inheritance in visual scripts, so this is enough
+}
+
StringName VisualScript::get_default_func() const {
return StringName("f_312843592");
}
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 29309aa156..c154e56703 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -272,6 +272,8 @@ protected:
static void _bind_methods();
public:
+ bool inherits_script(const Ref<Script> &p_script) const;
+
// TODO: Remove it in future when breaking changes are acceptable
StringName get_default_func() const;
void add_function(const StringName &p_name);
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 39d8f7c082..bb291b1cb6 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -506,10 +506,12 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
case MATH_CEIL: {
t = Variant::FLOAT;
} break;
- case MATH_POSMOD:
- case MATH_ROUND: {
+ case MATH_POSMOD: {
t = Variant::INT;
} break;
+ case MATH_ROUND: {
+ t = Variant::FLOAT;
+ } break;
case MATH_ABS: {
t = Variant::NIL;
} break;
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 30522930c7..9a4076bec4 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -30,7 +30,7 @@
#include "visual_script_editor.h"
-#include "core/input/input_filter.h"
+#include "core/input/input.h"
#include "core/object.h"
#include "core/os/keyboard.h"
#include "core/script_language.h"
@@ -350,8 +350,11 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::STRING: color = Color(0.42, 0.65, 0.93); break;
case Variant::VECTOR2: color = Color(0.74, 0.57, 0.95); break;
+ case Variant::VECTOR2I: color = Color(0.74, 0.57, 0.95); break;
case Variant::RECT2: color = Color(0.95, 0.57, 0.65); break;
+ case Variant::RECT2I: color = Color(0.95, 0.57, 0.65); break;
case Variant::VECTOR3: color = Color(0.84, 0.49, 0.93); break;
+ case Variant::VECTOR3I: color = Color(0.84, 0.49, 0.93); break;
case Variant::TRANSFORM2D: color = Color(0.77, 0.93, 0.41); break;
case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break;
case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break;
@@ -389,8 +392,11 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) {
case Variant::STRING: color = Color(0.27, 0.56, 0.91); break;
case Variant::VECTOR2: color = Color(0.68, 0.46, 0.93); break;
+ case Variant::VECTOR2I: color = Color(0.68, 0.46, 0.93); break;
case Variant::RECT2: color = Color(0.93, 0.46, 0.56); break;
+ case Variant::RECT2I: color = Color(0.93, 0.46, 0.56); break;
case Variant::VECTOR3: color = Color(0.86, 0.42, 0.93); break;
+ case Variant::VECTOR3I: color = Color(0.86, 0.42, 0.93); break;
case Variant::TRANSFORM2D: color = Color(0.59, 0.81, 0.1); break;
case Variant::PLANE: color = Color(0.97, 0.44, 0.44); break;
case Variant::QUAT: color = Color(0.93, 0.41, 0.64); break;
@@ -510,8 +516,11 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Control::get_theme_icon("float", "EditorIcons"),
Control::get_theme_icon("String", "EditorIcons"),
Control::get_theme_icon("Vector2", "EditorIcons"),
+ Control::get_theme_icon("Vector2i", "EditorIcons"),
Control::get_theme_icon("Rect2", "EditorIcons"),
+ Control::get_theme_icon("Rect2i", "EditorIcons"),
Control::get_theme_icon("Vector3", "EditorIcons"),
+ Control::get_theme_icon("Vector3i", "EditorIcons"),
Control::get_theme_icon("Transform2D", "EditorIcons"),
Control::get_theme_icon("Plane", "EditorIcons"),
Control::get_theme_icon("Quat", "EditorIcons"),
@@ -522,6 +531,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Control::get_theme_icon("NodePath", "EditorIcons"),
Control::get_theme_icon("RID", "EditorIcons"),
Control::get_theme_icon("MiniObject", "EditorIcons"),
+ Control::get_theme_icon("Callable", "EditorIcons"),
+ Control::get_theme_icon("Signal", "EditorIcons"),
Control::get_theme_icon("Dictionary", "EditorIcons"),
Control::get_theme_icon("Array", "EditorIcons"),
Control::get_theme_icon("PackedByteArray", "EditorIcons"),
@@ -974,8 +985,11 @@ void VisualScriptEditor::_update_members() {
Control::get_theme_icon("float", "EditorIcons"),
Control::get_theme_icon("String", "EditorIcons"),
Control::get_theme_icon("Vector2", "EditorIcons"),
+ Control::get_theme_icon("Vector2i", "EditorIcons"),
Control::get_theme_icon("Rect2", "EditorIcons"),
+ Control::get_theme_icon("Rect2i", "EditorIcons"),
Control::get_theme_icon("Vector3", "EditorIcons"),
+ Control::get_theme_icon("Vector3i", "EditorIcons"),
Control::get_theme_icon("Transform2D", "EditorIcons"),
Control::get_theme_icon("Plane", "EditorIcons"),
Control::get_theme_icon("Quat", "EditorIcons"),
@@ -986,6 +1000,8 @@ void VisualScriptEditor::_update_members() {
Control::get_theme_icon("NodePath", "EditorIcons"),
Control::get_theme_icon("RID", "EditorIcons"),
Control::get_theme_icon("MiniObject", "EditorIcons"),
+ Control::get_theme_icon("Callable", "EditorIcons"),
+ Control::get_theme_icon("Signal", "EditorIcons"),
Control::get_theme_icon("Dictionary", "EditorIcons"),
Control::get_theme_icon("Array", "EditorIcons"),
Control::get_theme_icon("PackedByteArray", "EditorIcons"),
@@ -1057,9 +1073,9 @@ void VisualScriptEditor::_member_selected() {
if (ti->get_parent() == members->get_root()->get_children()) {
#ifdef OSX_ENABLED
- bool held_ctrl = InputFilter::get_singleton()->is_key_pressed(KEY_META);
+ bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool held_ctrl = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool held_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
#endif
if (held_ctrl) {
ERR_FAIL_COND(!script->has_function(selected));
@@ -1155,6 +1171,8 @@ void VisualScriptEditor::_member_edited() {
undo_redo->add_undo_method(script.ptr(), "rename_variable", new_name, name);
undo_redo->add_do_method(this, "_update_members");
undo_redo->add_undo_method(this, "_update_members");
+ undo_redo->add_do_method(this, "_update_graph");
+ undo_redo->add_undo_method(this, "_update_graph");
undo_redo->add_do_method(this, "emit_signal", "edited_script_changed");
undo_redo->add_undo_method(this, "emit_signal", "edited_script_changed");
undo_redo->commit_action();
@@ -1262,7 +1280,7 @@ void VisualScriptEditor::_add_func_input() {
}
func_input_vbox->add_child(hbox);
- hbox->set_meta("id", hbox->get_position_in_parent());
+ hbox->set_meta("id", hbox->get_index());
delete_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_func_input), varray(hbox));
@@ -1360,7 +1378,7 @@ void VisualScriptEditor::_member_button(Object *p_item, int p_column, int p_butt
}
} else if (ti->get_parent() == root->get_children()) {
selected = ti->get_text(0);
- function_name_edit->set_position(InputFilter::get_singleton()->get_mouse_position() - Vector2(60, -10));
+ function_name_edit->set_position(Input::get_singleton()->get_mouse_position() - Vector2(60, -10));
function_name_edit->popup();
function_name_box->set_text(selected);
function_name_box->select_all();
@@ -1722,7 +1740,7 @@ void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> key = p_event;
if (key.is_valid() && !key->is_pressed()) {
- mouse_up_position = InputFilter::get_singleton()->get_mouse_position();
+ mouse_up_position = Input::get_singleton()->get_mouse_position();
}
}
@@ -1732,7 +1750,7 @@ void VisualScriptEditor::_graph_gui_input(const Ref<InputEvent> &p_event) {
if (key.is_valid() && key->is_pressed() && key->get_button_mask() == BUTTON_RIGHT) {
saved_position = graph->get_local_mouse_position();
- Point2 gpos = InputFilter::get_singleton()->get_mouse_position();
+ Point2 gpos = Input::get_singleton()->get_mouse_position();
_generic_search(script->get_instance_base_type(), gpos);
}
}
@@ -1986,9 +2004,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
if (String(d["type"]) == "visual_script_variable_drag") {
#ifdef OSX_ENABLED
- bool use_set = InputFilter::get_singleton()->is_key_pressed(KEY_META);
+ bool use_set = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool use_set = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool use_set = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
#endif
Vector2 ofs = graph->get_scroll_ofs() + p_point;
if (graph->is_using_snap()) {
@@ -2181,9 +2199,9 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
#ifdef OSX_ENABLED
- bool use_node = InputFilter::get_singleton()->is_key_pressed(KEY_META);
+ bool use_node = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool use_node = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool use_node = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
#endif
Array nodes = d["nodes"];
@@ -2245,7 +2263,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
Node *sn = _find_script_node(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root(), script);
- if (!sn && !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ if (!sn && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
EditorNode::get_singleton()->show_warning(vformat(TTR("Can't drop properties because script '%s' is not used in this scene.\nDrop holding 'Shift' to just copy the signature."), get_name()));
return;
}
@@ -2265,12 +2283,12 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
ofs /= EDSCALE;
#ifdef OSX_ENABLED
- bool use_get = InputFilter::get_singleton()->is_key_pressed(KEY_META);
+ bool use_get = Input::get_singleton()->is_key_pressed(KEY_META);
#else
- bool use_get = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL);
+ bool use_get = Input::get_singleton()->is_key_pressed(KEY_CONTROL);
#endif
- if (!node || InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ if (!node || Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
if (use_get)
undo_redo->create_action(TTR("Add Getter Property"));
@@ -3917,7 +3935,9 @@ void VisualScriptEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members));
+ variable_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED);
signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_members));
+ signal_editor->connect("changed", callable_mp(this, &VisualScriptEditor::_update_graph), varray(-1), CONNECT_DEFERRED);
[[fallthrough]];
}
case NOTIFICATION_THEME_CHANGED: {
@@ -4629,6 +4649,7 @@ void VisualScriptEditor::_bind_methods() {
ClassDB::bind_method("_input", &VisualScriptEditor::_input);
ClassDB::bind_method("_update_graph_connections", &VisualScriptEditor::_update_graph_connections);
+ ClassDB::bind_method("_update_members", &VisualScriptEditor::_update_members);
ClassDB::bind_method("_generic_search", &VisualScriptEditor::_generic_search);
}
diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp
index 475893e86d..8a644c6860 100644
--- a/modules/visual_script/visual_script_flow_control.cpp
+++ b/modules/visual_script/visual_script_flow_control.cpp
@@ -934,6 +934,6 @@ void register_visual_script_flow_control_nodes() {
VisualScriptLanguage::singleton->add_register_func("flow_control/iterator", create_node_generic<VisualScriptIterator>);
VisualScriptLanguage::singleton->add_register_func("flow_control/sequence", create_node_generic<VisualScriptSequence>);
VisualScriptLanguage::singleton->add_register_func("flow_control/switch", create_node_generic<VisualScriptSwitch>);
- //VisualScriptLanguage::singleton->add_register_func("flow_control/input_filter", create_node_generic<VisualScriptInputFilter>);
+ //VisualScriptLanguage::singleton->add_register_func("flow_control/input", create_node_generic<VisualScriptInputFilter>);
VisualScriptLanguage::singleton->add_register_func("flow_control/type_cast", create_node_generic<VisualScriptTypeCast>);
}
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 97c2686cd5..52399d29d0 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -32,7 +32,7 @@
#include "core/engine.h"
#include "core/global_constants.h"
-#include "core/input/input_filter.h"
+#include "core/input/input.h"
#include "core/os/os.h"
#include "core/project_settings.h"
#include "scene/main/node.h"
@@ -3870,16 +3870,16 @@ public:
switch (mode) {
case VisualScriptInputAction::MODE_PRESSED: {
- *p_outputs[0] = InputFilter::get_singleton()->is_action_pressed(action);
+ *p_outputs[0] = Input::get_singleton()->is_action_pressed(action);
} break;
case VisualScriptInputAction::MODE_RELEASED: {
- *p_outputs[0] = !InputFilter::get_singleton()->is_action_pressed(action);
+ *p_outputs[0] = !Input::get_singleton()->is_action_pressed(action);
} break;
case VisualScriptInputAction::MODE_JUST_PRESSED: {
- *p_outputs[0] = InputFilter::get_singleton()->is_action_just_pressed(action);
+ *p_outputs[0] = Input::get_singleton()->is_action_just_pressed(action);
} break;
case VisualScriptInputAction::MODE_JUST_RELEASED: {
- *p_outputs[0] = InputFilter::get_singleton()->is_action_just_released(action);
+ *p_outputs[0] = Input::get_singleton()->is_action_just_released(action);
} break;
}
@@ -4184,9 +4184,12 @@ void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("operators/logic/select", create_node_generic<VisualScriptSelect>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2), create_node_deconst_typed<Variant::Type::VECTOR2>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2I), create_node_deconst_typed<Variant::Type::VECTOR2I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3), create_node_deconst_typed<Variant::Type::VECTOR3>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3I), create_node_deconst_typed<Variant::Type::VECTOR3I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::COLOR), create_node_deconst_typed<Variant::Type::COLOR>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2), create_node_deconst_typed<Variant::Type::RECT2>);
+ VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2I), create_node_deconst_typed<Variant::Type::RECT2I>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM2D), create_node_deconst_typed<Variant::Type::TRANSFORM2D>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PLANE), create_node_deconst_typed<Variant::Type::PLANE>);
VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::QUAT), create_node_deconst_typed<Variant::Type::QUAT>);
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index ca78d664f7..a2d0f78f5f 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -474,7 +474,7 @@ void VideoStreamWebm::set_audio_track(int p_track) {
////////////
-RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress) {
+RES ResourceFormatLoaderWebm::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
diff --git a/modules/webm/video_stream_webm.h b/modules/webm/video_stream_webm.h
index bc209e0057..6677fb85aa 100644
--- a/modules/webm/video_stream_webm.h
+++ b/modules/webm/video_stream_webm.h
@@ -128,7 +128,7 @@ public:
class ResourceFormatLoaderWebm : public ResourceFormatLoader {
public:
- virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr);
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, bool p_no_cache = false);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
diff --git a/modules/xatlas_unwrap/register_types.cpp b/modules/xatlas_unwrap/register_types.cpp
index e293dfd50c..8c5525bed3 100644
--- a/modules/xatlas_unwrap/register_types.cpp
+++ b/modules/xatlas_unwrap/register_types.cpp
@@ -32,14 +32,91 @@
#include "core/error_macros.h"
+#include "core/crypto/crypto_core.h"
+
#include "thirdparty/xatlas/xatlas.h"
#include <stdio.h>
#include <stdlib.h>
-extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y);
+extern bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache);
+
+bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, float **r_uvs, int **r_vertices, int *r_vertex_count, int **r_indices, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y, int *&r_cache_data, unsigned int &r_cache_size, bool &r_used_cache) {
+
+ CryptoCore::MD5Context ctx;
+ ctx.start();
+
+ ctx.update((unsigned char *)&p_texel_size, sizeof(float));
+ ctx.update((unsigned char *)p_indices, sizeof(int) * p_index_count);
+ ctx.update((unsigned char *)p_vertices, sizeof(float) * p_vertex_count);
+ ctx.update((unsigned char *)p_normals, sizeof(float) * p_vertex_count);
+
+ unsigned char hash[16];
+ ctx.finish(hash);
+
+ bool cached = false;
+ unsigned int cache_idx = 0;
+
+ if (r_used_cache && r_cache_size) {
+ //Check if hash is in cache data
+
+ int *cache_data = r_cache_data;
+ int n_entries = cache_data[0];
+ unsigned int r_idx = 1;
+ for (int i = 0; i < n_entries; ++i) {
+ if (memcmp(&cache_data[r_idx], hash, 16) == 0) {
+ cached = true;
+ cache_idx = r_idx;
+ break;
+ }
+
+ r_idx += 4; // hash
+ r_idx += 2; // size hint
+
+ int vertex_count = cache_data[r_idx];
+ r_idx += 1; // vertex count
+ r_idx += vertex_count; // vertex
+ r_idx += vertex_count * 2; // uvs
+
+ int index_count = cache_data[r_idx];
+ r_idx += 1; // index count
+ r_idx += index_count; // indices
+ }
+ }
-bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, const int *p_face_materials, int p_index_count, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) {
+ if (r_used_cache && cached) {
+ int *cache_data = r_cache_data;
+
+ // Return cache data pointer to the caller
+ r_cache_data = &cache_data[cache_idx];
+
+ cache_idx += 4;
+
+ // Load size
+ *r_size_hint_x = cache_data[cache_idx];
+ *r_size_hint_y = cache_data[cache_idx + 1];
+ cache_idx += 2;
+
+ // Load vertices
+ *r_vertex_count = cache_data[cache_idx];
+ cache_idx++;
+ *r_vertices = &cache_data[cache_idx];
+ cache_idx += *r_vertex_count;
+
+ // Load UVs
+ *r_uvs = (float *)&cache_data[cache_idx];
+ cache_idx += *r_vertex_count * 2;
+
+ // Load indices
+ *r_index_count = cache_data[cache_idx];
+ cache_idx++;
+ *r_indices = &cache_data[cache_idx];
+
+ // Return cache data size to the caller
+ r_cache_size = sizeof(int) * (4 + 2 + 1 + *r_vertex_count + (*r_vertex_count * 2) + 1 + *r_index_count); // hash + size hint + vertex_count + vertices + uvs + index_count + indices
+ r_used_cache = true;
+ return true;
+ }
//set up input mesh
xatlas::MeshDecl input_mesh;
@@ -82,16 +159,16 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
const xatlas::Mesh &output = atlas->meshes[0];
- *r_vertex = (int *)malloc(sizeof(int) * output.vertexCount);
- *r_uv = (float *)malloc(sizeof(float) * output.vertexCount * 2);
- *r_index = (int *)malloc(sizeof(int) * output.indexCount);
+ *r_vertices = (int *)malloc(sizeof(int) * output.vertexCount);
+ *r_uvs = (float *)malloc(sizeof(float) * output.vertexCount * 2);
+ *r_indices = (int *)malloc(sizeof(int) * output.indexCount);
float max_x = 0;
float max_y = 0;
for (uint32_t i = 0; i < output.vertexCount; i++) {
- (*r_vertex)[i] = output.vertexArray[i].xref;
- (*r_uv)[i * 2 + 0] = output.vertexArray[i].uv[0] / w;
- (*r_uv)[i * 2 + 1] = output.vertexArray[i].uv[1] / h;
+ (*r_vertices)[i] = output.vertexArray[i].xref;
+ (*r_uvs)[i * 2 + 0] = output.vertexArray[i].uv[0] / w;
+ (*r_uvs)[i * 2 + 1] = output.vertexArray[i].uv[1] / h;
max_x = MAX(max_x, output.vertexArray[i].uv[0]);
max_y = MAX(max_y, output.vertexArray[i].uv[1]);
}
@@ -100,13 +177,54 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
*r_vertex_count = output.vertexCount;
for (uint32_t i = 0; i < output.indexCount; i++) {
- (*r_index)[i] = output.indexArray[i];
+ (*r_indices)[i] = output.indexArray[i];
}
*r_index_count = output.indexCount;
xatlas::Destroy(atlas);
- printf("Done\n");
+
+ if (r_used_cache) {
+ unsigned int new_cache_size = 4 + 2 + 1 + *r_vertex_count + (*r_vertex_count * 2) + 1 + *r_index_count; // hash + size hint + vertex_count + vertices + uvs + index_count + indices
+ new_cache_size *= sizeof(int);
+ int *new_cache_data = (int *)memalloc(new_cache_size);
+ unsigned int new_cache_idx = 0;
+
+ // hash
+ memcpy(&new_cache_data[new_cache_idx], hash, 16);
+ new_cache_idx += 4;
+
+ // size hint
+ new_cache_data[new_cache_idx] = *r_size_hint_x;
+ new_cache_data[new_cache_idx + 1] = *r_size_hint_y;
+ new_cache_idx += 2;
+
+ // vertex count
+ new_cache_data[new_cache_idx] = *r_vertex_count;
+ new_cache_idx++;
+
+ // vertices
+ memcpy(&new_cache_data[new_cache_idx], *r_vertices, sizeof(int) * *r_vertex_count);
+ new_cache_idx += *r_vertex_count;
+
+ // uvs
+ memcpy(&new_cache_data[new_cache_idx], *r_uvs, sizeof(float) * *r_vertex_count * 2);
+ new_cache_idx += *r_vertex_count * 2;
+
+ // index count
+ new_cache_data[new_cache_idx] = *r_index_count;
+ new_cache_idx++;
+
+ // indices
+ memcpy(&new_cache_data[new_cache_idx], *r_indices, sizeof(int) * *r_index_count);
+ new_cache_idx += *r_index_count;
+
+ // Return cache data to the caller
+ r_cache_data = new_cache_data;
+ r_cache_size = new_cache_size;
+ r_used_cache = false;
+ }
+
return true;
}