diff options
Diffstat (limited to 'modules')
27 files changed, 441 insertions, 71 deletions
diff --git a/modules/assimp/SCsub b/modules/assimp/SCsub index d8ef866bec..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,11 +66,11 @@ 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(env['platform'] == 'windows'): @@ -84,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/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 9d632aaf83..f475ba23f6 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -1234,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; } @@ -1245,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; } @@ -1261,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; @@ -1279,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; @@ -1314,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/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 8dcea26a7b..03258584ce 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -44,7 +44,7 @@ ["const godot_vector2 *", "p_to"], ["const godot_real", "p_delta"] ] - }, + }, { "name": "godot_string_count", "return_type": "godot_int", @@ -54,7 +54,7 @@ ["godot_int", "p_from"], ["godot_int", "p_to"] ] - }, + }, { "name": "godot_string_countn", "return_type": "godot_int", @@ -6548,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/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index f65f2a8935..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] 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/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 846c84d222..f8d201b4ca 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2913,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/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/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 12a3811230..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> { 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/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/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) { |