summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/SCsub6
-rw-r--r--modules/arkit/arkit_interface.mm12
-rw-r--r--modules/assimp/SCsub18
-rwxr-xr-x[-rw-r--r--]modules/assimp/godot_update_assimp.sh3
-rw-r--r--modules/bullet/rigid_body_bullet.h2
-rw-r--r--modules/bullet/space_bullet.cpp12
-rw-r--r--modules/bullet/space_bullet.h2
-rw-r--r--modules/etc/SCsub4
-rw-r--r--modules/gdnative/gdnative/string.cpp14
-rw-r--r--modules/gdnative/gdnative/vector2.cpp8
-rw-r--r--modules/gdnative/gdnative/vector3.cpp8
-rw-r--r--modules/gdnative/gdnative_api.json48
-rw-r--r--modules/gdnative/gdnative_library_editor_plugin.cpp45
-rw-r--r--modules/gdnative/gdnative_library_editor_plugin.h2
-rw-r--r--modules/gdnative/include/gdnative/string.h2
-rw-r--r--modules/gdnative/include/gdnative/vector2.h2
-rw-r--r--modules/gdnative/include/gdnative/vector3.h2
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h6
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml69
-rw-r--r--modules/gdscript/gdscript_parser.cpp1
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp36
-rw-r--r--modules/gdscript/gdscript_tokenizer.h6
-rw-r--r--modules/mono/csharp_script.cpp4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs38
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs17
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs11
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/MonoBuildTab.cs65
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs22
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs5
-rw-r--r--modules/mono/glue/Managed/Files/AABB.cs3
-rw-r--r--modules/mono/glue/Managed/Files/Basis.cs4
-rw-r--r--modules/mono/glue/Managed/Files/Color.cs30
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs8
-rw-r--r--modules/mono/glue/Managed/Files/NodePath.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Plane.cs3
-rw-r--r--modules/mono/glue/Managed/Files/Quat.cs13
-rw-r--r--modules/mono/glue/Managed/Files/Rect2.cs1
-rw-r--r--modules/mono/glue/Managed/Files/StringExtensions.cs60
-rw-r--r--modules/mono/glue/Managed/Files/Transform.cs3
-rw-r--r--modules/mono/glue/Managed/Files/Transform2D.cs8
-rw-r--r--modules/mono/glue/Managed/Files/Vector2.cs3
-rw-r--r--modules/mono/glue/Managed/Files/Vector3.cs3
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp57
-rw-r--r--modules/mono/mono_gd/gd_mono.h13
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp15
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp17
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h2
-rw-r--r--modules/tinyexr/image_saver_tinyexr.cpp279
-rw-r--r--modules/tinyexr/image_saver_tinyexr.h38
-rw-r--r--modules/tinyexr/register_types.cpp5
-rw-r--r--modules/vhacd/SCsub4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml1
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp2
-rw-r--r--modules/visual_script/visual_script_editor.cpp8
-rw-r--r--modules/visual_script/visual_script_property_selector.cpp14
-rw-r--r--modules/webm/SCsub4
-rw-r--r--modules/websocket/wsl_client.cpp12
-rw-r--r--modules/xatlas_unwrap/SCsub4
61 files changed, 842 insertions, 250 deletions
diff --git a/modules/SCsub b/modules/SCsub
index 36c2472c42..42d89d6ce2 100644
--- a/modules/SCsub
+++ b/modules/SCsub
@@ -6,9 +6,9 @@ env_modules = env.Clone()
Export('env_modules')
-env.modules_sources = [
- "register_module_types.gen.cpp",
-]
+env.modules_sources = []
+
+env_modules.add_source_files(env.modules_sources, "register_module_types.gen.cpp")
for x in env.module_list:
if (x in env.disabled_modules):
diff --git a/modules/arkit/arkit_interface.mm b/modules/arkit/arkit_interface.mm
index de58f93276..68844c54c2 100644
--- a/modules/arkit/arkit_interface.mm
+++ b/modules/arkit/arkit_interface.mm
@@ -430,7 +430,7 @@ void ARKitInterface::process() {
// get some info about our screen and orientation
Size2 screen_size = OS::get_singleton()->get_window_size();
- UIDeviceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
+ UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
// Grab our camera image for our backbuffer
CVPixelBufferRef pixelBuffer = current_frame.capturedImage;
@@ -531,7 +531,7 @@ void ARKitInterface::process() {
// we need to invert this, probably row v.s. column notation
affine_transform = CGAffineTransformInvert(affine_transform);
- if (orientation != UIDeviceOrientationPortrait) {
+ if (orientation != UIInterfaceOrientationPortrait) {
affine_transform.b = -affine_transform.b;
affine_transform.d = -affine_transform.d;
affine_transform.ty = 1.0 - affine_transform.ty;
@@ -582,28 +582,28 @@ void ARKitInterface::process() {
// copy our current frame transform
matrix_float4x4 m44 = camera.transform;
- if (orientation == UIDeviceOrientationLandscapeLeft) {
+ if (orientation == UIInterfaceOrientationLandscapeLeft) {
transform.basis.elements[0].x = m44.columns[0][0];
transform.basis.elements[1].x = m44.columns[0][1];
transform.basis.elements[2].x = m44.columns[0][2];
transform.basis.elements[0].y = m44.columns[1][0];
transform.basis.elements[1].y = m44.columns[1][1];
transform.basis.elements[2].y = m44.columns[1][2];
- } else if (orientation == UIDeviceOrientationPortrait) {
+ } else if (orientation == UIInterfaceOrientationPortrait) {
transform.basis.elements[0].x = m44.columns[1][0];
transform.basis.elements[1].x = m44.columns[1][1];
transform.basis.elements[2].x = m44.columns[1][2];
transform.basis.elements[0].y = -m44.columns[0][0];
transform.basis.elements[1].y = -m44.columns[0][1];
transform.basis.elements[2].y = -m44.columns[0][2];
- } else if (orientation == UIDeviceOrientationLandscapeRight) {
+ } else if (orientation == UIInterfaceOrientationLandscapeRight) {
transform.basis.elements[0].x = -m44.columns[0][0];
transform.basis.elements[1].x = -m44.columns[0][1];
transform.basis.elements[2].x = -m44.columns[0][2];
transform.basis.elements[0].y = -m44.columns[1][0];
transform.basis.elements[1].y = -m44.columns[1][1];
transform.basis.elements[2].y = -m44.columns[1][2];
- } else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
+ } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
// this may not be correct
transform.basis.elements[0].x = m44.columns[1][0];
transform.basis.elements[1].x = m44.columns[1][1];
diff --git a/modules/assimp/SCsub b/modules/assimp/SCsub
index 8a77e4f803..275f1ff5e9 100644
--- a/modules/assimp/SCsub
+++ b/modules/assimp/SCsub
@@ -9,6 +9,7 @@ env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/include'])
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/code/Importer/IFC'])
env_assimp.Prepend(CPPPATH=['#thirdparty/misc'])
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/code'])
+env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/common'])
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/contrib/irrXML/'])
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/contrib/unzip/'])
env_assimp.Prepend(CPPPATH=['#thirdparty/assimp/code/Importer/STEPParser'])
@@ -65,18 +66,13 @@ env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_STEP_IMPORTER'])
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_IFC_IMPORTER'])
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_XGL_IMPORTER'])
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_ASSBIN_IMPORTER'])
-env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF_IMPORTER'])
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_C4D_IMPORTER'])
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_3MF_IMPORTER'])
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_X3D_IMPORTER'])
-
+env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF_IMPORTER'])
+env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_NO_GLTF2_IMPORTER'])
env_assimp.Append(CPPDEFINES=['ASSIMP_BUILD_SINGLETHREADED'])
-if (not env.msvc):
- env_assimp.Append(CXXFLAGS=['-std=c++11'])
-elif (env.msvc == False and env['platform'] == 'windows'):
- env_assimp.Append(LDFLAGS=['-pthread'])
-
if(env['platform'] == 'windows'):
env_assimp.Append(CPPDEFINES=['PLATFORM_WINDOWS'])
env_assimp.Append(CPPDEFINES=[('PLATFORM', 'WINDOWS')])
@@ -89,7 +85,13 @@ elif(env['platform'] == 'osx'):
env_thirdparty = env_assimp.Clone()
env_thirdparty.disable_warnings()
-env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/*.cpp'))
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/Common/*.cpp'))
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/PostProcessing/*.cpp'))
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/Material/*.cpp'))
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/FBX/*.cpp'))
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/MMD/*.cpp'))
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/glTF/*.cpp'))
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/glTF2/*.cpp'))
# Godot's own source files
env_assimp.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/assimp/godot_update_assimp.sh b/modules/assimp/godot_update_assimp.sh
index dcf1e6d4a2..ff8ff59e97 100644..100755
--- a/modules/assimp/godot_update_assimp.sh
+++ b/modules/assimp/godot_update_assimp.sh
@@ -254,8 +254,9 @@ rm -rf contrib/irrXML
rm -rf contrib/Open3DGC
rm -rf contrib/openddlparser
rm -rf contrib/poly2tri
-rm -rf contrib/rapidjson
+#rm -rf contrib/rapidjson
rm -rf contrib/unzip
rm -rf contrib/zip
rm -rf contrib/stb_image
rm .travis*
+
diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h
index 2c9bdb8b0b..f63148092f 100644
--- a/modules/bullet/rigid_body_bullet.h
+++ b/modules/bullet/rigid_body_bullet.h
@@ -305,7 +305,7 @@ public:
void reload_axis_lock();
/// Doc:
- /// http://www.bulletphysics.org/mediawiki-1.5.8/index.php?title=Anti_tunneling_by_Motion_Clamping
+ /// https://web.archive.org/web/20180404091446/http://www.bulletphysics.org/mediawiki-1.5.8/index.php/Anti_tunneling_by_Motion_Clamping
void set_continuous_collision_detection(bool p_enable);
bool is_continuous_collision_detection_enabled() const;
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index 738b415d16..f475ba23f6 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -581,6 +581,10 @@ void SpaceBullet::create_empty_world(bool p_create_soft_world) {
} else {
world_mem = malloc(sizeof(btDiscreteDynamicsWorld));
}
+ if (!world_mem) {
+ ERR_EXPLAIN("Out of memory");
+ ERR_FAIL();
+ }
if (p_create_soft_world) {
collisionConfiguration = bulletnew(GodotSoftCollisionConfiguration(static_cast<btDiscreteDynamicsWorld *>(world_mem)));
@@ -1230,7 +1234,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
ERR_FAIL_COND_V(shape_idx < 0 || shape_idx >= cs->getNumChildShapes(), false);
if (cs->getChildShape(shape_idx)->isConvex()) {
- if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(shape_idx)), otherObject, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
+ if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(shape_idx)), otherObject, kinIndex, shape_idx, shape_transform, otherObject->getWorldTransform() * cs->getChildTransform(shape_idx), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
penetration = true;
}
@@ -1241,7 +1245,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
}
}
} else if (otherObject->getCollisionShape()->isConvex()) { /// Execute GJK test against object shape
- if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
+ if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, kinIndex, 0, shape_transform, otherObject->getWorldTransform(), p_recover_movement_scale, r_delta_recover_movement, r_recover_result)) {
penetration = true;
}
@@ -1257,7 +1261,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
return penetration;
}
-bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
+bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result) {
// Initialize GJK input
btGjkPairDetector::ClosestPointInput gjk_input;
@@ -1275,6 +1279,7 @@ bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const bt
if (r_recover_result) {
if (result.m_distance < r_recover_result->penetration_distance) {
r_recover_result->hasPenetration = true;
+ r_recover_result->local_shape_most_recovered = p_shapeId_A;
r_recover_result->other_collision_object = p_objectB;
r_recover_result->other_compound_shape_index = p_shapeId_B;
r_recover_result->penetration_distance = result.m_distance;
@@ -1310,6 +1315,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC
if (r_recover_result) {
if (contactPointResult.m_penetration_distance < r_recover_result->penetration_distance) {
r_recover_result->hasPenetration = true;
+ r_recover_result->local_shape_most_recovered = p_shapeId_A;
r_recover_result->other_collision_object = p_objectB;
r_recover_result->other_compound_shape_index = p_shapeId_B;
r_recover_result->penetration_distance = contactPointResult.m_penetration_distance;
diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h
index eb4a065e54..ecf8a2db9d 100644
--- a/modules/bullet/space_bullet.h
+++ b/modules/bullet/space_bullet.h
@@ -208,7 +208,7 @@ private:
bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
/// This is an API that recover a kinematic object from penetration
/// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions
- bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
+ bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
/// This is an API that recover a kinematic object from penetration
/// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm
bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL);
diff --git a/modules/etc/SCsub b/modules/etc/SCsub
index 532b97b006..1742d3534f 100644
--- a/modules/etc/SCsub
+++ b/modules/etc/SCsub
@@ -29,10 +29,6 @@ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_etc.Prepend(CPPPATH=[thirdparty_dir])
-# upstream uses c++11
-if not env.msvc:
- env_etc.Append(CXXFLAGS="-std=c++11")
-
env_thirdparty = env_etc.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp
index 913c57eb56..9086121940 100644
--- a/modules/gdnative/gdnative/string.cpp
+++ b/modules/gdnative/gdnative/string.cpp
@@ -186,6 +186,20 @@ godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_
return self->ends_with(*string);
}
+godot_int GDAPI godot_string_count(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to) {
+ const String *self = (const String *)p_self;
+ String *what = (String *)&p_what;
+
+ return self->count(*what, p_from, p_to);
+}
+
+godot_int GDAPI godot_string_countn(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to) {
+ const String *self = (const String *)p_self;
+ String *what = (String *)&p_what;
+
+ return self->countn(*what, p_from, p_to);
+}
+
godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what) {
const String *self = (const String *)p_self;
String *what = (String *)&p_what;
diff --git a/modules/gdnative/gdnative/vector2.cpp b/modules/gdnative/gdnative/vector2.cpp
index a2ac61b35e..d82f2c692d 100644
--- a/modules/gdnative/gdnative/vector2.cpp
+++ b/modules/gdnative/gdnative/vector2.cpp
@@ -77,6 +77,14 @@ godot_bool GDAPI godot_vector2_is_normalized(const godot_vector2 *p_self) {
return self->is_normalized();
}
+godot_vector2 GDAPI godot_vector2_direction_to(const godot_vector2 *p_self, const godot_vector2 *p_to) {
+ godot_vector2 dest;
+ const Vector2 *self = (const Vector2 *)p_self;
+ const Vector2 *to = (const Vector2 *)p_to;
+ *((Vector2 *)&dest) = self->direction_to(*to);
+ return dest;
+}
+
godot_real GDAPI godot_vector2_distance_to(const godot_vector2 *p_self, const godot_vector2 *p_to) {
const Vector2 *self = (const Vector2 *)p_self;
const Vector2 *to = (const Vector2 *)p_to;
diff --git a/modules/gdnative/gdnative/vector3.cpp b/modules/gdnative/gdnative/vector3.cpp
index 894683ab38..15a8ef9a2e 100644
--- a/modules/gdnative/gdnative/vector3.cpp
+++ b/modules/gdnative/gdnative/vector3.cpp
@@ -182,6 +182,14 @@ godot_vector3 GDAPI godot_vector3_ceil(const godot_vector3 *p_self) {
return dest;
}
+godot_vector3 GDAPI godot_vector3_direction_to(const godot_vector3 *p_self, const godot_vector3 *p_to) {
+ godot_vector3 dest;
+ const Vector3 *self = (const Vector3 *)p_self;
+ const Vector3 *to = (const Vector3 *)p_to;
+ *((Vector3 *)&dest) = self->direction_to(*to);
+ return dest;
+}
+
godot_real GDAPI godot_vector3_distance_to(const godot_vector3 *p_self, const godot_vector3 *p_b) {
const Vector3 *self = (const Vector3 *)p_self;
const Vector3 *b = (const Vector3 *)p_b;
diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json
index 6c12ee6534..03258584ce 100644
--- a/modules/gdnative/gdnative_api.json
+++ b/modules/gdnative/gdnative_api.json
@@ -44,6 +44,42 @@
["const godot_vector2 *", "p_to"],
["const godot_real", "p_delta"]
]
+ },
+ {
+ "name": "godot_string_count",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"],
+ ["godot_int", "p_from"],
+ ["godot_int", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_string_countn",
+ "return_type": "godot_int",
+ "arguments": [
+ ["const godot_string *", "p_self"],
+ ["godot_string", "p_what"],
+ ["godot_int", "p_from"],
+ ["godot_int", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_vector3_direction_to",
+ "return_type": "godot_vector3",
+ "arguments": [
+ ["const godot_vector3 *", "p_self"],
+ ["const godot_vector3 *", "p_to"]
+ ]
+ },
+ {
+ "name": "godot_vector2_direction_to",
+ "return_type": "godot_vector2",
+ "arguments": [
+ ["const godot_vector2 *", "p_self"],
+ ["const godot_vector2 *", "p_to"]
+ ]
}
]
},
@@ -6512,24 +6548,24 @@
"name": "godot_net_bind_stream_peer",
"return_type": "void",
"arguments": [
- ["godot_object *", "p_obj"],
- ["const godot_net_stream_peer *", "p_interface"]
+ ["godot_object *", "p_obj"],
+ ["const godot_net_stream_peer *", "p_interface"]
]
},
{
"name": "godot_net_bind_packet_peer",
"return_type": "void",
"arguments": [
- ["godot_object *", "p_obj"],
- ["const godot_net_packet_peer *", "p_interface"]
+ ["godot_object *", "p_obj"],
+ ["const godot_net_packet_peer *", "p_interface"]
]
},
{
"name": "godot_net_bind_multiplayer_peer",
"return_type": "void",
"arguments": [
- ["godot_object *", "p_obj"],
- ["const godot_net_multiplayer_peer *", "p_interface"]
+ ["godot_object *", "p_obj"],
+ ["const godot_net_multiplayer_peer *", "p_interface"]
]
}
]
diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp
index e2a69b1635..5d272a6cdc 100644
--- a/modules/gdnative/gdnative_library_editor_plugin.cpp
+++ b/modules/gdnative/gdnative_library_editor_plugin.cpp
@@ -66,10 +66,18 @@ void GDNativeLibraryEditor::_update_tree() {
tree->clear();
TreeItem *root = tree->create_item();
- for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) {
+ PopupMenu *filter_list = filter->get_popup();
+ String text = "";
+ for (int i = 0; i < filter_list->get_item_count(); i++) {
- if (showing_platform != E->key() && showing_platform != "All")
+ if (!filter_list->is_item_checked(i)) {
continue;
+ }
+ Map<String, NativePlatformConfig>::Element *E = platforms.find(filter_list->get_item_metadata(i));
+ if (!text.empty()) {
+ text += ", ";
+ }
+ text += E->get().name;
TreeItem *platform = tree->create_item(root);
platform->set_text(0, E->get().name);
@@ -119,6 +127,7 @@ void GDNativeLibraryEditor::_update_tree() {
platform->set_collapsed(collapsed_items.find(E->get().name) != NULL);
}
+ filter->set_text(text);
}
void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) {
@@ -162,9 +171,10 @@ void GDNativeLibraryEditor::_on_dependencies_selected(const PoolStringArray &fil
_set_target_value(file_dialog->get_meta("section"), file_dialog->get_meta("target"), files);
}
-void GDNativeLibraryEditor::_on_filter_selected(int id) {
+void GDNativeLibraryEditor::_on_filter_selected(int index) {
- showing_platform = filter->get_item_metadata(id);
+ PopupMenu *filter_list = filter->get_popup();
+ filter_list->set_item_checked(index, !filter_list->is_item_checked(index));
_update_tree();
}
@@ -265,8 +275,6 @@ void GDNativeLibraryEditor::_translate_to_config_file() {
GDNativeLibraryEditor::GDNativeLibraryEditor() {
- showing_platform = "All";
-
{ // Define platforms
NativePlatformConfig platform_windows;
platform_windows.name = "Windows";
@@ -336,20 +344,21 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() {
Label *label = memnew(Label);
label->set_text(TTR("Platform:"));
hbox->add_child(label);
- filter = memnew(OptionButton);
- hbox->add_child(filter);
+ filter = memnew(MenuButton);
filter->set_h_size_flags(SIZE_EXPAND_FILL);
+ filter->set_text_align(filter->ALIGN_LEFT);
+ hbox->add_child(filter);
+ PopupMenu *filter_list = filter->get_popup();
+ filter_list->set_hide_on_checkable_item_selection(false);
int idx = 0;
- filter->add_item(TTR("All"), idx);
- filter->set_item_metadata(idx, "All");
- idx += 1;
for (Map<String, NativePlatformConfig>::Element *E = platforms.front(); E; E = E->next()) {
- filter->add_item(E->get().name, idx);
- filter->set_item_metadata(idx, E->key());
+ filter_list->add_check_item(E->get().name, idx);
+ filter_list->set_item_metadata(idx, E->key());
+ filter_list->set_item_checked(idx, true);
idx += 1;
}
- filter->connect("item_selected", this, "_on_filter_selected");
+ filter_list->connect("index_pressed", this, "_on_filter_selected");
tree = memnew(Tree);
container->add_child(tree);
@@ -387,11 +396,9 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() {
void GDNativeLibraryEditorPlugin::edit(Object *p_node) {
- if (Object::cast_to<GDNativeLibrary>(p_node)) {
- library_editor->edit(Object::cast_to<GDNativeLibrary>(p_node));
- library_editor->show();
- } else
- library_editor->hide();
+ Ref<GDNativeLibrary> new_library = Object::cast_to<GDNativeLibrary>(p_node);
+ if (new_library.is_valid())
+ library_editor->edit(new_library);
}
bool GDNativeLibraryEditorPlugin::handles(Object *p_node) const {
diff --git a/modules/gdnative/gdnative_library_editor_plugin.h b/modules/gdnative/gdnative_library_editor_plugin.h
index e7d50ba29f..8c1449f55a 100644
--- a/modules/gdnative/gdnative_library_editor_plugin.h
+++ b/modules/gdnative/gdnative_library_editor_plugin.h
@@ -61,7 +61,7 @@ class GDNativeLibraryEditor : public Control {
};
Tree *tree;
- OptionButton *filter;
+ MenuButton *filter;
EditorFileDialog *file_dialog;
ConfirmationDialog *new_architecture_dialog;
LineEdit *new_architecture_input;
diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h
index f045ac9d58..7500d70f20 100644
--- a/modules/gdnative/include/gdnative/string.h
+++ b/modules/gdnative/include/gdnative/string.h
@@ -102,6 +102,8 @@ godot_bool GDAPI godot_string_begins_with_char_array(const godot_string *p_self,
godot_array GDAPI godot_string_bigrams(const godot_string *p_self);
godot_string GDAPI godot_string_chr(wchar_t p_character);
godot_bool GDAPI godot_string_ends_with(const godot_string *p_self, const godot_string *p_string);
+godot_int GDAPI godot_string_count(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to);
+godot_int GDAPI godot_string_countn(const godot_string *p_self, godot_string p_what, godot_int p_from, godot_int p_to);
godot_int GDAPI godot_string_find(const godot_string *p_self, godot_string p_what);
godot_int GDAPI godot_string_find_from(const godot_string *p_self, godot_string p_what, godot_int p_from);
godot_int GDAPI godot_string_findmk(const godot_string *p_self, const godot_array *p_keys);
diff --git a/modules/gdnative/include/gdnative/vector2.h b/modules/gdnative/include/gdnative/vector2.h
index 7a5ae6afa9..15a6c80887 100644
--- a/modules/gdnative/include/gdnative/vector2.h
+++ b/modules/gdnative/include/gdnative/vector2.h
@@ -71,6 +71,8 @@ godot_real GDAPI godot_vector2_length_squared(const godot_vector2 *p_self);
godot_bool GDAPI godot_vector2_is_normalized(const godot_vector2 *p_self);
+godot_vector2 GDAPI godot_vector2_direction_to(const godot_vector2 *p_self, const godot_vector2 *p_b);
+
godot_real GDAPI godot_vector2_distance_to(const godot_vector2 *p_self, const godot_vector2 *p_to);
godot_real GDAPI godot_vector2_distance_squared_to(const godot_vector2 *p_self, const godot_vector2 *p_to);
diff --git a/modules/gdnative/include/gdnative/vector3.h b/modules/gdnative/include/gdnative/vector3.h
index 70ec6422ac..ee7d029028 100644
--- a/modules/gdnative/include/gdnative/vector3.h
+++ b/modules/gdnative/include/gdnative/vector3.h
@@ -106,6 +106,8 @@ godot_vector3 GDAPI godot_vector3_floor(const godot_vector3 *p_self);
godot_vector3 GDAPI godot_vector3_ceil(const godot_vector3 *p_self);
+godot_vector3 GDAPI godot_vector3_direction_to(const godot_vector3 *p_self, const godot_vector3 *p_b);
+
godot_real GDAPI godot_vector3_distance_to(const godot_vector3 *p_self, const godot_vector3 *p_b);
godot_real GDAPI godot_vector3_distance_squared_to(const godot_vector3 *p_self, const godot_vector3 *p_b);
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index f3b9f7fb31..7f52f5736c 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -56,7 +56,7 @@ typedef enum {
GODOT_PROPERTY_HINT_ENUM, ///< hint_text= "val1,val2,val3,etc"
GODOT_PROPERTY_HINT_EXP_EASING, /// exponential easing function (Math::ease)
GODOT_PROPERTY_HINT_LENGTH, ///< hint_text= "length" (as integer)
- GODOT_PROPERTY_HINT_SPRITE_FRAME,
+ GODOT_PROPERTY_HINT_SPRITE_FRAME, // FIXME: Obsolete: drop whenever we can break compat
GODOT_PROPERTY_HINT_KEY_ACCEL, ///< hint_text= "length" (as integer)
GODOT_PROPERTY_HINT_FLAGS, ///< hint_text= "flag1,flag2,etc" (as bit flags)
GODOT_PROPERTY_HINT_LAYERS_2D_RENDER,
@@ -98,8 +98,8 @@ typedef enum {
GODOT_PROPERTY_USAGE_INTERNATIONALIZED = 64, //hint for internationalized strings
GODOT_PROPERTY_USAGE_GROUP = 128, //used for grouping props in the editor
GODOT_PROPERTY_USAGE_CATEGORY = 256,
- GODOT_PROPERTY_USAGE_STORE_IF_NONZERO = 512, //only store if nonzero
- GODOT_PROPERTY_USAGE_STORE_IF_NONONE = 1024, //only store if false
+ GODOT_PROPERTY_USAGE_STORE_IF_NONZERO = 512, // FIXME: Obsolete: drop whenever we can break compat
+ GODOT_PROPERTY_USAGE_STORE_IF_NONONE = 1024, // FIXME: Obsolete: drop whenever we can break compat
GODOT_PROPERTY_USAGE_NO_INSTANCE_STATE = 2048,
GODOT_PROPERTY_USAGE_RESTART_IF_CHANGED = 4096,
GODOT_PROPERTY_USAGE_SCRIPT_VARIABLE = 8192,
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 2a26df4714..ad47323613 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -322,6 +322,7 @@
<description>
The natural exponential function. It raises the mathematical constant [b]e[/b] to the power of [code]s[/code] and returns it.
[b]e[/b] has an approximate value of 2.71828.
+ For exponents to other bases use the method [method pow].
[codeblock]
a = exp(2) # Approximately 7.39
[/codeblock]
@@ -389,37 +390,6 @@
[/codeblock]
</description>
</method>
- <method name="posmod">
- <return type="int">
- </return>
- <argument index="0" name="a" type="int">
- </argument>
- <argument index="1" name="b" type="int">
- </argument>
- <description>
- Returns the integer modulus of [code]a/b[/code] that wraps equally in positive and negative.
- [codeblock]
- var i = -6
- while i &lt; 5:
- prints(i, posmod(i, 3))
- i += 1
- [/codeblock]
- Produces:
- [codeblock]
- -6 0
- -5 1
- -4 2
- -3 0
- -2 1
- -1 2
- 0 0
- 1 1
- 2 2
- 3 0
- 4 1
- [/codeblock]
- </description>
- </method>
<method name="funcref">
<return type="FuncRef">
</return>
@@ -753,12 +723,43 @@
Converts a 2D point expressed in the polar coordinate system (a distance from the origin [code]r[/code] and an angle [code]th[/code]) to the cartesian coordinate system (X and Y axis).
</description>
</method>
+ <method name="posmod">
+ <return type="int">
+ </return>
+ <argument index="0" name="a" type="int">
+ </argument>
+ <argument index="1" name="b" type="int">
+ </argument>
+ <description>
+ Returns the integer modulus of [code]a/b[/code] that wraps equally in positive and negative.
+ [codeblock]
+ var i = -6
+ while i &lt; 5:
+ prints(i, posmod(i, 3))
+ i += 1
+ [/codeblock]
+ Produces:
+ [codeblock]
+ -6 0
+ -5 1
+ -4 2
+ -3 0
+ -2 1
+ -1 2
+ 0 0
+ 1 1
+ 2 2
+ 3 0
+ 4 1
+ [/codeblock]
+ </description>
+ </method>
<method name="pow">
<return type="float">
</return>
- <argument index="0" name="x" type="float">
+ <argument index="0" name="base" type="float">
</argument>
- <argument index="1" name="y" type="float">
+ <argument index="1" name="exp" type="float">
</argument>
<description>
Returns the result of [code]x[/code] raised to the power of [code]y[/code].
@@ -1095,7 +1096,7 @@
<argument index="0" name="step" type="float">
</argument>
<description>
- Returns the position of the first non-zero digit, after the decimal point.
+ Returns the position of the first non-zero digit, after the decimal point. Note that the maximum return value is 10, which is a design decision in the implementation.
[codeblock]
# n is 0
n = step_decimals(5)
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index f006d50a83..357e9c9615 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -3487,6 +3487,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
} break;
case GDScriptTokenizer::TK_PR_CLASS_NAME: {
+ _mark_line_as_safe(tokenizer->get_token_line());
if (p_class->owner) {
_set_error("'class_name' is only valid for the main class namespace.");
return;
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 95715ab648..59b53b5f9a 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -517,7 +517,22 @@ void GDScriptTokenizerText::_advance() {
INCPOS(1);
column = 1;
int i = 0;
- while (GETCHAR(i) == ' ' || GETCHAR(i) == '\t') {
+ while (true) {
+ if (GETCHAR(i) == ' ') {
+ if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_SPACES;
+ if (file_indent_type != INDENT_SPACES) {
+ _make_error("Spaces used for indentation in tab-indented file!");
+ return;
+ }
+ } else if (GETCHAR(i) == '\t') {
+ if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_TABS;
+ if (file_indent_type != INDENT_TABS) {
+ _make_error("Tabs used for indentation in space-indented file!");
+ return;
+ }
+ } else {
+ break; // not indentation anymore
+ }
i++;
}
@@ -555,9 +570,25 @@ void GDScriptTokenizerText::_advance() {
column = 1;
line++;
int i = 0;
- while (GETCHAR(i) == ' ' || GETCHAR(i) == '\t') {
+ while (true) {
+ if (GETCHAR(i) == ' ') {
+ if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_SPACES;
+ if (file_indent_type != INDENT_SPACES) {
+ _make_error("Spaces used for indentation in tab-indented file!");
+ return;
+ }
+ } else if (GETCHAR(i) == '\t') {
+ if (file_indent_type == INDENT_NONE) file_indent_type = INDENT_TABS;
+ if (file_indent_type != INDENT_TABS) {
+ _make_error("Tabs used for indentation in space-indented file!");
+ return;
+ }
+ } else {
+ break; // not indentation anymore
+ }
i++;
}
+
_make_newline(i);
return;
@@ -1082,6 +1113,7 @@ void GDScriptTokenizerText::set_code(const String &p_code) {
ignore_warnings = false;
#endif // DEBUG_ENABLED
last_error = "";
+ file_indent_type = INDENT_NONE;
for (int i = 0; i < MAX_LOOKAHEAD + 1; i++)
_advance();
}
diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h
index 7b977ff67c..89d586b912 100644
--- a/modules/gdscript/gdscript_tokenizer.h
+++ b/modules/gdscript/gdscript_tokenizer.h
@@ -222,6 +222,12 @@ class GDScriptTokenizerText : public GDScriptTokenizer {
int tk_rb_pos;
String last_error;
bool error_flag;
+ enum {
+ INDENT_NONE,
+ INDENT_SPACES,
+ INDENT_TABS,
+ } file_indent_type;
+
#ifdef DEBUG_ENABLED
Vector<Pair<int, String> > warning_skips;
Set<String> warning_global_skips;
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 078a490b22..f8d201b4ca 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -629,7 +629,6 @@ void CSharpLanguage::frame() {
if (exc) {
GDMonoUtils::debug_unhandled_exception(exc);
- GD_UNREACHABLE();
}
}
}
@@ -2914,11 +2913,10 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Variant::Call
r_error.error = Variant::CallError::CALL_OK;
REF ref;
- Object *owner = NULL;
ERR_FAIL_NULL_V(native, Variant());
- owner = ClassDB::instance(NATIVE_GDMONOCLASS_NAME(native));
+ Object *owner = ClassDB::instance(NATIVE_GDMONOCLASS_NAME(native));
Reference *r = Object::cast_to<Reference>(owner);
if (r) {
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
index 1edc426e00..233aab45b3 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
@@ -85,7 +85,7 @@ namespace GodotTools.ProjectEditor
void AddPropertyIfNotPresent(string name, string condition, string value)
{
if (root.PropertyGroups
- .Any(g => g.Condition == string.Empty || g.Condition == condition &&
+ .Any(g => (g.Condition == string.Empty || g.Condition == condition) &&
g.Properties
.Any(p => p.Name == name &&
p.Value == value &&
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
index f849356919..d8cb9024c3 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs
@@ -137,7 +137,7 @@ namespace GodotTools.Build
private static string BuildArguments(string solution, string config, string loggerOutputDir, List<string> customProperties)
{
- string arguments = $@"""{solution}"" /v:normal /t:Rebuild ""/p:{"Configuration=" + config}"" " +
+ string arguments = $@"""{solution}"" /v:normal /t:Build ""/p:{"Configuration=" + config}"" " +
$@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{loggerOutputDir}""";
foreach (string customProperty in customProperties)
diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
index f0068385f4..926aabdf89 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs
@@ -15,7 +15,6 @@ namespace GodotTools.Build
{
private static string _msbuildToolsPath = string.Empty;
private static string _msbuildUnixPath = string.Empty;
- private static string _xbuildUnixPath = string.Empty;
public static string FindMsBuild()
{
@@ -44,7 +43,6 @@ namespace GodotTools.Build
return Path.Combine(_msbuildToolsPath, "MSBuild.exe");
}
-
case GodotSharpBuilds.BuildTool.MsBuildMono:
{
string msbuildPath = Path.Combine(Internal.MonoWindowsInstallRoot, "bin", "msbuild.bat");
@@ -56,19 +54,6 @@ namespace GodotTools.Build
return msbuildPath;
}
-
- case GodotSharpBuilds.BuildTool.XBuild:
- {
- string xbuildPath = Path.Combine(Internal.MonoWindowsInstallRoot, "bin", "xbuild.bat");
-
- if (!File.Exists(xbuildPath))
- {
- throw new FileNotFoundException($"Cannot find executable for '{GodotSharpBuilds.PropNameXbuild}'. Tried with path: {xbuildPath}");
- }
-
- return xbuildPath;
- }
-
default:
throw new IndexOutOfRangeException("Invalid build tool in editor settings");
}
@@ -76,20 +61,7 @@ namespace GodotTools.Build
if (OS.IsUnix())
{
- if (buildTool == GodotSharpBuilds.BuildTool.XBuild)
- {
- if (_xbuildUnixPath.Empty() || !File.Exists(_xbuildUnixPath))
- {
- // Try to search it again if it wasn't found last time or if it was removed from its location
- _xbuildUnixPath = FindBuildEngineOnUnix("msbuild");
- }
-
- if (_xbuildUnixPath.Empty())
- {
- throw new FileNotFoundException($"Cannot find binary for '{GodotSharpBuilds.PropNameXbuild}'");
- }
- }
- else
+ if (buildTool == GodotSharpBuilds.BuildTool.MsBuildMono)
{
if (_msbuildUnixPath.Empty() || !File.Exists(_msbuildUnixPath))
{
@@ -101,9 +73,13 @@ namespace GodotTools.Build
{
throw new FileNotFoundException($"Cannot find binary for '{GodotSharpBuilds.PropNameMsbuildMono}'");
}
- }
- return buildTool != GodotSharpBuilds.BuildTool.XBuild ? _msbuildUnixPath : _xbuildUnixPath;
+ return _msbuildUnixPath;
+ }
+ else
+ {
+ throw new IndexOutOfRangeException("Invalid build tool in editor settings");
+ }
}
throw new PlatformNotSupportedException();
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs
index a884b0ead0..de3a4d9a6e 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs
@@ -18,7 +18,6 @@ namespace GodotTools
public const string PropNameMsbuildMono = "MSBuild (Mono)";
public const string PropNameMsbuildVs = "MSBuild (VS Build Tools)";
- public const string PropNameXbuild = "xbuild (Deprecated)";
public const string MsBuildIssuesFileName = "msbuild_issues.csv";
public const string MsBuildLogFileName = "msbuild_log.txt";
@@ -26,8 +25,7 @@ namespace GodotTools
public enum BuildTool
{
MsBuildMono,
- MsBuildVs,
- XBuild // Deprecated
+ MsBuildVs
}
private static void RemoveOldIssuesFile(MonoBuildInfo buildInfo)
@@ -64,7 +62,7 @@ namespace GodotTools
private static string GetIssuesFilePath(MonoBuildInfo buildInfo)
{
- return Path.Combine(Godot.ProjectSettings.LocalizePath(buildInfo.LogsDirPath), MsBuildIssuesFileName);
+ return Path.Combine(buildInfo.LogsDirPath, MsBuildIssuesFileName);
}
private static void PrintVerbose(string text)
@@ -202,6 +200,9 @@ namespace GodotTools
// case the user decided to delete them at some point after they were loaded.
Internal.UpdateApiAssembliesFromPrebuilt();
+ var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
+ var buildTool = (BuildTool)editorSettings.GetSetting("mono/builds/build_tool");
+
using (var pr = new EditorProgress("mono_project_debug_build", "Building project solution...", 1))
{
pr.Step("Building project solution", 0);
@@ -209,7 +210,7 @@ namespace GodotTools
var buildInfo = new MonoBuildInfo(GodotSharpDirs.ProjectSlnPath, config);
// Add Godot defines
- string constants = OS.IsWindows() ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\"";
+ string constants = buildTool == BuildTool.MsBuildVs ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\"";
foreach (var godotDefine in godotDefines)
constants += $"GODOT_{godotDefine.ToUpper().Replace("-", "_").Replace(" ", "_").Replace(";", "_")};";
@@ -217,7 +218,7 @@ namespace GodotTools
if (Internal.GodotIsRealTDouble())
constants += "GODOT_REAL_T_IS_DOUBLE;";
- constants += OS.IsWindows() ? "\"" : "\\\"";
+ constants += buildTool == BuildTool.MsBuildVs ? "\"" : "\\\"";
buildInfo.CustomProperties.Add(constants);
@@ -267,8 +268,8 @@ namespace GodotTools
["name"] = "mono/builds/build_tool",
["hint"] = Godot.PropertyHint.Enum,
["hint_string"] = OS.IsWindows() ?
- $"{PropNameMsbuildMono},{PropNameMsbuildVs},{PropNameXbuild}" :
- $"{PropNameMsbuildMono},{PropNameXbuild}"
+ $"{PropNameMsbuildMono},{PropNameMsbuildVs}" :
+ $"{PropNameMsbuildMono}"
});
EditorDef("mono/builds/print_build_output", false);
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index 90dec43412..9b5afb94a3 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -298,7 +298,16 @@ namespace GodotTools
if (line >= 0)
scriptPath += $";{line + 1};{col}";
- GetMonoDevelopInstance(GodotSharpDirs.ProjectSlnPath).Execute(scriptPath);
+ try
+ {
+ GetMonoDevelopInstance(GodotSharpDirs.ProjectSlnPath).Execute(scriptPath);
+ }
+ catch (FileNotFoundException)
+ {
+ string editorName = editor == ExternalEditor.VisualStudioForMac ? "Visual Studio" : "MonoDevelop";
+ GD.PushError($"Cannot find code editor: {editorName}");
+ return Error.FileNotFound;
+ }
break;
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/MonoBuildTab.cs b/modules/mono/editor/GodotTools/GodotTools/MonoBuildTab.cs
index 75fdacc0da..3a74fa2f66 100644
--- a/modules/mono/editor/GodotTools/GodotTools/MonoBuildTab.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/MonoBuildTab.cs
@@ -61,41 +61,48 @@ namespace GodotTools
{
using (var file = new Godot.File())
{
- Error openError = file.Open(csvFile, Godot.File.ModeFlags.Read);
-
- if (openError != Error.Ok)
- return;
-
- while (!file.EofReached())
+ try
{
- string[] csvColumns = file.GetCsvLine();
+ Error openError = file.Open(csvFile, Godot.File.ModeFlags.Read);
- if (csvColumns.Length == 1 && csvColumns[0].Empty())
+ if (openError != Error.Ok)
return;
- if (csvColumns.Length != 7)
+ while (!file.EofReached())
{
- GD.PushError($"Expected 7 columns, got {csvColumns.Length}");
- continue;
+ string[] csvColumns = file.GetCsvLine();
+
+ if (csvColumns.Length == 1 && csvColumns[0].Empty())
+ return;
+
+ if (csvColumns.Length != 7)
+ {
+ GD.PushError($"Expected 7 columns, got {csvColumns.Length}");
+ continue;
+ }
+
+ var issue = new BuildIssue
+ {
+ Warning = csvColumns[0] == "warning",
+ File = csvColumns[1],
+ Line = int.Parse(csvColumns[2]),
+ Column = int.Parse(csvColumns[3]),
+ Code = csvColumns[4],
+ Message = csvColumns[5],
+ ProjectFile = csvColumns[6]
+ };
+
+ if (issue.Warning)
+ WarningCount += 1;
+ else
+ ErrorCount += 1;
+
+ issues.Add(issue);
}
-
- var issue = new BuildIssue
- {
- Warning = csvColumns[0] == "warning",
- File = csvColumns[1],
- Line = int.Parse(csvColumns[2]),
- Column = int.Parse(csvColumns[3]),
- Code = csvColumns[4],
- Message = csvColumns[5],
- ProjectFile = csvColumns[6]
- };
-
- if (issue.Warning)
- WarningCount += 1;
- else
- ErrorCount += 1;
-
- issues.Add(issue);
+ }
+ finally
+ {
+ file.Close(); // Disposing it is not enough. We need to call Close()
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs b/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs
index 0c8d86e799..61a0a992ce 100644
--- a/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/MonoDevelopInstance.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using GodotTools.Internals;
+using GodotTools.Utils;
namespace GodotTools
{
@@ -30,7 +31,7 @@ namespace GodotTools
if (Utils.OS.IsOSX())
{
- string bundleId = CodeEditorBundleIds[editorId];
+ string bundleId = BundleIds[editorId];
if (Internal.IsOsxAppBundleInstalled(bundleId))
{
@@ -47,12 +48,12 @@ namespace GodotTools
}
else
{
- command = CodeEditorPaths[editorId];
+ command = OS.PathWhich(ExecutableNames[editorId]);
}
}
else
{
- command = CodeEditorPaths[editorId];
+ command = OS.PathWhich(ExecutableNames[editorId]);
}
args.Add("--ipc-tcp");
@@ -70,6 +71,9 @@ namespace GodotTools
args.Add("\"" + Path.GetFullPath(filePath.NormalizePath()) + cursor + "\"");
}
+ if (command == null)
+ throw new FileNotFoundException();
+
if (newWindow)
{
process = Process.Start(new ProcessStartInfo
@@ -99,20 +103,20 @@ namespace GodotTools
this.editorId = editorId;
}
- private static readonly IReadOnlyDictionary<EditorId, string> CodeEditorPaths;
- private static readonly IReadOnlyDictionary<EditorId, string> CodeEditorBundleIds;
+ private static readonly IReadOnlyDictionary<EditorId, string> ExecutableNames;
+ private static readonly IReadOnlyDictionary<EditorId, string> BundleIds;
static MonoDevelopInstance()
{
if (Utils.OS.IsOSX())
{
- CodeEditorPaths = new Dictionary<EditorId, string>
+ ExecutableNames = new Dictionary<EditorId, string>
{
// Rely on PATH
{EditorId.MonoDevelop, "monodevelop"},
{EditorId.VisualStudioForMac, "VisualStudio"}
};
- CodeEditorBundleIds = new Dictionary<EditorId, string>
+ BundleIds = new Dictionary<EditorId, string>
{
// TODO EditorId.MonoDevelop
{EditorId.VisualStudioForMac, "com.microsoft.visual-studio"}
@@ -120,7 +124,7 @@ namespace GodotTools
}
else if (Utils.OS.IsWindows())
{
- CodeEditorPaths = new Dictionary<EditorId, string>
+ ExecutableNames = new Dictionary<EditorId, string>
{
// XamarinStudio is no longer a thing, and the latest version is quite old
// MonoDevelop is available from source only on Windows. The recommendation
@@ -131,7 +135,7 @@ namespace GodotTools
}
else if (Utils.OS.IsUnix())
{
- CodeEditorPaths = new Dictionary<EditorId, string>
+ ExecutableNames = new Dictionary<EditorId, string>
{
// Rely on PATH
{EditorId.MonoDevelop, "monodevelop"}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs
index 3ae6c10bbf..288c65de74 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/CollectionExtensions.cs
@@ -10,8 +10,9 @@ namespace GodotTools.Utils
{
foreach (T elem in enumerable)
{
- if (predicate(elem) != null)
- return elem;
+ T result = predicate(elem);
+ if (result != null)
+ return result;
}
return orElse;
diff --git a/modules/mono/glue/Managed/Files/AABB.cs b/modules/mono/glue/Managed/Files/AABB.cs
index a2ebbc0736..98a73382f4 100644
--- a/modules/mono/glue/Managed/Files/AABB.cs
+++ b/modules/mono/glue/Managed/Files/AABB.cs
@@ -5,6 +5,7 @@
// file: core/variant_call.cpp
// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
using System;
+using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
@@ -13,6 +14,8 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
public struct AABB : IEquatable<AABB>
{
private Vector3 _position;
diff --git a/modules/mono/glue/Managed/Files/Basis.cs b/modules/mono/glue/Managed/Files/Basis.cs
index 9cc31a0557..421532b68f 100644
--- a/modules/mono/glue/Managed/Files/Basis.cs
+++ b/modules/mono/glue/Managed/Files/Basis.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Basis : IEquatable<Basis>
{
@@ -225,7 +226,7 @@ namespace Godot
return orthonormalizedBasis.Quat();
}
- internal void SetQuantScale(Quat quat, Vector3 scale)
+ internal void SetQuatScale(Quat quat, Vector3 scale)
{
SetDiagonal(scale);
Rotate(quat);
@@ -241,7 +242,6 @@ namespace Godot
Row0 = new Vector3(diagonal.x, 0, 0);
Row1 = new Vector3(0, diagonal.y, 0);
Row2 = new Vector3(0, 0, diagonal.z);
-
}
public real_t Determinant()
diff --git a/modules/mono/glue/Managed/Files/Color.cs b/modules/mono/glue/Managed/Files/Color.cs
index 84ff19fc54..447697c671 100644
--- a/modules/mono/glue/Managed/Files/Color.cs
+++ b/modules/mono/glue/Managed/Files/Color.cs
@@ -1,7 +1,10 @@
using System;
+using System.Runtime.InteropServices;
namespace Godot
{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
public struct Color : IEquatable<Color>
{
public float r;
@@ -375,7 +378,7 @@ namespace Godot
return c;
}
- public string ToHtml(bool include_alpha = true)
+ public string ToHtml(bool includeAlpha = true)
{
var txt = string.Empty;
@@ -383,7 +386,7 @@ namespace Godot
txt += ToHex32(g);
txt += ToHex32(b);
- if (include_alpha)
+ if (includeAlpha)
txt = ToHex32(a) + txt;
return txt;
@@ -465,13 +468,13 @@ namespace Godot
for (int i = 0; i < 2; i++)
{
- char[] c = { (char)0, (char)0 };
+ char c;
int lv = v & 0xF;
if (lv < 10)
- c[0] = (char)('0' + lv);
+ c = (char)('0' + lv);
else
- c[0] = (char)('a' + lv - 10);
+ c = (char)('a' + lv - 10);
v >>= 4;
ret = c + ret;
@@ -490,12 +493,17 @@ namespace Godot
bool alpha;
- if (color.Length == 8)
- alpha = true;
- else if (color.Length == 6)
- alpha = false;
- else
- return false;
+ switch (color.Length)
+ {
+ case 8:
+ alpha = true;
+ break;
+ case 6:
+ alpha = false;
+ break;
+ default:
+ return false;
+ }
if (alpha)
{
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index 6c1a51fcf9..15adf0a13b 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -336,14 +336,14 @@ namespace Godot
public static int Wrap(int value, int min, int max)
{
- int rng = max - min;
- return rng != 0 ? min + ((value - min) % rng + rng) % rng : min;
+ int range = max - min;
+ return range == 0 ? min : min + ((value - min) % range + range) % range;
}
public static real_t Wrap(real_t value, real_t min, real_t max)
{
- real_t rng = max - min;
- return !IsEqualApprox(rng, default(real_t)) ? min + ((value - min) % rng + rng) % rng : min;
+ real_t range = max - min;
+ return IsZeroApprox(range) ? min : min + ((value - min) % range + range) % range;
}
}
}
diff --git a/modules/mono/glue/Managed/Files/NodePath.cs b/modules/mono/glue/Managed/Files/NodePath.cs
index 94a4ed1de9..4de4e1e6a9 100644
--- a/modules/mono/glue/Managed/Files/NodePath.cs
+++ b/modules/mono/glue/Managed/Files/NodePath.cs
@@ -55,7 +55,7 @@ namespace Godot
get { return ptr; }
}
- public NodePath() : this(string.Empty) { }
+ public NodePath() : this(string.Empty) {}
public NodePath(string path)
{
diff --git a/modules/mono/glue/Managed/Files/Plane.cs b/modules/mono/glue/Managed/Files/Plane.cs
index e16d4315be..a13161d2e6 100644
--- a/modules/mono/glue/Managed/Files/Plane.cs
+++ b/modules/mono/glue/Managed/Files/Plane.cs
@@ -1,4 +1,5 @@
using System;
+using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
@@ -7,6 +8,8 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
public struct Plane : IEquatable<Plane>
{
private Vector3 _normal;
diff --git a/modules/mono/glue/Managed/Files/Quat.cs b/modules/mono/glue/Managed/Files/Quat.cs
index 0d4349084a..845c7c730e 100644
--- a/modules/mono/glue/Managed/Files/Quat.cs
+++ b/modules/mono/glue/Managed/Files/Quat.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Quat : IEquatable<Quat>
{
@@ -95,6 +96,7 @@ namespace Godot
return this / Length;
}
+ [Obsolete("Set is deprecated. Use the Quat(" + nameof(real_t) + ", " + nameof(real_t) + ", " + nameof(real_t) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void Set(real_t x, real_t y, real_t z, real_t w)
{
this.x = x;
@@ -103,16 +105,19 @@ namespace Godot
this.w = w;
}
+ [Obsolete("Set is deprecated. Use the Quat(" + nameof(Quat) + ") constructor instead.", error: true)]
public void Set(Quat q)
{
this = q;
}
+ [Obsolete("SetAxisAngle is deprecated. Use the Quat(" + nameof(Vector3) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void SetAxisAngle(Vector3 axis, real_t angle)
{
this = new Quat(axis, angle);
}
+ [Obsolete("SetEuler is deprecated. Use the Quat(" + nameof(Vector3) + ") constructor instead.", error: true)]
public void SetEuler(Vector3 eulerYXZ)
{
this = new Quat(eulerYXZ);
@@ -229,9 +234,9 @@ namespace Godot
public Quat(Vector3 eulerYXZ)
{
- real_t half_a1 = eulerYXZ.y * (real_t)0.5;
- real_t half_a2 = eulerYXZ.x * (real_t)0.5;
- real_t half_a3 = eulerYXZ.z * (real_t)0.5;
+ real_t half_a1 = eulerYXZ.y * 0.5f;
+ real_t half_a2 = eulerYXZ.x * 0.5f;
+ real_t half_a3 = eulerYXZ.z * 0.5f;
// R = Y(a1).X(a2).Z(a3) convention for Euler angles.
// Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6)
@@ -246,7 +251,7 @@ namespace Godot
x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3;
y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3;
- z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3;
+ z = cos_a1 * cos_a2 * sin_a3 - sin_a1 * sin_a2 * cos_a3;
w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3;
}
diff --git a/modules/mono/glue/Managed/Files/Rect2.cs b/modules/mono/glue/Managed/Files/Rect2.cs
index 888f300347..f3dc9d8490 100644
--- a/modules/mono/glue/Managed/Files/Rect2.cs
+++ b/modules/mono/glue/Managed/Files/Rect2.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Rect2 : IEquatable<Rect2>
{
diff --git a/modules/mono/glue/Managed/Files/StringExtensions.cs b/modules/mono/glue/Managed/Files/StringExtensions.cs
index b43034fbb5..6045c83e95 100644
--- a/modules/mono/glue/Managed/Files/StringExtensions.cs
+++ b/modules/mono/glue/Managed/Files/StringExtensions.cs
@@ -98,6 +98,66 @@ namespace Godot
}
// <summary>
+ // Return the amount of substrings in string.
+ // </summary>
+ public static int Count(this string instance, string what, bool caseSensitive = true, int from = 0, int to = 0)
+ {
+ if (what.Length == 0)
+ {
+ return 0;
+ }
+
+ int len = instance.Length;
+ int slen = what.Length;
+
+ if (len < slen)
+ {
+ return 0;
+ }
+
+ string str;
+
+ if (from >= 0 && to >= 0)
+ {
+ if (to == 0)
+ {
+ to = len;
+ }
+ else if (from >= to)
+ {
+ return 0;
+ }
+ if (from == 0 && to == len)
+ {
+ str = instance;
+ }
+ else
+ {
+ str = instance.Substring(from, to - from);
+ }
+ }
+ else
+ {
+ return 0;
+ }
+
+ int c = 0;
+ int idx;
+
+ do
+ {
+ idx = str.IndexOf(what, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
+ if (idx != -1)
+ {
+ str = str.Substring(idx + slen);
+ ++c;
+ }
+ } while (idx != -1);
+
+ return c;
+ }
+
+ // <summary>
// Return a copy of the string with special characters escaped using the C language standard.
// </summary>
public static string CEscape(this string instance)
diff --git a/modules/mono/glue/Managed/Files/Transform.cs b/modules/mono/glue/Managed/Files/Transform.cs
index bd79144873..cc4d26158d 100644
--- a/modules/mono/glue/Managed/Files/Transform.cs
+++ b/modules/mono/glue/Managed/Files/Transform.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Transform : IEquatable<Transform>
{
@@ -33,7 +34,7 @@ namespace Godot
Vector3 destinationLocation = transform.origin;
var interpolated = new Transform();
- interpolated.basis.SetQuantScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.LinearInterpolate(destinationScale, c));
+ interpolated.basis.SetQuatScale(sourceRotation.Slerp(destinationRotation, c).Normalized(), sourceScale.LinearInterpolate(destinationScale, c));
interpolated.origin = sourceLocation.LinearInterpolate(destinationLocation, c);
return interpolated;
diff --git a/modules/mono/glue/Managed/Files/Transform2D.cs b/modules/mono/glue/Managed/Files/Transform2D.cs
index 33ff286769..814332dc07 100644
--- a/modules/mono/glue/Managed/Files/Transform2D.cs
+++ b/modules/mono/glue/Managed/Files/Transform2D.cs
@@ -8,6 +8,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Transform2D : IEquatable<Transform2D>
{
@@ -98,6 +99,8 @@ namespace Godot
return x[columnIndex];
case 1:
return y[columnIndex];
+ case 2:
+ return origin[columnIndex];
default:
throw new IndexOutOfRangeException();
}
@@ -112,6 +115,9 @@ namespace Godot
case 1:
y[columnIndex] = value;
return;
+ case 2:
+ origin[columnIndex] = value;
+ return;
default:
throw new IndexOutOfRangeException();
}
@@ -136,7 +142,7 @@ namespace Godot
inv[0] *= new Vector2(detInv, -detInv);
inv[1] *= new Vector2(-detInv, detInv);
- inv[2] = BasisXform(-inv[2]);
+ inv[2] = inv.BasisXform(-inv[2]);
return inv;
}
diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs
index a7f26283a7..b1c1dae3c2 100644
--- a/modules/mono/glue/Managed/Files/Vector2.cs
+++ b/modules/mono/glue/Managed/Files/Vector2.cs
@@ -14,6 +14,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector2 : IEquatable<Vector2>
{
@@ -222,11 +223,13 @@ namespace Godot
return new Vector2(Mathf.Round(x), Mathf.Round(y));
}
+ [Obsolete("Set is deprecated. Use the Vector2(" + nameof(real_t) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void Set(real_t x, real_t y)
{
this.x = x;
this.y = y;
}
+ [Obsolete("Set is deprecated. Use the Vector2(" + nameof(Vector2) + ") constructor instead.", error: true)]
public void Set(Vector2 v)
{
x = v.x;
diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs
index 16803ae55c..c2da7b8bb1 100644
--- a/modules/mono/glue/Managed/Files/Vector3.cs
+++ b/modules/mono/glue/Managed/Files/Vector3.cs
@@ -14,6 +14,7 @@ using real_t = System.Single;
namespace Godot
{
+ [Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Vector3 : IEquatable<Vector3>
{
@@ -248,12 +249,14 @@ namespace Godot
return new Basis(axis, phi).Xform(this);
}
+ [Obsolete("Set is deprecated. Use the Vector3(" + nameof(real_t) + ", " + nameof(real_t) + ", " + nameof(real_t) + ") constructor instead.", error: true)]
public void Set(real_t x, real_t y, real_t z)
{
this.x = x;
this.y = y;
this.z = z;
}
+ [Obsolete("Set is deprecated. Use the Vector3(" + nameof(Vector3) + ") constructor instead.", error: true)]
public void Set(Vector3 v)
{
x = v.x;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 2497f083b5..45f79074be 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -283,6 +283,18 @@ void GDMono::initialize() {
add_mono_shared_libs_dir_to_path();
+ {
+ PropertyInfo exc_policy_prop = PropertyInfo(Variant::INT, "mono/unhandled_exception_policy", PROPERTY_HINT_ENUM,
+ vformat("Terminate Application:%s,Log Error:%s", (int)POLICY_TERMINATE_APP, (int)POLICY_LOG_ERROR));
+ unhandled_exception_policy = (UnhandledExceptionPolicy)(int)GLOBAL_DEF(exc_policy_prop.name, (int)POLICY_TERMINATE_APP);
+ ProjectSettings::get_singleton()->set_custom_property_info(exc_policy_prop.name, exc_policy_prop);
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // Unhandled exceptions should not terminate the editor
+ unhandled_exception_policy = POLICY_LOG_ERROR;
+ }
+ }
+
GDMonoAssembly::initialize();
gdmono_profiler_init();
@@ -602,12 +614,12 @@ bool GDMono::copy_prebuilt_api_assembly(APIAssembly::Type p_api_type) {
String GDMono::update_api_assemblies_from_prebuilt() {
-#define FAIL_REASON(m_out_of_sync, m_prebuilt_exist) \
+#define FAIL_REASON(m_out_of_sync, m_prebuilt_exists) \
( \
(m_out_of_sync ? \
String("The assembly is invalidated") : \
String("The assembly was not found")) + \
- (m_prebuilt_exist ? \
+ (m_prebuilt_exists ? \
String(" and the prebuilt assemblies are missing") : \
String(" and we failed to copy the prebuilt assemblies")))
@@ -619,16 +631,18 @@ String GDMono::update_api_assemblies_from_prebuilt() {
if (!api_assembly_out_of_sync && FileAccess::exists(core_assembly_path) && FileAccess::exists(editor_assembly_path))
return String(); // No update needed
+ print_verbose("Updating API assemblies");
+
String prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file("Debug");
String prebuilt_core_dll_path = prebuilt_api_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll");
String prebuilt_editor_dll_path = prebuilt_api_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
if (!FileAccess::exists(prebuilt_core_dll_path) || !FileAccess::exists(prebuilt_editor_dll_path))
- return FAIL_REASON(api_assembly_out_of_sync, /* prebuilt_exist: */ false);
+ return FAIL_REASON(api_assembly_out_of_sync, /* prebuilt_exists: */ false);
// Copy the prebuilt Api
if (!copy_prebuilt_api_assembly(APIAssembly::API_CORE) || !copy_prebuilt_api_assembly(APIAssembly::API_EDITOR))
- return FAIL_REASON(api_assembly_out_of_sync, /* prebuilt_exist: */ true);
+ return FAIL_REASON(api_assembly_out_of_sync, /* prebuilt_exists: */ true);
return String(); // Updated successfully
@@ -643,7 +657,14 @@ bool GDMono::_load_core_api_assembly() {
#ifdef TOOLS_ENABLED
// For the editor and the editor player we want to load it from a specific path to make sure we can keep it up to date
- String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(CORE_API_ASSEMBLY_NAME ".dll");
+
+ // If running the project manager, load it from the prebuilt API directory
+ String assembly_dir = !Main::is_project_manager() ?
+ GodotSharpDirs::get_res_assemblies_dir() :
+ GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file("Debug");
+
+ String assembly_path = assembly_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll");
+
bool success = FileAccess::exists(assembly_path) &&
load_assembly_from(CORE_API_ASSEMBLY_NAME, assembly_path, &core_api_assembly);
#else
@@ -674,7 +695,14 @@ bool GDMono::_load_editor_api_assembly() {
return true;
// For the editor and the editor player we want to load it from a specific path to make sure we can keep it up to date
- String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
+
+ // If running the project manager, load it from the prebuilt API directory
+ String assembly_dir = !Main::is_project_manager() ?
+ GodotSharpDirs::get_res_assemblies_dir() :
+ GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file("Debug");
+
+ String assembly_path = assembly_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
+
bool success = FileAccess::exists(assembly_path) &&
load_assembly_from(EDITOR_API_ASSEMBLY_NAME, assembly_path, &editor_api_assembly);
@@ -699,9 +727,6 @@ bool GDMono::_try_load_api_assemblies() {
return false;
}
- if (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated)
- return false;
-
#ifdef TOOLS_ENABLED
if (!_load_editor_api_assembly()) {
if (OS::get_singleton()->is_stdout_verbose())
@@ -713,6 +738,12 @@ bool GDMono::_try_load_api_assemblies() {
return false;
#endif
+ // Check if the core API assembly is out of sync only after trying to load the
+ // editor API assembly. Otherwise, if both assemblies are out of sync, we would
+ // only update the former as we won't know the latter also needs to be updated.
+ if (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated)
+ return false;
+
return true;
}
@@ -723,6 +754,12 @@ void GDMono::_load_api_assemblies() {
// The API assemblies are out of sync. Fine, try one more time, but this time
// update them from the prebuilt assemblies directory before trying to load them.
+ // Shouldn't happen. The project manager loads the prebuilt API assemblies
+ if (Main::is_project_manager()) {
+ ERR_EXPLAIN("Failed to load one of the prebuilt API assemblies");
+ CRASH_NOW();
+ }
+
// 1. Unload the scripts domain
if (_unload_scripts_domain() != OK) {
ERR_EXPLAIN("Mono: Failed to unload scripts domain");
@@ -1058,6 +1095,8 @@ GDMono::GDMono() {
#ifdef TOOLS_ENABLED
api_editor_hash = 0;
#endif
+
+ unhandled_exception_policy = POLICY_TERMINATE_APP;
}
GDMono::~GDMono() {
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index deebe5fd50..c5bcce4fa1 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -80,6 +80,13 @@ String to_string(Type p_type);
class GDMono {
+public:
+ enum UnhandledExceptionPolicy {
+ POLICY_TERMINATE_APP,
+ POLICY_LOG_ERROR
+ };
+
+private:
bool runtime_initialized;
bool finalizing_scripts_domain;
@@ -102,6 +109,8 @@ class GDMono {
HashMap<uint32_t, HashMap<String, GDMonoAssembly *> > assemblies;
+ UnhandledExceptionPolicy unhandled_exception_policy;
+
void _domain_assemblies_cleanup(uint32_t p_domain_id);
bool _are_api_assemblies_out_of_sync();
@@ -162,7 +171,9 @@ public:
static GDMono *get_singleton() { return singleton; }
- static void unhandled_exception_hook(MonoObject *p_exc, void *p_user_data);
+ GD_NORETURN static void unhandled_exception_hook(MonoObject *p_exc, void *p_user_data);
+
+ UnhandledExceptionPolicy get_unhandled_exception_policy() const { return unhandled_exception_policy; }
// Do not use these, unless you know what you're doing
void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly);
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index a84332d4cd..e50e3b0794 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -108,9 +108,18 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
void unhandled_exception(MonoException *p_exc) {
mono_unhandled_exception((MonoObject *)p_exc); // prints the exception as well
- // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders
- GDMono::unhandled_exception_hook((MonoObject *)p_exc, NULL);
- GD_UNREACHABLE();
+
+ if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) {
+ // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders
+ GDMono::unhandled_exception_hook((MonoObject *)p_exc, NULL);
+ GD_UNREACHABLE();
+ } else {
+#ifdef DEBUG_ENABLED
+ GDMonoUtils::debug_send_unhandled_exception_error((MonoException *)p_exc);
+ if (ScriptDebugger::get_singleton())
+ ScriptDebugger::get_singleton()->idle_poll();
+#endif
+ }
}
} // namespace GDMonoInternals
diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h
index 2d77bde27c..0d82723913 100644
--- a/modules/mono/mono_gd/gd_mono_internals.h
+++ b/modules/mono/mono_gd/gd_mono_internals.h
@@ -45,7 +45,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
* Do not call this function directly.
* Use GDMonoUtils::debug_unhandled_exception(MonoException *) instead.
*/
-GD_NORETURN void unhandled_exception(MonoException *p_exc);
+void unhandled_exception(MonoException *p_exc);
} // namespace GDMonoInternals
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 5987fa8ebb..7afdfc8ac8 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -37,6 +37,10 @@
#include "core/project_settings.h"
#include "core/reference.h"
+#ifdef TOOLS_ENABLED
+#include "editor/script_editor_debugger.h"
+#endif
+
#include "../csharp_script.h"
#include "../utils/macros.h"
#include "../utils/mutex_utils.h"
@@ -596,8 +600,14 @@ void debug_print_unhandled_exception(MonoException *p_exc) {
void debug_send_unhandled_exception_error(MonoException *p_exc) {
#ifdef DEBUG_ENABLED
- if (!ScriptDebugger::get_singleton())
+ if (!ScriptDebugger::get_singleton()) {
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ ERR_PRINTS(GDMonoUtils::get_exception_name_and_message(p_exc));
+ }
+#endif
return;
+ }
_TLS_RECURSION_GUARD_;
@@ -621,7 +631,7 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) {
if (unexpected_exc) {
GDMonoInternals::unhandled_exception(unexpected_exc);
- GD_UNREACHABLE();
+ return;
}
Vector<ScriptLanguage::StackInfo> _si;
@@ -655,7 +665,6 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) {
void debug_unhandled_exception(MonoException *p_exc) {
GDMonoInternals::unhandled_exception(p_exc); // prints the exception as well
- GD_UNREACHABLE();
}
void print_unhandled_exception(MonoException *p_exc) {
@@ -665,11 +674,9 @@ void print_unhandled_exception(MonoException *p_exc) {
void set_pending_exception(MonoException *p_exc) {
#ifdef NO_PENDING_EXCEPTIONS
debug_unhandled_exception(p_exc);
- GD_UNREACHABLE();
#else
if (get_runtime_invoke_count() == 0) {
debug_unhandled_exception(p_exc);
- GD_UNREACHABLE();
}
if (!mono_runtime_set_pending_exception(p_exc, false)) {
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index f535fbb6d0..d73743bf0b 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -289,7 +289,7 @@ void set_exception_message(MonoException *p_exc, String message);
void debug_print_unhandled_exception(MonoException *p_exc);
void debug_send_unhandled_exception_error(MonoException *p_exc);
-GD_NORETURN void debug_unhandled_exception(MonoException *p_exc);
+void debug_unhandled_exception(MonoException *p_exc);
void print_unhandled_exception(MonoException *p_exc);
/**
diff --git a/modules/tinyexr/image_saver_tinyexr.cpp b/modules/tinyexr/image_saver_tinyexr.cpp
new file mode 100644
index 0000000000..e1d42d3217
--- /dev/null
+++ b/modules/tinyexr/image_saver_tinyexr.cpp
@@ -0,0 +1,279 @@
+/*************************************************************************/
+/* image_saver_tinyexr.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "image_saver_tinyexr.h"
+#include "core/math/math_funcs.h"
+
+#include "thirdparty/tinyexr/tinyexr.h"
+
+static bool is_supported_format(Image::Format p_format) {
+ // This is checked before anything else.
+ // Mostly uncompressed formats are considered.
+ switch (p_format) {
+ case Image::FORMAT_RF:
+ case Image::FORMAT_RGF:
+ case Image::FORMAT_RGBF:
+ case Image::FORMAT_RGBAF:
+ case Image::FORMAT_RH:
+ case Image::FORMAT_RGH:
+ case Image::FORMAT_RGBH:
+ case Image::FORMAT_RGBAH:
+ case Image::FORMAT_R8:
+ case Image::FORMAT_RG8:
+ case Image::FORMAT_RGB8:
+ case Image::FORMAT_RGBA8:
+ return true;
+ default:
+ return false;
+ }
+}
+
+enum SrcPixelType {
+ SRC_FLOAT,
+ SRC_HALF,
+ SRC_BYTE
+};
+
+static SrcPixelType get_source_pixel_type(Image::Format p_format) {
+ switch (p_format) {
+ case Image::FORMAT_RF:
+ case Image::FORMAT_RGF:
+ case Image::FORMAT_RGBF:
+ case Image::FORMAT_RGBAF:
+ return SRC_FLOAT;
+ case Image::FORMAT_RH:
+ case Image::FORMAT_RGH:
+ case Image::FORMAT_RGBH:
+ case Image::FORMAT_RGBAH:
+ return SRC_HALF;
+ case Image::FORMAT_R8:
+ case Image::FORMAT_RG8:
+ case Image::FORMAT_RGB8:
+ case Image::FORMAT_RGBA8:
+ return SRC_BYTE;
+ default:
+ CRASH_NOW();
+ }
+}
+
+static int get_target_pixel_type(Image::Format p_format) {
+ switch (p_format) {
+ case Image::FORMAT_RF:
+ case Image::FORMAT_RGF:
+ case Image::FORMAT_RGBF:
+ case Image::FORMAT_RGBAF:
+ return TINYEXR_PIXELTYPE_FLOAT;
+ case Image::FORMAT_RH:
+ case Image::FORMAT_RGH:
+ case Image::FORMAT_RGBH:
+ case Image::FORMAT_RGBAH:
+ // EXR doesn't support 8-bit channels so in that case we'll convert
+ case Image::FORMAT_R8:
+ case Image::FORMAT_RG8:
+ case Image::FORMAT_RGB8:
+ case Image::FORMAT_RGBA8:
+ return TINYEXR_PIXELTYPE_HALF;
+ default:
+ CRASH_NOW();
+ }
+}
+
+static int get_pixel_type_size(int p_pixel_type) {
+ switch (p_pixel_type) {
+ case TINYEXR_PIXELTYPE_HALF:
+ return 2;
+ case TINYEXR_PIXELTYPE_FLOAT:
+ return 4;
+ }
+ CRASH_NOW();
+}
+
+static int get_channel_count(Image::Format p_format) {
+ switch (p_format) {
+ case Image::FORMAT_RF:
+ case Image::FORMAT_RH:
+ case Image::FORMAT_R8:
+ return 1;
+ case Image::FORMAT_RGF:
+ case Image::FORMAT_RGH:
+ case Image::FORMAT_RG8:
+ return 2;
+ case Image::FORMAT_RGBF:
+ case Image::FORMAT_RGBH:
+ case Image::FORMAT_RGB8:
+ return 3;
+ case Image::FORMAT_RGBAF:
+ case Image::FORMAT_RGBAH:
+ case Image::FORMAT_RGBA8:
+ return 4;
+ default:
+ CRASH_NOW();
+ }
+}
+
+Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale) {
+
+ Image::Format format = p_img->get_format();
+
+ if (!is_supported_format(format)) {
+ // Format not supported
+ print_error("Image format not supported for saving as EXR. Consider saving as PNG.");
+ return ERR_UNAVAILABLE;
+ }
+
+ EXRHeader header;
+ InitEXRHeader(&header);
+
+ EXRImage image;
+ InitEXRImage(&image);
+
+ const int max_channels = 4;
+
+ // Godot does not support more than 4 channels,
+ // so we can preallocate header infos on the stack and use only the subset we need
+ PoolByteArray channels[max_channels];
+ unsigned char *channels_ptrs[max_channels];
+ EXRChannelInfo channel_infos[max_channels];
+ int pixel_types[max_channels];
+ int requested_pixel_types[max_channels] = { -1 };
+
+ // Gimp and Blender are a bit annoying so order of channels isn't straightforward.
+ const int channel_mappings[4][4] = {
+ { 0 }, // R
+ { 1, 0 }, // GR
+ { 2, 1, 0 }, // BGR
+ { 2, 1, 0, 3 } // BGRA
+ };
+
+ int channel_count = get_channel_count(format);
+ ERR_FAIL_COND_V(p_grayscale && channel_count != 1, ERR_INVALID_PARAMETER);
+
+ int target_pixel_type = get_target_pixel_type(format);
+ int target_pixel_type_size = get_pixel_type_size(target_pixel_type);
+ SrcPixelType src_pixel_type = get_source_pixel_type(format);
+ const int pixel_count = p_img->get_width() * p_img->get_height();
+
+ const int *channel_mapping = channel_mappings[channel_count - 1];
+
+ {
+ PoolByteArray src_data = p_img->get_data();
+ PoolByteArray::Read src_r = src_data.read();
+
+ for (int channel_index = 0; channel_index < channel_count; ++channel_index) {
+
+ // De-interleave channels
+
+ PoolByteArray &dst = channels[channel_index];
+ dst.resize(pixel_count * target_pixel_type_size);
+
+ PoolByteArray::Write dst_w = dst.write();
+
+ if (src_pixel_type == SRC_FLOAT && target_pixel_type == TINYEXR_PIXELTYPE_FLOAT) {
+
+ // Note: we don't save mipmaps
+ CRASH_COND(src_data.size() < pixel_count * channel_count * target_pixel_type_size);
+
+ const float *src_rp = (float *)src_r.ptr();
+ float *dst_wp = (float *)dst_w.ptr();
+
+ for (int i = 0; i < pixel_count; ++i) {
+ dst_wp[i] = src_rp[channel_index + i * channel_count];
+ }
+
+ } else if (src_pixel_type == SRC_HALF && target_pixel_type == TINYEXR_PIXELTYPE_HALF) {
+
+ CRASH_COND(src_data.size() < pixel_count * channel_count * target_pixel_type_size);
+
+ const uint16_t *src_rp = (uint16_t *)src_r.ptr();
+ uint16_t *dst_wp = (uint16_t *)dst_w.ptr();
+
+ for (int i = 0; i < pixel_count; ++i) {
+ dst_wp[i] = src_rp[channel_index + i * channel_count];
+ }
+
+ } else if (src_pixel_type == SRC_BYTE && target_pixel_type == TINYEXR_PIXELTYPE_HALF) {
+
+ CRASH_COND(src_data.size() < pixel_count * channel_count);
+
+ const uint8_t *src_rp = (uint8_t *)src_r.ptr();
+ uint16_t *dst_wp = (uint16_t *)dst_w.ptr();
+
+ for (int i = 0; i < pixel_count; ++i) {
+ dst_wp[i] = Math::make_half_float(src_rp[channel_index + i * channel_count] / 255.f);
+ }
+
+ } else {
+ CRASH_NOW();
+ }
+
+ int remapped_index = channel_mapping[channel_index];
+
+ channels_ptrs[remapped_index] = dst_w.ptr();
+
+ // No conversion
+ pixel_types[remapped_index] = target_pixel_type;
+ requested_pixel_types[remapped_index] = target_pixel_type;
+
+ // Write channel name
+ if (p_grayscale) {
+ channel_infos[remapped_index].name[0] = 'Y';
+ channel_infos[remapped_index].name[1] = '\0';
+ } else {
+ const char *rgba = "RGBA";
+ channel_infos[remapped_index].name[0] = rgba[channel_index];
+ channel_infos[remapped_index].name[1] = '\0';
+ }
+ }
+ }
+
+ image.images = channels_ptrs;
+ image.num_channels = channel_count;
+ image.width = p_img->get_width();
+ image.height = p_img->get_height();
+
+ header.num_channels = image.num_channels;
+ header.channels = channel_infos;
+ header.pixel_types = pixel_types;
+ header.requested_pixel_types = requested_pixel_types;
+ // TODO DEBUG REMOVE
+ for (int i = 0; i < 4; ++i) {
+ print_line(String("requested_pixel_types{0}: {1}").format(varray(i, requested_pixel_types[i])));
+ }
+
+ CharString utf8_filename = p_path.utf8();
+ const char *err;
+ int ret = SaveEXRImageToFile(&image, &header, utf8_filename.ptr(), &err);
+ if (ret != TINYEXR_SUCCESS) {
+ print_error(String("Saving EXR failed. Error: {0}").format(varray(err)));
+ return ERR_FILE_CANT_WRITE;
+ }
+
+ return OK;
+}
diff --git a/modules/tinyexr/image_saver_tinyexr.h b/modules/tinyexr/image_saver_tinyexr.h
new file mode 100644
index 0000000000..298bd1d21c
--- /dev/null
+++ b/modules/tinyexr/image_saver_tinyexr.h
@@ -0,0 +1,38 @@
+/*************************************************************************/
+/* image_saver_tinyexr.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef IMAGE_SAVER_TINYEXR_H
+#define IMAGE_SAVER_TINYEXR_H
+
+#include "core/os/os.h"
+
+Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale);
+
+#endif // IMAGE_SAVER_TINYEXR_H
diff --git a/modules/tinyexr/register_types.cpp b/modules/tinyexr/register_types.cpp
index 5473a55687..233b3afa08 100644
--- a/modules/tinyexr/register_types.cpp
+++ b/modules/tinyexr/register_types.cpp
@@ -31,6 +31,7 @@
#include "register_types.h"
#include "image_loader_tinyexr.h"
+#include "image_saver_tinyexr.h"
static ImageLoaderTinyEXR *image_loader_tinyexr = NULL;
@@ -38,9 +39,13 @@ void register_tinyexr_types() {
image_loader_tinyexr = memnew(ImageLoaderTinyEXR);
ImageLoader::add_image_format_loader(image_loader_tinyexr);
+
+ Image::save_exr_func = save_exr;
}
void unregister_tinyexr_types() {
memdelete(image_loader_tinyexr);
+
+ Image::save_exr_func = NULL;
}
diff --git a/modules/vhacd/SCsub b/modules/vhacd/SCsub
index e581fb7bb2..685976dc33 100644
--- a/modules/vhacd/SCsub
+++ b/modules/vhacd/SCsub
@@ -26,10 +26,6 @@ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_vhacd.Prepend(CPPPATH=[thirdparty_dir + "/inc"])
-# upstream uses c++11
-if not env.msvc:
- env_vhacd.Append(CXXFLAGS="-std=c++11")
-
env_thirdparty = env_vhacd.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
index 29e9cc31e5..9e3670ec35 100644
--- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
@@ -212,6 +212,7 @@
var t = clamp((weight - from) / (to - from), 0.0, 1.0)
return t * t * (3.0 - 2.0 * t)
[/codeblock]
+ </constant>
<constant name="MATH_POSMOD" value="65" enum="BuiltinFunc">
</constant>
<constant name="MATH_LERP_ANGLE" value="66" enum="BuiltinFunc">
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index f1ccb64e70..8088a71198 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1320,7 +1320,6 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(MATH_SQRT);
BIND_ENUM_CONSTANT(MATH_FMOD);
BIND_ENUM_CONSTANT(MATH_FPOSMOD);
- BIND_ENUM_CONSTANT(MATH_POSMOD);
BIND_ENUM_CONSTANT(MATH_FLOOR);
BIND_ENUM_CONSTANT(MATH_CEIL);
BIND_ENUM_CONSTANT(MATH_ROUND);
@@ -1373,6 +1372,7 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(BYTES_TO_VAR);
BIND_ENUM_CONSTANT(COLORN);
BIND_ENUM_CONSTANT(MATH_SMOOTHSTEP);
+ BIND_ENUM_CONSTANT(MATH_POSMOD);
BIND_ENUM_CONSTANT(MATH_LERP_ANGLE);
BIND_ENUM_CONSTANT(FUNC_MAX);
}
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 603c5a7f3c..eef3f0f8ae 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -776,8 +776,8 @@ void VisualScriptEditor::_update_members() {
TreeItem *functions = members->create_item(root);
functions->set_selectable(0, false);
functions->set_text(0, TTR("Functions:"));
- functions->add_button(0, Control::get_icon("Override", "EditorIcons"), 1);
- functions->add_button(0, Control::get_icon("Add", "EditorIcons"), 0);
+ functions->add_button(0, Control::get_icon("Override", "EditorIcons"), 1, false, TTR("Override an existing built-in function."));
+ functions->add_button(0, Control::get_icon("Add", "EditorIcons"), 0, false, TTR("Create a new function."));
functions->set_custom_color(0, Control::get_color("mono_color", "Editor"));
List<StringName> func_names;
@@ -795,7 +795,7 @@ void VisualScriptEditor::_update_members() {
TreeItem *variables = members->create_item(root);
variables->set_selectable(0, false);
variables->set_text(0, TTR("Variables:"));
- variables->add_button(0, Control::get_icon("Add", "EditorIcons"));
+ variables->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new variable."));
variables->set_custom_color(0, Control::get_color("mono_color", "Editor"));
Ref<Texture> type_icons[Variant::VARIANT_MAX] = {
@@ -848,7 +848,7 @@ void VisualScriptEditor::_update_members() {
TreeItem *_signals = members->create_item(root);
_signals->set_selectable(0, false);
_signals->set_text(0, TTR("Signals:"));
- _signals->add_button(0, Control::get_icon("Add", "EditorIcons"));
+ _signals->add_button(0, Control::get_icon("Add", "EditorIcons"), -1, false, TTR("Create a new signal."));
_signals->set_custom_color(0, Control::get_color("mono_color", "Editor"));
List<StringName> signal_names;
diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp
index 41828f040e..764807cffd 100644
--- a/modules/visual_script/visual_script_property_selector.cpp
+++ b/modules/visual_script/visual_script_property_selector.cpp
@@ -130,12 +130,14 @@ void VisualScriptPropertySelector::_update_search() {
{
String b = String(E->get());
category = search_options->create_item(root);
- category->set_text(0, b.replace_first("*", ""));
- category->set_selectable(0, false);
- Ref<Texture> icon;
- String rep = b.replace("*", "");
- icon = EditorNode::get_singleton()->get_class_icon(rep);
- category->set_icon(0, icon);
+ if (category) {
+ category->set_text(0, b.replace_first("*", ""));
+ category->set_selectable(0, false);
+ Ref<Texture> icon;
+ String rep = b.replace("*", "");
+ icon = EditorNode::get_singleton()->get_class_icon(rep);
+ category->set_icon(0, icon);
+ }
}
if (properties || seq_connect) {
if (instance) {
diff --git a/modules/webm/SCsub b/modules/webm/SCsub
index e57437229f..32e6727656 100644
--- a/modules/webm/SCsub
+++ b/modules/webm/SCsub
@@ -17,10 +17,6 @@ thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_webm.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "libwebm/"])
-# upstream uses c++11
-if (not env_webm.msvc):
- env_webm.Append(CXXFLAGS="-std=c++11")
-
# also requires libogg, libvorbis and libopus
if env['builtin_libogg']:
env_webm.Prepend(CPPPATH=["#thirdparty/libogg"])
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index 86374e8f80..af75f2a320 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -190,8 +190,8 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
Error err = _tcp->connect_to_host(addr, p_port);
if (err != OK) {
- _on_error();
_tcp->disconnect_from_host();
+ _on_error();
return err;
}
_connection = _tcp;
@@ -230,8 +230,8 @@ void WSLClient::poll() {
if (_peer->is_connected_to_host()) {
_peer->poll();
if (!_peer->is_connected_to_host()) {
- _on_disconnect(_peer->close_code != -1);
disconnect_from_host();
+ _on_disconnect(_peer->close_code != -1);
}
return;
}
@@ -242,8 +242,8 @@ void WSLClient::poll() {
switch (_tcp->get_status()) {
case StreamPeerTCP::STATUS_NONE:
// Clean close
- _on_error();
disconnect_from_host();
+ _on_error();
break;
case StreamPeerTCP::STATUS_CONNECTED: {
Ref<StreamPeerSSL> ssl;
@@ -255,8 +255,8 @@ void WSLClient::poll() {
ERR_FAIL_COND(ssl.is_null());
ssl->set_blocking_handshake_enabled(false);
if (ssl->connect_to_stream(_tcp, verify_ssl, _host) != OK) {
- _on_error();
disconnect_from_host();
+ _on_error();
return;
}
_connection = ssl;
@@ -268,8 +268,8 @@ void WSLClient::poll() {
if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING)
return; // Need more polling.
else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) {
- _on_error();
disconnect_from_host();
+ _on_error();
return; // Error.
}
}
@@ -277,8 +277,8 @@ void WSLClient::poll() {
_do_handshake();
} break;
case StreamPeerTCP::STATUS_ERROR:
- _on_error();
disconnect_from_host();
+ _on_error();
break;
case StreamPeerTCP::STATUS_CONNECTING:
break; // Wait for connection
diff --git a/modules/xatlas_unwrap/SCsub b/modules/xatlas_unwrap/SCsub
index 50e3cb1551..b242fd4673 100644
--- a/modules/xatlas_unwrap/SCsub
+++ b/modules/xatlas_unwrap/SCsub
@@ -15,10 +15,6 @@ if env['builtin_xatlas']:
env_xatlas_unwrap.Prepend(CPPPATH=[thirdparty_dir])
- # upstream uses c++11
- if (not env.msvc):
- env_xatlas_unwrap.Append(CXXFLAGS="-std=c++11")
-
env_thirdparty = env_xatlas_unwrap.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)