summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/Input.xml4
-rw-r--r--doc/classes/NavigationServer2D.xml40
-rw-r--r--doc/classes/NavigationServer3D.xml40
-rw-r--r--modules/gdnative/gdnative/aabb.cpp4
-rw-r--r--modules/gdnative/gdnative/array.cpp4
-rw-r--r--modules/gdnative/gdnative/basis.cpp4
-rw-r--r--modules/gdnative/gdnative/callable.cpp4
-rw-r--r--modules/gdnative/gdnative/color.cpp4
-rw-r--r--modules/gdnative/gdnative/dictionary.cpp4
-rw-r--r--modules/gdnative/gdnative/node_path.cpp4
-rw-r--r--modules/gdnative/gdnative/packed_arrays.cpp44
-rw-r--r--modules/gdnative/gdnative/plane.cpp4
-rw-r--r--modules/gdnative/gdnative/quat.cpp4
-rw-r--r--modules/gdnative/gdnative/rect2.cpp8
-rw-r--r--modules/gdnative/gdnative/rid.cpp4
-rw-r--r--modules/gdnative/gdnative/signal.cpp4
-rw-r--r--modules/gdnative/gdnative/string.cpp44
-rw-r--r--modules/gdnative/gdnative/string_name.cpp4
-rw-r--r--modules/gdnative/gdnative/transform.cpp4
-rw-r--r--modules/gdnative/gdnative/transform2d.cpp4
-rw-r--r--modules/gdnative/gdnative/variant.cpp81
-rw-r--r--modules/gdnative/gdnative/vector2.cpp8
-rw-r--r--modules/gdnative/gdnative/vector3.cpp8
-rw-r--r--modules/gdnative/gdnative_api.json598
-rw-r--r--modules/gdnative/include/gdnative/aabb.h1
-rw-r--r--modules/gdnative/include/gdnative/array.h1
-rw-r--r--modules/gdnative/include/gdnative/basis.h1
-rw-r--r--modules/gdnative/include/gdnative/callable.h1
-rw-r--r--modules/gdnative/include/gdnative/color.h1
-rw-r--r--modules/gdnative/include/gdnative/dictionary.h1
-rw-r--r--modules/gdnative/include/gdnative/node_path.h1
-rw-r--r--modules/gdnative/include/gdnative/packed_arrays.h11
-rw-r--r--modules/gdnative/include/gdnative/plane.h1
-rw-r--r--modules/gdnative/include/gdnative/quat.h1
-rw-r--r--modules/gdnative/include/gdnative/rect2.h2
-rw-r--r--modules/gdnative/include/gdnative/rid.h1
-rw-r--r--modules/gdnative/include/gdnative/signal.h1
-rw-r--r--modules/gdnative/include/gdnative/string.h10
-rw-r--r--modules/gdnative/include/gdnative/transform.h1
-rw-r--r--modules/gdnative/include/gdnative/transform2d.h1
-rw-r--r--modules/gdnative/include/gdnative/variant.h4
-rw-r--r--modules/gdnative/include/gdnative/vector2.h2
-rw-r--r--modules/gdnative/include/gdnative/vector3.h2
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp3
-rw-r--r--modules/gdnavigation/gd_navigation_server.cpp40
-rw-r--r--modules/gdnavigation/gd_navigation_server.h7
-rw-r--r--modules/gdnavigation/nav_map.cpp512
-rw-r--r--modules/gdnavigation/nav_map.h1
-rw-r--r--modules/gdnavigation/nav_region.cpp22
-rw-r--r--modules/gdnavigation/nav_region.h8
-rw-r--r--modules/gdnavigation/nav_utils.h39
-rw-r--r--modules/gltf/gltf_document.cpp25
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml6
-rw-r--r--platform/android/java/app/assets/.gitignore2
-rw-r--r--platform/android/java/app/build.gradle8
-rw-r--r--platform/android/java/app/config.gradle21
-rw-r--r--platform/android/java/lib/build.gradle6
-rw-r--r--platform/android/java/nativeSrcsConfigs/build.gradle3
-rw-r--r--platform/iphone/godot_view.mm12
-rw-r--r--platform/uwp/os_uwp.cpp8
-rw-r--r--scene/2d/navigation_region_2d.cpp70
-rw-r--r--scene/2d/navigation_region_2d.h1
-rw-r--r--scene/3d/collision_object_3d.cpp3
-rw-r--r--scene/animation/animation_tree.cpp1
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/resources/world_2d.cpp2
-rw-r--r--servers/navigation_server_2d.cpp15
-rw-r--r--servers/navigation_server_2d.h9
-rw-r--r--servers/navigation_server_3d.cpp7
-rw-r--r--servers/navigation_server_3d.h9
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.cpp51
-rw-r--r--servers/physics_3d/gjk_epa.cpp95
-rw-r--r--servers/physics_3d/gjk_epa.h2
-rw-r--r--servers/rendering/rendering_server_default.h2
74 files changed, 1554 insertions, 413 deletions
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index 1f872db6c6..977f2bb565 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -49,7 +49,7 @@
<return type="Vector3">
</return>
<description>
- Returns the acceleration of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
+ Returns the acceleration in m/s² of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
Note this method returns an empty [Vector3] when running from the editor even when your device has an accelerometer. You must export your project to a supported device to read values from the accelerometer.
[b]Note:[/b] This method only works on iOS, Android, and UWP. On other platforms, it always returns [constant Vector3.ZERO].
</description>
@@ -106,7 +106,7 @@
<return type="Vector3">
</return>
<description>
- Returns the gravity of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
+ Returns the gravity in m/s² of the device's accelerometer sensor, if the device has one. Otherwise, the method returns [constant Vector3.ZERO].
[b]Note:[/b] This method only works on Android and iOS. On other platforms, it always returns [constant Vector3.ZERO].
</description>
</method>
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 4f34a8a424..b811607bad 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -267,6 +267,37 @@
Creates a new region.
</description>
</method>
+ <method name="region_get_connection_pathway_end" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the ending point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connection_pathway_start" qualifiers="const">
+ <return type="Vector2">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the starting point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connections_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <description>
+ Returns how many connections this [code]region[/code] has with other regions in the map.
+ </description>
+ </method>
<method name="region_get_layers" qualifiers="const">
<return type="int">
</return>
@@ -321,6 +352,15 @@
</description>
</method>
</methods>
+ <signals>
+ <signal name="map_changed">
+ <argument index="0" name="map" type="RID">
+ </argument>
+ <description>
+ Emitted when a navigation map is updated, when a region moves or is modified.
+ </description>
+ </signal>
+ </signals>
<constants>
</constants>
</class>
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 0653c0d27d..6d56428933 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -335,6 +335,37 @@
Creates a new region.
</description>
</method>
+ <method name="region_get_connection_pathway_end" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the ending point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connection_pathway_start" qualifiers="const">
+ <return type="Vector3">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <argument index="1" name="connection" type="int">
+ </argument>
+ <description>
+ Returns the starting point of a connection door. [code]connection[/code] is an index between 0 and the return value of [method region_get_connections_count].
+ </description>
+ </method>
+ <method name="region_get_connections_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="region" type="RID">
+ </argument>
+ <description>
+ Returns how many connections this [code]region[/code] has with other regions in the map.
+ </description>
+ </method>
<method name="region_get_layers" qualifiers="const">
<return type="int">
</return>
@@ -398,6 +429,15 @@
</description>
</method>
</methods>
+ <signals>
+ <signal name="map_changed">
+ <argument index="0" name="map" type="RID">
+ </argument>
+ <description>
+ Emitted when a navigation map is updated, when a region moves or is modified.
+ </description>
+ </signal>
+ </signals>
<constants>
</constants>
</class>
diff --git a/modules/gdnative/gdnative/aabb.cpp b/modules/gdnative/gdnative/aabb.cpp
index 5d3f224adc..c42b874b4b 100644
--- a/modules/gdnative/gdnative/aabb.cpp
+++ b/modules/gdnative/gdnative/aabb.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_aabb_new(godot_aabb *p_self) {
memnew_placement(p_self, AABB);
}
+void GDAPI godot_aabb_new_copy(godot_aabb *r_dest, const godot_aabb *p_src) {
+ memnew_placement(r_dest, AABB(*(AABB *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp
index e68b60c5e6..76e131dc06 100644
--- a/modules/gdnative/gdnative/array.cpp
+++ b/modules/gdnative/gdnative/array.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_array_new(godot_array *p_self) {
memnew_placement(p_self, Array);
}
+void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src) {
+ memnew_placement(r_dest, Array(*(Array *)p_src));
+}
+
void GDAPI godot_array_destroy(godot_array *p_self) {
((Array *)p_self)->~Array();
}
diff --git a/modules/gdnative/gdnative/basis.cpp b/modules/gdnative/gdnative/basis.cpp
index df3e1255ac..4641f0bacc 100644
--- a/modules/gdnative/gdnative/basis.cpp
+++ b/modules/gdnative/gdnative/basis.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_basis_new(godot_basis *p_self) {
memnew_placement(p_self, Basis);
}
+void GDAPI godot_basis_new_copy(godot_basis *r_dest, const godot_basis *p_src) {
+ memnew_placement(r_dest, Basis(*(Basis *)p_src));
+}
+
godot_vector3 GDAPI *godot_basis_operator_index(godot_basis *p_self, godot_int p_index) {
Basis *self = (Basis *)p_self;
return (godot_vector3 *)&self->operator[](p_index);
diff --git a/modules/gdnative/gdnative/callable.cpp b/modules/gdnative/gdnative/callable.cpp
index 7c62b5928f..85274e5e22 100644
--- a/modules/gdnative/gdnative/callable.cpp
+++ b/modules/gdnative/gdnative/callable.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_callable_new(godot_callable *p_self) {
memnew_placement(p_self, Callable);
}
+void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src) {
+ memnew_placement(r_dest, Callable(*(Callable *)p_src));
+}
+
void GDAPI godot_callable_destroy(godot_callable *p_self) {
Callable *self = (Callable *)p_self;
self->~Callable();
diff --git a/modules/gdnative/gdnative/color.cpp b/modules/gdnative/gdnative/color.cpp
index 12a800d333..502f89c027 100644
--- a/modules/gdnative/gdnative/color.cpp
+++ b/modules/gdnative/gdnative/color.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_color_new(godot_color *p_self) {
memnew_placement(p_self, Color);
}
+void GDAPI godot_color_new_copy(godot_color *r_dest, const godot_color *p_src) {
+ memnew_placement(r_dest, Color(*(Color *)p_src));
+}
+
float GDAPI *godot_color_operator_index(godot_color *p_self, godot_int p_index) {
Color *self = (Color *)p_self;
return (float *)&self->operator[](p_index);
diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp
index 9fa4a27a83..2bfad6e695 100644
--- a/modules/gdnative/gdnative/dictionary.cpp
+++ b/modules/gdnative/gdnative/dictionary.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_dictionary_new(godot_dictionary *p_self) {
memnew_placement(p_self, Dictionary);
}
+void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src) {
+ memnew_placement(r_dest, Dictionary(*(Dictionary *)p_src));
+}
+
void GDAPI godot_dictionary_destroy(godot_dictionary *p_self) {
Dictionary *self = (Dictionary *)p_self;
self->~Dictionary();
diff --git a/modules/gdnative/gdnative/node_path.cpp b/modules/gdnative/gdnative/node_path.cpp
index 02c2f9b22b..57d67b9abb 100644
--- a/modules/gdnative/gdnative/node_path.cpp
+++ b/modules/gdnative/gdnative/node_path.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_node_path_new(godot_node_path *p_self) {
memnew_placement(p_self, NodePath);
}
+void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src) {
+ memnew_placement(r_dest, NodePath(*(NodePath *)p_src));
+}
+
void GDAPI godot_node_path_destroy(godot_node_path *p_self) {
NodePath *self = (NodePath *)p_self;
self->~NodePath();
diff --git a/modules/gdnative/gdnative/packed_arrays.cpp b/modules/gdnative/gdnative/packed_arrays.cpp
index 63a2425b87..396109e576 100644
--- a/modules/gdnative/gdnative/packed_arrays.cpp
+++ b/modules/gdnative/gdnative/packed_arrays.cpp
@@ -59,6 +59,10 @@ void GDAPI godot_packed_byte_array_new(godot_packed_byte_array *p_self) {
memnew_placement(p_self, PackedByteArray);
}
+void GDAPI godot_packed_byte_array_new_copy(godot_packed_byte_array *r_dest, const godot_packed_byte_array *p_src) {
+ memnew_placement(r_dest, PackedByteArray(*(PackedByteArray *)p_src));
+}
+
void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self) {
((PackedByteArray *)p_self)->~PackedByteArray();
}
@@ -79,6 +83,10 @@ void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *p_self) {
memnew_placement(p_self, PackedInt32Array);
}
+void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src) {
+ memnew_placement(r_dest, PackedInt32Array(*(PackedInt32Array *)p_src));
+}
+
void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self) {
((PackedInt32Array *)p_self)->~PackedInt32Array();
}
@@ -99,6 +107,10 @@ void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *p_self) {
memnew_placement(p_self, PackedInt64Array);
}
+void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src) {
+ memnew_placement(r_dest, PackedInt64Array(*(PackedInt64Array *)p_src));
+}
+
void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self) {
((PackedInt64Array *)p_self)->~PackedInt64Array();
}
@@ -119,6 +131,10 @@ void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *p_self) {
memnew_placement(p_self, PackedFloat32Array);
}
+void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src) {
+ memnew_placement(r_dest, PackedFloat32Array(*(PackedFloat32Array *)p_src));
+}
+
void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self) {
((PackedFloat32Array *)p_self)->~PackedFloat32Array();
}
@@ -139,6 +155,10 @@ void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *p_self) {
memnew_placement(p_self, PackedFloat64Array);
}
+void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src) {
+ memnew_placement(r_dest, PackedFloat64Array(*(PackedFloat64Array *)p_src));
+}
+
void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self) {
((PackedFloat64Array *)p_self)->~PackedFloat64Array();
}
@@ -159,6 +179,10 @@ void GDAPI godot_packed_string_array_new(godot_packed_string_array *p_self) {
memnew_placement(p_self, PackedStringArray);
}
+void GDAPI godot_packed_string_array_new_copy(godot_packed_string_array *r_dest, const godot_packed_string_array *p_src) {
+ memnew_placement(r_dest, PackedStringArray(*(PackedStringArray *)p_src));
+}
+
void GDAPI godot_packed_string_array_destroy(godot_packed_string_array *p_self) {
((PackedStringArray *)p_self)->~PackedStringArray();
}
@@ -179,6 +203,10 @@ void GDAPI godot_packed_vector2_array_new(godot_packed_vector2_array *p_self) {
memnew_placement(p_self, PackedVector2Array);
}
+void GDAPI godot_packed_vector2_array_new_copy(godot_packed_vector2_array *r_dest, const godot_packed_vector2_array *p_src) {
+ memnew_placement(r_dest, PackedVector2Array(*(PackedVector2Array *)p_src));
+}
+
void GDAPI godot_packed_vector2_array_destroy(godot_packed_vector2_array *p_self) {
((PackedVector2Array *)p_self)->~PackedVector2Array();
}
@@ -199,6 +227,10 @@ void GDAPI godot_packed_vector2i_array_new(godot_packed_vector2i_array *p_self)
memnew_placement(p_self, Vector<Vector2i>);
}
+void GDAPI godot_packed_vector2i_array_new_copy(godot_packed_vector2i_array *r_dest, const godot_packed_vector2i_array *p_src) {
+ memnew_placement(r_dest, Vector<Vector2i>(*(Vector<Vector2i> *)p_src));
+}
+
void GDAPI godot_packed_vector2i_array_destroy(godot_packed_vector2i_array *p_self) {
((Vector<Vector2i> *)p_self)->~Vector();
}
@@ -219,6 +251,10 @@ void GDAPI godot_packed_vector3_array_new(godot_packed_vector3_array *p_self) {
memnew_placement(p_self, PackedVector3Array);
}
+void GDAPI godot_packed_vector3_array_new_copy(godot_packed_vector3_array *r_dest, const godot_packed_vector3_array *p_src) {
+ memnew_placement(r_dest, PackedVector3Array(*(PackedVector3Array *)p_src));
+}
+
void GDAPI godot_packed_vector3_array_destroy(godot_packed_vector3_array *p_self) {
((PackedVector3Array *)p_self)->~PackedVector3Array();
}
@@ -239,6 +275,10 @@ void GDAPI godot_packed_vector3i_array_new(godot_packed_vector3i_array *p_self)
memnew_placement(p_self, Vector<Vector3i>);
}
+void GDAPI godot_packed_vector3i_array_new_copy(godot_packed_vector3i_array *r_dest, const godot_packed_vector3i_array *p_src) {
+ memnew_placement(r_dest, Vector<Vector3i>(*(Vector<Vector3i> *)p_src));
+}
+
void GDAPI godot_packed_vector3i_array_destroy(godot_packed_vector3i_array *p_self) {
((Vector<Vector3i> *)p_self)->~Vector();
}
@@ -259,6 +299,10 @@ void GDAPI godot_packed_color_array_new(godot_packed_color_array *p_self) {
memnew_placement(p_self, PackedColorArray);
}
+void GDAPI godot_packed_color_array_new_copy(godot_packed_color_array *r_dest, const godot_packed_color_array *p_src) {
+ memnew_placement(r_dest, PackedColorArray(*(PackedColorArray *)p_src));
+}
+
void GDAPI godot_packed_color_array_destroy(godot_packed_color_array *p_self) {
((PackedColorArray *)p_self)->~PackedColorArray();
}
diff --git a/modules/gdnative/gdnative/plane.cpp b/modules/gdnative/gdnative/plane.cpp
index 61d5e09fad..8b8e84e3c1 100644
--- a/modules/gdnative/gdnative/plane.cpp
+++ b/modules/gdnative/gdnative/plane.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_plane_new(godot_plane *p_self) {
memnew_placement(p_self, Plane);
}
+void GDAPI godot_plane_new_copy(godot_plane *r_dest, const godot_plane *p_src) {
+ memnew_placement(r_dest, Plane(*(Plane *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/quat.cpp b/modules/gdnative/gdnative/quat.cpp
index 836d6390d6..8ebcf7c91f 100644
--- a/modules/gdnative/gdnative/quat.cpp
+++ b/modules/gdnative/gdnative/quat.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_quat_new(godot_quat *p_self) {
memnew_placement(p_self, Quat);
}
+void GDAPI godot_quat_new_copy(godot_quat *r_dest, const godot_quat *p_src) {
+ memnew_placement(r_dest, Quat(*(Quat *)p_src));
+}
+
godot_real_t GDAPI *godot_quat_operator_index(godot_quat *p_self, godot_int p_index) {
Quat *self = (Quat *)p_self;
return (godot_real_t *)&self->operator[](p_index);
diff --git a/modules/gdnative/gdnative/rect2.cpp b/modules/gdnative/gdnative/rect2.cpp
index 086592ec22..a196a63188 100644
--- a/modules/gdnative/gdnative/rect2.cpp
+++ b/modules/gdnative/gdnative/rect2.cpp
@@ -43,10 +43,18 @@ void GDAPI godot_rect2_new(godot_rect2 *p_self) {
memnew_placement(p_self, Rect2);
}
+void GDAPI godot_rect2_new_copy(godot_rect2 *r_dest, const godot_rect2 *p_src) {
+ memnew_placement(r_dest, Rect2(*(Rect2 *)p_src));
+}
+
void GDAPI godot_rect2i_new(godot_rect2i *p_self) {
memnew_placement(p_self, Rect2i);
}
+void GDAPI godot_rect2i_new_copy(godot_rect2i *r_dest, const godot_rect2i *p_src) {
+ memnew_placement(r_dest, Rect2i(*(Rect2i *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/rid.cpp b/modules/gdnative/gdnative/rid.cpp
index 5cab9a21ed..f8599afcf9 100644
--- a/modules/gdnative/gdnative/rid.cpp
+++ b/modules/gdnative/gdnative/rid.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_rid_new(godot_rid *p_self) {
memnew_placement(p_self, RID);
}
+void GDAPI godot_rid_new_copy(godot_rid *r_dest, const godot_rid *p_src) {
+ memnew_placement(r_dest, RID(*(RID *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/signal.cpp b/modules/gdnative/gdnative/signal.cpp
index bcb4c93b62..5963c0e6c6 100644
--- a/modules/gdnative/gdnative/signal.cpp
+++ b/modules/gdnative/gdnative/signal.cpp
@@ -43,6 +43,10 @@ void GDAPI godot_signal_new(godot_signal *p_self) {
memnew_placement(p_self, Signal);
}
+void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src) {
+ memnew_placement(r_dest, Signal(*(Signal *)p_src));
+}
+
void GDAPI godot_signal_destroy(godot_signal *p_self) {
Signal *self = (Signal *)p_self;
self->~Signal();
diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp
index 19d95f2048..1ad1ea8bdf 100644
--- a/modules/gdnative/gdnative/string.cpp
+++ b/modules/gdnative/gdnative/string.cpp
@@ -45,10 +45,7 @@ void GDAPI godot_string_new(godot_string *r_dest) {
}
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src) {
- String *dest = (String *)r_dest;
- const String *src = (const String *)p_src;
- memnew_placement(dest, String);
- *dest = String(*src);
+ memnew_placement(r_dest, String(*(String *)p_src));
}
void GDAPI godot_string_new_with_latin1_chars(godot_string *r_dest, const char *p_contents) {
@@ -125,6 +122,45 @@ void GDAPI godot_string_new_with_wide_chars_and_len(godot_string *r_dest, const
}
}
+const char GDAPI *godot_string_to_latin1_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->ascii(true).get_data();
+}
+
+const char GDAPI *godot_string_to_utf8_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->utf8().get_data();
+}
+
+const char16_t GDAPI *godot_string_to_utf16_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->utf16().get_data();
+}
+
+const char32_t GDAPI *godot_string_to_utf32_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ return self->get_data();
+}
+
+const wchar_t GDAPI *godot_string_to_wide_chars(const godot_string *p_self) {
+ String *self = (String *)p_self;
+ if (sizeof(wchar_t) == 2) {
+ return (const wchar_t *)self->utf16().get_data();
+ } else {
+ return (const wchar_t *)self->get_data();
+ }
+}
+
+char32_t GDAPI *godot_string_operator_index(godot_string *p_self, godot_int p_index) {
+ String *self = (String *)p_self;
+ return self->ptrw();
+}
+
+const char32_t GDAPI *godot_string_operator_index_const(const godot_string *p_self, godot_int p_index) {
+ const String *self = (const String *)p_self;
+ return self->ptr();
+}
+
void GDAPI godot_string_destroy(godot_string *p_self) {
String *self = (String *)p_self;
self->~String();
diff --git a/modules/gdnative/gdnative/string_name.cpp b/modules/gdnative/gdnative/string_name.cpp
index c9d2dd5bc3..bd8f69674e 100644
--- a/modules/gdnative/gdnative/string_name.cpp
+++ b/modules/gdnative/gdnative/string_name.cpp
@@ -44,9 +44,7 @@ void GDAPI godot_string_name_new(godot_string_name *r_dest) {
}
void GDAPI godot_string_name_new_copy(godot_string_name *r_dest, const godot_string_name *p_src) {
- StringName *dest = (StringName *)r_dest;
- const StringName *src = (const StringName *)p_src;
- memnew_placement(dest, StringName(*src));
+ memnew_placement(r_dest, StringName(*(StringName *)p_src));
}
void GDAPI godot_string_name_new_with_latin1_chars(godot_string_name *r_dest, const char *p_contents) {
diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp
index eae981bd07..bfaaa13db2 100644
--- a/modules/gdnative/gdnative/transform.cpp
+++ b/modules/gdnative/gdnative/transform.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_transform_new(godot_transform *p_self) {
memnew_placement(p_self, Transform);
}
+void GDAPI godot_transform_new_copy(godot_transform *r_dest, const godot_transform *p_src) {
+ memnew_placement(r_dest, Transform(*(Transform *)p_src));
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/gdnative/transform2d.cpp b/modules/gdnative/gdnative/transform2d.cpp
index 679174d5a5..2864818831 100644
--- a/modules/gdnative/gdnative/transform2d.cpp
+++ b/modules/gdnative/gdnative/transform2d.cpp
@@ -42,6 +42,10 @@ void GDAPI godot_transform2d_new(godot_transform2d *p_self) {
memnew_placement(p_self, Transform2D);
}
+void GDAPI godot_transform2d_new_copy(godot_transform2d *r_dest, const godot_transform2d *p_src) {
+ memnew_placement(r_dest, Transform2D(*(Transform2D *)p_src));
+}
+
godot_vector2 GDAPI *godot_transform2d_operator_index(godot_transform2d *p_self, godot_int p_index) {
Transform2D *self = (Transform2D *)p_self;
return (godot_vector2 *)&self->operator[](p_index);
diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index ee4353bb48..7801e21ab2 100644
--- a/modules/gdnative/gdnative/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -577,6 +577,54 @@ void GDAPI godot_variant_call(godot_variant *p_self, const godot_string_name *p_
}
}
+void GDAPI godot_variant_call_with_cstring(godot_variant *p_self, const char *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant *r_return, godot_variant_call_error *r_error) {
+ Variant *self = (Variant *)p_self;
+ const StringName method(p_method);
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ self->call(method, args, p_argcount, ret, error);
+ memnew_placement_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (godot_variant_call_error_error)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = (godot_variant_type)error.expected;
+ }
+}
+
+void GDAPI godot_variant_call_static(godot_variant_type p_type, const godot_string_name *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant *r_return, godot_variant_call_error *r_error) {
+ Variant::Type type = (Variant::Type)p_type;
+ const StringName *method = (const StringName *)p_method;
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ Variant::call_static(type, *method, args, p_argcount, ret, error);
+ memnew_placement_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (godot_variant_call_error_error)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = (godot_variant_type)error.expected;
+ }
+}
+
+void GDAPI godot_variant_call_static_with_cstring(godot_variant_type p_type, const char *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant *r_return, godot_variant_call_error *r_error) {
+ Variant::Type type = (Variant::Type)p_type;
+ const StringName method(p_method);
+ const Variant **args = (const Variant **)p_args;
+ Variant ret;
+ Callable::CallError error;
+ Variant::call_static(type, method, args, p_argcount, ret, error);
+ memnew_placement_custom(r_return, Variant, Variant(ret));
+
+ if (r_error) {
+ r_error->error = (godot_variant_call_error_error)error.error;
+ r_error->argument = error.argument;
+ r_error->expected = (godot_variant_type)error.expected;
+ }
+}
+
void GDAPI godot_variant_evaluate(godot_variant_operator p_op, const godot_variant *p_a, const godot_variant *p_b, godot_variant *r_return, bool *r_valid) {
Variant::Operator op = (Variant::Operator)p_op;
const Variant *a = (const Variant *)p_a;
@@ -593,12 +641,20 @@ void GDAPI godot_variant_set(godot_variant *p_self, const godot_variant *p_key,
self->set(*key, *value, r_valid);
}
-void GDAPI godot_variant_set_named(godot_variant *p_self, const godot_string_name *p_name, const godot_variant *p_value, bool *r_valid) {
+void GDAPI godot_variant_set_named(godot_variant *p_self, const godot_string_name *p_key, const godot_variant *p_value, bool *r_valid) {
+ Variant *self = (Variant *)p_self;
+ const StringName *key = (const StringName *)p_key;
+ const Variant *value = (const Variant *)p_value;
+
+ self->set_named(*key, *value, *r_valid);
+}
+
+void GDAPI godot_variant_set_named_with_cstring(godot_variant *p_self, const char *p_key, const godot_variant *p_value, bool *r_valid) {
Variant *self = (Variant *)p_self;
- const StringName *name = (const StringName *)p_name;
+ const StringName key(p_key);
const Variant *value = (const Variant *)p_value;
- self->set_named(*name, *value, *r_valid);
+ self->set_named(key, *value, *r_valid);
}
void GDAPI godot_variant_set_keyed(godot_variant *p_self, const godot_variant *p_key, const godot_variant *p_value, bool *r_valid) {
@@ -638,6 +694,17 @@ godot_variant GDAPI godot_variant_get_named(const godot_variant *p_self, const g
return result;
}
+godot_variant GDAPI godot_variant_get_named_with_cstring(const godot_variant *p_self, const char *p_key, bool *r_valid) {
+ const Variant *self = (const Variant *)p_self;
+ const StringName *key = (const StringName *)p_key;
+ Variant ret;
+
+ ret = self->get_named(*key, *r_valid);
+ godot_variant result;
+ memnew_placement_custom(&result, Variant, Variant(ret));
+ return result;
+}
+
godot_variant GDAPI godot_variant_get_keyed(const godot_variant *p_self, const godot_variant *p_key, bool *r_valid) {
const Variant *self = (const Variant *)p_self;
const Variant *key = (const Variant *)p_key;
@@ -824,6 +891,14 @@ bool GDAPI godot_variant_is_builtin_method_const_with_cstring(godot_variant_type
return Variant::is_builtin_method_const((Variant::Type)p_type, StringName(p_method));
}
+bool GDAPI godot_variant_is_builtin_method_static(godot_variant_type p_type, const godot_string_name *p_method) {
+ return Variant::is_builtin_method_static((Variant::Type)p_type, *((const StringName *)p_method));
+}
+
+bool GDAPI godot_variant_is_builtin_method_static_with_cstring(godot_variant_type p_type, const char *p_method) {
+ return Variant::is_builtin_method_static((Variant::Type)p_type, StringName(p_method));
+}
+
bool GDAPI godot_variant_is_builtin_method_vararg(godot_variant_type p_type, const godot_string_name *p_method) {
return Variant::is_builtin_method_vararg((Variant::Type)p_type, *((const StringName *)p_method));
}
diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index ebb1996649..6a01a7ad59 100644
--- a/modules/gdnative/gdnative/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -43,10 +43,18 @@ void GDAPI godot_vector2_new(godot_vector2 *p_self) {
memnew_placement(p_self, Vector2);
}
+void GDAPI godot_vector2_new_copy(godot_vector2 *r_dest, const godot_vector2 *p_src) {
+ memnew_placement(r_dest, Vector2(*(Vector2 *)p_src));
+}
+
void GDAPI godot_vector2i_new(godot_vector2i *p_self) {
memnew_placement(p_self, Vector2i);
}
+void GDAPI godot_vector2i_new_copy(godot_vector2i *r_dest, const godot_vector2i *p_src) {
+ memnew_placement(r_dest, Vector2i(*(Vector2i *)p_src));
+}
+
godot_real_t GDAPI *godot_vector2_operator_index(godot_vector2 *p_self, godot_int p_index) {
Vector2 *self = (Vector2 *)p_self;
return (godot_real_t *)&self->operator[](p_index);
diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index 0fe1b292a7..fb426c8ac4 100644
--- a/modules/gdnative/gdnative/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -43,10 +43,18 @@ void GDAPI godot_vector3_new(godot_vector3 *p_self) {
memnew_placement(p_self, Vector3);
}
+void GDAPI godot_vector3_new_copy(godot_vector3 *r_dest, const godot_vector3 *p_src) {
+ memnew_placement(r_dest, Vector3(*(Vector3 *)p_src));
+}
+
void GDAPI godot_vector3i_new(godot_vector3i *p_self) {
memnew_placement(p_self, Vector3i);
}
+void GDAPI godot_vector3i_new_copy(godot_vector3i *r_dest, const godot_vector3i *p_src) {
+ memnew_placement(r_dest, Vector3i(*(Vector3i *)p_src));
+}
+
godot_real_t GDAPI *godot_vector3_operator_index(godot_vector3 *p_self, godot_int p_index) {
Vector3 *self = (Vector3 *)p_self;
return (godot_real_t *)&self->operator[](p_index);
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index c163fbbc1b..59b078f2b6 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -1143,6 +1143,36 @@
]
},
{
+ "name": "godot_variant_call_with_cstring",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_variant *",
+ "p_self"
+ ],
+ [
+ "const char *",
+ "p_method"
+ ],
+ [
+ "const godot_variant **",
+ "p_args"
+ ],
+ [
+ "const godot_int",
+ "p_argument_count"
+ ],
+ [
+ "godot_variant *",
+ "r_return"
+ ],
+ [
+ "godot_variant_call_error *",
+ "r_error"
+ ]
+ ]
+ },
+ {
"name": "godot_variant_evaluate",
"return_type": "void",
"arguments": [
@@ -1200,7 +1230,29 @@
],
[
"const godot_string_name *",
- "p_name"
+ "p_key"
+ ],
+ [
+ "const godot_variant *",
+ "p_value"
+ ],
+ [
+ "bool *",
+ "r_valid"
+ ]
+ ]
+ },
+ {
+ "name": "godot_variant_set_named_with_cstring",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_variant *",
+ "p_self"
+ ],
+ [
+ "const char *",
+ "p_key"
],
[
"const godot_variant *",
@@ -1297,6 +1349,24 @@
]
},
{
+ "name": "godot_variant_get_named_with_cstring",
+ "return_type": "godot_variant",
+ "arguments": [
+ [
+ "const godot_variant *",
+ "p_self"
+ ],
+ [
+ "const char *",
+ "p_key"
+ ],
+ [
+ "bool *",
+ "r_valid"
+ ]
+ ]
+ },
+ {
"name": "godot_variant_get_keyed",
"return_type": "godot_variant",
"arguments": [
@@ -1815,6 +1885,34 @@
]
},
{
+ "name": "godot_variant_is_builtin_method_static",
+ "return_type": "bool",
+ "arguments": [
+ [
+ "godot_variant_type",
+ "p_type"
+ ],
+ [
+ "const godot_string_name *",
+ "p_method"
+ ]
+ ]
+ },
+ {
+ "name": "godot_variant_is_builtin_method_static_with_cstring",
+ "return_type": "bool",
+ "arguments": [
+ [
+ "godot_variant_type",
+ "p_type"
+ ],
+ [
+ "const char *",
+ "p_method"
+ ]
+ ]
+ },
+ {
"name": "godot_variant_is_builtin_method_vararg",
"return_type": "bool",
"arguments": [
@@ -2752,6 +2850,20 @@
]
},
{
+ "name": "godot_aabb_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_aabb *",
+ "r_dest"
+ ],
+ [
+ "const godot_aabb *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_array_new",
"return_type": "void",
"arguments": [
@@ -2762,6 +2874,20 @@
]
},
{
+ "name": "godot_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_array_destroy",
"return_type": "void",
"arguments": [
@@ -2810,6 +2936,20 @@
]
},
{
+ "name": "godot_basis_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_basis *",
+ "r_dest"
+ ],
+ [
+ "const godot_basis *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_basis_operator_index",
"return_type": "godot_vector3 *",
"arguments": [
@@ -2848,6 +2988,20 @@
]
},
{
+ "name": "godot_callable_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_callable *",
+ "r_dest"
+ ],
+ [
+ "const godot_callable *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_callable_destroy",
"return_type": "void",
"arguments": [
@@ -2868,6 +3022,20 @@
]
},
{
+ "name": "godot_color_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_color *",
+ "r_dest"
+ ],
+ [
+ "const godot_color *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_color_operator_index",
"return_type": "float *",
"arguments": [
@@ -2906,6 +3074,20 @@
]
},
{
+ "name": "godot_dictionary_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_dictionary *",
+ "r_dest"
+ ],
+ [
+ "const godot_dictionary *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_dictionary_destroy",
"return_type": "void",
"arguments": [
@@ -2954,6 +3136,20 @@
]
},
{
+ "name": "godot_node_path_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_node_path *",
+ "r_dest"
+ ],
+ [
+ "const godot_node_path *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_node_path_destroy",
"return_type": "void",
"arguments": [
@@ -2974,6 +3170,20 @@
]
},
{
+ "name": "godot_packed_byte_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_byte_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_byte_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_byte_array_destroy",
"return_type": "void",
"arguments": [
@@ -3022,6 +3232,20 @@
]
},
{
+ "name": "godot_packed_int32_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_int32_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_int32_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_int32_array_destroy",
"return_type": "void",
"arguments": [
@@ -3070,6 +3294,20 @@
]
},
{
+ "name": "godot_packed_int64_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_int64_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_int64_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_int64_array_destroy",
"return_type": "void",
"arguments": [
@@ -3118,6 +3356,20 @@
]
},
{
+ "name": "godot_packed_float32_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_float32_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_float32_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_float32_array_destroy",
"return_type": "void",
"arguments": [
@@ -3166,6 +3418,20 @@
]
},
{
+ "name": "godot_packed_float64_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_float64_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_float64_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_float64_array_destroy",
"return_type": "void",
"arguments": [
@@ -3214,6 +3480,20 @@
]
},
{
+ "name": "godot_packed_string_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_string_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_string_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_string_array_destroy",
"return_type": "void",
"arguments": [
@@ -3262,6 +3542,20 @@
]
},
{
+ "name": "godot_packed_vector2_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector2_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector2_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector2_array_destroy",
"return_type": "void",
"arguments": [
@@ -3310,6 +3604,20 @@
]
},
{
+ "name": "godot_packed_vector2i_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector2i_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector2i_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector2i_array_destroy",
"return_type": "void",
"arguments": [
@@ -3358,6 +3666,20 @@
]
},
{
+ "name": "godot_packed_vector3_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector3_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector3_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector3_array_destroy",
"return_type": "void",
"arguments": [
@@ -3406,6 +3728,20 @@
]
},
{
+ "name": "godot_packed_vector3i_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_vector3i_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_vector3i_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_vector3i_array_destroy",
"return_type": "void",
"arguments": [
@@ -3454,6 +3790,20 @@
]
},
{
+ "name": "godot_packed_color_array_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_packed_color_array *",
+ "r_dest"
+ ],
+ [
+ "const godot_packed_color_array *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_packed_color_array_destroy",
"return_type": "void",
"arguments": [
@@ -3502,6 +3852,20 @@
]
},
{
+ "name": "godot_plane_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_plane *",
+ "r_dest"
+ ],
+ [
+ "const godot_plane *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_quat_new",
"return_type": "void",
"arguments": [
@@ -3512,6 +3876,20 @@
]
},
{
+ "name": "godot_quat_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_quat *",
+ "r_dest"
+ ],
+ [
+ "const godot_quat *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_quat_operator_index",
"return_type": "godot_real_t *",
"arguments": [
@@ -3550,6 +3928,20 @@
]
},
{
+ "name": "godot_rect2_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_rect2 *",
+ "r_dest"
+ ],
+ [
+ "const godot_rect2 *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_rect2i_new",
"return_type": "void",
"arguments": [
@@ -3560,6 +3952,20 @@
]
},
{
+ "name": "godot_rect2i_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_rect2i *",
+ "r_dest"
+ ],
+ [
+ "const godot_rect2i *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_rid_new",
"return_type": "void",
"arguments": [
@@ -3570,6 +3976,20 @@
]
},
{
+ "name": "godot_rid_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_rid *",
+ "r_dest"
+ ],
+ [
+ "const godot_rid *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_signal_new",
"return_type": "void",
"arguments": [
@@ -3580,6 +4000,20 @@
]
},
{
+ "name": "godot_signal_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_signal *",
+ "r_dest"
+ ],
+ [
+ "const godot_signal *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_signal_destroy",
"return_type": "void",
"arguments": [
@@ -3784,6 +4218,84 @@
]
},
{
+ "name": "godot_string_to_latin1_chars",
+ "return_type": "const char *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_utf8_chars",
+ "return_type": "const char *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_utf16_chars",
+ "return_type": "const char16_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_utf32_chars",
+ "return_type": "const char32_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_to_wide_chars",
+ "return_type": "const wchar_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_operator_index",
+ "return_type": "char32_t *",
+ "arguments": [
+ [
+ "godot_string *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
+ "name": "godot_string_operator_index_const",
+ "return_type": "const char32_t *",
+ "arguments": [
+ [
+ "const godot_string *",
+ "p_self"
+ ],
+ [
+ "godot_int",
+ "p_index"
+ ]
+ ]
+ },
+ {
"name": "godot_string_name_new",
"return_type": "void",
"arguments": [
@@ -3842,6 +4354,20 @@
]
},
{
+ "name": "godot_transform_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_transform *",
+ "r_dest"
+ ],
+ [
+ "const godot_transform *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_transform2d_new",
"return_type": "void",
"arguments": [
@@ -3852,6 +4378,20 @@
]
},
{
+ "name": "godot_transform2d_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_transform2d *",
+ "r_dest"
+ ],
+ [
+ "const godot_transform2d *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_transform2d_operator_index",
"return_type": "godot_vector2 *",
"arguments": [
@@ -3890,6 +4430,20 @@
]
},
{
+ "name": "godot_vector2_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector2 *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector2 *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_vector2_operator_index",
"return_type": "godot_real_t *",
"arguments": [
@@ -3928,6 +4482,20 @@
]
},
{
+ "name": "godot_vector2i_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector2i *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector2i *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_vector2i_operator_index",
"return_type": "int32_t *",
"arguments": [
@@ -3966,6 +4534,20 @@
]
},
{
+ "name": "godot_vector3_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector3 *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector3 *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_vector3_operator_index",
"return_type": "godot_real_t *",
"arguments": [
@@ -4004,6 +4586,20 @@
]
},
{
+ "name": "godot_vector3i_new_copy",
+ "return_type": "void",
+ "arguments": [
+ [
+ "godot_vector3i *",
+ "r_dest"
+ ],
+ [
+ "const godot_vector3i *",
+ "p_src"
+ ]
+ ]
+ },
+ {
"name": "godot_vector3i_operator_index",
"return_type": "int32_t *",
"arguments": [
diff --git a/modules/gdnative/include/gdnative/aabb.h b/modules/gdnative/include/gdnative/aabb.h
index be0235221f..860675065d 100644
--- a/modules/gdnative/include/gdnative/aabb.h
+++ b/modules/gdnative/include/gdnative/aabb.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_aabb_new(godot_aabb *p_self);
+void GDAPI godot_aabb_new_copy(godot_aabb *r_dest, const godot_aabb *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h
index 7603edaa73..bf4b852449 100644
--- a/modules/gdnative/include/gdnative/array.h
+++ b/modules/gdnative/include/gdnative/array.h
@@ -50,6 +50,7 @@ typedef struct {
#include <gdnative/variant_struct.h>
void GDAPI godot_array_new(godot_array *p_self);
+void GDAPI godot_array_new_copy(godot_array *r_dest, const godot_array *p_src);
void GDAPI godot_array_destroy(godot_array *p_self);
godot_variant GDAPI *godot_array_operator_index(godot_array *p_self, godot_int p_index);
const godot_variant GDAPI *godot_array_operator_index_const(const godot_array *p_self, godot_int p_index);
diff --git a/modules/gdnative/include/gdnative/basis.h b/modules/gdnative/include/gdnative/basis.h
index af8d7cbdd3..5477dbf811 100644
--- a/modules/gdnative/include/gdnative/basis.h
+++ b/modules/gdnative/include/gdnative/basis.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_basis_new(godot_basis *p_self);
+void GDAPI godot_basis_new_copy(godot_basis *r_dest, const godot_basis *p_src);
godot_vector3 GDAPI *godot_basis_operator_index(godot_basis *p_self, godot_int p_index);
const godot_vector3 GDAPI *godot_basis_operator_index_const(const godot_basis *p_self, godot_int p_index);
diff --git a/modules/gdnative/include/gdnative/callable.h b/modules/gdnative/include/gdnative/callable.h
index 6f359ada5e..b84b0c1f1f 100644
--- a/modules/gdnative/include/gdnative/callable.h
+++ b/modules/gdnative/include/gdnative/callable.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_callable_new(godot_callable *p_self);
+void GDAPI godot_callable_new_copy(godot_callable *r_dest, const godot_callable *p_src);
void GDAPI godot_callable_destroy(godot_callable *p_self);
#ifdef __cplusplus
diff --git a/modules/gdnative/include/gdnative/color.h b/modules/gdnative/include/gdnative/color.h
index 17a021e6ea..3334013147 100644
--- a/modules/gdnative/include/gdnative/color.h
+++ b/modules/gdnative/include/gdnative/color.h
@@ -50,6 +50,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_color_new(godot_color *p_self);
+void GDAPI godot_color_new_copy(godot_color *r_dest, const godot_color *p_src);
float GDAPI *godot_color_operator_index(godot_color *p_self, godot_int p_index);
const float GDAPI *godot_color_operator_index_const(const godot_color *p_self, godot_int p_index);
diff --git a/modules/gdnative/include/gdnative/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h
index d2afbc4c94..b9525fb5e6 100644
--- a/modules/gdnative/include/gdnative/dictionary.h
+++ b/modules/gdnative/include/gdnative/dictionary.h
@@ -50,6 +50,7 @@ typedef struct {
#include <gdnative/variant_struct.h>
void GDAPI godot_dictionary_new(godot_dictionary *p_self);
+void GDAPI godot_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src);
void GDAPI godot_dictionary_destroy(godot_dictionary *p_self);
godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_self, const godot_variant *p_key);
const godot_variant GDAPI *godot_dictionary_operator_index_const(const godot_dictionary *p_self, const godot_variant *p_key);
diff --git a/modules/gdnative/include/gdnative/node_path.h b/modules/gdnative/include/gdnative/node_path.h
index 3c31b9a98f..a4607c0152 100644
--- a/modules/gdnative/include/gdnative/node_path.h
+++ b/modules/gdnative/include/gdnative/node_path.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_node_path_new(godot_node_path *p_self);
+void GDAPI godot_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src);
void GDAPI godot_node_path_destroy(godot_node_path *p_self);
#ifdef __cplusplus
diff --git a/modules/gdnative/include/gdnative/packed_arrays.h b/modules/gdnative/include/gdnative/packed_arrays.h
index 621ed60cdf..f9e4ba3a8d 100644
--- a/modules/gdnative/include/gdnative/packed_arrays.h
+++ b/modules/gdnative/include/gdnative/packed_arrays.h
@@ -163,6 +163,7 @@ typedef struct {
// Byte.
void GDAPI godot_packed_byte_array_new(godot_packed_byte_array *p_self);
+void GDAPI godot_packed_byte_array_new_copy(godot_packed_byte_array *r_dest, const godot_packed_byte_array *p_src);
void GDAPI godot_packed_byte_array_destroy(godot_packed_byte_array *p_self);
uint8_t GDAPI *godot_packed_byte_array_operator_index(godot_packed_byte_array *p_self, godot_int p_index);
const uint8_t GDAPI *godot_packed_byte_array_operator_index_const(const godot_packed_byte_array *p_self, godot_int p_index);
@@ -170,6 +171,7 @@ const uint8_t GDAPI *godot_packed_byte_array_operator_index_const(const godot_pa
// Int32.
void GDAPI godot_packed_int32_array_new(godot_packed_int32_array *p_self);
+void GDAPI godot_packed_int32_array_new_copy(godot_packed_int32_array *r_dest, const godot_packed_int32_array *p_src);
void GDAPI godot_packed_int32_array_destroy(godot_packed_int32_array *p_self);
int32_t GDAPI *godot_packed_int32_array_operator_index(godot_packed_int32_array *p_self, godot_int p_index);
const int32_t GDAPI *godot_packed_int32_array_operator_index_const(const godot_packed_int32_array *p_self, godot_int p_index);
@@ -177,6 +179,7 @@ const int32_t GDAPI *godot_packed_int32_array_operator_index_const(const godot_p
// Int64.
void GDAPI godot_packed_int64_array_new(godot_packed_int64_array *p_self);
+void GDAPI godot_packed_int64_array_new_copy(godot_packed_int64_array *r_dest, const godot_packed_int64_array *p_src);
void GDAPI godot_packed_int64_array_destroy(godot_packed_int64_array *p_self);
int64_t GDAPI *godot_packed_int64_array_operator_index(godot_packed_int64_array *p_self, godot_int p_index);
const int64_t GDAPI *godot_packed_int64_array_operator_index_const(const godot_packed_int64_array *p_self, godot_int p_index);
@@ -184,6 +187,7 @@ const int64_t GDAPI *godot_packed_int64_array_operator_index_const(const godot_p
// Float32.
void GDAPI godot_packed_float32_array_new(godot_packed_float32_array *p_self);
+void GDAPI godot_packed_float32_array_new_copy(godot_packed_float32_array *r_dest, const godot_packed_float32_array *p_src);
void GDAPI godot_packed_float32_array_destroy(godot_packed_float32_array *p_self);
float GDAPI *godot_packed_float32_array_operator_index(godot_packed_float32_array *p_self, godot_int p_index);
const float GDAPI *godot_packed_float32_array_operator_index_const(const godot_packed_float32_array *p_self, godot_int p_index);
@@ -191,6 +195,7 @@ const float GDAPI *godot_packed_float32_array_operator_index_const(const godot_p
// Float64.
void GDAPI godot_packed_float64_array_new(godot_packed_float64_array *p_self);
+void GDAPI godot_packed_float64_array_new_copy(godot_packed_float64_array *r_dest, const godot_packed_float64_array *p_src);
void GDAPI godot_packed_float64_array_destroy(godot_packed_float64_array *p_self);
double GDAPI *godot_packed_float64_array_operator_index(godot_packed_float64_array *p_self, godot_int p_index);
const double GDAPI *godot_packed_float64_array_operator_index_const(const godot_packed_float64_array *p_self, godot_int p_index);
@@ -198,6 +203,7 @@ const double GDAPI *godot_packed_float64_array_operator_index_const(const godot_
// String.
void GDAPI godot_packed_string_array_new(godot_packed_string_array *p_self);
+void GDAPI godot_packed_string_array_new_copy(godot_packed_string_array *r_dest, const godot_packed_string_array *p_src);
void GDAPI godot_packed_string_array_destroy(godot_packed_string_array *p_self);
godot_string GDAPI *godot_packed_string_array_operator_index(godot_packed_string_array *p_self, godot_int p_index);
const godot_string GDAPI *godot_packed_string_array_operator_index_const(const godot_packed_string_array *p_self, godot_int p_index);
@@ -205,6 +211,7 @@ const godot_string GDAPI *godot_packed_string_array_operator_index_const(const g
// Vector2.
void GDAPI godot_packed_vector2_array_new(godot_packed_vector2_array *p_self);
+void GDAPI godot_packed_vector2_array_new_copy(godot_packed_vector2_array *r_dest, const godot_packed_vector2_array *p_src);
void GDAPI godot_packed_vector2_array_destroy(godot_packed_vector2_array *p_self);
godot_vector2 GDAPI *godot_packed_vector2_array_operator_index(godot_packed_vector2_array *p_self, godot_int p_index);
const godot_vector2 GDAPI *godot_packed_vector2_array_operator_index_const(const godot_packed_vector2_array *p_self, godot_int p_index);
@@ -212,6 +219,7 @@ const godot_vector2 GDAPI *godot_packed_vector2_array_operator_index_const(const
// Vector2i.
void GDAPI godot_packed_vector2i_array_new(godot_packed_vector2i_array *p_self);
+void GDAPI godot_packed_vector2i_array_new_copy(godot_packed_vector2i_array *r_dest, const godot_packed_vector2i_array *p_src);
void GDAPI godot_packed_vector2i_array_destroy(godot_packed_vector2i_array *p_self);
godot_vector2i GDAPI *godot_packed_vector2i_array_operator_index(godot_packed_vector2i_array *p_self, godot_int p_index);
const godot_vector2i GDAPI *godot_packed_vector2i_array_operator_index_const(const godot_packed_vector2i_array *p_self, godot_int p_index);
@@ -219,6 +227,7 @@ const godot_vector2i GDAPI *godot_packed_vector2i_array_operator_index_const(con
// Vector3.
void GDAPI godot_packed_vector3_array_new(godot_packed_vector3_array *p_self);
+void GDAPI godot_packed_vector3_array_new_copy(godot_packed_vector3_array *r_dest, const godot_packed_vector3_array *p_src);
void GDAPI godot_packed_vector3_array_destroy(godot_packed_vector3_array *p_self);
godot_vector3 GDAPI *godot_packed_vector3_array_operator_index(godot_packed_vector3_array *p_self, godot_int p_index);
const godot_vector3 GDAPI *godot_packed_vector3_array_operator_index_const(const godot_packed_vector3_array *p_self, godot_int p_index);
@@ -226,6 +235,7 @@ const godot_vector3 GDAPI *godot_packed_vector3_array_operator_index_const(const
// Vector3i.
void GDAPI godot_packed_vector3i_array_new(godot_packed_vector3i_array *p_self);
+void GDAPI godot_packed_vector3i_array_new_copy(godot_packed_vector3i_array *r_dest, const godot_packed_vector3i_array *p_src);
void GDAPI godot_packed_vector3i_array_destroy(godot_packed_vector3i_array *p_self);
godot_vector3i GDAPI *godot_packed_vector3i_array_operator_index(godot_packed_vector3i_array *p_self, godot_int p_index);
const godot_vector3i GDAPI *godot_packed_vector3i_array_operator_index_const(const godot_packed_vector3i_array *p_self, godot_int p_index);
@@ -233,6 +243,7 @@ const godot_vector3i GDAPI *godot_packed_vector3i_array_operator_index_const(con
// Color.
void GDAPI godot_packed_color_array_new(godot_packed_color_array *p_self);
+void GDAPI godot_packed_color_array_new_copy(godot_packed_color_array *r_dest, const godot_packed_color_array *p_src);
void GDAPI godot_packed_color_array_destroy(godot_packed_color_array *p_self);
godot_color GDAPI *godot_packed_color_array_operator_index(godot_packed_color_array *p_self, godot_int p_index);
const godot_color GDAPI *godot_packed_color_array_operator_index_const(const godot_packed_color_array *p_self, godot_int p_index);
diff --git a/modules/gdnative/include/gdnative/plane.h b/modules/gdnative/include/gdnative/plane.h
index ed10955e5f..6cd0ed6307 100644
--- a/modules/gdnative/include/gdnative/plane.h
+++ b/modules/gdnative/include/gdnative/plane.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_plane_new(godot_plane *p_self);
+void GDAPI godot_plane_new_copy(godot_plane *r_dest, const godot_plane *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/quat.h b/modules/gdnative/include/gdnative/quat.h
index 69bf427611..00abdb4404 100644
--- a/modules/gdnative/include/gdnative/quat.h
+++ b/modules/gdnative/include/gdnative/quat.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_quat_new(godot_quat *p_self);
+void GDAPI godot_quat_new_copy(godot_quat *r_dest, const godot_quat *p_src);
godot_real_t GDAPI *godot_quat_operator_index(godot_quat *p_self, godot_int p_index);
const godot_real_t GDAPI *godot_quat_operator_index_const(const godot_quat *p_self, godot_int p_index);
diff --git a/modules/gdnative/include/gdnative/rect2.h b/modules/gdnative/include/gdnative/rect2.h
index 9e51254cfe..326462be43 100644
--- a/modules/gdnative/include/gdnative/rect2.h
+++ b/modules/gdnative/include/gdnative/rect2.h
@@ -58,7 +58,9 @@ typedef struct godot_rect2i {
#include <gdnative/gdnative.h>
void GDAPI godot_rect2_new(godot_rect2 *p_self);
+void GDAPI godot_rect2_new_copy(godot_rect2 *r_dest, const godot_rect2 *p_src);
void GDAPI godot_rect2i_new(godot_rect2i *p_self);
+void GDAPI godot_rect2i_new_copy(godot_rect2i *r_dest, const godot_rect2i *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/rid.h b/modules/gdnative/include/gdnative/rid.h
index 7ea8cfd174..bc832fbeb9 100644
--- a/modules/gdnative/include/gdnative/rid.h
+++ b/modules/gdnative/include/gdnative/rid.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_rid_new(godot_rid *p_self);
+void GDAPI godot_rid_new_copy(godot_rid *r_dest, const godot_rid *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/signal.h b/modules/gdnative/include/gdnative/signal.h
index ad84542677..f4dc17e089 100644
--- a/modules/gdnative/include/gdnative/signal.h
+++ b/modules/gdnative/include/gdnative/signal.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_signal_new(godot_signal *p_self);
+void GDAPI godot_signal_new_copy(godot_signal *r_dest, const godot_signal *p_src);
void GDAPI godot_signal_destroy(godot_signal *p_self);
#ifdef __cplusplus
diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h
index 10fbb2c078..79de52c80f 100644
--- a/modules/gdnative/include/gdnative/string.h
+++ b/modules/gdnative/include/gdnative/string.h
@@ -55,6 +55,7 @@ typedef struct {
#endif
#include <gdnative/gdnative.h>
+#include <gdnative/math_defs.h>
void GDAPI godot_string_new(godot_string *r_dest);
void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src);
@@ -72,6 +73,15 @@ void GDAPI godot_string_new_with_utf16_chars_and_len(godot_string *r_dest, const
void GDAPI godot_string_new_with_utf32_chars_and_len(godot_string *r_dest, const char32_t *p_contents, const int p_size);
void GDAPI godot_string_new_with_wide_chars_and_len(godot_string *r_dest, const wchar_t *p_contents, const int p_size);
+const char GDAPI *godot_string_to_latin1_chars(const godot_string *p_self);
+const char GDAPI *godot_string_to_utf8_chars(const godot_string *p_self);
+const char16_t GDAPI *godot_string_to_utf16_chars(const godot_string *p_self);
+const char32_t GDAPI *godot_string_to_utf32_chars(const godot_string *p_self);
+const wchar_t GDAPI *godot_string_to_wide_chars(const godot_string *p_self);
+
+char32_t GDAPI *godot_string_operator_index(godot_string *p_self, godot_int p_index);
+const char32_t GDAPI *godot_string_operator_index_const(const godot_string *p_self, godot_int p_index);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h
index e67862d140..3861b5683a 100644
--- a/modules/gdnative/include/gdnative/transform.h
+++ b/modules/gdnative/include/gdnative/transform.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_transform_new(godot_transform *p_self);
+void GDAPI godot_transform_new_copy(godot_transform *r_dest, const godot_transform *p_src);
#ifdef __cplusplus
}
diff --git a/modules/gdnative/include/gdnative/transform2d.h b/modules/gdnative/include/gdnative/transform2d.h
index 4a2bca7cfc..5acb172081 100644
--- a/modules/gdnative/include/gdnative/transform2d.h
+++ b/modules/gdnative/include/gdnative/transform2d.h
@@ -49,6 +49,7 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_transform2d_new(godot_transform2d *p_self);
+void GDAPI godot_transform2d_new_copy(godot_transform2d *r_dest, const godot_transform2d *p_src);
godot_vector2 GDAPI *godot_transform2d_operator_index(godot_transform2d *p_self, godot_int p_index);
const godot_vector2 GDAPI *godot_transform2d_operator_index_const(const godot_transform2d *p_self, godot_int p_index);
diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h
index 329a6faf51..3e06ed9aa4 100644
--- a/modules/gdnative/include/gdnative/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -272,6 +272,8 @@ void GDAPI godot_variant_destroy(godot_variant *p_self);
void GDAPI godot_variant_call(godot_variant *p_self, const godot_string_name *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
void GDAPI godot_variant_call_with_cstring(godot_variant *p_self, const char *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
+void GDAPI godot_variant_call_static(godot_variant_type p_type, const godot_string_name *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
+void GDAPI godot_variant_call_static_with_cstring(godot_variant_type p_type, const char *p_method, const godot_variant **p_args, const godot_int p_argument_count, godot_variant *r_return, godot_variant_call_error *r_error);
void GDAPI godot_variant_evaluate(godot_variant_operator p_op, const godot_variant *p_a, const godot_variant *p_b, godot_variant *r_return, bool *r_valid);
void GDAPI godot_variant_set(godot_variant *p_self, const godot_variant *p_key, const godot_variant *p_value, bool *r_valid);
void GDAPI godot_variant_set_named(godot_variant *p_self, const godot_string_name *p_name, const godot_variant *p_value, bool *r_valid);
@@ -323,6 +325,8 @@ godot_variant_type GDAPI godot_variant_get_builtin_method_return_type(godot_vari
godot_variant_type GDAPI godot_variant_get_builtin_method_return_type_with_cstring(godot_variant_type p_type, const char *p_method);
bool GDAPI godot_variant_is_builtin_method_const(godot_variant_type p_type, const godot_string_name *p_method);
bool GDAPI godot_variant_is_builtin_method_const_with_cstring(godot_variant_type p_type, const char *p_method);
+bool GDAPI godot_variant_is_builtin_method_static(godot_variant_type p_type, const godot_string_name *p_method);
+bool GDAPI godot_variant_is_builtin_method_static_with_cstring(godot_variant_type p_type, const char *p_method);
bool GDAPI godot_variant_is_builtin_method_vararg(godot_variant_type p_type, const godot_string_name *p_method);
bool GDAPI godot_variant_is_builtin_method_vararg_with_cstring(godot_variant_type p_type, const char *p_method);
int GDAPI godot_variant_get_builtin_method_count(godot_variant_type p_type);
diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index 5ebb705ba4..00faffbad7 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -58,7 +58,9 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_vector2_new(godot_vector2 *p_self);
+void GDAPI godot_vector2_new_copy(godot_vector2 *r_dest, const godot_vector2 *p_src);
void GDAPI godot_vector2i_new(godot_vector2i *p_self);
+void GDAPI godot_vector2i_new_copy(godot_vector2i *r_dest, const godot_vector2i *p_src);
godot_real_t GDAPI *godot_vector2_operator_index(godot_vector2 *p_self, godot_int p_index);
const godot_real_t GDAPI *godot_vector2_operator_index_const(const godot_vector2 *p_self, godot_int p_index);
int32_t GDAPI *godot_vector2i_operator_index(godot_vector2i *p_self, godot_int p_index);
diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index d37ebd3cc9..7db093ce52 100644
--- a/modules/gdnative/include/gdnative/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -58,7 +58,9 @@ typedef struct {
#include <gdnative/gdnative.h>
void GDAPI godot_vector3_new(godot_vector3 *p_self);
+void GDAPI godot_vector3_new_copy(godot_vector3 *r_dest, const godot_vector3 *p_src);
void GDAPI godot_vector3i_new(godot_vector3i *p_self);
+void GDAPI godot_vector3i_new_copy(godot_vector3i *r_dest, const godot_vector3i *p_src);
godot_real_t GDAPI *godot_vector3_operator_index(godot_vector3 *p_self, godot_int p_index);
const godot_real_t GDAPI *godot_vector3_operator_index_const(const godot_vector3 *p_self, godot_int p_index);
int32_t GDAPI *godot_vector3i_operator_index(godot_vector3i *p_self, godot_int p_index);
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index 3e75478cd8..f184c84615 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -71,6 +71,7 @@ struct MethodAPI {
bool is_editor = false;
bool is_noscript = false;
bool is_const = false;
+ bool is_static = false; // For builtin types.
bool is_reverse = false;
bool is_virtual = false;
bool is_from_script = false;
@@ -528,6 +529,7 @@ List<ClassAPI> generate_c_builtin_api_types() {
method_api.argument_count = Variant::get_builtin_method_argument_count(type, method_name);
method_api.has_varargs = Variant::is_builtin_method_vararg(type, method_name);
method_api.is_const = Variant::is_builtin_method_const(type, method_name);
+ method_api.is_static = Variant::is_builtin_method_static(type, method_name);
for (int i = 0; i < method_api.argument_count; i++) {
method_api.argument_names.push_back(Variant::get_builtin_method_argument_name(type, method_name, i));
@@ -757,6 +759,7 @@ static void write_builtin_method(StringBuilder &p_source, const MethodAPI &p_met
append_indented(p_source, vformat(R"("name": "%s",)", p_method.method_name));
append_indented(p_source, vformat(R"("return_type": "%s",)", p_method.return_type));
append_indented(p_source, vformat(R"("is_const": %s,)", p_method.is_const ? "true" : "false"));
+ append_indented(p_source, vformat(R"("is_static": %s,)", p_method.is_static ? "true" : "false"));
append_indented(p_source, vformat(R"("has_varargs": %s,)", p_method.has_varargs ? "true" : "false"));
append_indented(p_source, R"("arguments": [)");
diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp
index af76d9a4cc..39f208c7a4 100644
--- a/modules/gdnavigation/gd_navigation_server.cpp
+++ b/modules/gdnavigation/gd_navigation_server.cpp
@@ -145,9 +145,13 @@ COMMAND_2(map_set_active, RID, p_map, bool, p_active) {
if (p_active) {
if (!map_is_active(p_map)) {
active_maps.push_back(map);
+ active_maps_update_id.push_back(map->get_map_update_id());
}
} else {
- active_maps.erase(map);
+ int map_index = active_maps.find(map);
+ ERR_FAIL_COND(map_index < 0);
+ active_maps.remove(map_index);
+ active_maps_update_id.remove(map_index);
}
}
@@ -304,6 +308,27 @@ void GdNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p
#endif
}
+int GdNavigationServer::region_get_connections_count(RID p_region) const {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND_V(!region, 0);
+
+ return region->get_connections_count();
+}
+
+Vector3 GdNavigationServer::region_get_connection_pathway_start(RID p_region, int p_connection_id) const {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND_V(!region, Vector3());
+
+ return region->get_connection_pathway_start(p_connection_id);
+}
+
+Vector3 GdNavigationServer::region_get_connection_pathway_end(RID p_region, int p_connection_id) const {
+ NavRegion *region = region_owner.getornull(p_region);
+ ERR_FAIL_COND_V(!region, Vector3());
+
+ return region->get_connection_pathway_end(p_connection_id);
+}
+
RID GdNavigationServer::agent_create() const {
auto mut_this = const_cast<GdNavigationServer *>(this);
MutexLock lock(mut_this->operations_mutex);
@@ -443,7 +468,9 @@ COMMAND_1(free, RID, p_object) {
agents[i]->set_map(nullptr);
}
- active_maps.erase(map);
+ int map_index = active_maps.find(map);
+ active_maps.remove(map_index);
+ active_maps_update_id.remove(map_index);
map_owner.free(p_object);
memdelete(map);
@@ -504,10 +531,17 @@ void GdNavigationServer::process(real_t p_delta_time) {
// In c++ we can't be sure that this is performed in the main thread
// even with mutable functions.
MutexLock lock(operations_mutex);
- for (int i(0); i < active_maps.size(); i++) {
+ for (uint32_t i(0); i < active_maps.size(); i++) {
active_maps[i]->sync();
active_maps[i]->step(p_delta_time);
active_maps[i]->dispatch_callbacks();
+
+ // Emit a signal if a map changed.
+ const uint32_t new_map_update_id = active_maps[i]->get_map_update_id();
+ if (new_map_update_id != active_maps_update_id[i]) {
+ emit_signal("map_changed", active_maps[i]->get_self());
+ active_maps_update_id[i] = new_map_update_id;
+ }
}
}
diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h
index 8bc65eccab..2f51f6431e 100644
--- a/modules/gdnavigation/gd_navigation_server.h
+++ b/modules/gdnavigation/gd_navigation_server.h
@@ -31,6 +31,7 @@
#ifndef GD_NAVIGATION_SERVER_H
#define GD_NAVIGATION_SERVER_H
+#include "core/templates/local_vector.h"
#include "core/templates/rid.h"
#include "core/templates/rid_owner.h"
#include "servers/navigation_server_3d.h"
@@ -79,7 +80,8 @@ class GdNavigationServer : public NavigationServer3D {
mutable RID_PtrOwner<RvoAgent> agent_owner;
bool active = true;
- Vector<NavMap *> active_maps;
+ LocalVector<NavMap *> active_maps;
+ LocalVector<uint32_t> active_maps_update_id;
public:
GdNavigationServer();
@@ -114,6 +116,9 @@ public:
COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform);
COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const;
+ virtual int region_get_connections_count(RID p_region) const;
+ virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const;
+ virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const;
virtual RID agent_create() const;
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp
index 5289975e4b..80f367f3a6 100644
--- a/modules/gdnavigation/nav_map.cpp
+++ b/modules/gdnavigation/nav_map.cpp
@@ -40,7 +40,7 @@
@author AndreaCatania
*/
-#define USE_ENTRY_POINT
+#define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a)))
void NavMap::set_up(Vector3 p_up) {
up = p_up;
@@ -71,13 +71,13 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
}
Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_layers) const {
+ // Find the start poly and the end poly on this map.
const gd::Polygon *begin_poly = nullptr;
const gd::Polygon *end_poly = nullptr;
Vector3 begin_point;
Vector3 end_point;
float begin_d = 1e20;
float end_d = 1e20;
-
// Find the initial poly and the end poly on this map.
for (size_t i(0); i < polygons.size(); i++) {
const gd::Polygon &p = polygons[i];
@@ -88,31 +88,34 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
}
// For each point cast a face and check the distance between the origin/destination
- for (size_t point_id = 2; point_id < p.points.size(); point_id++) {
- Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos);
- Vector3 spoint = f.get_closest_point_to(p_origin);
- float dpoint = spoint.distance_to(p_origin);
- if (dpoint < begin_d) {
- begin_d = dpoint;
+ for (size_t point_id = 0; point_id < p.points.size(); point_id++) {
+ const Vector3 p1 = p.points[point_id].pos;
+ const Vector3 p2 = p.points[(point_id + 1) % p.points.size()].pos;
+ const Vector3 p3 = p.points[(point_id + 2) % p.points.size()].pos;
+ const Face3 face(p1, p2, p3);
+
+ Vector3 point = face.get_closest_point_to(p_origin);
+ float distance_to_point = point.distance_to(p_origin);
+ if (distance_to_point < begin_d) {
+ begin_d = distance_to_point;
begin_poly = &p;
- begin_point = spoint;
+ begin_point = point;
}
- spoint = f.get_closest_point_to(p_destination);
- dpoint = spoint.distance_to(p_destination);
- if (dpoint < end_d) {
- end_d = dpoint;
+ point = face.get_closest_point_to(p_destination);
+ distance_to_point = point.distance_to(p_destination);
+ if (distance_to_point < end_d) {
+ end_d = distance_to_point;
end_poly = &p;
- end_point = spoint;
+ end_point = point;
}
}
}
+ // Check for trival cases
if (!begin_poly || !end_poly) {
- // No path
return Vector<Vector3>();
}
-
if (begin_poly == end_poly) {
Vector<Vector3> path;
path.resize(2);
@@ -121,95 +124,89 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
return path;
}
+ // List of all reachable navigation polys.
std::vector<gd::NavigationPoly> navigation_polys;
navigation_polys.reserve(polygons.size() * 0.75);
- // The elements indices in the `navigation_polys`.
- int least_cost_id(-1);
- List<uint32_t> open_list;
- bool found_route = false;
+ // Add the start polygon to the reachable navigation polygons.
+ gd::NavigationPoly begin_navigation_poly = gd::NavigationPoly(begin_poly);
+ begin_navigation_poly.self_id = 0;
+ begin_navigation_poly.entry = begin_point;
+ begin_navigation_poly.back_navigation_edge_pathway_start = begin_point;
+ begin_navigation_poly.back_navigation_edge_pathway_end = begin_point;
+ navigation_polys.push_back(begin_navigation_poly);
- navigation_polys.push_back(gd::NavigationPoly(begin_poly));
- {
- least_cost_id = 0;
- gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id];
- least_cost_poly->self_id = least_cost_id;
- least_cost_poly->entry = begin_point;
- }
+ // List of polygon IDs to visit.
+ List<uint32_t> to_visit;
+ to_visit.push_back(0);
- open_list.push_back(0);
+ // This is an implementation of the A* algorithm.
+ int least_cost_id = 0;
+ bool found_route = false;
const gd::Polygon *reachable_end = nullptr;
float reachable_d = 1e30;
bool is_reachable = true;
- while (found_route == false) {
- {
- // Takes the current least_cost_poly neighbors and compute the traveled_distance of each
- for (size_t i = 0; i < navigation_polys[least_cost_id].poly->edges.size(); i++) {
- gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id];
+ while (true) {
+ gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id];
- // Only consider the polygon if it in a region with compatible layers.
- if ((p_layers & least_cost_poly->poly->owner->get_layers()) == 0) {
- continue;
- }
+ // Takes the current least_cost_poly neighbors (iterating over its edges) and compute the traveled_distance.
+ for (size_t i = 0; i < least_cost_poly->poly->edges.size(); i++) {
+ const gd::Edge &edge = least_cost_poly->poly->edges[i];
+
+ // Iterate over connections in this edge, then compute the new optimized travel distance assigned to this polygon.
+ for (int connection_index = 0; connection_index < edge.connections.size(); connection_index++) {
+ const gd::Edge::Connection &connection = edge.connections[connection_index];
- const gd::Edge &edge = least_cost_poly->poly->edges[i];
- if (!edge.other_polygon) {
+ // Only consider the connection to another polygon if this polygon is in a region with compatible layers.
+ if ((p_layers & connection.polygon->owner->get_layers()) == 0) {
continue;
}
-#ifdef USE_ENTRY_POINT
- Vector3 edge_line[2] = {
- least_cost_poly->poly->points[i].pos,
- least_cost_poly->poly->points[(i + 1) % least_cost_poly->poly->points.size()].pos
- };
-
- const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, edge_line);
+ Vector3 pathway[2] = { connection.pathway_start, connection.pathway_end };
+ const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway);
const float new_distance = least_cost_poly->entry.distance_to(new_entry) + least_cost_poly->traveled_distance;
-#else
- const float new_distance = least_cost_poly->poly->center.distance_to(edge.other_polygon->center) + least_cost_poly->traveled_distance;
-#endif
auto it = std::find(
navigation_polys.begin(),
navigation_polys.end(),
- gd::NavigationPoly(edge.other_polygon));
+ gd::NavigationPoly(connection.polygon));
if (it != navigation_polys.end()) {
- // Oh this was visited already, can we win the cost?
- if (it->traveled_distance > new_distance) {
- it->prev_navigation_poly_id = least_cost_id;
- it->back_navigation_edge = edge.other_edge;
+ // Polygon already visited, check if we can reduce the travel cost.
+ if (new_distance < it->traveled_distance) {
+ it->back_navigation_poly_id = least_cost_id;
+ it->back_navigation_edge = connection.edge;
+ it->back_navigation_edge_pathway_start = connection.pathway_start;
+ it->back_navigation_edge_pathway_end = connection.pathway_end;
it->traveled_distance = new_distance;
-#ifdef USE_ENTRY_POINT
it->entry = new_entry;
-#endif
}
} else {
- // Add to open neighbours
-
- navigation_polys.push_back(gd::NavigationPoly(edge.other_polygon));
- gd::NavigationPoly *np = &navigation_polys[navigation_polys.size() - 1];
-
- np->self_id = navigation_polys.size() - 1;
- np->prev_navigation_poly_id = least_cost_id;
- np->back_navigation_edge = edge.other_edge;
- np->traveled_distance = new_distance;
-#ifdef USE_ENTRY_POINT
- np->entry = new_entry;
-#endif
- open_list.push_back(navigation_polys.size() - 1);
+ // Add the neighbour polygon to the reachable ones.
+ gd::NavigationPoly new_navigation_poly = gd::NavigationPoly(connection.polygon);
+ new_navigation_poly.self_id = navigation_polys.size();
+ new_navigation_poly.back_navigation_poly_id = least_cost_id;
+ new_navigation_poly.back_navigation_edge = connection.edge;
+ new_navigation_poly.back_navigation_edge_pathway_start = connection.pathway_start;
+ new_navigation_poly.back_navigation_edge_pathway_end = connection.pathway_end;
+ new_navigation_poly.traveled_distance = new_distance;
+ new_navigation_poly.entry = new_entry;
+ navigation_polys.push_back(new_navigation_poly);
+
+ // Add the neighbour polygon to the polygons to visit.
+ to_visit.push_back(navigation_polys.size() - 1);
}
}
}
- // Removes the least cost polygon from the open list so we can advance.
- open_list.erase(least_cost_id);
+ // Removes the least cost polygon from the list of polygons to visit so we can advance.
+ to_visit.erase(least_cost_id);
- if (open_list.size() == 0) {
- // When the open list is empty at this point the End Polygon is not reachable
- // so use the further reachable polygon
+ // When the list of polygons to visit is empty at this point it means the End Polygon is not reachable
+ if (to_visit.size() == 0) {
+ // Thus use the further reachable polygon
ERR_BREAK_MSG(is_reachable == false, "It's not expect to not find the most reachable polygons");
is_reachable = false;
if (reachable_end == nullptr) {
@@ -234,26 +231,21 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
gd::NavigationPoly np = navigation_polys[0];
navigation_polys.clear();
navigation_polys.push_back(np);
- open_list.clear();
- open_list.push_back(0);
+ to_visit.clear();
+ to_visit.push_back(0);
reachable_end = nullptr;
continue;
}
- // Now take the new least_cost_poly from the open list.
+ // Find the polygon with the minimum cost from the list of polygons to visit.
least_cost_id = -1;
float least_cost = 1e30;
-
- for (auto element = open_list.front(); element != nullptr; element = element->next()) {
+ for (List<uint32_t>::Element *element = to_visit.front(); element != nullptr; element = element->next()) {
gd::NavigationPoly *np = &navigation_polys[element->get()];
float cost = np->traveled_distance;
-#ifdef USE_ENTRY_POINT
cost += np->entry.distance_to(end_point);
-#else
- cost += np->poly->center.distance_to(end_point);
-#endif
if (cost < least_cost) {
least_cost_id = np->self_id;
least_cost = cost;
@@ -273,124 +265,108 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
// Check if we reached the end
if (navigation_polys[least_cost_id].poly == end_poly) {
- // Yep, done!!
found_route = true;
break;
}
}
- if (found_route) {
- Vector<Vector3> path;
- if (p_optimize) {
- // String pulling
-
- gd::NavigationPoly *apex_poly = &navigation_polys[least_cost_id];
- Vector3 apex_point = end_point;
- Vector3 portal_left = apex_point;
- Vector3 portal_right = apex_point;
- gd::NavigationPoly *left_poly = apex_poly;
- gd::NavigationPoly *right_poly = apex_poly;
- gd::NavigationPoly *p = apex_poly;
-
- path.push_back(end_point);
+ // If we did not find a route, return an empty path.
+ if (!found_route) {
+ return Vector<Vector3>();
+ }
- while (p) {
- Vector3 left;
- Vector3 right;
+ Vector<Vector3> path;
+ // Optimize the path.
+ if (p_optimize) {
+ // Set the apex poly/point to the end point
+ gd::NavigationPoly *apex_poly = &navigation_polys[least_cost_id];
+ Vector3 apex_point = end_point;
-#define CLOCK_TANGENT(m_a, m_b, m_c) (((m_a) - (m_c)).cross((m_a) - (m_b)))
+ gd::NavigationPoly *left_poly = apex_poly;
+ Vector3 left_portal = apex_point;
+ gd::NavigationPoly *right_poly = apex_poly;
+ Vector3 right_portal = apex_point;
- if (p->poly == begin_poly) {
- left = begin_point;
- right = begin_point;
- } else {
- int prev = p->back_navigation_edge;
- int prev_n = (p->back_navigation_edge + 1) % p->poly->points.size();
- left = p->poly->points[prev].pos;
- right = p->poly->points[prev_n].pos;
+ gd::NavigationPoly *p = apex_poly;
- if (p->poly->clockwise) {
- SWAP(left, right);
- }
- }
+ path.push_back(end_point);
- bool skip = false;
-
- if (CLOCK_TANGENT(apex_point, portal_left, left).dot(up) >= 0) {
- //process
- if (portal_left == apex_point || CLOCK_TANGENT(apex_point, left, portal_right).dot(up) > 0) {
- left_poly = p;
- portal_left = left;
- } else {
- clip_path(navigation_polys, path, apex_poly, portal_right, right_poly);
-
- apex_point = portal_right;
- p = right_poly;
- left_poly = p;
- apex_poly = p;
- portal_left = apex_point;
- portal_right = apex_point;
- path.push_back(apex_point);
- skip = true;
- }
- }
+ while (p) {
+ // Set left and right points of the pathway between polygons.
+ Vector3 left = p->back_navigation_edge_pathway_start;
+ Vector3 right = p->back_navigation_edge_pathway_end;
+ if (THREE_POINTS_CROSS_PRODUCT(apex_point, left, right).dot(up) < 0) {
+ SWAP(left, right);
+ }
- if (!skip && CLOCK_TANGENT(apex_point, portal_right, right).dot(up) <= 0) {
- //process
- if (portal_right == apex_point || CLOCK_TANGENT(apex_point, right, portal_left).dot(up) < 0) {
- right_poly = p;
- portal_right = right;
- } else {
- clip_path(navigation_polys, path, apex_poly, portal_left, left_poly);
-
- apex_point = portal_left;
- p = left_poly;
- right_poly = p;
- apex_poly = p;
- portal_right = apex_point;
- portal_left = apex_point;
- path.push_back(apex_point);
- }
+ bool skip = false;
+ if (THREE_POINTS_CROSS_PRODUCT(apex_point, left_portal, left).dot(up) >= 0) {
+ //process
+ if (left_portal == apex_point || THREE_POINTS_CROSS_PRODUCT(apex_point, left, right_portal).dot(up) > 0) {
+ left_poly = p;
+ left_portal = left;
+ } else {
+ clip_path(navigation_polys, path, apex_poly, right_portal, right_poly);
+
+ apex_point = right_portal;
+ p = right_poly;
+ left_poly = p;
+ apex_poly = p;
+ left_portal = apex_point;
+ right_portal = apex_point;
+ path.push_back(apex_point);
+ skip = true;
}
+ }
- if (p->prev_navigation_poly_id != -1) {
- p = &navigation_polys[p->prev_navigation_poly_id];
+ if (!skip && THREE_POINTS_CROSS_PRODUCT(apex_point, right_portal, right).dot(up) <= 0) {
+ //process
+ if (right_portal == apex_point || THREE_POINTS_CROSS_PRODUCT(apex_point, right, left_portal).dot(up) < 0) {
+ right_poly = p;
+ right_portal = right;
} else {
- // The end
- p = nullptr;
+ clip_path(navigation_polys, path, apex_poly, left_portal, left_poly);
+
+ apex_point = left_portal;
+ p = left_poly;
+ right_poly = p;
+ apex_poly = p;
+ right_portal = apex_point;
+ left_portal = apex_point;
+ path.push_back(apex_point);
}
}
- if (path[path.size() - 1] != begin_point) {
- path.push_back(begin_point);
+ // Go to the previous polygon.
+ if (p->back_navigation_poly_id != -1) {
+ p = &navigation_polys[p->back_navigation_poly_id];
+ } else {
+ // The end
+ p = nullptr;
}
+ }
- path.invert();
-
- } else {
- path.push_back(end_point);
+ // If the last point is not the begin point, add it to the list.
+ if (path[path.size() - 1] != begin_point) {
+ path.push_back(begin_point);
+ }
- // Add mid points
- int np_id = least_cost_id;
- while (np_id != -1) {
-#ifdef USE_ENTRY_POINT
- Vector3 point = navigation_polys[np_id].entry;
-#else
- int prev = navigation_polys[np_id].back_navigation_edge;
- int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size();
- Vector3 point = (navigation_polys[np_id].poly->points[prev].pos + navigation_polys[np_id].poly->points[prev_n].pos) * 0.5;
-#endif
+ path.invert();
- path.push_back(point);
- np_id = navigation_polys[np_id].prev_navigation_poly_id;
- }
+ } else {
+ path.push_back(end_point);
- path.invert();
+ // Add mid points
+ int np_id = least_cost_id;
+ while (np_id != -1) {
+ path.push_back(navigation_polys[np_id].entry);
+ np_id = navigation_polys[np_id].back_navigation_poly_id;
}
- return path;
+ path.invert();
}
- return Vector<Vector3>();
+
+ return path;
}
Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
@@ -571,6 +547,7 @@ void NavMap::remove_agent_as_controlled(RvoAgent *agent) {
}
void NavMap::sync() {
+ // Check if we need to update the links.
if (regenerate_polygons) {
for (size_t r(0); r < regions.size(); r++) {
regions[r]->scratch_polygons();
@@ -585,27 +562,30 @@ void NavMap::sync() {
}
if (regenerate_links) {
- // Copy all region polygons in the map.
+ // Remove regions connections.
+ for (size_t r(0); r < regions.size(); r++) {
+ regions[r]->get_connections().clear();
+ }
+
+ // Resize the polygon count.
int count = 0;
for (size_t r(0); r < regions.size(); r++) {
count += regions[r]->get_polygons().size();
}
-
polygons.resize(count);
- count = 0;
+ // Copy all region polygons in the map.
+ count = 0;
for (size_t r(0); r < regions.size(); r++) {
std::copy(
regions[r]->get_polygons().data(),
regions[r]->get_polygons().data() + regions[r]->get_polygons().size(),
polygons.begin() + count);
-
count += regions[r]->get_polygons().size();
}
- // Connects the `Edges` of all the `Polygons` of all `Regions` each other.
- Map<gd::EdgeKey, gd::Connection> connections;
-
+ // Group all edges per key.
+ Map<gd::EdgeKey, Vector<gd::Edge::Connection>> connections;
for (size_t poly_id(0); poly_id < polygons.size(); poly_id++) {
gd::Polygon &poly(polygons[poly_id]);
@@ -613,30 +593,18 @@ void NavMap::sync() {
int next_point = (p + 1) % poly.points.size();
gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key);
- Map<gd::EdgeKey, gd::Connection>::Element *connection = connections.find(ek);
+ Map<gd::EdgeKey, Vector<gd::Edge::Connection>>::Element *connection = connections.find(ek);
if (!connection) {
- // Nothing yet
- gd::Connection c;
- c.A = &poly;
- c.A_edge = p;
- c.B = nullptr;
- c.B_edge = -1;
- connections[ek] = c;
-
- } else if (connection->get().B == nullptr) {
- CRASH_COND(connection->get().A == nullptr); // Unreachable
-
- // Connect the two Polygons by this edge
- connection->get().B = &poly;
- connection->get().B_edge = p;
-
- connection->get().A->edges[connection->get().A_edge].this_edge = connection->get().A_edge;
- connection->get().A->edges[connection->get().A_edge].other_polygon = connection->get().B;
- connection->get().A->edges[connection->get().A_edge].other_edge = connection->get().B_edge;
-
- connection->get().B->edges[connection->get().B_edge].this_edge = connection->get().B_edge;
- connection->get().B->edges[connection->get().B_edge].other_polygon = connection->get().A;
- connection->get().B->edges[connection->get().B_edge].other_edge = connection->get().A_edge;
+ connections[ek] = Vector<gd::Edge::Connection>();
+ }
+ if (connections[ek].size() <= 1) {
+ // Add the polygon/edge tuple to this key.
+ gd::Edge::Connection new_connection;
+ new_connection.polygon = &poly;
+ new_connection.edge = p;
+ new_connection.pathway_start = poly.points[p].pos;
+ new_connection.pathway_end = poly.points[next_point].pos;
+ connections[ek].push_back(new_connection);
} else {
// The edge is already connected with another edge, skip.
ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the current `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem.");
@@ -644,38 +612,21 @@ void NavMap::sync() {
}
}
- // Takes all the free edges.
- std::vector<gd::FreeEdge> free_edges;
- free_edges.reserve(connections.size());
-
- for (auto connection_element = connections.front(); connection_element; connection_element = connection_element->next()) {
- if (connection_element->get().B == nullptr) {
- CRASH_COND(connection_element->get().A == nullptr); // Unreachable
- CRASH_COND(connection_element->get().A_edge < 0); // Unreachable
-
- // This is a free edge
- uint32_t id(free_edges.size());
- free_edges.push_back(gd::FreeEdge());
- free_edges[id].is_free = true;
- free_edges[id].poly = connection_element->get().A;
- free_edges[id].edge_id = connection_element->get().A_edge;
- uint32_t point_0(free_edges[id].edge_id);
- uint32_t point_1((free_edges[id].edge_id + 1) % free_edges[id].poly->points.size());
- Vector3 pos_0 = free_edges[id].poly->points[point_0].pos;
- Vector3 pos_1 = free_edges[id].poly->points[point_1].pos;
- Vector3 relative = pos_1 - pos_0;
- free_edges[id].edge_center = (pos_0 + pos_1) / 2.0;
- free_edges[id].edge_dir = relative.normalized();
- free_edges[id].edge_len_squared = relative.length_squared();
+ Vector<gd::Edge::Connection> free_edges;
+ for (Map<gd::EdgeKey, Vector<gd::Edge::Connection>>::Element *E = connections.front(); E; E = E->next()) {
+ if (E->get().size() == 2) {
+ // Connect edge that are shared in different polygons.
+ gd::Edge::Connection &c1 = E->get().write[0];
+ gd::Edge::Connection &c2 = E->get().write[1];
+ c1.polygon->edges[c1.edge].connections.push_back(c2);
+ c2.polygon->edges[c2.edge].connections.push_back(c1);
+ // Note: The pathway_start/end are full for those connection and do not need to be modified.
+ } else {
+ CRASH_COND_MSG(E->get().size() != 1, vformat("Number of connection != 1. Found: %d", E->get().size()));
+ free_edges.push_back(E->get()[0]);
}
}
- const float ecm_squared(edge_connection_margin * edge_connection_margin);
-#define LEN_TOLLERANCE 0.1
-#define DIR_TOLLERANCE 0.9
- // In front of tolerance
-#define IFO_TOLLERANCE 0.5
-
// Find the compatible near edges.
//
// Note:
@@ -683,43 +634,67 @@ void NavMap::sync() {
// to be connected, create new polygons to remove that small gap is
// not really useful and would result in wasteful computation during
// connection, integration and path finding.
- for (size_t i(0); i < free_edges.size(); i++) {
- if (!free_edges[i].is_free) {
- continue;
- }
- gd::FreeEdge &edge = free_edges[i];
- for (size_t y(0); y < free_edges.size(); y++) {
- gd::FreeEdge &other_edge = free_edges[y];
- if (i == y || !other_edge.is_free || edge.poly->owner == other_edge.poly->owner) {
+ for (int i = 0; i < free_edges.size(); i++) {
+ const gd::Edge::Connection &free_edge = free_edges[i];
+ Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos;
+ Vector3 edge_p2 = free_edge.polygon->points[(free_edge.edge + 1) % free_edge.polygon->points.size()].pos;
+
+ for (int j = 0; j < free_edges.size(); j++) {
+ const gd::Edge::Connection &other_edge = free_edges[j];
+ if (i == j || free_edge.polygon->owner == other_edge.polygon->owner) {
+ continue;
+ }
+
+ Vector3 other_edge_p1 = other_edge.polygon->points[other_edge.edge].pos;
+ Vector3 other_edge_p2 = other_edge.polygon->points[(other_edge.edge + 1) % other_edge.polygon->points.size()].pos;
+
+ // Compute the projection of the opposite edge on the current one
+ Vector3 edge_vector = edge_p2 - edge_p1;
+ float projected_p1_ratio = edge_vector.dot(other_edge_p1 - edge_p1) / (edge_vector.length_squared());
+ float projected_p2_ratio = edge_vector.dot(other_edge_p2 - edge_p1) / (edge_vector.length_squared());
+ if ((projected_p1_ratio < 0.0 && projected_p2_ratio < 0.0) || (projected_p1_ratio > 1.0 && projected_p2_ratio > 1.0)) {
continue;
}
- Vector3 rel_centers = other_edge.edge_center - edge.edge_center;
- if (ecm_squared > rel_centers.length_squared() // Are enough closer?
- && ABS(edge.edge_len_squared - other_edge.edge_len_squared) < LEN_TOLLERANCE // Are the same length?
- && ABS(edge.edge_dir.dot(other_edge.edge_dir)) > DIR_TOLLERANCE // Are aligned?
- && ABS(rel_centers.normalized().dot(edge.edge_dir)) < IFO_TOLLERANCE // Are one in front the other?
- ) {
- // The edges can be connected
- edge.is_free = false;
- other_edge.is_free = false;
-
- edge.poly->edges[edge.edge_id].this_edge = edge.edge_id;
- edge.poly->edges[edge.edge_id].other_edge = other_edge.edge_id;
- edge.poly->edges[edge.edge_id].other_polygon = other_edge.poly;
-
- other_edge.poly->edges[other_edge.edge_id].this_edge = other_edge.edge_id;
- other_edge.poly->edges[other_edge.edge_id].other_edge = edge.edge_id;
- other_edge.poly->edges[other_edge.edge_id].other_polygon = edge.poly;
+ // Check if the two edges are close to each other enough and compute a pathway between the two regions.
+ Vector3 self1 = edge_vector * CLAMP(projected_p1_ratio, 0.0, 1.0) + edge_p1;
+ Vector3 other1;
+ if (projected_p1_ratio >= 0.0 && projected_p1_ratio <= 1.0) {
+ other1 = other_edge_p1;
+ } else {
+ other1 = other_edge_p1.lerp(other_edge_p2, (1.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio));
}
+ if ((self1 - other1).length() > edge_connection_margin) {
+ continue;
+ }
+
+ Vector3 self2 = edge_vector * CLAMP(projected_p2_ratio, 0.0, 1.0) + edge_p1;
+ Vector3 other2;
+ if (projected_p2_ratio >= 0.0 && projected_p2_ratio <= 1.0) {
+ other2 = other_edge_p2;
+ } else {
+ other2 = other_edge_p1.lerp(other_edge_p2, (0.0 - projected_p1_ratio) / (projected_p2_ratio - projected_p1_ratio));
+ }
+ if ((self2 - other2).length() > edge_connection_margin) {
+ continue;
+ }
+
+ // The edges can now be connected.
+ gd::Edge::Connection new_connection = other_edge;
+ new_connection.pathway_start = (self1 + other1) / 2.0;
+ new_connection.pathway_end = (self2 + other2) / 2.0;
+ free_edge.polygon->edges[free_edge.edge].connections.push_back(new_connection);
+
+ // Add the connection to the region_connection map.
+ free_edge.polygon->owner->get_connections().push_back(new_connection);
}
}
- }
- if (regenerate_links) {
+ // Update the update ID.
map_update_id = (map_update_id + 1) % 9999999;
}
+ // Update agents tree.
if (agents_dirty) {
std::vector<RVO::Agent *> raw_agents;
raw_agents.reserve(agents.size());
@@ -771,16 +746,15 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys
cut_plane.d = cut_plane.normal.dot(from);
while (from_poly != p_to_poly) {
- int back_nav_edge = from_poly->back_navigation_edge;
- Vector3 a = from_poly->poly->points[back_nav_edge].pos;
- Vector3 b = from_poly->poly->points[(back_nav_edge + 1) % from_poly->poly->points.size()].pos;
+ Vector3 pathway_start = from_poly->back_navigation_edge_pathway_start;
+ Vector3 pathway_end = from_poly->back_navigation_edge_pathway_end;
- ERR_FAIL_COND(from_poly->prev_navigation_poly_id == -1);
- from_poly = &p_navigation_polys[from_poly->prev_navigation_poly_id];
+ ERR_FAIL_COND(from_poly->back_navigation_poly_id == -1);
+ from_poly = &p_navigation_polys[from_poly->back_navigation_poly_id];
- if (a.distance_to(b) > CMP_EPSILON) {
+ if (pathway_start.distance_to(pathway_end) > CMP_EPSILON) {
Vector3 inters;
- if (cut_plane.intersects_segment(a, b, &inters)) {
+ if (cut_plane.intersects_segment(pathway_start, pathway_end, &inters)) {
if (inters.distance_to(p_to_point) > CMP_EPSILON && inters.distance_to(path[path.size() - 1]) > CMP_EPSILON) {
path.push_back(inters);
}
diff --git a/modules/gdnavigation/nav_map.h b/modules/gdnavigation/nav_map.h
index 6b7cfae324..8e013a72eb 100644
--- a/modules/gdnavigation/nav_map.h
+++ b/modules/gdnavigation/nav_map.h
@@ -34,6 +34,7 @@
#include "nav_rid.h"
#include "core/math/math_defs.h"
+#include "core/templates/map.h"
#include "nav_utils.h"
#include <KdTree.h>
diff --git a/modules/gdnavigation/nav_region.cpp b/modules/gdnavigation/nav_region.cpp
index a07995bc11..c1690b2a4b 100644
--- a/modules/gdnavigation/nav_region.cpp
+++ b/modules/gdnavigation/nav_region.cpp
@@ -39,6 +39,9 @@
void NavRegion::set_map(NavMap *p_map) {
map = p_map;
polygons_dirty = true;
+ if (!map) {
+ connections.clear();
+ }
}
void NavRegion::set_layers(uint32_t p_layers) {
@@ -59,6 +62,25 @@ void NavRegion::set_mesh(Ref<NavigationMesh> p_mesh) {
polygons_dirty = true;
}
+int NavRegion::get_connections_count() const {
+ if (!map) {
+ return 0;
+ }
+ return connections.size();
+}
+
+Vector3 NavRegion::get_connection_pathway_start(int p_connection_id) const {
+ ERR_FAIL_COND_V(!map, Vector3());
+ ERR_FAIL_INDEX_V(p_connection_id, connections.size(), Vector3());
+ return connections[p_connection_id].pathway_start;
+}
+
+Vector3 NavRegion::get_connection_pathway_end(int p_connection_id) const {
+ ERR_FAIL_COND_V(!map, Vector3());
+ ERR_FAIL_INDEX_V(p_connection_id, connections.size(), Vector3());
+ return connections[p_connection_id].pathway_end;
+}
+
bool NavRegion::sync() {
bool something_changed = polygons_dirty /* || something_dirty? */;
diff --git a/modules/gdnavigation/nav_region.h b/modules/gdnavigation/nav_region.h
index fff7843fde..527b2500ac 100644
--- a/modules/gdnavigation/nav_region.h
+++ b/modules/gdnavigation/nav_region.h
@@ -49,6 +49,7 @@ class NavRegion : public NavRid {
Transform transform;
Ref<NavigationMesh> mesh;
uint32_t layers = 1;
+ Vector<gd::Edge::Connection> connections;
bool polygons_dirty = true;
@@ -80,6 +81,13 @@ public:
return mesh;
}
+ Vector<gd::Edge::Connection> &get_connections() {
+ return connections;
+ }
+ int get_connections_count() const;
+ Vector3 get_connection_pathway_start(int p_connection_id) const;
+ Vector3 get_connection_pathway_end(int p_connection_id) const;
+
std::vector<gd::Polygon> const &get_polygons() const {
return polygons;
}
diff --git a/modules/gdnavigation/nav_utils.h b/modules/gdnavigation/nav_utils.h
index d257a95ef1..35da391eea 100644
--- a/modules/gdnavigation/nav_utils.h
+++ b/modules/gdnavigation/nav_utils.h
@@ -81,11 +81,14 @@ struct Edge {
/// This edge ID
int this_edge = -1;
- /// Other Polygon
- Polygon *other_polygon = nullptr;
-
- /// The other `Polygon` at this edge id has this `Polygon`.
- int other_edge = -1;
+ /// The gateway in the edge, as, in some case, the whole edge might not be navigable.
+ struct Connection {
+ Polygon *polygon = nullptr;
+ int edge = -1;
+ Vector3 pathway_start;
+ Vector3 pathway_end;
+ };
+ Vector<Connection> connections;
};
struct Polygon {
@@ -104,21 +107,17 @@ struct Polygon {
Vector3 center;
};
-struct Connection {
- Polygon *A = nullptr;
- int A_edge = -1;
- Polygon *B = nullptr;
- int B_edge = -1;
-};
-
struct NavigationPoly {
uint32_t self_id = 0;
/// This poly.
const Polygon *poly;
- /// The previous navigation poly (id in the `navigation_poly` array).
- int prev_navigation_poly_id = -1;
- /// The edge id in this `Poly` to reach the `prev_navigation_poly_id`.
- uint32_t back_navigation_edge = 0;
+
+ /// Those 4 variables are used to travel the path backwards.
+ int back_navigation_poly_id = -1;
+ uint32_t back_navigation_edge = UINT32_MAX;
+ Vector3 back_navigation_edge_pathway_start;
+ Vector3 back_navigation_edge_pathway_end;
+
/// The entry location of this poly.
Vector3 entry;
/// The distance to the destination.
@@ -136,14 +135,6 @@ struct NavigationPoly {
}
};
-struct FreeEdge {
- bool is_free = false;
- Polygon *poly = nullptr;
- uint32_t edge_id = 0;
- Vector3 edge_center;
- Vector3 edge_dir;
- float edge_len_squared = 0.0;
-};
} // namespace gd
#endif // NAV_UTILS_H
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 0a4d4055b4..caf8e3f48f 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -63,7 +63,6 @@
#ifdef MODULE_GRIDMAP_ENABLED
#include "modules/gridmap/grid_map.h"
#endif // MODULE_GRIDMAP_ENABLED
-#include "modules/regex/regex.h"
#include "scene/2d/node_2d.h"
#include "scene/3d/bone_attachment_3d.h"
#include "scene/3d/camera_3d.h"
@@ -505,25 +504,11 @@ String GLTFDocument::_gen_unique_animation_name(Ref<GLTFState> state, const Stri
return name;
}
-String GLTFDocument::_sanitize_bone_name(const String &name) {
- String p_name = name.camelcase_to_underscore(true);
-
- RegEx pattern_nocolon(":");
- p_name = pattern_nocolon.sub(p_name, "_", true);
-
- RegEx pattern_noslash("/");
- p_name = pattern_noslash.sub(p_name, "_", true);
-
- RegEx pattern_nospace(" +");
- p_name = pattern_nospace.sub(p_name, "_", true);
-
- RegEx pattern_multiple("_+");
- p_name = pattern_multiple.sub(p_name, "_", true);
-
- RegEx pattern_padded("0+(\\d+)");
- p_name = pattern_padded.sub(p_name, "$1", true);
-
- return p_name;
+String GLTFDocument::_sanitize_bone_name(const String &p_name) {
+ String name = p_name;
+ name = name.replace(":", "_");
+ name = name.replace("/", "_");
+ return name;
}
String GLTFDocument::_gen_unique_bone_name(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i, const String &p_name) {
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 25776b1f6d..9b6fa138e5 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -214,12 +214,12 @@
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
The physics layers this GridMap detects collisions in. See [url=https://docs.godotengine.org/en/latest/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information.
</member>
- <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
- The navigation layers the GridMap generates its navigable regions in.
- </member>
<member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library">
The assigned [MeshLibrary].
</member>
+ <member name="navigation_layers" type="int" setter="set_navigation_layers" getter="get_navigation_layers" default="1">
+ The navigation layers the GridMap generates its navigable regions in.
+ </member>
</members>
<signals>
<signal name="cell_size_changed">
diff --git a/platform/android/java/app/assets/.gitignore b/platform/android/java/app/assets/.gitignore
new file mode 100644
index 0000000000..d6b7ef32c8
--- /dev/null
+++ b/platform/android/java/app/assets/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle
index 934c4bf441..f103f22db2 100644
--- a/platform/android/java/app/build.gradle
+++ b/platform/android/java/app/build.gradle
@@ -77,7 +77,7 @@ android {
defaultConfig {
// The default ignore pattern for the 'assets' directory includes hidden files and directories which are used by Godot projects.
aaptOptions {
- ignoreAssetsPattern "!.svn:!.git:!.ds_store:!*.scc:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"
+ ignoreAssetsPattern "!.svn:!.git:!.gitignore:!.ds_store:!*.scc:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
ndk {
@@ -106,8 +106,10 @@ android {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
- // Should be uncommented for development purpose within Android Studio
- // doNotStrip '**/*.so'
+ // 'doNotStrip' is enabled for development within Android Studio
+ if (shouldNotStrip()) {
+ doNotStrip '**/*.so'
+ }
}
signingConfigs {
diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle
index 585e517631..c0ae4007d2 100644
--- a/platform/android/java/app/config.gradle
+++ b/platform/android/java/app/config.gradle
@@ -209,10 +209,19 @@ ext.getReleaseKeyAlias = { ->
return keyAlias
}
+ext.isAndroidStudio = { ->
+ def sysProps = System.getProperties()
+ return sysProps != null && sysProps['idea.platform.prefix'] != null
+}
+
ext.shouldZipAlign = { ->
String zipAlignFlag = project.hasProperty("perform_zipalign") ? project.property("perform_zipalign") : ""
if (zipAlignFlag == null || zipAlignFlag.isEmpty()) {
- zipAlignFlag = "false"
+ if (isAndroidStudio()) {
+ zipAlignFlag = "true"
+ } else {
+ zipAlignFlag = "false"
+ }
}
return Boolean.parseBoolean(zipAlignFlag)
}
@@ -220,7 +229,15 @@ ext.shouldZipAlign = { ->
ext.shouldSign = { ->
String signFlag = project.hasProperty("perform_signing") ? project.property("perform_signing") : ""
if (signFlag == null || signFlag.isEmpty()) {
- signFlag = "false"
+ if (isAndroidStudio()) {
+ signFlag = "true"
+ } else {
+ signFlag = "false"
+ }
}
return Boolean.parseBoolean(signFlag)
}
+
+ext.shouldNotStrip = { ->
+ return isAndroidStudio()
+}
diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle
index 6fc9a11a08..663ba73d40 100644
--- a/platform/android/java/lib/build.gradle
+++ b/platform/android/java/lib/build.gradle
@@ -36,8 +36,10 @@ android {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
- // Should be uncommented for development purpose within Android Studio
- // doNotStrip '**/*.so'
+ // 'doNotStrip' is enabled for development within Android Studio
+ if (shouldNotStrip()) {
+ doNotStrip '**/*.so'
+ }
}
sourceSets {
diff --git a/platform/android/java/nativeSrcsConfigs/build.gradle b/platform/android/java/nativeSrcsConfigs/build.gradle
index 66077060ea..158bb2b98e 100644
--- a/platform/android/java/nativeSrcsConfigs/build.gradle
+++ b/platform/android/java/nativeSrcsConfigs/build.gradle
@@ -20,9 +20,6 @@ android {
packagingOptions {
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
-
- // Should be uncommented for development purpose within Android Studio
- // doNotStrip '**/*.so'
}
sourceSets {
diff --git a/platform/iphone/godot_view.mm b/platform/iphone/godot_view.mm
index 887297848e..468fa2928a 100644
--- a/platform/iphone/godot_view.mm
+++ b/platform/iphone/godot_view.mm
@@ -39,6 +39,7 @@
#import <CoreMotion/CoreMotion.h>
static const int max_touches = 8;
+static const float earth_gravity = 9.80665;
@interface GodotView () {
UITouch *godot_touches[max_touches];
@@ -402,10 +403,19 @@ static const int max_touches = 8;
// https://developer.apple.com/reference/coremotion/cmmotionmanager?language=objc
// Apple splits our accelerometer date into a gravity and user movement
- // component. We add them back together
+ // component. We add them back together.
CMAcceleration gravity = self.motionManager.deviceMotion.gravity;
CMAcceleration acceleration = self.motionManager.deviceMotion.userAcceleration;
+ // To be consistent with Android we convert the unit of measurement from g (Earth's gravity)
+ // to m/s^2.
+ gravity.x *= earth_gravity;
+ gravity.y *= earth_gravity;
+ gravity.z *= earth_gravity;
+ acceleration.x *= earth_gravity;
+ acceleration.y *= earth_gravity;
+ acceleration.z *= earth_gravity;
+
///@TODO We don't seem to be getting data here, is my device broken or
/// is this code incorrect?
CMMagneticField magnetic = self.motionManager.deviceMotion.magneticField.field;
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index fa97948395..33992069f9 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -62,6 +62,8 @@ using namespace Windows::Devices::Sensors;
using namespace Windows::ApplicationModel::DataTransfer;
using namespace concurrency;
+static const float earth_gravity = 9.80665;
+
int OS_UWP::get_video_driver_count() const {
return 2;
}
@@ -372,9 +374,9 @@ void OS_UWP::ManagedType::on_accelerometer_reading_changed(Accelerometer ^ sende
AccelerometerReading ^ reading = args->Reading;
os->input->set_accelerometer(Vector3(
- reading->AccelerationX,
- reading->AccelerationY,
- reading->AccelerationZ));
+ reading->AccelerationX * earth_gravity,
+ reading->AccelerationY * earth_gravity,
+ reading->AccelerationZ * earth_gravity));
}
void OS_UWP::ManagedType::on_magnetometer_reading_changed(Magnetometer ^ sender, MagnetometerReadingChangedEventArgs ^ args) {
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index 794993f892..8be8c8db4a 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -364,8 +364,10 @@ void NavigationRegion2D::set_enabled(bool p_enabled) {
if (!enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
+ NavigationServer2D::get_singleton()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
} else {
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
+ NavigationServer2D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
}
if (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) {
@@ -401,6 +403,7 @@ void NavigationRegion2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
+ NavigationServer2D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
}
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -408,12 +411,14 @@ void NavigationRegion2D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_TREE: {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
+ if (enabled) {
+ NavigationServer2D::get_singleton()->disconnect("map_changed", callable_mp(this, &NavigationRegion2D::_map_changed));
+ }
} break;
case NOTIFICATION_DRAW: {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint()) && navpoly.is_valid()) {
Vector<Vector2> verts = navpoly->get_vertices();
- int vsize = verts.size();
- if (vsize < 3) {
+ if (verts.size() < 3) {
return;
}
@@ -423,33 +428,47 @@ void NavigationRegion2D::_notification(int p_what) {
} else {
color = get_tree()->get_debug_navigation_disabled_color();
}
- Vector<Color> colors;
- Vector<Vector2> vertices;
- vertices.resize(vsize);
- colors.resize(vsize);
- {
- const Vector2 *vr = verts.ptr();
- for (int i = 0; i < vsize; i++) {
- vertices.write[i] = vr[i];
- colors.write[i] = color;
- }
- }
+ Color doors_color = color.lightened(0.2);
- Vector<int> indices;
+ RandomPCG rand;
for (int i = 0; i < navpoly->get_polygon_count(); i++) {
+ // An array of vertices for this polygon.
Vector<int> polygon = navpoly->get_polygon(i);
-
- for (int j = 2; j < polygon.size(); j++) {
- int kofs[3] = { 0, j - 1, j };
- for (int k = 0; k < 3; k++) {
- int idx = polygon[kofs[k]];
- ERR_FAIL_INDEX(idx, vsize);
- indices.push_back(idx);
- }
+ Vector<Vector2> vertices;
+ vertices.resize(polygon.size());
+ for (int j = 0; j < polygon.size(); j++) {
+ ERR_FAIL_INDEX(polygon[j], verts.size());
+ vertices.write[j] = verts[polygon[j]];
}
+
+ // Generate the polygon color, slightly randomly modified from the settings one.
+ Color random_variation_color;
+ random_variation_color.set_hsv(color.get_h() + rand.random(-1.0, 1.0) * 0.05, color.get_s(), color.get_v() + rand.random(-1.0, 1.0) * 0.1);
+ random_variation_color.a = color.a;
+ Vector<Color> colors;
+ colors.push_back(random_variation_color);
+
+ RS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), vertices, colors);
+ }
+
+ // Draw the region
+ Transform2D xform = get_global_transform();
+ const NavigationServer2D *ns = NavigationServer2D::get_singleton();
+ float radius = ns->map_get_edge_connection_margin(get_world_2d()->get_navigation_map()) / 2.0;
+ for (int i = 0; i < ns->region_get_connections_count(region); i++) {
+ // Two main points
+ Vector2 a = ns->region_get_connection_pathway_start(region, i);
+ a = xform.affine_inverse().xform(a);
+ Vector2 b = ns->region_get_connection_pathway_end(region, i);
+ b = xform.affine_inverse().xform(b);
+ draw_line(a, b, doors_color);
+
+ // Draw a circle to illustrate the margins.
+ float angle = (b - a).angle();
+ draw_arc(a, radius, angle + Math_PI / 2.0, angle - Math_PI / 2.0 + Math_TAU, 10, doors_color);
+ draw_arc(b, radius, angle - Math_PI / 2.0, angle + Math_PI / 2.0, 10, doors_color);
}
- RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, vertices, colors);
}
} break;
}
@@ -484,6 +503,11 @@ void NavigationRegion2D::_navpoly_changed() {
update();
}
}
+void NavigationRegion2D::_map_changed(RID p_map) {
+ if (enabled && get_world_2d()->get_navigation_map() == p_map) {
+ update();
+ }
+}
String NavigationRegion2D::get_configuration_warning() const {
if (!is_visible_in_tree() || !is_inside_tree()) {
diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h
index 7b471bd555..58f04599be 100644
--- a/scene/2d/navigation_region_2d.h
+++ b/scene/2d/navigation_region_2d.h
@@ -99,6 +99,7 @@ class NavigationRegion2D : public Node2D {
Ref<NavigationPolygon> navpoly;
void _navpoly_changed();
+ void _map_changed(RID p_RID);
protected:
void _notification(int p_what);
diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp
index 849ef7a2bf..39880db29c 100644
--- a/scene/3d/collision_object_3d.cpp
+++ b/scene/3d/collision_object_3d.cpp
@@ -30,6 +30,7 @@
#include "collision_object_3d.h"
+#include "core/config/engine.h"
#include "mesh_instance_3d.h"
#include "scene/scene_string_names.h"
#include "servers/physics_server_3d.h"
@@ -139,7 +140,7 @@ void CollisionObject3D::_update_debug_shapes() {
}
void CollisionObject3D::_update_shape_data(uint32_t p_owner) {
- if (is_inside_tree() && get_tree()->is_debugging_collisions_hint()) {
+ if (is_inside_tree() && get_tree()->is_debugging_collisions_hint() && !Engine::get_singleton()->is_editor_hint()) {
if (debug_shapes_to_update.is_empty()) {
call_deferred("_update_debug_shapes");
}
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 24c73a6b1b..4b4d3943c9 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -1337,6 +1337,7 @@ void AnimationTree::_tree_changed() {
}
void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<AnimationNode> node) {
+ ERR_FAIL_COND(node.is_null());
if (!property_parent_map.has(p_base_path)) {
property_parent_map[p_base_path] = HashMap<StringName, StringName>();
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index e2b30cfa3d..e4cda4b96f 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1163,7 +1163,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
if (p_world_2d.is_valid()) {
world_2d = p_world_2d;
} else {
- WARN_PRINT("Invalid world_3d");
+ WARN_PRINT("Invalid world_2d");
world_2d = Ref<World2D>(memnew(World2D));
}
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index a064ade362..ccdc5bebd0 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -368,7 +368,7 @@ World2D::World2D() {
navigation_map = NavigationServer2D::get_singleton()->map_create();
NavigationServer2D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer2D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_DEF("navigation/2d/default_cell_size", 10));
- NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 100));
+ NavigationServer2D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 5));
indexer = memnew(SpatialIndexer2D);
}
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index fee74f3dbc..7e579c36f4 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -156,6 +156,10 @@ static Ref<NavigationMesh> poly_to_mesh(Ref<NavigationPolygon> d) {
}
}
+void NavigationServer2D::_emit_map_changed(RID p_map) {
+ emit_signal("map_changed", p_map);
+}
+
void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create);
ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active);
@@ -174,6 +178,9 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly);
+ ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count);
+ ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start);
+ ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map);
@@ -189,10 +196,14 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer2D::free);
+
+ ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
}
NavigationServer2D::NavigationServer2D() {
singleton = this;
+ ERR_FAIL_COND_MSG(!NavigationServer3D::get_singleton(), "The Navigation3D singleton should be initialized before the 2D one.");
+ NavigationServer3D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationServer2D::_emit_map_changed));
}
NavigationServer2D::~NavigationServer2D() {
@@ -226,6 +237,10 @@ void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon>
NavigationServer3D::get_singleton()->region_set_navmesh(p_region, poly_to_mesh(p_nav_mesh));
}
+int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid);
+Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
+Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
+
RID NavigationServer2D::agent_create() const {
RID agent = NavigationServer3D::get_singleton()->agent_create();
NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 46c8f6a71d..d56c719839 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -45,12 +45,14 @@ class NavigationServer2D : public Object {
static NavigationServer2D *singleton;
+ void _emit_map_changed(RID p_map);
+
protected:
static void _bind_methods();
public:
/// Thread safe, can be used across many threads.
- static const NavigationServer2D *get_singleton() { return singleton; }
+ static NavigationServer2D *get_singleton() { return singleton; }
/// MUST be used in single thread!
static NavigationServer2D *get_singleton_mut() { return singleton; }
@@ -98,6 +100,11 @@ public:
/// Set the navigation poly of this region.
virtual void region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const;
+ /// Get a list of a region's connection to other regions.
+ virtual int region_get_connections_count(RID p_region) const;
+ virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const;
+ virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const;
+
/// Creates the agent.
virtual RID agent_create() const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index d81ce70af6..b0047a250a 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -59,6 +59,9 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh);
ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh);
+ ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer3D::region_get_connections_count);
+ ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start);
+ ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end);
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map);
@@ -77,9 +80,11 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active);
ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process);
+
+ ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
}
-const NavigationServer3D *NavigationServer3D::get_singleton() {
+NavigationServer3D *NavigationServer3D::get_singleton() {
return singleton;
}
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index beed19d563..420f9c9c18 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -55,7 +55,7 @@ protected:
public:
/// Thread safe, can be used across many threads.
- static const NavigationServer3D *get_singleton();
+ static NavigationServer3D *get_singleton();
/// MUST be used in single thread!
static NavigationServer3D *get_singleton_mut();
@@ -111,9 +111,14 @@ public:
/// Set the navigation mesh of this region.
virtual void region_set_navmesh(RID p_region, Ref<NavigationMesh> p_nav_mesh) const = 0;
- /// Bake the navigation mesh
+ /// Bake the navigation mesh.
virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const = 0;
+ /// Get a list of a region's connection to other regions.
+ virtual int region_get_connections_count(RID p_region) const = 0;
+ virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0;
+ virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0;
+
/// Creates the agent.
virtual RID agent_create() const = 0;
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp
index 651961433c..33075a38be 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/collision_solver_3d_sat.cpp
@@ -1627,10 +1627,55 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform &p
SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin> separator(capsule_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b);
+ if (!separator.test_previous_axis()) {
+ return;
+ }
+
+ // Cylinder B end caps.
+ Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1).normalized();
+ if (!separator.test_axis(cylinder_B_axis)) {
+ return;
+ }
+
+ // Cylinder edge against capsule balls.
+
+ Vector3 capsule_A_axis = p_transform_a.basis.get_axis(1);
+
+ Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis * (capsule_A->get_height() * 0.5);
+ Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis * (capsule_A->get_height() * 0.5);
+
+ if (!separator.test_axis((p_transform_b.origin - capsule_A_ball_1).cross(cylinder_B_axis).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ if (!separator.test_axis((p_transform_b.origin - capsule_A_ball_2).cross(cylinder_B_axis).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ // Cylinder edge against capsule edge.
+
+ Vector3 center_diff = p_transform_b.origin - p_transform_a.origin;
+
+ if (!separator.test_axis(capsule_A_axis.cross(center_diff).cross(capsule_A_axis).normalized())) {
+ return;
+ }
+
+ if (!separator.test_axis(cylinder_B_axis.cross(center_diff).cross(cylinder_B_axis).normalized())) {
+ return;
+ }
+
+ real_t proj = capsule_A_axis.cross(cylinder_B_axis).cross(cylinder_B_axis).dot(capsule_A_axis);
+ if (Math::is_zero_approx(proj)) {
+ // Parallel capsule and cylinder axes, handle with specific axes only.
+ // Note: GJKEPA with no margin can lead to degenerate cases in this situation.
+ separator.generate_contacts();
+ return;
+ }
+
CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points;
// Fallback to generic algorithm to find the best separating axis.
- if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator)) {
+ if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
return;
}
@@ -1805,7 +1850,7 @@ static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform &
CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points;
// Fallback to generic algorithm to find the best separating axis.
- if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator)) {
+ if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
return;
}
@@ -1822,7 +1867,7 @@ static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Trans
CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, ConvexPolygonShape3DSW, withMargin>::test_contact_points;
// Fallback to generic algorithm to find the best separating axis.
- if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator)) {
+ if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) {
return;
}
diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp
index aa7c11eec5..e44c92da79 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/servers/physics_3d/gjk_epa.cpp
@@ -110,26 +110,60 @@ struct MinkowskiDiff {
Transform transform_A;
Transform transform_B;
+ real_t margin_A = 0.0;
+ real_t margin_B = 0.0;
+
+ Vector3 (*get_support)(const Shape3DSW*, const Vector3&, real_t);
+
+ void Initialize(const Shape3DSW* shape0, const Transform& wtrs0, const real_t margin0,
+ const Shape3DSW* shape1, const Transform& wtrs1, const real_t margin1) {
+ m_shapes[0] = shape0;
+ m_shapes[1] = shape1;
+ transform_A = wtrs0;
+ transform_B = wtrs1;
+ margin_A = margin0;
+ margin_B = margin1;
+
+ if ((margin0 > 0.0) || (margin1 > 0.0)) {
+ get_support = get_support_with_margin;
+ } else {
+ get_support = get_support_without_margin;
+ }
+ }
+
+ static Vector3 get_support_without_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) {
+ return p_shape->get_support(p_dir.normalized());
+ }
+
+ static Vector3 get_support_with_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) {
+ Vector3 local_dir_norm = p_dir;
+ if (local_dir_norm.length_squared() < CMP_EPSILON2) {
+ local_dir_norm = Vector3(-1.0, -1.0, -1.0);
+ }
+ local_dir_norm.normalize();
+
+ return p_shape->get_support(local_dir_norm) + p_margin * local_dir_norm;
+ }
+
// i wonder how this could be sped up... if it can
- _FORCE_INLINE_ Vector3 Support0 ( const Vector3& d ) const {
- return transform_A.xform( m_shapes[0]->get_support( transform_A.basis.xform_inv(d).normalized() ) );
+ _FORCE_INLINE_ Vector3 Support0(const Vector3& d) const {
+ return transform_A.xform(get_support(m_shapes[0], transform_A.basis.xform_inv(d), margin_A));
}
- _FORCE_INLINE_ Vector3 Support1 ( const Vector3& d ) const {
- return transform_B.xform( m_shapes[1]->get_support( transform_B.basis.xform_inv(d).normalized() ) );
+ _FORCE_INLINE_ Vector3 Support1(const Vector3& d) const {
+ return transform_B.xform(get_support(m_shapes[1], transform_B.basis.xform_inv(d), margin_B));
}
- _FORCE_INLINE_ Vector3 Support ( const Vector3& d ) const {
- return ( Support0 ( d )-Support1 ( -d ) );
+ _FORCE_INLINE_ Vector3 Support (const Vector3& d) const {
+ return (Support0(d) - Support1(-d));
}
- _FORCE_INLINE_ Vector3 Support ( const Vector3& d,U index ) const
- {
- if ( index ) {
- return ( Support1 ( d ) );
+ _FORCE_INLINE_ Vector3 Support(const Vector3& d, U index) const {
+ if (index) {
+ return Support1(d);
} else {
- return ( Support0 ( d ) );
-}
+ return Support0(d);
+ }
}
};
@@ -828,22 +862,17 @@ struct GJK
};
//
- static void Initialize( const Shape3DSW* shape0,const Transform& wtrs0,
- const Shape3DSW* shape1,const Transform& wtrs1,
+ static void Initialize( const Shape3DSW* shape0, const Transform& wtrs0, real_t margin0,
+ const Shape3DSW* shape1, const Transform& wtrs1, real_t margin1,
sResults& results,
- tShape& shape,
- bool withmargins)
+ tShape& shape)
{
/* Results */
- results.witnesses[0] =
- results.witnesses[1] = Vector3(0,0,0);
+ results.witnesses[0] = Vector3(0,0,0);
+ results.witnesses[1] = Vector3(0,0,0);
results.status = sResults::Separated;
/* Shape */
- shape.m_shapes[0] = shape0;
- shape.m_shapes[1] = shape1;
- shape.transform_A = wtrs0;
- shape.transform_B = wtrs1;
-
+ shape.Initialize(shape0, wtrs0, margin0, shape1, wtrs1, margin1);
}
@@ -857,13 +886,15 @@ struct GJK
//
bool Distance( const Shape3DSW* shape0,
const Transform& wtrs0,
- const Shape3DSW* shape1,
+ real_t margin0,
+ const Shape3DSW* shape1,
const Transform& wtrs1,
+ real_t margin1,
const Vector3& guess,
sResults& results)
{
tShape shape;
- Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+ Initialize(shape0, wtrs0, margin0, shape1, wtrs1, margin1, results, shape);
GJK gjk;
GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
if(gjk_status==GJK::eStatus::Valid)
@@ -896,14 +927,16 @@ bool Distance( const Shape3DSW* shape0,
//
bool Penetration( const Shape3DSW* shape0,
const Transform& wtrs0,
- const Shape3DSW* shape1,
+ real_t margin0,
+ const Shape3DSW* shape1,
const Transform& wtrs1,
- const Vector3& guess,
+ real_t margin1,
+ const Vector3& guess,
sResults& results
)
{
tShape shape;
- Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+ Initialize(shape0, wtrs0, margin0, shape1, wtrs1, margin1, results, shape);
GJK gjk;
GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess);
switch(gjk_status)
@@ -963,7 +996,7 @@ bool Penetration( const Shape3DSW* shape0,
bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) {
GjkEpa2::sResults res;
- if (GjkEpa2::Distance(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) {
+ if (GjkEpa2::Distance(p_shape_A, p_transform_A, 0.0, p_shape_B, p_transform_B, 0.0, p_transform_B.origin - p_transform_A.origin, res)) {
r_result_A = res.witnesses[0];
r_result_B = res.witnesses[1];
return true;
@@ -972,10 +1005,10 @@ bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_t
return false;
}
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap) {
+bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) {
GjkEpa2::sResults res;
- if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) {
+ if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_margin_A, p_shape_B, p_transform_B, p_margin_B, p_transform_B.origin - p_transform_A.origin, res)) {
if (p_result_callback) {
if (p_swap) {
p_result_callback(res.witnesses[1], res.witnesses[0], p_userdata);
diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h
index be3ba4e664..a7e2e1719e 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/servers/physics_3d/gjk_epa.h
@@ -34,7 +34,7 @@
#include "collision_solver_3d_sw.h"
#include "shape_3d_sw.h"
-bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false);
+bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
#endif
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index c6be07a3de..e82d5cc3f8 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -233,7 +233,7 @@ public:
FUNC2(shader_set_code, RID, const String &)
FUNC1RC(String, shader_get_code, RID)
- FUNC2C(shader_get_param_list, RID, List<PropertyInfo> *)
+ FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)