summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/assimp/SCsub95
-rw-r--r--modules/assimp/config.py5
-rw-r--r--modules/assimp/editor_scene_importer_assimp.cpp2181
-rw-r--r--modules/assimp/editor_scene_importer_assimp.h206
-rw-r--r--modules/assimp/godot_update_assimp.sh261
-rw-r--r--modules/assimp/register_types.cpp59
-rw-r--r--modules/assimp/register_types.h32
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml2
-rw-r--r--modules/bullet/doc_classes/BulletPhysicsServer.xml2
-rw-r--r--modules/bullet/shape_bullet.cpp9
-rw-r--r--modules/csg/csg_shape.cpp8
-rw-r--r--modules/csg/doc_classes/CSGBox.xml2
-rw-r--r--modules/csg/doc_classes/CSGCombiner.xml2
-rw-r--r--modules/csg/doc_classes/CSGCylinder.xml2
-rw-r--r--modules/csg/doc_classes/CSGMesh.xml2
-rw-r--r--modules/csg/doc_classes/CSGPolygon.xml2
-rw-r--r--modules/csg/doc_classes/CSGPrimitive.xml2
-rw-r--r--modules/csg/doc_classes/CSGShape.xml2
-rw-r--r--modules/csg/doc_classes/CSGSphere.xml2
-rw-r--r--modules/csg/doc_classes/CSGTorus.xml2
-rw-r--r--modules/enet/doc_classes/NetworkedMultiplayerENet.xml2
-rw-r--r--modules/gdnative/arvr/arvr_interface_gdnative.cpp11
-rw-r--r--modules/gdnative/arvr/arvr_interface_gdnative.h1
-rw-r--r--modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/GDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/GDNativeLibrary.xml2
-rw-r--r--modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/NativeScript.xml2
-rw-r--r--modules/gdnative/doc_classes/PacketPeerGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/PluginScript.xml2
-rw-r--r--modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/StreamPeerGDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/VideoStreamGDNative.xml2
-rw-r--r--modules/gdnative/include/arvr/godot_arvr.h4
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp3
-rw-r--r--modules/gdnative/pluginscript/pluginscript_script.cpp2
-rw-r--r--modules/gdscript/doc_classes/GDScript.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptFunctionState.xml2
-rw-r--r--modules/gdscript/doc_classes/GDScriptNativeClass.xml2
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gdscript/gdscript.h1
-rw-r--r--modules/gdscript/gdscript_editor.cpp59
-rw-r--r--modules/gdscript/gdscript_functions.cpp71
-rw-r--r--modules/gdscript/gdscript_functions.h1
-rw-r--r--modules/gdscript/gdscript_parser.cpp24
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp10
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml2
-rw-r--r--modules/mobile_vr/doc_classes/MobileVRInterface.xml2
-rw-r--r--modules/mono/SCsub341
-rw-r--r--modules/mono/build_scripts/__init__.py0
-rw-r--r--modules/mono/build_scripts/godotsharptools_build.py263
-rw-r--r--modules/mono/build_scripts/make_cs_compressed_header.py61
-rw-r--r--modules/mono/build_scripts/mono_configure.py414
-rw-r--r--modules/mono/build_scripts/mono_reg_utils.py (renamed from modules/mono/mono_reg_utils.py)14
-rw-r--r--modules/mono/build_scripts/tls_configure.py (renamed from modules/mono/tls_configure.py)0
-rw-r--r--modules/mono/config.py426
-rw-r--r--modules/mono/csharp_script.cpp21
-rw-r--r--modules/mono/doc_classes/@C#.xml2
-rw-r--r--modules/mono/doc_classes/CSharpScript.xml2
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml2
-rw-r--r--modules/mono/editor/bindings_generator.cpp98
-rw-r--r--modules/mono/editor/bindings_generator.h11
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp6
-rw-r--r--modules/mono/editor/godotsharp_editor.h6
-rw-r--r--modules/mono/glue/Managed/Files/Array.cs196
-rw-r--r--modules/mono/glue/Managed/Files/Dictionary.cs258
-rw-r--r--modules/mono/glue/Managed/Files/GD.cs16
-rw-r--r--modules/mono/glue/Managed/Files/MarshalUtils.cs60
-rw-r--r--modules/mono/glue/Managed/Files/Mathf.cs10
-rw-r--r--modules/mono/glue/Managed/Files/Vector2.cs5
-rw-r--r--modules/mono/glue/Managed/Files/Vector3.cs5
-rw-r--r--modules/mono/glue/Managed/IgnoredFiles/Variant.cs11
-rw-r--r--modules/mono/glue/arguments_vector.h14
-rw-r--r--modules/mono/glue/base_object_glue.cpp2
-rw-r--r--modules/mono/glue/collections_glue.cpp3
-rw-r--r--modules/mono/glue/collections_glue.h2
-rw-r--r--modules/mono/glue/gd_glue.cpp10
-rw-r--r--modules/mono/glue/gd_glue.h4
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp8
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp32
-rw-r--r--modules/mono/mono_gd/gd_mono_header.h18
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp128
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h21
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp27
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h40
-rw-r--r--modules/mono/mono_gd/managed_type.cpp58
-rw-r--r--modules/mono/mono_gd/managed_type.h58
-rw-r--r--modules/mono/signal_awaiter_utils.cpp4
-rw-r--r--modules/mono/utils/mono_reg_utils.cpp6
-rw-r--r--modules/mono/utils/thread_local.h4
-rw-r--r--modules/opensimplex/doc_classes/NoiseTexture.xml2
-rw-r--r--modules/opensimplex/doc_classes/OpenSimplexNoise.xml2
-rw-r--r--modules/opensimplex/open_simplex_noise.cpp6
-rw-r--r--modules/opensimplex/open_simplex_noise.h1
-rw-r--r--modules/opus/SCsub11
-rw-r--r--modules/regex/doc_classes/RegEx.xml2
-rw-r--r--modules/regex/doc_classes/RegExMatch.xml2
-rw-r--r--modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml2
-rw-r--r--modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml2
-rw-r--r--modules/theora/doc_classes/VideoStreamTheora.xml2
-rw-r--r--modules/tinyexr/image_loader_tinyexr.cpp37
-rw-r--r--modules/upnp/doc_classes/UPNP.xml2
-rw-r--r--modules/upnp/doc_classes/UPNPDevice.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScript.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml11
-rw-r--r--modules/visual_script/doc_classes/VisualScriptClassConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptComment.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCondition.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptConstructor.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptDeconstruct.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEditor.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEmitSignal.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptExpression.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionCall.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptFunctionState.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIndexSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptInputAction.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptIterator.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVar.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptMathConstant.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptOperator.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPreload.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertyGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPropertySet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptResourcePath.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptReturn.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneNode.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSceneTree.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelect.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSelf.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSequence.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSubCall.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptSwitch.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptTypeCast.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableGet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptVariableSet.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptWhile.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYield.xml2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptYieldSignal.xml2
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.cpp62
-rw-r--r--modules/visual_script/visual_script_builtin_funcs.h1
-rw-r--r--modules/visual_script/visual_script_editor.cpp6
-rw-r--r--modules/webm/doc_classes/VideoStreamWebm.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketPeer.xml2
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml2
-rw-r--r--modules/websocket/packet_buffer.h2
159 files changed, 4770 insertions, 1255 deletions
diff --git a/modules/assimp/SCsub b/modules/assimp/SCsub
new file mode 100644
index 0000000000..61a357809a
--- /dev/null
+++ b/modules/assimp/SCsub
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+
+Import('env')
+Import('env_modules')
+
+env_assimp = env_modules.Clone()
+env_assimp.Append(CPPPATH=['#thirdparty/assimp'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/include'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/code/Importer/IFC'])
+env_assimp.Append(CPPPATH=['#thirdparty/misc'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/code'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/contrib/irrXML/'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/contrib/unzip/'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/code/Importer/STEPParser'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/'])
+env_assimp.Append(CPPPATH=['#thirdparty/zlib/'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/contrib/openddlparser/include'])
+env_assimp.Append(CPPPATH=['#thirdparty/assimp/contrib/rapidjson/include'])
+env_assimp.Append(CPPPATH=['.'])
+#env_assimp.Append(CPPFLAGS=['-DASSIMP_DOUBLE_PRECISION']) # TODO default to what godot is compiled with for future double support
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_BOOST_WORKAROUND'])
+env_assimp.Append(CPPFLAGS=['-DOPENDDLPARSER_BUILD'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_OWN_ZLIB'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_EXPORT'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_X_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_AMF_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_3DS_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_MD3_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_MD5_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_MDL_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_MD2_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_PLY_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_ASE_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_OBJ_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_HMP_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_SMD_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_MDC_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_MD5_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_STL_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_LWO_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_DXF_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_NFF_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_RAW_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_SIB_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_OFF_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_AC_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_BVH_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_IRRMESH_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_IRR_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_Q3D_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_B3D_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_COLLADA_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_TERRAGEN_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_CSM_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_3D_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_LWS_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_OGRE_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_OPENGEX_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_MS3D_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_COB_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_BLEND_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_Q3BSP_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_NDO_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_STEP_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_IFC_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_XGL_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_ASSBIN_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_GLTF_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_C4D_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_3MF_IMPORTER'])
+env_assimp.Append(CPPFLAGS=['-DASSIMP_BUILD_NO_X3D_IMPORTER'])
+
+env_assimp.Append(CPPFLAGS=['-DASSIMP_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(CPPFLAGS=['-DPLATFORM_WINDOWS'])
+ env_assimp.Append(CPPFLAGS=['-DPLATFORM=WINDOWS'])
+elif(env['platform'] == 'x11'):
+ env_assimp.Append(CPPFLAGS=['-DPLATFORM_LINUX'])
+ env_assimp.Append(CPPFLAGS=['-DPLATFORM=LINUX'])
+elif(env['platform'] == 'osx'):
+ env_assimp.Append(CPPFLAGS=['-DPLATFORM_DARWIN'])
+ env_assimp.Append(CPPFLAGS=['-DPLATFORM=DARWIN'])
+
+env_thirdparty = env_assimp.Clone()
+env_thirdparty.disable_warnings()
+env_thirdparty.add_source_files(env.modules_sources, Glob('#thirdparty/assimp/code/*.cpp'))
+
+# Godot's own source files
+env_assimp.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/assimp/config.py b/modules/assimp/config.py
new file mode 100644
index 0000000000..098f1eafa9
--- /dev/null
+++ b/modules/assimp/config.py
@@ -0,0 +1,5 @@
+def can_build(env, platform):
+ return env['tools']
+
+def configure(env):
+ pass
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp
new file mode 100644
index 0000000000..ee66097ffd
--- /dev/null
+++ b/modules/assimp/editor_scene_importer_assimp.cpp
@@ -0,0 +1,2181 @@
+/*************************************************************************/
+/* editor_scene_importer_assimp.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 "assimp/DefaultLogger.hpp"
+#include "assimp/Importer.hpp"
+#include "assimp/LogStream.hpp"
+#include "assimp/Logger.hpp"
+#include "assimp/SceneCombiner.h"
+#include "assimp/cexport.h"
+#include "assimp/cimport.h"
+#include "assimp/matrix4x4.h"
+#include "assimp/pbrmaterial.h"
+#include "assimp/postprocess.h"
+#include "assimp/scene.h"
+
+#include "core/bind/core_bind.h"
+#include "core/io/image_loader.h"
+#include "editor/editor_file_system.h"
+#include "editor/import/resource_importer_scene.h"
+#include "editor_scene_importer_assimp.h"
+#include "editor_settings.h"
+#include "scene/3d/camera.h"
+#include "scene/3d/light.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/animation/animation_player.h"
+#include "scene/main/node.h"
+#include "scene/resources/material.h"
+#include "scene/resources/surface_tool.h"
+#include "zutil.h"
+#include <string>
+
+void EditorSceneImporterAssimp::get_extensions(List<String> *r_extensions) const {
+
+ const String import_setting_string = "filesystem/import/open_asset_import/";
+
+ Map<String, ImportFormat> import_format;
+ {
+ Vector<String> exts;
+ exts.push_back("fbx");
+ ImportFormat import = { exts, true };
+ import_format.insert("fbx", import);
+ }
+ {
+ Vector<String> exts;
+ exts.push_back("pmx");
+ ImportFormat import = { exts, true };
+ import_format.insert("mmd", import);
+ }
+ for (Map<String, ImportFormat>::Element *E = import_format.front(); E; E = E->next()) {
+ _register_project_setting_import(E->key(), import_setting_string, E->get().extensions, r_extensions, E->get().is_default);
+ }
+}
+
+void EditorSceneImporterAssimp::_register_project_setting_import(const String generic, const String import_setting_string, const Vector<String> &exts, List<String> *r_extensions, const bool p_enabled) const {
+ const String use_generic = "use_" + generic;
+ _GLOBAL_DEF(import_setting_string + use_generic, p_enabled, true);
+ if (ProjectSettings::get_singleton()->get(import_setting_string + use_generic)) {
+ for (int32_t i = 0; i < exts.size(); i++) {
+ r_extensions->push_back(exts[i]);
+ }
+ }
+}
+
+uint32_t EditorSceneImporterAssimp::get_import_flags() const {
+ return IMPORT_SCENE;
+}
+
+AssimpStream::AssimpStream() {
+ // empty
+}
+
+AssimpStream::~AssimpStream() {
+ // empty
+}
+
+void AssimpStream::write(const char *message) {
+ print_verbose(String("Open Asset Import: ") + String(message).strip_edges());
+}
+
+void EditorSceneImporterAssimp::_bind_methods() {
+}
+
+Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+ Assimp::Importer importer;
+ std::wstring w_path = ProjectSettings::get_singleton()->globalize_path(p_path).c_str();
+ std::string s_path(w_path.begin(), w_path.end());
+ importer.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true);
+ // Cannot remove pivot points because the static mesh will be in the wrong place
+ importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
+ int32_t max_bone_weights = 4;
+ //if (p_flags & IMPORT_ANIMATION_EIGHT_WEIGHTS) {
+ // const int eight_bones = 8;
+ // importer.SetPropertyBool(AI_CONFIG_PP_LBW_MAX_WEIGHTS, eight_bones);
+ // max_bone_weights = eight_bones;
+ //}
+
+ importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT);
+ //importer.SetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD, 1.0f);
+ int32_t post_process_Steps = aiProcess_CalcTangentSpace |
+ //aiProcess_FlipUVs |
+ //aiProcess_FlipWindingOrder |
+ aiProcess_DropNormals |
+ aiProcess_GenSmoothNormals |
+ aiProcess_JoinIdenticalVertices |
+ aiProcess_ImproveCacheLocality |
+ aiProcess_LimitBoneWeights |
+ //aiProcess_RemoveRedundantMaterials | // Causes a crash
+ aiProcess_SplitLargeMeshes |
+ aiProcess_Triangulate |
+ aiProcess_GenUVCoords |
+ //aiProcess_FindDegenerates |
+ aiProcess_SortByPType |
+ aiProcess_FindInvalidData |
+ aiProcess_TransformUVCoords |
+ aiProcess_FindInstances |
+ //aiProcess_FixInfacingNormals |
+ //aiProcess_ValidateDataStructure |
+ aiProcess_OptimizeMeshes |
+ //aiProcess_OptimizeGraph |
+ //aiProcess_Debone |
+ aiProcess_EmbedTextures |
+ aiProcess_SplitByBoneCount |
+ 0;
+ const aiScene *scene = importer.ReadFile(s_path.c_str(),
+ post_process_Steps);
+ ERR_EXPLAIN(String("Open Asset Import failed to open: ") + String(importer.GetErrorString()));
+ ERR_FAIL_COND_V(scene == NULL, NULL);
+ return _generate_scene(p_path, scene, p_flags, p_bake_fps, max_bone_weights);
+}
+
+template <class T>
+struct EditorSceneImporterAssetImportInterpolate {
+
+ T lerp(const T &a, const T &b, float c) const {
+
+ return a + (b - a) * c;
+ }
+
+ T catmull_rom(const T &p0, const T &p1, const T &p2, const T &p3, float t) {
+
+ float t2 = t * t;
+ float t3 = t2 * t;
+
+ return 0.5f * ((2.0f * p1) + (-p0 + p2) * t + (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 + (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
+ }
+
+ T bezier(T start, T control_1, T control_2, T end, float t) {
+ /* Formula from Wikipedia article on Bezier curves. */
+ real_t omt = (1.0 - t);
+ real_t omt2 = omt * omt;
+ real_t omt3 = omt2 * omt;
+ real_t t2 = t * t;
+ real_t t3 = t2 * t;
+
+ return start * omt3 + control_1 * omt2 * t * 3.0 + control_2 * omt * t2 * 3.0 + end * t3;
+ }
+};
+
+//thank you for existing, partial specialization
+template <>
+struct EditorSceneImporterAssetImportInterpolate<Quat> {
+
+ Quat lerp(const Quat &a, const Quat &b, float c) const {
+ ERR_FAIL_COND_V(!a.is_normalized(), Quat());
+ ERR_FAIL_COND_V(!b.is_normalized(), Quat());
+
+ return a.slerp(b, c).normalized();
+ }
+
+ Quat catmull_rom(const Quat &p0, const Quat &p1, const Quat &p2, const Quat &p3, float c) {
+ ERR_FAIL_COND_V(!p1.is_normalized(), Quat());
+ ERR_FAIL_COND_V(!p2.is_normalized(), Quat());
+
+ return p1.slerp(p2, c).normalized();
+ }
+
+ Quat bezier(Quat start, Quat control_1, Quat control_2, Quat end, float t) {
+ ERR_FAIL_COND_V(!start.is_normalized(), Quat());
+ ERR_FAIL_COND_V(!end.is_normalized(), Quat());
+
+ return start.slerp(end, t).normalized();
+ }
+};
+
+template <class T>
+T EditorSceneImporterAssimp::_interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp) {
+ //could use binary search, worth it?
+ int idx = -1;
+ for (int i = 0; i < p_times.size(); i++) {
+ if (p_times[i] > p_time)
+ break;
+ idx++;
+ }
+
+ EditorSceneImporterAssetImportInterpolate<T> interp;
+
+ switch (p_interp) {
+ case AssetImportAnimation::INTERP_LINEAR: {
+
+ if (idx == -1) {
+ return p_values[0];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[p_times.size() - 1];
+ }
+
+ float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+
+ return interp.lerp(p_values[idx], p_values[idx + 1], c);
+
+ } break;
+ case AssetImportAnimation::INTERP_STEP: {
+
+ if (idx == -1) {
+ return p_values[0];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[p_times.size() - 1];
+ }
+
+ return p_values[idx];
+
+ } break;
+ case AssetImportAnimation::INTERP_CATMULLROMSPLINE: {
+
+ if (idx == -1) {
+ return p_values[1];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[1 + p_times.size() - 1];
+ }
+
+ float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+
+ return interp.catmull_rom(p_values[idx - 1], p_values[idx], p_values[idx + 1], p_values[idx + 3], c);
+
+ } break;
+ case AssetImportAnimation::INTERP_CUBIC_SPLINE: {
+
+ if (idx == -1) {
+ return p_values[1];
+ } else if (idx >= p_times.size() - 1) {
+ return p_values[(p_times.size() - 1) * 3 + 1];
+ }
+
+ float c = (p_time - p_times[idx]) / (p_times[idx + 1] - p_times[idx]);
+
+ T from = p_values[idx * 3 + 1];
+ T c1 = from + p_values[idx * 3 + 2];
+ T to = p_values[idx * 3 + 4];
+ T c2 = to + p_values[idx * 3 + 3];
+
+ return interp.bezier(from, c1, c2, to, c);
+
+ } break;
+ }
+
+ ERR_FAIL_V(p_values[0]);
+}
+
+Spatial *EditorSceneImporterAssimp::_generate_scene(const String &p_path, const aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights) {
+ ERR_FAIL_COND_V(scene == NULL, NULL);
+ Spatial *root = memnew(Spatial);
+ AnimationPlayer *ap = NULL;
+ if (p_flags & IMPORT_ANIMATION) {
+ ap = memnew(AnimationPlayer);
+ root->add_child(ap);
+ ap->set_owner(root);
+ ap->set_name(TTR("AnimationPlayer"));
+ }
+ Set<String> bone_names;
+ Set<String> light_names;
+ Set<String> camera_names;
+ real_t factor = 1.0f;
+ String ext = p_path.get_file().get_extension().to_lower();
+ if ((ext == "fbx")) {
+ if (scene->mMetaData != NULL) {
+ scene->mMetaData->Get("UnitScaleFactor", factor);
+ factor = factor * 0.01f;
+ }
+ }
+ for (size_t l = 0; l < scene->mNumLights; l++) {
+ Light *light = NULL;
+ aiLight *ai_light = scene->mLights[l];
+ ERR_CONTINUE(ai_light == NULL);
+ if (ai_light->mType == aiLightSource_DIRECTIONAL) {
+ light = memnew(DirectionalLight);
+ Vector3 dir = Vector3(ai_light->mDirection.y, ai_light->mDirection.x, ai_light->mDirection.z);
+ dir.normalize();
+ Transform xform;
+ Quat quat;
+ quat.set_euler(dir);
+ Vector3 pos = Vector3(ai_light->mPosition.x, ai_light->mPosition.y, ai_light->mPosition.z);
+ pos = factor * pos;
+ xform.origin = pos;
+ light->set_transform(xform);
+ } else if (ai_light->mType == aiLightSource_POINT) {
+ light = memnew(OmniLight);
+ Vector3 pos = Vector3(ai_light->mPosition.x, ai_light->mPosition.y, ai_light->mPosition.z);
+ Transform xform;
+ xform.origin = pos;
+ pos = factor * pos;
+ light->set_transform(xform);
+ // No idea for energy
+ light->set_param(Light::PARAM_ATTENUATION, 0.0f);
+ } else if (ai_light->mType == aiLightSource_SPOT) {
+ light = memnew(SpotLight);
+ Vector3 pos = Vector3(ai_light->mPosition.x, ai_light->mPosition.y, ai_light->mPosition.z);
+ pos = factor * pos;
+ Transform xform;
+ xform.origin = pos;
+ Vector3 dir = Vector3(ai_light->mDirection.y, ai_light->mDirection.x, ai_light->mDirection.z);
+ dir.normalize();
+ Quat quat;
+ quat.set_euler(dir);
+ xform.basis = quat;
+ light->set_transform(xform);
+ // No idea for energy
+ light->set_param(Light::PARAM_ATTENUATION, 0.0f);
+ }
+ ERR_CONTINUE(light == NULL);
+ light->set_color(Color(ai_light->mColorDiffuse.r, ai_light->mColorDiffuse.g, ai_light->mColorDiffuse.b));
+ root->add_child(light);
+ light->set_name(_ai_string_to_string(ai_light->mName));
+ light->set_owner(root);
+ light_names.insert(_ai_string_to_string(scene->mLights[l]->mName));
+ }
+ for (size_t c = 0; c < scene->mNumCameras; c++) {
+ aiCamera *ai_camera = scene->mCameras[c];
+ Camera *camera = memnew(Camera);
+ float near = ai_camera->mClipPlaneNear;
+ if (Math::is_equal_approx(near, 0.0f)) {
+ near = 0.1f;
+ }
+ camera->set_perspective(Math::rad2deg(ai_camera->mHorizontalFOV) * 2.0f, near, ai_camera->mClipPlaneFar);
+ Vector3 pos = Vector3(ai_camera->mPosition.x, ai_camera->mPosition.y, ai_camera->mPosition.z);
+
+ Vector3 look_at = Vector3(ai_camera->mLookAt.y, ai_camera->mLookAt.x, ai_camera->mLookAt.z).normalized();
+ Quat quat;
+ quat.set_euler(look_at);
+ Transform xform;
+ xform.basis = quat;
+ xform.set_origin(pos);
+ root->add_child(camera);
+ camera->set_transform(xform);
+ camera->set_name(_ai_string_to_string(ai_camera->mName));
+ camera->set_owner(root);
+ camera_names.insert(_ai_string_to_string(scene->mCameras[c]->mName));
+ }
+ Map<Skeleton *, MeshInstance *> skeletons;
+ Map<String, Transform> bone_rests;
+ Vector<MeshInstance *> meshes;
+ int32_t mesh_count = 0;
+ Skeleton *s = memnew(Skeleton);
+ Set<String> removed_bones;
+ Map<String, Map<uint32_t, String> > path_morph_mesh_names;
+ _generate_node(p_path, scene, scene->mRootNode, root, root, bone_names, light_names, camera_names, skeletons, bone_rests, meshes, mesh_count, s, p_max_bone_weights, removed_bones, path_morph_mesh_names);
+ for (Map<Skeleton *, MeshInstance *>::Element *E = skeletons.front(); E; E = E->next()) {
+ E->key()->localize_rests();
+ }
+ Set<String> removed_nodes;
+ Set<Node *> keep_nodes;
+ _keep_node(p_path, root, root, keep_nodes);
+ _fill_kept_node(keep_nodes);
+ _filter_node(p_path, root, root, keep_nodes, removed_nodes);
+ if (p_flags & IMPORT_ANIMATION) {
+ for (size_t i = 0; i < scene->mNumAnimations; i++) {
+ _import_animation(p_path, meshes, scene, ap, i, p_bake_fps, skeletons, removed_nodes, removed_bones, path_morph_mesh_names);
+ }
+ List<StringName> animation_names;
+ ap->get_animation_list(&animation_names);
+ if (animation_names.empty()) {
+ root->remove_child(ap);
+ memdelete(ap);
+ }
+ }
+ return root;
+}
+
+void EditorSceneImporterAssimp::_fill_kept_node(Set<Node *> &keep_nodes) {
+ for (Set<Node *>::Element *E = keep_nodes.front(); E; E = E->next()) {
+ Node *node = E->get();
+ while (node != NULL) {
+ if (keep_nodes.has(node) == false) {
+ keep_nodes.insert(node);
+ }
+ node = node->get_parent();
+ }
+ }
+}
+
+String EditorSceneImporterAssimp::_find_skeleton_bone_root(Map<Skeleton *, MeshInstance *> &skeletons, Map<MeshInstance *, String> &meshes, Spatial *root) {
+ for (Map<Skeleton *, MeshInstance *>::Element *E = skeletons.front(); E; E = E->next()) {
+ if (meshes.has(E->get())) {
+ String name = meshes[E->get()];
+ if (name != "") {
+ return name;
+ }
+ }
+ }
+ return "";
+}
+
+void EditorSceneImporterAssimp::_set_bone_parent(Skeleton *s, Node *p_owner, aiNode *p_node) {
+ for (int32_t j = 0; j < s->get_bone_count(); j++) {
+ String bone_name = s->get_bone_name(j);
+ const aiNode *ai_bone_node = _ai_find_node(p_node, bone_name);
+ if (ai_bone_node == NULL) {
+ continue;
+ }
+ ai_bone_node = ai_bone_node->mParent;
+ while (ai_bone_node != NULL) {
+ int32_t node_parent_index = -1;
+ String parent_bone_name = _ai_string_to_string(ai_bone_node->mName);
+ node_parent_index = s->find_bone(parent_bone_name);
+ if (node_parent_index != -1) {
+ s->set_bone_parent(j, node_parent_index);
+ break;
+ }
+ ai_bone_node = ai_bone_node->mParent;
+ }
+ }
+}
+
+void EditorSceneImporterAssimp::_insert_animation_track(const aiScene *p_scene, const String p_path, int p_bake_fps, Ref<Animation> animation, float ticks_per_second, float length, const Skeleton *sk, const aiNodeAnim *track, String node_name, NodePath node_path) {
+
+ if (track->mNumRotationKeys || track->mNumPositionKeys || track->mNumScalingKeys) {
+ //make transform track
+ int track_idx = animation->get_track_count();
+ animation->add_track(Animation::TYPE_TRANSFORM);
+ animation->track_set_path(track_idx, node_path);
+ //first determine animation length
+
+ for (size_t i = 0; i < track->mNumRotationKeys; i++) {
+ length = MAX(length, track->mRotationKeys[i].mTime / ticks_per_second);
+ }
+ for (size_t i = 0; i < track->mNumPositionKeys; i++) {
+ length = MAX(length, track->mPositionKeys[i].mTime / ticks_per_second);
+ }
+ for (size_t i = 0; i < track->mNumScalingKeys; i++) {
+ length = MAX(length, track->mScalingKeys[i].mTime / ticks_per_second);
+ }
+
+ float increment = 1.0 / float(p_bake_fps);
+ float time = 0.0;
+
+ Vector3 base_pos;
+ Quat base_rot;
+ Vector3 base_scale = Vector3(1, 1, 1);
+
+ if (track->mNumRotationKeys != 0) {
+ aiQuatKey key = track->mRotationKeys[0];
+ real_t x = key.mValue.x;
+ real_t y = key.mValue.y;
+ real_t z = key.mValue.z;
+ real_t w = key.mValue.w;
+ Quat q(x, y, z, w);
+ q = q.normalized();
+ base_rot = q;
+ }
+
+ if (track->mNumPositionKeys != 0) {
+ aiVectorKey key = track->mPositionKeys[0];
+ real_t x = key.mValue.x;
+ real_t y = key.mValue.y;
+ real_t z = key.mValue.z;
+ base_pos = Vector3(x, y, z);
+ }
+
+ if (track->mNumScalingKeys != 0) {
+ aiVectorKey key = track->mScalingKeys[0];
+ real_t x = key.mValue.x;
+ real_t y = key.mValue.y;
+ real_t z = key.mValue.z;
+ base_scale = Vector3(x, y, z);
+ }
+
+ bool last = false;
+
+ Vector<Vector3> pos_values;
+ Vector<float> pos_times;
+ Vector<Vector3> scale_values;
+ Vector<float> scale_times;
+ Vector<Quat> rot_values;
+ Vector<float> rot_times;
+
+ for (size_t p = 0; p < track->mNumPositionKeys; p++) {
+ aiVector3D pos = track->mPositionKeys[p].mValue;
+ pos_values.push_back(Vector3(pos.x, pos.y, pos.z));
+ pos_times.push_back(track->mPositionKeys[p].mTime / ticks_per_second);
+ }
+
+ for (size_t r = 0; r < track->mNumRotationKeys; r++) {
+ aiQuaternion quat = track->mRotationKeys[r].mValue;
+ rot_values.push_back(Quat(quat.x, quat.y, quat.z, quat.w).normalized());
+ rot_times.push_back(track->mRotationKeys[r].mTime / ticks_per_second);
+ }
+
+ for (size_t sc = 0; sc < track->mNumScalingKeys; sc++) {
+ aiVector3D scale = track->mScalingKeys[sc].mValue;
+ scale_values.push_back(Vector3(scale.x, scale.y, scale.z));
+ scale_times.push_back(track->mScalingKeys[sc].mTime / ticks_per_second);
+ }
+ while (true) {
+ Vector3 pos = base_pos;
+ Quat rot = base_rot;
+ Vector3 scale = base_scale;
+
+ if (pos_values.size()) {
+ pos = _interpolate_track<Vector3>(pos_times, pos_values, time, AssetImportAnimation::INTERP_LINEAR);
+ }
+
+ if (rot_values.size()) {
+ rot = _interpolate_track<Quat>(rot_times, rot_values, time, AssetImportAnimation::INTERP_LINEAR).normalized();
+ }
+
+ if (scale_values.size()) {
+ scale = _interpolate_track<Vector3>(scale_times, scale_values, time, AssetImportAnimation::INTERP_LINEAR);
+ }
+
+ if (sk != NULL && sk->find_bone(node_name) != -1) {
+ Transform xform;
+ xform.basis.set_quat_scale(rot, scale);
+ xform.origin = pos;
+
+ int bone = sk->find_bone(node_name);
+ Transform rest_xform = sk->get_bone_rest(bone);
+ xform = rest_xform.affine_inverse() * xform;
+ rot = xform.basis.get_rotation_quat();
+ scale = xform.basis.get_scale();
+ pos = xform.origin;
+ }
+ {
+ Transform xform;
+ xform.basis.set_quat_scale(rot, scale);
+ xform.origin = pos;
+ Transform anim_xform;
+ String ext = p_path.get_file().get_extension().to_lower();
+ if (ext == "fbx") {
+ real_t factor = 1.0f;
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("UnitScaleFactor", factor);
+ }
+ anim_xform = anim_xform.scaled(Vector3(factor, factor, factor));
+ }
+ xform = anim_xform * xform;
+ rot = xform.basis.get_rotation_quat();
+ scale = xform.basis.get_scale();
+ pos = xform.origin;
+ }
+ rot.normalize();
+
+ animation->track_set_interpolation_type(track_idx, Animation::INTERPOLATION_LINEAR);
+ animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
+
+ if (last) {
+ break;
+ }
+ time += increment;
+ if (time >= length) {
+ last = true;
+ time = length;
+ }
+ }
+ }
+}
+
+void EditorSceneImporterAssimp::_import_animation(const String p_path, const Vector<MeshInstance *> p_meshes, const aiScene *p_scene, AnimationPlayer *ap, int32_t p_index, int p_bake_fps, Map<Skeleton *, MeshInstance *> p_skeletons, const Set<String> p_removed_nodes, const Set<String> removed_bones, const Map<String, Map<uint32_t, String> > p_path_morph_mesh_names) {
+ String name = "Animation";
+ aiAnimation const *anim = NULL;
+ if (p_index != -1) {
+ anim = p_scene->mAnimations[p_index];
+ if (anim->mName.length > 0) {
+ name = _ai_anim_string_to_string(anim->mName);
+ }
+ }
+
+ Ref<Animation> animation;
+ animation.instance();
+ float length = 0.0f;
+ animation->set_name(name);
+ float ticks_per_second = p_scene->mAnimations[p_index]->mTicksPerSecond;
+
+ if (p_scene->mMetaData != NULL && Math::is_equal_approx(ticks_per_second, 0.0f)) {
+ int32_t time_mode = 0;
+ p_scene->mMetaData->Get("TimeMode", time_mode);
+ ticks_per_second = _get_fbx_fps(time_mode, p_scene);
+ }
+
+ if ((p_path.get_file().get_extension().to_lower() == "glb" || p_path.get_file().get_extension().to_lower() == "gltf") && Math::is_equal_approx(ticks_per_second, 0.0f)) {
+ ticks_per_second = 1000.0f;
+ }
+
+ if (Math::is_equal_approx(ticks_per_second, 0.0f)) {
+ ticks_per_second = 25.0f;
+ }
+
+ length = anim->mDuration / ticks_per_second;
+ if (anim) {
+ Map<String, Vector<const aiNodeAnim *> > node_tracks;
+ for (size_t i = 0; i < anim->mNumChannels; i++) {
+ const aiNodeAnim *track = anim->mChannels[i];
+ String node_name = _ai_string_to_string(track->mNodeName);
+ NodePath node_path = node_name;
+ bool is_bone = false;
+ if (node_name.split(ASSIMP_FBX_KEY).size() > 1) {
+ String p_track_type = node_name.split(ASSIMP_FBX_KEY)[1];
+ if (p_track_type == "_Translation" || p_track_type == "_Rotation" || p_track_type == "_Scaling") {
+ continue;
+ }
+ }
+ for (Map<Skeleton *, MeshInstance *>::Element *E = p_skeletons.front(); E; E = E->next()) {
+ Skeleton *sk = E->key();
+ const String path = ap->get_owner()->get_path_to(sk);
+ if (path.empty()) {
+ continue;
+ }
+ if (sk->find_bone(node_name) == -1) {
+ continue;
+ }
+ node_path = path + ":" + node_name;
+ ERR_CONTINUE(ap->get_owner()->has_node(node_path) == false);
+ _insert_animation_track(p_scene, p_path, p_bake_fps, animation, ticks_per_second, length, sk, track, node_name, node_path);
+ is_bone = true;
+ }
+ if (is_bone) {
+ continue;
+ }
+ Node *node = ap->get_owner()->find_node(node_name);
+ if (node == NULL) {
+ continue;
+ }
+ if (p_removed_nodes.has(node_name)) {
+ continue;
+ }
+ const String path = ap->get_owner()->get_path_to(node);
+ if (path.empty()) {
+ print_verbose("Can't animate path");
+ continue;
+ }
+ node_path = path;
+ if (ap->get_owner()->has_node(node_path) == false) {
+ continue;
+ }
+ _insert_animation_track(p_scene, p_path, p_bake_fps, animation, ticks_per_second, length, NULL, track, node_name, node_path);
+ }
+ for (size_t i = 0; i < anim->mNumChannels; i++) {
+ const aiNodeAnim *track = anim->mChannels[i];
+ String node_name = _ai_string_to_string(track->mNodeName);
+ Vector<String> split_name = node_name.split(ASSIMP_FBX_KEY);
+ String bare_name = split_name[0];
+ Node *node = ap->get_owner()->find_node(bare_name);
+ if (node != NULL && split_name.size() > 1) {
+ Map<String, Vector<const aiNodeAnim *> >::Element *E = node_tracks.find(bare_name);
+ Vector<const aiNodeAnim *> ai_tracks;
+ if (E) {
+ ai_tracks = E->get();
+ ai_tracks.push_back(anim->mChannels[i]);
+ } else {
+ ai_tracks.push_back(anim->mChannels[i]);
+ }
+ node_tracks.insert(bare_name, ai_tracks);
+ }
+ }
+ for (Map<Skeleton *, MeshInstance *>::Element *E = p_skeletons.front(); E; E = E->next()) {
+ Skeleton *sk = E->key();
+ Map<String, Vector<const aiNodeAnim *> > anim_tracks;
+ for (int32_t i = 0; i < sk->get_bone_count(); i++) {
+ String _bone_name = sk->get_bone_name(i);
+ Vector<const aiNodeAnim *> ai_tracks;
+
+ if (sk->find_bone(_bone_name) == -1) {
+ continue;
+ }
+ for (size_t j = 0; j < anim->mNumChannels; j++) {
+ if (_ai_string_to_string(anim->mChannels[j]->mNodeName).split(ASSIMP_FBX_KEY).size() == 1) {
+ continue;
+ }
+ String track_name = _ai_string_to_string(anim->mChannels[j]->mNodeName).split(ASSIMP_FBX_KEY)[0];
+ if (track_name != _bone_name) {
+ continue;
+ }
+ if (sk->find_bone(_bone_name) == -1) {
+ continue;
+ }
+ ai_tracks.push_back(anim->mChannels[j]);
+ }
+ if (ai_tracks.size() == 0) {
+ continue;
+ }
+ anim_tracks.insert(_bone_name, ai_tracks);
+ }
+ for (Map<String, Vector<const aiNodeAnim *> >::Element *F = anim_tracks.front(); F; F = F->next()) {
+ _insert_pivot_anim_track(p_meshes, F->key(), F->get(), ap, sk, length, ticks_per_second, animation, p_bake_fps, p_path, p_scene);
+ }
+ }
+ for (Map<String, Vector<const aiNodeAnim *> >::Element *E = node_tracks.front(); E; E = E->next()) {
+ if (p_removed_nodes.has(E->key())) {
+ continue;
+ }
+ if (removed_bones.find(E->key())) {
+ continue;
+ }
+ _insert_pivot_anim_track(p_meshes, E->key(), E->get(), ap, NULL, length, ticks_per_second, animation, p_bake_fps, p_path, p_scene);
+ }
+ for (size_t i = 0; i < anim->mNumMorphMeshChannels; i++) {
+ const aiMeshMorphAnim *anim_mesh = anim->mMorphMeshChannels[i];
+ const String prop_name = _ai_string_to_string(anim_mesh->mName);
+ const String mesh_name = prop_name.split("*")[0];
+ if (p_removed_nodes.has(mesh_name)) {
+ continue;
+ }
+ ERR_CONTINUE(prop_name.split("*").size() != 2);
+ const MeshInstance *mesh_instance = Object::cast_to<MeshInstance>(ap->get_owner()->find_node(mesh_name));
+ ERR_CONTINUE(mesh_instance == NULL);
+ if (ap->get_owner()->find_node(mesh_instance->get_name()) == NULL) {
+ print_verbose("Can't find mesh in scene: " + mesh_instance->get_name());
+ continue;
+ }
+ const String path = ap->get_owner()->get_path_to(mesh_instance);
+ if (path.empty()) {
+ print_verbose("Can't find mesh in scene");
+ continue;
+ }
+ Ref<Mesh> mesh = mesh_instance->get_mesh();
+ ERR_CONTINUE(mesh.is_null());
+ const Map<String, Map<uint32_t, String> >::Element *E = p_path_morph_mesh_names.find(mesh_name);
+ ERR_CONTINUE(E == NULL);
+ for (size_t k = 0; k < anim_mesh->mNumKeys; k++) {
+ for (size_t j = 0; j < anim_mesh->mKeys[k].mNumValuesAndWeights; j++) {
+ const Map<uint32_t, String>::Element *F = E->get().find(anim_mesh->mKeys[k].mValues[j]);
+ ERR_CONTINUE(F == NULL);
+ const String prop = "blend_shapes/" + F->get();
+ const NodePath node_path = String(path) + ":" + prop;
+ ERR_CONTINUE(ap->get_owner()->has_node(node_path) == false);
+ int32_t blend_track_idx = -1;
+ if (animation->find_track(node_path) == -1) {
+ blend_track_idx = animation->get_track_count();
+ animation->add_track(Animation::TYPE_VALUE);
+ animation->track_set_interpolation_type(blend_track_idx, Animation::INTERPOLATION_LINEAR);
+ animation->track_set_path(blend_track_idx, node_path);
+ } else {
+ blend_track_idx = animation->find_track(node_path);
+ }
+ float t = anim_mesh->mKeys[k].mTime / ticks_per_second;
+ float w = anim_mesh->mKeys[k].mWeights[j];
+ animation->track_insert_key(blend_track_idx, t, w);
+ }
+ }
+ }
+ }
+ animation->set_length(length);
+ if (animation->get_track_count()) {
+ ap->add_animation(name, animation);
+ }
+}
+
+void EditorSceneImporterAssimp::_insert_pivot_anim_track(const Vector<MeshInstance *> p_meshes, const String p_node_name, Vector<const aiNodeAnim *> F, AnimationPlayer *ap, Skeleton *sk, float &length, float ticks_per_second, Ref<Animation> animation, int p_bake_fps, const String &p_path, const aiScene *p_scene) {
+ NodePath node_path;
+ if (sk != NULL) {
+ const String path = ap->get_owner()->get_path_to(sk);
+ if (path.empty()) {
+ return;
+ }
+ if (sk->find_bone(p_node_name) == -1) {
+ return;
+ }
+ node_path = path + ":" + p_node_name;
+ } else {
+ Node *node = ap->get_owner()->find_node(p_node_name);
+ if (node == NULL) {
+ return;
+ }
+ const String path = ap->get_owner()->get_path_to(node);
+ node_path = path;
+ }
+ if (node_path.is_empty()) {
+ return;
+ }
+
+ Vector<Vector3> pos_values;
+ Vector<float> pos_times;
+ Vector<Vector3> scale_values;
+ Vector<float> scale_times;
+ Vector<Quat> rot_values;
+ Vector<float> rot_times;
+ Vector3 base_pos;
+ Quat base_rot;
+ Vector3 base_scale = Vector3(1, 1, 1);
+ bool is_translation = false;
+ bool is_rotation = false;
+ bool is_scaling = false;
+ for (int32_t k = 0; k < F.size(); k++) {
+ String p_track_type = _ai_string_to_string(F[k]->mNodeName).split(ASSIMP_FBX_KEY)[1];
+ if (p_track_type == "_Translation") {
+ is_translation = is_translation || true;
+ } else if (p_track_type == "_Rotation") {
+ is_rotation = is_rotation || true;
+ } else if (p_track_type == "_Scaling") {
+ is_scaling = is_scaling || true;
+ } else {
+ continue;
+ }
+ ERR_CONTINUE(ap->get_owner()->has_node(node_path) == false);
+
+ if (F[k]->mNumRotationKeys || F[k]->mNumPositionKeys || F[k]->mNumScalingKeys) {
+
+ if (is_rotation) {
+ for (size_t i = 0; i < F[k]->mNumRotationKeys; i++) {
+ length = MAX(length, F[k]->mRotationKeys[i].mTime / ticks_per_second);
+ }
+ }
+ if (is_translation) {
+ for (size_t i = 0; i < F[k]->mNumPositionKeys; i++) {
+ length = MAX(length, F[k]->mPositionKeys[i].mTime / ticks_per_second);
+ }
+ }
+ if (is_scaling) {
+ for (size_t i = 0; i < F[k]->mNumScalingKeys; i++) {
+ length = MAX(length, F[k]->mScalingKeys[i].mTime / ticks_per_second);
+ }
+ }
+
+ if (is_rotation == false && is_translation == false && is_scaling == false) {
+ return;
+ }
+
+ if (is_rotation) {
+ if (F[k]->mNumRotationKeys != 0) {
+ aiQuatKey key = F[k]->mRotationKeys[0];
+ real_t x = key.mValue.x;
+ real_t y = key.mValue.y;
+ real_t z = key.mValue.z;
+ real_t w = key.mValue.w;
+ Quat q(x, y, z, w);
+ q = q.normalized();
+ base_rot = q;
+ }
+ }
+
+ if (is_translation) {
+ if (F[k]->mNumPositionKeys != 0) {
+ aiVectorKey key = F[k]->mPositionKeys[0];
+ real_t x = key.mValue.x;
+ real_t y = key.mValue.y;
+ real_t z = key.mValue.z;
+ base_pos = Vector3(x, y, z);
+ }
+ }
+
+ if (is_scaling) {
+ if (F[k]->mNumScalingKeys != 0) {
+ aiVectorKey key = F[k]->mScalingKeys[0];
+ real_t x = key.mValue.x;
+ real_t y = key.mValue.y;
+ real_t z = key.mValue.z;
+ base_scale = Vector3(x, y, z);
+ }
+ }
+ if (is_translation) {
+ for (size_t p = 0; p < F[k]->mNumPositionKeys; p++) {
+ aiVector3D pos = F[k]->mPositionKeys[p].mValue;
+ pos_values.push_back(Vector3(pos.x, pos.y, pos.z));
+ pos_times.push_back(F[k]->mPositionKeys[p].mTime / ticks_per_second);
+ }
+ }
+
+ if (is_rotation) {
+ for (size_t r = 0; r < F[k]->mNumRotationKeys; r++) {
+ aiQuaternion quat = F[k]->mRotationKeys[r].mValue;
+ rot_values.push_back(Quat(quat.x, quat.y, quat.z, quat.w).normalized());
+ rot_times.push_back(F[k]->mRotationKeys[r].mTime / ticks_per_second);
+ }
+ }
+
+ if (is_scaling) {
+ for (size_t sc = 0; sc < F[k]->mNumScalingKeys; sc++) {
+ aiVector3D scale = F[k]->mScalingKeys[sc].mValue;
+ scale_values.push_back(Vector3(scale.x, scale.y, scale.z));
+ scale_times.push_back(F[k]->mScalingKeys[sc].mTime / ticks_per_second);
+ }
+ }
+ }
+ }
+ int32_t track_idx = animation->get_track_count();
+ animation->add_track(Animation::TYPE_TRANSFORM);
+ animation->track_set_path(track_idx, node_path);
+ float increment = 1.0 / float(p_bake_fps);
+ float time = 0.0;
+ bool last = false;
+ while (true) {
+ Vector3 pos = Vector3();
+ Quat rot = Quat();
+ Vector3 scale = Vector3(1.0f, 1.0f, 1.0f);
+ if (is_translation && pos_values.size()) {
+ pos = _interpolate_track<Vector3>(pos_times, pos_values, time, AssetImportAnimation::INTERP_LINEAR);
+ Transform anim_xform;
+ String ext = p_path.get_file().get_extension().to_lower();
+ if (ext == "fbx") {
+ aiNode *ai_node = _ai_find_node(p_scene->mRootNode, p_node_name);
+ Transform mesh_xform = _get_global_ai_node_transform(p_scene, ai_node);
+ pos = mesh_xform.origin + pos;
+ real_t factor = 1.0f;
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("UnitScaleFactor", factor);
+ factor = factor * 0.01f;
+ }
+ pos = pos * factor;
+ }
+ }
+ if (is_rotation && rot_values.size()) {
+ rot = _interpolate_track<Quat>(rot_times, rot_values, time, AssetImportAnimation::INTERP_LINEAR).normalized();
+ }
+ if (is_scaling && scale_values.size()) {
+ scale = _interpolate_track<Vector3>(scale_times, scale_values, time, AssetImportAnimation::INTERP_LINEAR);
+ }
+ animation->track_set_interpolation_type(track_idx, Animation::INTERPOLATION_LINEAR);
+ animation->transform_track_insert_key(track_idx, time, pos, rot, scale);
+
+ if (last) {
+ break;
+ }
+ time += increment;
+ if (time >= length) {
+ last = true;
+ time = length;
+ }
+ }
+}
+
+float EditorSceneImporterAssimp::_get_fbx_fps(int32_t time_mode, const aiScene *p_scene) {
+ switch (time_mode) {
+ case AssetImportFbx::TIME_MODE_DEFAULT: return 24; //hack
+ case AssetImportFbx::TIME_MODE_120: return 120;
+ case AssetImportFbx::TIME_MODE_100: return 100;
+ case AssetImportFbx::TIME_MODE_60: return 60;
+ case AssetImportFbx::TIME_MODE_50: return 50;
+ case AssetImportFbx::TIME_MODE_48: return 48;
+ case AssetImportFbx::TIME_MODE_30: return 30;
+ case AssetImportFbx::TIME_MODE_30_DROP: return 30;
+ case AssetImportFbx::TIME_MODE_NTSC_DROP_FRAME: return 29.9700262f;
+ case AssetImportFbx::TIME_MODE_NTSC_FULL_FRAME: return 29.9700262f;
+ case AssetImportFbx::TIME_MODE_PAL: return 25;
+ case AssetImportFbx::TIME_MODE_CINEMA: return 24;
+ case AssetImportFbx::TIME_MODE_1000: return 1000;
+ case AssetImportFbx::TIME_MODE_CINEMA_ND: return 23.976f;
+ case AssetImportFbx::TIME_MODE_CUSTOM:
+ int32_t frame_rate;
+ p_scene->mMetaData->Get("FrameRate", frame_rate);
+ return frame_rate;
+ }
+ return 0;
+}
+
+Transform EditorSceneImporterAssimp::_get_global_ai_node_transform(const aiScene *p_scene, const aiNode *p_current_node) {
+ aiNode const *current_node = p_current_node;
+ Transform xform;
+ while (current_node != NULL) {
+ xform = _ai_matrix_transform(current_node->mTransformation) * xform;
+ current_node = current_node->mParent;
+ }
+ return xform;
+}
+
+void EditorSceneImporterAssimp::_generate_node_bone(const aiScene *p_scene, const aiNode *p_node, Map<String, bool> &p_mesh_bones, Skeleton *p_skeleton, const String p_path, const int32_t p_max_bone_weights) {
+ for (size_t i = 0; i < p_node->mNumMeshes; i++) {
+ const unsigned int mesh_idx = p_node->mMeshes[i];
+ const aiMesh *ai_mesh = p_scene->mMeshes[mesh_idx];
+ for (size_t j = 0; j < ai_mesh->mNumBones; j++) {
+ String bone_name = _ai_string_to_string(ai_mesh->mBones[j]->mName);
+ if (p_skeleton->find_bone(bone_name) != -1) {
+ continue;
+ }
+ p_mesh_bones.insert(bone_name, true);
+ p_skeleton->add_bone(bone_name);
+ int32_t idx = p_skeleton->find_bone(bone_name);
+ Transform xform = _ai_matrix_transform(ai_mesh->mBones[j]->mOffsetMatrix);
+ String ext = p_path.get_file().get_extension().to_lower();
+ if (ext == "fbx") {
+ Transform mesh_xform = _get_global_ai_node_transform(p_scene, p_node);
+ mesh_xform.basis = Basis();
+ xform = mesh_xform.affine_inverse() * xform;
+ }
+ p_skeleton->set_bone_rest(idx, xform.affine_inverse());
+ }
+ }
+}
+
+void EditorSceneImporterAssimp::_generate_node_bone_parents(const aiScene *p_scene, const aiNode *p_node, Map<String, bool> &p_mesh_bones, Skeleton *p_skeleton, const MeshInstance *p_mi) {
+ for (size_t i = 0; i < p_node->mNumMeshes; i++) {
+ const unsigned int mesh_idx = p_node->mMeshes[i];
+ const aiMesh *ai_mesh = p_scene->mMeshes[mesh_idx];
+
+ for (size_t j = 0; j < ai_mesh->mNumBones; j++) {
+ aiNode *bone_node = p_scene->mRootNode->FindNode(ai_mesh->mBones[j]->mName);
+ ERR_CONTINUE(bone_node == NULL);
+ aiNode *bone_node_parent = bone_node->mParent;
+ while (bone_node_parent != NULL) {
+ String bone_parent_name = _ai_string_to_string(bone_node_parent->mName);
+ bone_parent_name = bone_parent_name.split(ASSIMP_FBX_KEY)[0];
+ if (bone_parent_name == p_mi->get_name()) {
+ break;
+ }
+ if (p_mi->get_parent() == NULL) {
+ break;
+ }
+ if (bone_parent_name == p_mi->get_parent()->get_name()) {
+ break;
+ }
+ if (bone_node_parent->mParent == p_scene->mRootNode) {
+ break;
+ }
+ if (p_skeleton->find_bone(bone_parent_name) == -1) {
+ p_mesh_bones.insert(bone_parent_name, true);
+ }
+ bone_node_parent = bone_node_parent->mParent;
+ }
+ }
+ }
+}
+void EditorSceneImporterAssimp::_calculate_skeleton_root(Skeleton *s, const aiScene *p_scene, aiNode *&p_ai_skeleton_root, Map<String, bool> &mesh_bones, const aiNode *p_node) {
+ if (s->get_bone_count() > 0) {
+ String bone_name = s->get_bone_name(0);
+ p_ai_skeleton_root = _ai_find_node(p_scene->mRootNode, bone_name);
+ for (size_t i = 0; i < p_scene->mRootNode->mNumChildren; i++) {
+ if (p_ai_skeleton_root == NULL) {
+ break;
+ }
+ aiNode *found = p_scene->mRootNode->mChildren[i]->FindNode(p_ai_skeleton_root->mName);
+ if (found) {
+ p_ai_skeleton_root = p_scene->mRootNode->mChildren[i];
+ break;
+ }
+ }
+ }
+
+ if (p_ai_skeleton_root == NULL) {
+ p_ai_skeleton_root = p_scene->mRootNode->FindNode(p_node->mName);
+ while (p_ai_skeleton_root && p_ai_skeleton_root->mParent && p_ai_skeleton_root->mParent != p_scene->mRootNode) {
+ p_ai_skeleton_root = p_scene->mRootNode->FindNode(p_ai_skeleton_root->mName)->mParent;
+ }
+ }
+ p_ai_skeleton_root = _ai_find_node(p_scene->mRootNode, _ai_string_to_string(p_ai_skeleton_root->mName).split(ASSIMP_FBX_KEY)[0]);
+}
+
+void EditorSceneImporterAssimp::_fill_skeleton(const aiScene *p_scene, const aiNode *p_node, Spatial *p_current, Node *p_owner, Skeleton *p_skeleton, const Map<String, bool> p_mesh_bones, const Map<String, Transform> &p_bone_rests, Set<String> p_tracks, const String p_path, Set<String> &r_removed_bones) {
+ String node_name = _ai_string_to_string(p_node->mName);
+ if (p_mesh_bones.find(node_name) != NULL && p_skeleton->find_bone(node_name) == -1) {
+ r_removed_bones.insert(node_name);
+ p_skeleton->add_bone(node_name);
+ int32_t idx = p_skeleton->find_bone(node_name);
+ Transform xform = _get_global_ai_node_transform(p_scene, p_node);
+ xform = _format_rot_xform(p_path, p_scene) * xform;
+ p_skeleton->set_bone_rest(idx, xform);
+ }
+
+ for (size_t i = 0; i < p_node->mNumChildren; i++) {
+ _fill_skeleton(p_scene, p_node->mChildren[i], p_current, p_owner, p_skeleton, p_mesh_bones, p_bone_rests, p_tracks, p_path, r_removed_bones);
+ }
+}
+
+void EditorSceneImporterAssimp::_keep_node(const String &p_path, Node *p_current, Node *p_owner, Set<Node *> &r_keep_nodes) {
+ if (p_current == p_owner) {
+ r_keep_nodes.insert(p_current);
+ }
+
+ if (p_current->get_class() != Spatial().get_class()) {
+ r_keep_nodes.insert(p_current);
+ }
+
+ for (int i = 0; i < p_current->get_child_count(); i++) {
+ _keep_node(p_path, p_current->get_child(i), p_owner, r_keep_nodes);
+ }
+}
+
+void EditorSceneImporterAssimp::_filter_node(const String &p_path, Node *p_current, Node *p_owner, const Set<Node *> p_keep_nodes, Set<String> &r_removed_nodes) {
+ if (p_keep_nodes.has(p_current) == false) {
+ r_removed_nodes.insert(p_current->get_name());
+ p_current->queue_delete();
+ }
+ for (int i = 0; i < p_current->get_child_count(); i++) {
+ _filter_node(p_path, p_current->get_child(i), p_owner, p_keep_nodes, r_removed_nodes);
+ }
+}
+
+void EditorSceneImporterAssimp::_generate_node(const String &p_path, const aiScene *p_scene, const aiNode *p_node, Node *p_parent, Node *p_owner, Set<String> &r_bone_name, Set<String> p_light_names, Set<String> p_camera_names, Map<Skeleton *, MeshInstance *> &r_skeletons, const Map<String, Transform> &p_bone_rests, Vector<MeshInstance *> &r_mesh_instances, int32_t &r_mesh_count, Skeleton *p_skeleton, const int32_t p_max_bone_weights, Set<String> &r_removed_bones, Map<String, Map<uint32_t, String> > &r_name_morph_mesh_names) {
+ Spatial *child_node = NULL;
+ if (p_node == NULL) {
+ return;
+ }
+ String node_name = _ai_string_to_string(p_node->mName);
+ real_t factor = 1.0f;
+ String ext = p_path.get_file().get_extension().to_lower();
+ if (ext == "fbx") {
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("UnitScaleFactor", factor);
+ factor = factor * 0.01f;
+ }
+ }
+ {
+ Transform xform = _ai_matrix_transform(p_node->mTransformation);
+
+ child_node = memnew(Spatial);
+ p_parent->add_child(child_node);
+ child_node->set_owner(p_owner);
+ if (p_node == p_scene->mRootNode) {
+ if ((ext == "fbx") && p_node == p_scene->mRootNode) {
+ xform = xform.scaled(Vector3(factor, factor, factor));
+ Transform format_xform = _format_rot_xform(p_path, p_scene);
+ xform = format_xform * xform;
+ }
+ }
+ child_node->set_transform(xform * child_node->get_transform());
+ }
+
+ if (p_node->mNumMeshes > 0) {
+ MeshInstance *mesh_node = memnew(MeshInstance);
+ p_parent->add_child(mesh_node);
+ mesh_node->set_owner(p_owner);
+ mesh_node->set_transform(child_node->get_transform());
+ {
+ Map<String, bool> mesh_bones;
+ p_skeleton->set_use_bones_in_world_transform(true);
+ _generate_node_bone(p_scene, p_node, mesh_bones, p_skeleton, p_path, p_max_bone_weights);
+ Set<String> tracks;
+ _get_track_set(p_scene, tracks);
+ aiNode *skeleton_root = NULL;
+ _calculate_skeleton_root(p_skeleton, p_scene, skeleton_root, mesh_bones, p_node);
+ _generate_node_bone_parents(p_scene, p_node, mesh_bones, p_skeleton, mesh_node);
+ if (p_skeleton->get_bone_count() > 0) {
+ _fill_skeleton(p_scene, skeleton_root, mesh_node, p_owner, p_skeleton, mesh_bones, p_bone_rests, tracks, p_path, r_removed_bones);
+ _set_bone_parent(p_skeleton, p_owner, p_scene->mRootNode);
+ }
+ MeshInstance *mi = Object::cast_to<MeshInstance>(mesh_node);
+ if (mi) {
+ r_mesh_instances.push_back(mi);
+ }
+ _add_mesh_to_mesh_instance(p_node, p_scene, p_skeleton, p_path, mesh_node, p_owner, r_bone_name, r_mesh_count, p_max_bone_weights, r_name_morph_mesh_names);
+ }
+ if (mesh_node != NULL && p_skeleton->get_bone_count() > 0 && p_owner->find_node(p_skeleton->get_name()) == NULL) {
+ Node *node = p_owner->find_node(_ai_string_to_string(p_scene->mRootNode->mName));
+ ERR_FAIL_COND(node == NULL);
+ node->add_child(p_skeleton);
+ p_skeleton->set_owner(p_owner);
+ if (ext == "fbx") {
+ Transform mesh_xform = _get_global_ai_node_transform(p_scene, p_node);
+ mesh_xform.origin = Vector3();
+ p_skeleton->set_transform(mesh_xform);
+ }
+ r_skeletons.insert(p_skeleton, mesh_node);
+ }
+ for (size_t i = 0; i < p_node->mNumMeshes; i++) {
+ if (p_scene->mMeshes[p_node->mMeshes[i]]->HasBones()) {
+ mesh_node->set_name(node_name);
+ // Meshes without skeletons must not have skeletons
+ mesh_node->set_skeleton_path(String(mesh_node->get_path_to(p_owner)) + "/" + p_owner->get_path_to(p_skeleton));
+ }
+ }
+ child_node->get_parent()->remove_child(child_node);
+ memdelete(child_node);
+ child_node = mesh_node;
+ } else if (p_light_names.has(node_name)) {
+ Spatial *light_node = Object::cast_to<Light>(p_owner->find_node(node_name));
+ ERR_FAIL_COND(light_node == NULL);
+ if (!p_parent->has_node(light_node->get_path())) {
+ p_parent->add_child(light_node);
+ }
+ light_node->set_owner(p_owner);
+ light_node->set_transform(child_node->get_transform().scaled(Vector3(factor, factor, factor)) *
+ light_node->get_transform().scaled(Vector3(factor, factor, factor)));
+ child_node->get_parent()->remove_child(child_node);
+ memdelete(child_node);
+ child_node = light_node;
+ } else if (p_camera_names.has(node_name)) {
+ Spatial *camera_node = Object::cast_to<Camera>(p_owner->find_node(node_name));
+ ERR_FAIL_COND(camera_node == NULL);
+ if (!p_parent->has_node(camera_node->get_path())) {
+ p_parent->add_child(camera_node);
+ }
+ camera_node->set_owner(p_owner);
+ camera_node->set_transform(child_node->get_transform().scaled(Vector3(factor, factor, factor)) *
+ camera_node->get_transform().scaled(Vector3(factor, factor, factor)));
+ camera_node->scale(Vector3(factor, factor, factor));
+ child_node->get_parent()->remove_child(child_node);
+ memdelete(child_node);
+ child_node = camera_node;
+ }
+ child_node->set_name(node_name);
+ for (size_t i = 0; i < p_node->mNumChildren; i++) {
+ _generate_node(p_path, p_scene, p_node->mChildren[i], child_node, p_owner, r_bone_name, p_light_names, p_camera_names, r_skeletons, p_bone_rests, r_mesh_instances, r_mesh_count, p_skeleton, p_max_bone_weights, r_removed_bones, r_name_morph_mesh_names);
+ }
+}
+
+aiNode *EditorSceneImporterAssimp::_ai_find_node(aiNode *ai_child_node, const String bone_name) {
+
+ if (_ai_string_to_string(ai_child_node->mName) == bone_name) {
+ return ai_child_node;
+ }
+ aiNode *target = NULL;
+ for (size_t i = 0; i < ai_child_node->mNumChildren; i++) {
+
+ target = _ai_find_node(ai_child_node->mChildren[i], bone_name);
+ if (target != NULL) {
+ return target;
+ }
+ }
+ return target;
+}
+
+Transform EditorSceneImporterAssimp::_format_rot_xform(const String p_path, const aiScene *p_scene) {
+ String ext = p_path.get_file().get_extension().to_lower();
+
+ Transform xform;
+ int32_t up_axis = 0;
+ Vector3 up_axis_vec3 = Vector3();
+
+ int32_t front_axis = 0;
+ Vector3 front_axis_vec3 = Vector3();
+
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("UpAxis", up_axis);
+ if (up_axis == AssetImportFbx::UP_VECTOR_AXIS_X) {
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("FrontAxis", front_axis);
+ if (front_axis == AssetImportFbx::FRONT_PARITY_EVEN) {
+ // y
+ } else if (front_axis == AssetImportFbx::FRONT_PARITY_ODD) {
+ // z
+ //front_axis_vec3 = Vector3(0.0f, Math::deg2rad(-180.f), 0.0f);
+ }
+ }
+ } else if (up_axis == AssetImportFbx::UP_VECTOR_AXIS_Y) {
+ up_axis_vec3 = Vector3(Math::deg2rad(-90.f), 0.0f, 0.0f);
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("FrontAxis", front_axis);
+ if (front_axis == AssetImportFbx::FRONT_PARITY_EVEN) {
+ // x
+ } else if (front_axis == AssetImportFbx::FRONT_PARITY_ODD) {
+ // z
+ }
+ }
+ } else if (up_axis == AssetImportFbx::UP_VECTOR_AXIS_Z) {
+ up_axis_vec3 = Vector3(0.0f, Math ::deg2rad(90.f), 0.0f);
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("FrontAxis", front_axis);
+ if (front_axis == AssetImportFbx::FRONT_PARITY_EVEN) {
+ // x
+ } else if (front_axis == AssetImportFbx::FRONT_PARITY_ODD) {
+ // y
+ }
+ }
+ }
+ }
+
+ int32_t up_axis_sign = 0;
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("UpAxisSign", up_axis_sign);
+ up_axis_vec3 = up_axis_vec3 * up_axis_sign;
+ }
+
+ int32_t front_axis_sign = 0;
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("FrontAxisSign", front_axis_sign);
+ front_axis_vec3 = front_axis_vec3 * front_axis_sign;
+ }
+
+ int32_t coord_axis = 0;
+ Vector3 coord_axis_vec3 = Vector3();
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("CoordAxis", coord_axis);
+ if (coord_axis == AssetImportFbx::COORD_LEFT) {
+ } else if (coord_axis == AssetImportFbx::COORD_RIGHT) {
+ }
+ }
+
+ int32_t coord_axis_sign = 0;
+ if (p_scene->mMetaData != NULL) {
+ p_scene->mMetaData->Get("CoordAxisSign", coord_axis_sign);
+ }
+
+ Quat up_quat;
+ up_quat.set_euler(up_axis_vec3);
+
+ Quat coord_quat;
+ coord_quat.set_euler(coord_axis_vec3);
+
+ Quat front_quat;
+ front_quat.set_euler(front_axis_vec3);
+
+ xform.basis.set_quat(up_quat * coord_quat * front_quat);
+ return xform;
+}
+
+void EditorSceneImporterAssimp::_get_track_set(const aiScene *p_scene, Set<String> &tracks) {
+ for (size_t i = 0; i < p_scene->mNumAnimations; i++) {
+ for (size_t j = 0; j < p_scene->mAnimations[i]->mNumChannels; j++) {
+ aiString ai_name = p_scene->mAnimations[i]->mChannels[j]->mNodeName;
+ String name = _ai_string_to_string(ai_name);
+ tracks.insert(name);
+ }
+ }
+}
+
+void EditorSceneImporterAssimp::_add_mesh_to_mesh_instance(const aiNode *p_node, const aiScene *p_scene, Skeleton *s, const String &p_path, MeshInstance *p_mesh_instance, Node *p_owner, Set<String> &r_bone_name, int32_t &r_mesh_count, int32_t p_max_bone_weights, Map<String, Map<uint32_t, String> > &r_name_morph_mesh_names) {
+ Ref<ArrayMesh> mesh;
+ mesh.instance();
+ bool has_uvs = false;
+ for (size_t i = 0; i < p_node->mNumMeshes; i++) {
+ const unsigned int mesh_idx = p_node->mMeshes[i];
+ const aiMesh *ai_mesh = p_scene->mMeshes[mesh_idx];
+
+ Map<uint32_t, Vector<float> > vertex_weight;
+ Map<uint32_t, Vector<String> > vertex_bone_name;
+ for (size_t b = 0; b < ai_mesh->mNumBones; b++) {
+ aiBone *bone = ai_mesh->mBones[b];
+ for (size_t w = 0; w < bone->mNumWeights; w++) {
+ String name = _ai_string_to_string(bone->mName);
+ aiVertexWeight ai_weights = bone->mWeights[w];
+ uint32_t vertexId = ai_weights.mVertexId;
+ Map<uint32_t, Vector<float> >::Element *result = vertex_weight.find(vertexId);
+ Vector<float> weights;
+ if (result != NULL) {
+ weights.append_array(result->value());
+ }
+ weights.push_back(ai_weights.mWeight);
+ if (vertex_weight.has(vertexId)) {
+ vertex_weight[vertexId] = weights;
+ } else {
+ vertex_weight.insert(vertexId, weights);
+ }
+ Map<uint32_t, Vector<String> >::Element *bone_result = vertex_bone_name.find(vertexId);
+ Vector<String> bone_names;
+ if (bone_result != NULL) {
+ bone_names.append_array(bone_result->value());
+ }
+ bone_names.push_back(name);
+ if (vertex_bone_name.has(vertexId)) {
+ vertex_bone_name[vertexId] = bone_names;
+ } else {
+ vertex_bone_name.insert(vertexId, bone_names);
+ }
+ }
+ }
+
+ Ref<SurfaceTool> st;
+ st.instance();
+ st->begin(Mesh::PRIMITIVE_TRIANGLES);
+
+ for (size_t j = 0; j < ai_mesh->mNumVertices; j++) {
+ if (ai_mesh->HasTextureCoords(0)) {
+ has_uvs = true;
+ st->add_uv(Vector2(ai_mesh->mTextureCoords[0][j].x, 1.0f - ai_mesh->mTextureCoords[0][j].y));
+ }
+ if (ai_mesh->HasTextureCoords(1)) {
+ has_uvs = true;
+ st->add_uv2(Vector2(ai_mesh->mTextureCoords[1][j].x, 1.0f - ai_mesh->mTextureCoords[1][j].y));
+ }
+ if (ai_mesh->HasVertexColors(0)) {
+ Color color = Color(ai_mesh->mColors[0]->r, ai_mesh->mColors[0]->g, ai_mesh->mColors[0]->b, ai_mesh->mColors[0]->a);
+ st->add_color(color);
+ }
+ if (ai_mesh->mNormals != NULL) {
+ const aiVector3D normals = ai_mesh->mNormals[j];
+ const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z);
+ st->add_normal(godot_normal);
+ if (ai_mesh->HasTangentsAndBitangents()) {
+ const aiVector3D tangents = ai_mesh->mTangents[j];
+ const Vector3 godot_tangent = Vector3(tangents.x, tangents.y, tangents.z);
+ const aiVector3D bitangent = ai_mesh->mBitangents[j];
+ const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z);
+ float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f;
+ st->add_tangent(Plane(tangents.x, tangents.y, tangents.z, d));
+ }
+ }
+
+ if (s != NULL && s->get_bone_count() > 0) {
+ Map<uint32_t, Vector<String> >::Element *I = vertex_bone_name.find(j);
+ Vector<int32_t> bones;
+ if (I != NULL) {
+ Vector<String> bone_names;
+ bone_names.append_array(I->value());
+ for (int32_t f = 0; f < bone_names.size(); f++) {
+ int32_t bone = s->find_bone(bone_names[f]);
+ ERR_EXPLAIN("Asset Importer: Mesh can't find bone " + bone_names[f]);
+ ERR_FAIL_COND(bone == -1);
+ bones.push_back(bone);
+ }
+ if (s->get_bone_count()) {
+ int32_t add = CLAMP(p_max_bone_weights - bones.size(), 0, p_max_bone_weights);
+ for (int32_t f = 0; f < add; f++) {
+ bones.push_back(0);
+ }
+ }
+ st->add_bones(bones);
+ Map<uint32_t, Vector<float> >::Element *E = vertex_weight.find(j);
+ Vector<float> weights;
+ if (E != NULL) {
+ weights = E->value();
+ if (weights.size() != p_max_bone_weights) {
+ int32_t add = CLAMP(p_max_bone_weights - weights.size(), 0, p_max_bone_weights);
+ for (int32_t f = 0; f < add; f++) {
+ weights.push_back(0.0f);
+ }
+ }
+ }
+ ERR_CONTINUE(weights.size() == 0);
+ st->add_weights(weights);
+ }
+ }
+ const aiVector3D pos = ai_mesh->mVertices[j];
+ Vector3 godot_pos = Vector3(pos.x, pos.y, pos.z);
+ st->add_vertex(godot_pos);
+ }
+ for (size_t j = 0; j < ai_mesh->mNumFaces; j++) {
+ const aiFace face = ai_mesh->mFaces[j];
+ ERR_FAIL_COND(face.mNumIndices != 3);
+ Vector<size_t> order;
+ order.push_back(2);
+ order.push_back(1);
+ order.push_back(0);
+ for (int32_t k = 0; k < order.size(); k++) {
+ st->add_index(face.mIndices[order[k]]);
+ }
+ }
+ if (ai_mesh->HasTangentsAndBitangents() == false && has_uvs) {
+ st->generate_tangents();
+ }
+ aiMaterial *ai_material = p_scene->mMaterials[ai_mesh->mMaterialIndex];
+ Ref<SpatialMaterial> mat;
+ mat.instance();
+
+ int32_t mat_two_sided = 0;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_TWOSIDED, mat_two_sided)) {
+ if (mat_two_sided > 0) {
+ mat->set_cull_mode(SpatialMaterial::CULL_DISABLED);
+ }
+ }
+
+ const String mesh_name = _ai_string_to_string(ai_mesh->mName);
+ aiString mat_name;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_NAME, mat_name)) {
+ mat->set_name(_ai_string_to_string(mat_name));
+ }
+
+ aiTextureType tex_normal = aiTextureType_NORMALS;
+ {
+ aiString ai_filename = aiString();
+ String filename = "";
+ aiTextureMapMode map_mode[2];
+
+ if (AI_SUCCESS == ai_material->GetTexture(tex_normal, 0, &ai_filename, NULL, NULL, NULL, NULL, map_mode)) {
+ filename = _ai_raw_string_to_string(ai_filename);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+
+ if (texture != NULL) {
+ if (map_mode != NULL) {
+ _set_texture_mapping_mode(map_mode, texture);
+ }
+ mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
+ }
+ }
+ }
+ }
+
+ {
+ aiString ai_filename = aiString();
+ String filename = "";
+
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_NORMAL_TEXTURE, ai_filename)) {
+ filename = _ai_raw_string_to_string(ai_filename);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
+ }
+ }
+ }
+ }
+
+ aiTextureType tex_emissive = aiTextureType_EMISSIVE;
+
+ if (ai_material->GetTextureCount(tex_emissive) > 0) {
+
+ aiString ai_filename = aiString();
+ String filename = "";
+ aiTextureMapMode map_mode[2];
+
+ if (AI_SUCCESS == ai_material->GetTexture(tex_emissive, 0, &ai_filename, NULL, NULL, NULL, NULL, map_mode)) {
+ filename = _ai_raw_string_to_string(ai_filename);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ _set_texture_mapping_mode(map_mode, texture);
+ mat->set_feature(SpatialMaterial::FEATURE_EMISSION, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_EMISSION, texture);
+ }
+ }
+ }
+ }
+
+ aiTextureType tex_albedo = aiTextureType_DIFFUSE;
+ if (ai_material->GetTextureCount(tex_albedo) > 0) {
+
+ aiString ai_filename = aiString();
+ String filename = "";
+ aiTextureMapMode map_mode[2];
+ if (AI_SUCCESS == ai_material->GetTexture(tex_albedo, 0, &ai_filename, NULL, NULL, NULL, NULL, map_mode)) {
+ filename = _ai_raw_string_to_string(ai_filename);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ if (texture->get_data()->detect_alpha() != Image::ALPHA_NONE) {
+ _set_texture_mapping_mode(map_mode, texture);
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ }
+ mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
+ }
+ }
+ }
+ } else {
+ aiColor4D clr_diffuse;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_COLOR_DIFFUSE, clr_diffuse)) {
+ if (Math::is_equal_approx(clr_diffuse.a, 1.0f) == false) {
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ }
+ mat->set_albedo(Color(clr_diffuse.r, clr_diffuse.g, clr_diffuse.b, clr_diffuse.a));
+ }
+ }
+
+ aiString tex_gltf_base_color_path = aiString();
+ aiTextureMapMode map_mode[2];
+ if (AI_SUCCESS == ai_material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE, &tex_gltf_base_color_path, NULL, NULL, NULL, NULL, map_mode)) {
+ String filename = _ai_raw_string_to_string(tex_gltf_base_color_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ _find_texture_path(p_path, path, found);
+ if (texture != NULL) {
+ if (texture->get_data()->detect_alpha() == Image::ALPHA_BLEND) {
+ _set_texture_mapping_mode(map_mode, texture);
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ }
+ mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
+ }
+ }
+ } else {
+ aiColor4D pbr_base_color;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR, pbr_base_color)) {
+ if (Math::is_equal_approx(pbr_base_color.a, 1.0f) == false) {
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ }
+ mat->set_albedo(Color(pbr_base_color.r, pbr_base_color.g, pbr_base_color.b, pbr_base_color.a));
+ }
+ }
+ {
+ aiString tex_fbx_pbs_base_color_path = aiString();
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_BASE_COLOR_TEXTURE, tex_fbx_pbs_base_color_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_base_color_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ _find_texture_path(p_path, path, found);
+ if (texture != NULL) {
+ if (texture->get_data()->detect_alpha() == Image::ALPHA_BLEND) {
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ }
+ mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
+ }
+ }
+ } else {
+ aiColor4D pbr_base_color;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_BASE_COLOR_FACTOR, pbr_base_color)) {
+ mat->set_albedo(Color(pbr_base_color.r, pbr_base_color.g, pbr_base_color.b, pbr_base_color.a));
+ }
+ }
+
+ aiUVTransform pbr_base_color_uv_xform;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_BASE_COLOR_UV_XFORM, pbr_base_color_uv_xform)) {
+ mat->set_uv1_offset(Vector3(pbr_base_color_uv_xform.mTranslation.x, pbr_base_color_uv_xform.mTranslation.y, 0.0f));
+ mat->set_uv1_scale(Vector3(pbr_base_color_uv_xform.mScaling.x, pbr_base_color_uv_xform.mScaling.y, 1.0f));
+ }
+ }
+
+ {
+ aiString tex_fbx_pbs_normal_path = aiString();
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_NORMAL_TEXTURE, tex_fbx_pbs_normal_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_normal_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ _find_texture_path(p_path, path, found);
+ if (texture != NULL) {
+ mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
+ }
+ }
+ }
+ }
+
+ aiString cull_mode;
+ if (p_node->mMetaData) {
+ p_node->mMetaData->Get("Culling", cull_mode);
+ }
+ if (cull_mode.length != 0 && cull_mode == aiString("CullingOff")) {
+ mat->set_cull_mode(SpatialMaterial::CULL_DISABLED);
+ }
+
+ {
+ aiString tex_fbx_stingray_normal_path = aiString();
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_NORMAL_TEXTURE, tex_fbx_stingray_normal_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_stingray_normal_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ _find_texture_path(p_path, path, found);
+ if (texture != NULL) {
+ mat->set_feature(SpatialMaterial::Feature::FEATURE_NORMAL_MAPPING, true);
+ mat->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
+ }
+ }
+ }
+ }
+
+ {
+ aiString tex_fbx_pbs_base_color_path = aiString();
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_TEXTURE, tex_fbx_pbs_base_color_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_base_color_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ _find_texture_path(p_path, path, found);
+ if (texture != NULL) {
+ if (texture->get_data()->detect_alpha() == Image::ALPHA_BLEND) {
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ }
+ mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
+ }
+ }
+ } else {
+ aiColor4D pbr_base_color;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_BASE_COLOR_FACTOR, pbr_base_color)) {
+ mat->set_albedo(Color(pbr_base_color.r, pbr_base_color.g, pbr_base_color.b, pbr_base_color.a));
+ }
+ }
+
+ aiUVTransform pbr_base_color_uv_xform;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_UV_XFORM, pbr_base_color_uv_xform)) {
+ mat->set_uv1_offset(Vector3(pbr_base_color_uv_xform.mTranslation.x, pbr_base_color_uv_xform.mTranslation.y, 0.0f));
+ mat->set_uv1_scale(Vector3(pbr_base_color_uv_xform.mScaling.x, pbr_base_color_uv_xform.mScaling.y, 1.0f));
+ }
+ }
+
+ {
+ aiString tex_fbx_pbs_emissive_path = aiString();
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_TEXTURE, tex_fbx_pbs_emissive_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_emissive_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ _find_texture_path(p_path, path, found);
+ if (texture != NULL) {
+ if (texture->get_data()->detect_alpha() == Image::ALPHA_BLEND) {
+ mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
+ mat->set_depth_draw_mode(SpatialMaterial::DepthDrawMode::DEPTH_DRAW_ALPHA_OPAQUE_PREPASS);
+ }
+ mat->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
+ }
+ }
+ } else {
+ aiColor4D pbr_emmissive_color;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_FACTOR, pbr_emmissive_color)) {
+ mat->set_emission(Color(pbr_emmissive_color.r, pbr_emmissive_color.g, pbr_emmissive_color.b, pbr_emmissive_color.a));
+ }
+ }
+
+ real_t pbr_emission_intensity;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_INTENSITY_FACTOR, pbr_emission_intensity)) {
+ mat->set_emission_energy(pbr_emission_intensity);
+ }
+ }
+
+ aiString tex_gltf_pbr_metallicroughness_path;
+ if (AI_SUCCESS == ai_material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &tex_gltf_pbr_metallicroughness_path)) {
+ String filename = _ai_raw_string_to_string(tex_gltf_pbr_metallicroughness_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ mat->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture);
+ mat->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_BLUE);
+ mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, texture);
+ mat->set_roughness_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GREEN);
+ }
+ }
+ } else {
+ float pbr_roughness = 0.0f;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, pbr_roughness)) {
+ mat->set_roughness(pbr_roughness);
+ }
+ float pbr_metallic = 0.0f;
+
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, pbr_metallic)) {
+ mat->set_metallic(pbr_metallic);
+ }
+ }
+ {
+ aiString tex_fbx_pbs_metallic_path;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_TEXTURE, tex_fbx_pbs_metallic_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_metallic_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ mat->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture);
+ mat->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GRAYSCALE);
+ }
+ }
+ } else {
+ float pbr_metallic = 0.0f;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_FACTOR, pbr_metallic)) {
+ mat->set_metallic(pbr_metallic);
+ }
+ }
+
+ aiString tex_fbx_pbs_rough_path;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_TEXTURE, tex_fbx_pbs_rough_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_rough_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, texture);
+ mat->set_roughness_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GRAYSCALE);
+ }
+ }
+ } else {
+ float pbr_roughness = 0.04f;
+
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_FACTOR, pbr_roughness)) {
+ mat->set_roughness(pbr_roughness);
+ }
+ }
+ }
+
+ {
+ aiString tex_fbx_pbs_metallic_path;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_METALNESS_TEXTURE, tex_fbx_pbs_metallic_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_metallic_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ mat->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture);
+ mat->set_metallic_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GRAYSCALE);
+ }
+ }
+ } else {
+ float pbr_metallic = 0.0f;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_METALNESS_FACTOR, pbr_metallic)) {
+ mat->set_metallic(pbr_metallic);
+ }
+ }
+
+ aiString tex_fbx_pbs_rough_path;
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_TEXTURE, tex_fbx_pbs_rough_path)) {
+ String filename = _ai_raw_string_to_string(tex_fbx_pbs_rough_path);
+ String path = p_path.get_base_dir() + "/" + filename.replace("\\", "/");
+ bool found = false;
+ _find_texture_path(p_path, path, found);
+ if (found) {
+ Ref<Texture> texture = _load_texture(p_scene, path);
+ if (texture != NULL) {
+ mat->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, texture);
+ mat->set_roughness_texture_channel(SpatialMaterial::TEXTURE_CHANNEL_GRAYSCALE);
+ }
+ }
+ } else {
+ float pbr_roughness = 0.04f;
+
+ if (AI_SUCCESS == ai_material->Get(AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_FACTOR, pbr_roughness)) {
+ mat->set_roughness(pbr_roughness);
+ }
+ }
+ }
+
+ Array array_mesh = st->commit_to_arrays();
+ Array morphs;
+ morphs.resize(ai_mesh->mNumAnimMeshes);
+ Mesh::PrimitiveType primitive = Mesh::PRIMITIVE_TRIANGLES;
+ Map<uint32_t, String> morph_mesh_idx_names;
+ for (size_t j = 0; j < ai_mesh->mNumAnimMeshes; j++) {
+
+ String ai_anim_mesh_name = _ai_string_to_string(ai_mesh->mAnimMeshes[j]->mName);
+ mesh->set_blend_shape_mode(Mesh::BLEND_SHAPE_MODE_NORMALIZED);
+ if (ai_anim_mesh_name.empty()) {
+ ai_anim_mesh_name = String("morph_") + itos(j);
+ }
+ mesh->add_blend_shape(ai_anim_mesh_name);
+ morph_mesh_idx_names.insert(j, ai_anim_mesh_name);
+ Array array_copy;
+ array_copy.resize(VisualServer::ARRAY_MAX);
+
+ for (int l = 0; l < VisualServer::ARRAY_MAX; l++) {
+ array_copy[l] = array_mesh[l].duplicate(true);
+ }
+
+ const size_t num_vertices = ai_mesh->mAnimMeshes[j]->mNumVertices;
+ array_copy[Mesh::ARRAY_INDEX] = Variant();
+ if (ai_mesh->mAnimMeshes[j]->HasPositions()) {
+ PoolVector3Array vertices;
+ vertices.resize(num_vertices);
+ for (size_t l = 0; l < num_vertices; l++) {
+ const aiVector3D ai_pos = ai_mesh->mAnimMeshes[j]->mVertices[l];
+ Vector3 position = Vector3(ai_pos.x, ai_pos.y, ai_pos.z);
+ vertices.write()[l] = position;
+ }
+ PoolVector3Array new_vertices = array_copy[VisualServer::ARRAY_VERTEX].duplicate(true);
+
+ for (int32_t l = 0; l < vertices.size(); l++) {
+ PoolVector3Array::Write w = new_vertices.write();
+ w[l] = vertices[l];
+ }
+ ERR_CONTINUE(vertices.size() != new_vertices.size());
+ array_copy[VisualServer::ARRAY_VERTEX] = new_vertices;
+ }
+
+ int32_t color_set = 0;
+ if (ai_mesh->mAnimMeshes[j]->HasVertexColors(color_set)) {
+ PoolColorArray colors;
+ colors.resize(num_vertices);
+ for (size_t l = 0; l < num_vertices; l++) {
+ const aiColor4D ai_color = ai_mesh->mAnimMeshes[j]->mColors[color_set][l];
+ Color color = Color(ai_color.r, ai_color.g, ai_color.b, ai_color.a);
+ colors.write()[l] = color;
+ }
+ PoolColorArray new_colors = array_copy[VisualServer::ARRAY_COLOR].duplicate(true);
+
+ for (int32_t l = 0; l < colors.size(); l++) {
+ PoolColorArray::Write w = new_colors.write();
+ w[l] = colors[l];
+ }
+ array_copy[VisualServer::ARRAY_COLOR] = new_colors;
+ }
+
+ if (ai_mesh->mAnimMeshes[j]->HasNormals()) {
+ PoolVector3Array normals;
+ normals.resize(num_vertices);
+ for (size_t l = 0; l < num_vertices; l++) {
+ const aiVector3D ai_normal = ai_mesh->mAnimMeshes[i]->mNormals[l];
+ Vector3 normal = Vector3(ai_normal.x, ai_normal.y, ai_normal.z);
+ normals.write()[l] = normal;
+ }
+ PoolVector3Array new_normals = array_copy[VisualServer::ARRAY_NORMAL].duplicate(true);
+
+ for (int l = 0; l < normals.size(); l++) {
+ PoolVector3Array::Write w = new_normals.write();
+ w[l] = normals[l];
+ }
+ array_copy[VisualServer::ARRAY_NORMAL] = new_normals;
+ }
+
+ if (ai_mesh->mAnimMeshes[j]->HasTangentsAndBitangents()) {
+ PoolColorArray tangents;
+ tangents.resize(num_vertices);
+ PoolColorArray::Write w = tangents.write();
+ for (size_t l = 0; l < num_vertices; l++) {
+ _calc_tangent_from_mesh(ai_mesh, j, l, l, w);
+ }
+ PoolRealArray new_tangents = array_copy[VisualServer::ARRAY_TANGENT].duplicate(true);
+ ERR_CONTINUE(new_tangents.size() != tangents.size() * 4);
+ for (int32_t l = 0; l < tangents.size(); l++) {
+ new_tangents.write()[l + 0] = tangents[l].r;
+ new_tangents.write()[l + 1] = tangents[l].g;
+ new_tangents.write()[l + 2] = tangents[l].b;
+ new_tangents.write()[l + 3] = tangents[l].a;
+ }
+
+ array_copy[VisualServer::ARRAY_TANGENT] = new_tangents;
+ }
+
+ morphs[j] = array_copy;
+ }
+ r_name_morph_mesh_names.insert(_ai_string_to_string(p_node->mName), morph_mesh_idx_names);
+ mesh->add_surface_from_arrays(primitive, array_mesh, morphs);
+ mesh->surface_set_material(i, mat);
+ mesh->surface_set_name(i, _ai_string_to_string(ai_mesh->mName));
+ r_mesh_count++;
+ print_line(String("Open Asset Import: Created mesh (including instances) ") + _ai_string_to_string(ai_mesh->mName) + " " + itos(r_mesh_count) + " of " + itos(p_scene->mNumMeshes));
+ }
+ p_mesh_instance->set_mesh(mesh);
+}
+
+Ref<Texture> EditorSceneImporterAssimp::_load_texture(const aiScene *p_scene, String p_path) {
+ Vector<String> split_path = p_path.get_basename().split("*");
+ if (split_path.size() == 2) {
+ size_t texture_idx = split_path[1].to_int();
+ ERR_FAIL_COND_V(texture_idx >= p_scene->mNumTextures, Ref<Texture>());
+ aiTexture *tex = p_scene->mTextures[texture_idx];
+ String filename = _ai_raw_string_to_string(tex->mFilename);
+ filename = filename.get_file();
+ print_verbose("Open Asset Import: Loading embedded texture " + filename);
+ if (tex->mHeight == 0) {
+ if (tex->CheckFormat("png")) {
+ Ref<Image> img = Image::_png_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth);
+ ERR_FAIL_COND_V(img.is_null(), Ref<Texture>());
+
+ Ref<ImageTexture> t;
+ t.instance();
+ t->create_from_image(img);
+ t->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
+ return t;
+ } else if (tex->CheckFormat("jpg")) {
+ Ref<Image> img = Image::_jpg_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth);
+ ERR_FAIL_COND_V(img.is_null(), Ref<Texture>());
+ Ref<ImageTexture> t;
+ t.instance();
+ t->create_from_image(img);
+ t->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
+ return t;
+ } else if (tex->CheckFormat("dds")) {
+ ERR_EXPLAIN("Open Asset Import: Embedded dds not implemented");
+ ERR_FAIL_COND_V(true, Ref<Texture>());
+ //Ref<Image> img = Image::_dds_mem_loader_func((uint8_t *)tex->pcData, tex->mWidth);
+ //ERR_FAIL_COND_V(img.is_null(), Ref<Texture>());
+ //Ref<ImageTexture> t;
+ //t.instance();
+ //t->create_from_image(img);
+ //t->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
+ //return t;
+ }
+ } else {
+ Ref<Image> img;
+ img.instance();
+ PoolByteArray arr;
+ uint32_t size = tex->mWidth * tex->mHeight;
+ arr.resize(size);
+ memcpy(arr.write().ptr(), tex->pcData, size);
+ ERR_FAIL_COND_V(arr.size() % 4 != 0, Ref<Texture>());
+ //ARGB8888 to RGBA8888
+ for (int32_t i = 0; i < arr.size() / 4; i++) {
+ arr.write().ptr()[(4 * i) + 3] = arr[(4 * i) + 0];
+ arr.write().ptr()[(4 * i) + 0] = arr[(4 * i) + 1];
+ arr.write().ptr()[(4 * i) + 1] = arr[(4 * i) + 2];
+ arr.write().ptr()[(4 * i) + 2] = arr[(4 * i) + 3];
+ }
+ img->create(tex->mWidth, tex->mHeight, true, Image::FORMAT_RGBA8, arr);
+ ERR_FAIL_COND_V(img.is_null(), Ref<Texture>());
+
+ Ref<ImageTexture> t;
+ t.instance();
+ t->create_from_image(img);
+ t->set_storage(ImageTexture::STORAGE_COMPRESS_LOSSY);
+ return t;
+ }
+ return Ref<Texture>();
+ }
+ Ref<Texture> p_texture = ResourceLoader::load(p_path, "Texture");
+ return p_texture;
+}
+
+void EditorSceneImporterAssimp::_calc_tangent_from_mesh(const aiMesh *ai_mesh, int i, int tri_index, int index, PoolColorArray::Write &w) {
+ const aiVector3D normals = ai_mesh->mAnimMeshes[i]->mNormals[tri_index];
+ const Vector3 godot_normal = Vector3(normals.x, normals.y, normals.z);
+ const aiVector3D tangent = ai_mesh->mAnimMeshes[i]->mTangents[tri_index];
+ const Vector3 godot_tangent = Vector3(tangent.x, tangent.y, tangent.z);
+ const aiVector3D bitangent = ai_mesh->mAnimMeshes[i]->mBitangents[tri_index];
+ const Vector3 godot_bitangent = Vector3(bitangent.x, bitangent.y, bitangent.z);
+ float d = godot_normal.cross(godot_tangent).dot(godot_bitangent) > 0.0f ? 1.0f : -1.0f;
+ Color plane_tangent = Color(tangent.x, tangent.y, tangent.z, d);
+ w[index] = plane_tangent;
+}
+
+void EditorSceneImporterAssimp::_set_texture_mapping_mode(aiTextureMapMode *map_mode, Ref<Texture> texture) {
+ ERR_FAIL_COND(map_mode == NULL);
+ aiTextureMapMode tex_mode = aiTextureMapMode::aiTextureMapMode_Wrap;
+ //for (size_t i = 0; i < 3; i++) {
+ tex_mode = map_mode[0];
+ //}
+ int32_t flags = Texture::FLAGS_DEFAULT;
+ if (tex_mode == aiTextureMapMode_Wrap) {
+ //Default
+ } else if (tex_mode == aiTextureMapMode_Clamp) {
+ flags = flags & ~Texture::FLAG_REPEAT;
+ } else if (tex_mode == aiTextureMapMode_Mirror) {
+ flags = flags | Texture::FLAG_MIRRORED_REPEAT;
+ }
+ texture->set_flags(flags);
+}
+
+void EditorSceneImporterAssimp::_find_texture_path(const String &r_p_path, String &r_path, bool &r_found) {
+
+ _Directory dir;
+
+ List<String> exts;
+ ImageLoader::get_recognized_extensions(&exts);
+
+ Vector<String> split_path = r_path.get_basename().split("*");
+ if (split_path.size() == 2) {
+ r_found = true;
+ return;
+ }
+
+ if (dir.file_exists(r_p_path.get_base_dir() + r_path.get_file())) {
+ r_path = r_p_path.get_base_dir() + r_path.get_file();
+ r_found = true;
+ return;
+ }
+
+ for (int32_t i = 0; i < exts.size(); i++) {
+ if (r_found) {
+ return;
+ }
+ if (r_found == false) {
+ _find_texture_path(r_p_path, dir, r_path, r_found, "." + exts[i]);
+ }
+ }
+}
+
+void EditorSceneImporterAssimp::_find_texture_path(const String &p_path, _Directory &dir, String &path, bool &found, String extension) {
+ String name = path.get_basename() + extension;
+ if (dir.file_exists(name)) {
+ found = true;
+ path = name;
+ return;
+ }
+ String name_ignore_sub_directory = p_path.get_base_dir() + "/" + path.get_file().get_basename() + extension;
+ if (dir.file_exists(name_ignore_sub_directory)) {
+ found = true;
+ path = name_ignore_sub_directory;
+ return;
+ }
+
+ String name_find_texture_sub_directory = p_path.get_base_dir() + "/textures/" + path.get_file().get_basename() + extension;
+ if (dir.file_exists(name_find_texture_sub_directory)) {
+ found = true;
+ path = name_find_texture_sub_directory;
+ return;
+ }
+ String name_find_texture_upper_sub_directory = p_path.get_base_dir() + "/Textures/" + path.get_file().get_basename() + extension;
+ if (dir.file_exists(name_find_texture_upper_sub_directory)) {
+ found = true;
+ path = name_find_texture_upper_sub_directory;
+ return;
+ }
+ String name_find_texture_outside_sub_directory = p_path.get_base_dir() + "/../textures/" + path.get_file().get_basename() + extension;
+ if (dir.file_exists(name_find_texture_outside_sub_directory)) {
+ found = true;
+ path = name_find_texture_outside_sub_directory;
+ return;
+ }
+
+ String name_find_upper_texture_outside_sub_directory = p_path.get_base_dir() + "/../Textures/" + path.get_file().get_basename() + extension;
+ if (dir.file_exists(name_find_upper_texture_outside_sub_directory)) {
+ found = true;
+ path = name_find_upper_texture_outside_sub_directory;
+ return;
+ }
+}
+
+String EditorSceneImporterAssimp::_ai_string_to_string(const aiString p_string) const {
+ Vector<char> raw_name;
+ raw_name.resize(p_string.length);
+ memcpy(raw_name.ptrw(), p_string.C_Str(), p_string.length);
+ String name;
+ name.parse_utf8(raw_name.ptrw(), raw_name.size());
+ if (name.find(":") != -1) {
+ String replaced_name = name.split(":")[1];
+ print_verbose("Replacing " + name + " containing : with " + replaced_name);
+ name = replaced_name;
+ }
+ if (name.find(".") != -1) {
+ String replaced_name = name.replace(".", "");
+ print_verbose("Replacing " + name + " containing . with " + replaced_name);
+ name = replaced_name;
+ }
+ return name;
+}
+
+String EditorSceneImporterAssimp::_ai_anim_string_to_string(const aiString p_string) const {
+ Vector<char> raw_name;
+ raw_name.resize(p_string.length);
+ memcpy(raw_name.ptrw(), p_string.C_Str(), p_string.length);
+ String name;
+ name.parse_utf8(raw_name.ptrw(), raw_name.size());
+ if (name.find(":") != -1) {
+ String replaced_name = name.split(":")[1];
+ print_verbose("Replacing " + name + " containing : with " + replaced_name);
+ name = replaced_name;
+ }
+ return name;
+}
+
+String EditorSceneImporterAssimp::_ai_raw_string_to_string(const aiString p_string) const {
+ Vector<char> raw_name;
+ raw_name.resize(p_string.length);
+ memcpy(raw_name.ptrw(), p_string.C_Str(), p_string.length);
+ String name;
+ name.parse_utf8(raw_name.ptrw(), raw_name.size());
+ return name;
+}
+
+Ref<Animation> EditorSceneImporterAssimp::import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps) {
+ return Ref<Animation>();
+}
+
+const Transform EditorSceneImporterAssimp::_ai_matrix_transform(const aiMatrix4x4 p_matrix) {
+ aiMatrix4x4 matrix = p_matrix;
+ Transform xform;
+ xform.set(matrix.a1, matrix.b1, matrix.c1, matrix.a2, matrix.b2, matrix.c2, matrix.a3, matrix.b3, matrix.c3, matrix.a4, matrix.b4, matrix.c4);
+ xform.basis.inverse();
+ xform.basis.transpose();
+ Vector3 scale = xform.basis.get_scale();
+ Quat rot = xform.basis.get_rotation_quat();
+ xform.basis.set_quat_scale(rot, scale);
+ return xform;
+}
diff --git a/modules/assimp/editor_scene_importer_assimp.h b/modules/assimp/editor_scene_importer_assimp.h
new file mode 100644
index 0000000000..8f9ed434ae
--- /dev/null
+++ b/modules/assimp/editor_scene_importer_assimp.h
@@ -0,0 +1,206 @@
+/*************************************************************************/
+/* editor_scene_importer_assimp.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 EDITOR_SCENE_IMPORTER_ASSIMP_H
+#define EDITOR_SCENE_IMPORTER_ASSIMP_H
+
+#ifdef TOOLS_ENABLED
+#include "core/bind/core_bind.h"
+#include "core/io/resource_importer.h"
+#include "core/vector.h"
+#include "editor/import/resource_importer_scene.h"
+#include "editor/project_settings_editor.h"
+#include "scene/3d/mesh_instance.h"
+#include "scene/3d/skeleton.h"
+#include "scene/3d/spatial.h"
+#include "scene/animation/animation_player.h"
+#include "scene/resources/animation.h"
+#include "scene/resources/surface_tool.h"
+
+#include "assimp/DefaultLogger.hpp"
+#include "assimp/LogStream.hpp"
+#include "assimp/Logger.hpp"
+#include "assimp/matrix4x4.h"
+#include "assimp/scene.h"
+#include "assimp/types.h"
+
+class AssimpStream : public Assimp::LogStream {
+public:
+ // Constructor
+ AssimpStream();
+
+ // Destructor
+ ~AssimpStream();
+ // Write something using your own functionality
+ void write(const char *message);
+};
+
+#define AI_MATKEY_FBX_MAYA_BASE_COLOR_FACTOR "$raw.Maya|baseColor", 0, 0
+#define AI_MATKEY_FBX_MAYA_METALNESS_FACTOR "$raw.Maya|metalness", 0, 0
+#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_FACTOR "$raw.Maya|diffuseRoughness", 0, 0
+
+#define AI_MATKEY_FBX_MAYA_METALNESS_TEXTURE "$raw.Maya|metalness|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_METALNESS_UV_XFORM "$raw.Maya|metalness|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_TEXTURE "$raw.Maya|diffuseRoughness|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_DIFFUSE_ROUGHNESS_UV_XFORM "$raw.Maya|diffuseRoughness|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_BASE_COLOR_TEXTURE "$raw.Maya|baseColor|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_BASE_COLOR_UV_XFORM "$raw.Maya|baseColor|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_NORMAL_TEXTURE "$raw.Maya|normalCamera|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_NORMAL_UV_XFORM "$raw.Maya|normalCamera|uvtrafo", aiTextureType_UNKNOWN, 0
+
+#define AI_MATKEY_FBX_NORMAL_TEXTURE "$raw.Maya|normalCamera|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_NORMAL_UV_XFORM "$raw.Maya|normalCamera|uvtrafo", aiTextureType_UNKNOWN, 0
+
+#define AI_MATKEY_FBX_MAYA_STINGRAY_DISPLACEMENT_SCALING_FACTOR "$raw.Maya|displacementscaling", 0, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_BASE_COLOR_FACTOR "$raw.Maya|base_color", 0, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_FACTOR "$raw.Maya|emissive", 0, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_FACTOR "$raw.Maya|metallic", 0, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_FACTOR "$raw.Maya|roughness", 0, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_INTENSITY_FACTOR "$raw.Maya|emissive_intensity", 0, 0
+
+#define AI_MATKEY_FBX_MAYA_STINGRAY_NORMAL_TEXTURE "$raw.Maya|TEX_normal_map|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_NORMAL_UV_XFORM "$raw.Maya|TEX_normal_map|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_TEXTURE "$raw.Maya|TEX_color_map|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_COLOR_UV_XFORM "$raw.Maya|TEX_color_map|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_TEXTURE "$raw.Maya|TEX_metallic_map|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_METALLIC_UV_XFORM "$raw.Maya|TEX_metallic_map|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_TEXTURE "$raw.Maya|TEX_roughness_map|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_ROUGHNESS_UV_XFORM "$raw.Maya|TEX_roughness_map|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_TEXTURE "$raw.Maya|TEX_emissive_map|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_EMISSIVE_UV_XFORM "$raw.Maya|TEX_emissive_map|uvtrafo", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_AO_TEXTURE "$raw.Maya|TEX_ao_map|file", aiTextureType_UNKNOWN, 0
+#define AI_MATKEY_FBX_MAYA_STINGRAY_AO_UV_XFORM "$raw.Maya|TEX_ao_map|uvtrafo", aiTextureType_UNKNOWN, 0
+
+class EditorSceneImporterAssimp : public EditorSceneImporter {
+private:
+ GDCLASS(EditorSceneImporterAssimp, EditorSceneImporter);
+ const String ASSIMP_FBX_KEY = "_$AssimpFbx$";
+
+ struct AssetImportAnimation {
+ enum Interpolation {
+ INTERP_LINEAR,
+ INTERP_STEP,
+ INTERP_CATMULLROMSPLINE,
+ INTERP_CUBIC_SPLINE
+ };
+ };
+
+ struct AssetImportFbx {
+ enum ETimeMode {
+ TIME_MODE_DEFAULT = 0,
+ TIME_MODE_120 = 1,
+ TIME_MODE_100 = 2,
+ TIME_MODE_60 = 3,
+ TIME_MODE_50 = 4,
+ TIME_MODE_48 = 5,
+ TIME_MODE_30 = 6,
+ TIME_MODE_30_DROP = 7,
+ TIME_MODE_NTSC_DROP_FRAME = 8,
+ TIME_MODE_NTSC_FULL_FRAME = 9,
+ TIME_MODE_PAL = 10,
+ TIME_MODE_CINEMA = 11,
+ TIME_MODE_1000 = 12,
+ TIME_MODE_CINEMA_ND = 13,
+ TIME_MODE_CUSTOM = 14,
+ TIME_MODE_TIME_MODE_COUNT = 15
+ };
+ enum UpAxis {
+ UP_VECTOR_AXIS_X = 1,
+ UP_VECTOR_AXIS_Y = 2,
+ UP_VECTOR_AXIS_Z = 3
+ };
+ enum FrontAxis {
+ FRONT_PARITY_EVEN = 1,
+ FRONT_PARITY_ODD = 2,
+ };
+
+ enum CoordAxis {
+ COORD_RIGHT = 0,
+ COORD_LEFT = 1
+ };
+ };
+ Spatial *_generate_scene(const String &p_path, const aiScene *scene, const uint32_t p_flags, int p_bake_fps, const int32_t p_max_bone_weights);
+ void _fill_kept_node(Set<Node *> &keep_nodes);
+ String _find_skeleton_bone_root(Map<Skeleton *, MeshInstance *> &skeletons, Map<MeshInstance *, String> &meshes, Spatial *root);
+ void _set_bone_parent(Skeleton *s, Node *p_owner, aiNode *p_node);
+ Transform _get_global_ai_node_transform(const aiScene *p_scene, const aiNode *p_current_node);
+ void _generate_node_bone(const aiScene *p_scene, const aiNode *p_node, Map<String, bool> &p_mesh_bones, Skeleton *p_skeleton, const String p_path, const int32_t p_max_bone_weights);
+ void _generate_node_bone_parents(const aiScene *p_scene, const aiNode *p_node, Map<String, bool> &p_mesh_bones, Skeleton *p_skeleton, const MeshInstance *p_mi);
+ void _calculate_skeleton_root(Skeleton *s, const aiScene *p_scene, aiNode *&p_ai_skeleton_root, Map<String, bool> &mesh_bones, const aiNode *p_node);
+ void _fill_skeleton(const aiScene *p_scene, const aiNode *p_node, Spatial *p_current, Node *p_owner, Skeleton *p_skeleton, const Map<String, bool> p_mesh_bones, const Map<String, Transform> &p_bone_rests, Set<String> p_tracks, const String p_path, Set<String> &r_removed_bones);
+ void _keep_node(const String &p_path, Node *p_current, Node *p_owner, Set<Node *> &r_keep_nodes);
+ void _filter_node(const String &p_path, Node *p_current, Node *p_owner, const Set<Node *> p_keep_nodes, Set<String> &r_removed_nodes);
+ void _generate_node(const String &p_path, const aiScene *p_scene, const aiNode *p_node, Node *p_parent, Node *p_owner, Set<String> &r_bone_name, Set<String> p_light_names, Set<String> p_camera_names, Map<Skeleton *, MeshInstance *> &r_skeletons, const Map<String, Transform> &p_bone_rests, Vector<MeshInstance *> &r_mesh_instances, int32_t &r_mesh_count, Skeleton *p_skeleton, const int32_t p_max_bone_weights, Set<String> &r_removed_bones, Map<String, Map<uint32_t, String> > &r_name_morph_mesh_names);
+ aiNode *_ai_find_node(aiNode *ai_child_node, const String bone_name);
+ Transform _format_rot_xform(const String p_path, const aiScene *p_scene);
+ void _get_track_set(const aiScene *p_scene, Set<String> &tracks);
+ void _insert_animation_track(const aiScene *p_scene, const String p_path, int p_bake_fps, Ref<Animation> animation, float ticks_per_second, float length, const Skeleton *sk, const aiNodeAnim *track, String node_name, NodePath node_path);
+ void _add_mesh_to_mesh_instance(const aiNode *p_node, const aiScene *p_scene, Skeleton *s, const String &p_path, MeshInstance *p_mesh_instance, Node *p_owner, Set<String> &r_bone_name, int32_t &r_mesh_count, int32_t p_max_bone_weights, Map<String, Map<uint32_t, String> > &r_name_morph_mesh_names);
+ Ref<Texture> _load_texture(const aiScene *p_scene, String p_path);
+ void _calc_tangent_from_mesh(const aiMesh *ai_mesh, int i, int tri_index, int index, PoolColorArray::Write &w);
+ void _set_texture_mapping_mode(aiTextureMapMode *map_mode, Ref<Texture> texture);
+ void _find_texture_path(const String &p_path, String &path, bool &r_found);
+ void _find_texture_path(const String &p_path, _Directory &dir, String &path, bool &found, String extension);
+ String _ai_string_to_string(const aiString p_string) const;
+ String _ai_anim_string_to_string(const aiString p_string) const;
+ String _ai_raw_string_to_string(const aiString p_string) const;
+ void _import_animation(const String p_path, const Vector<MeshInstance *> p_meshes, const aiScene *p_scene, AnimationPlayer *ap, int32_t p_index, int p_bake_fps, Map<Skeleton *, MeshInstance *> p_skeletons, const Set<String> p_removed_nodes, const Set<String> removed_bones, const Map<String, Map<uint32_t, String> > p_path_morph_mesh_names);
+ void _insert_pivot_anim_track(const Vector<MeshInstance *> p_meshes, const String p_node_name, Vector<const aiNodeAnim *> F, AnimationPlayer *ap, Skeleton *sk, float &length, float ticks_per_second, Ref<Animation> animation, int p_bake_fps, const String &p_path, const aiScene *p_scene);
+ float _get_fbx_fps(int32_t time_mode, const aiScene *p_scene);
+ template <class T>
+ T _interpolate_track(const Vector<float> &p_times, const Vector<T> &p_values, float p_time, AssetImportAnimation::Interpolation p_interp);
+ const Transform _ai_matrix_transform(const aiMatrix4x4 p_matrix);
+ void _register_project_setting_import(const String generic, const String import_setting_string, const Vector<String> &exts, List<String> *r_extensions, const bool p_enabled) const;
+
+ struct ImportFormat {
+ Vector<String> extensions;
+ bool is_default;
+ };
+
+protected:
+ static void _bind_methods();
+
+public:
+ EditorSceneImporterAssimp() {
+ Assimp::DefaultLogger::create("", Assimp::Logger::VERBOSE);
+ unsigned int severity = Assimp::Logger::Info | Assimp::Logger::Err | Assimp::Logger::Warn;
+ Assimp::DefaultLogger::get()->attachStream(new AssimpStream(), severity);
+ }
+ ~EditorSceneImporterAssimp() {
+ Assimp::DefaultLogger::kill();
+ }
+
+ virtual void get_extensions(List<String> *r_extensions) const;
+ virtual uint32_t get_import_flags() const;
+ virtual Node *import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = NULL);
+ virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, int p_bake_fps);
+};
+#endif
+#endif
diff --git a/modules/assimp/godot_update_assimp.sh b/modules/assimp/godot_update_assimp.sh
new file mode 100644
index 0000000000..dcf1e6d4a2
--- /dev/null
+++ b/modules/assimp/godot_update_assimp.sh
@@ -0,0 +1,261 @@
+rm -rf ../../thirdparty/assimp
+cd ../../thirdparty/
+git clone https://github.com/assimp/assimp.git
+cd assimp
+rm -rf code/3DSExporter.h
+rm -rf code/3DSLoader.h
+rm -rf code/3MFXmlTags.h
+rm -rf code/ABCImporter.h
+rm -rf code/ACLoader.h
+rm -rf code/AMFImporter_Macro.hpp
+rm -rf code/ASELoader.h
+rm -rf code/assbin_chunks.h
+rm -rf code/AssbinExporter.h
+rm -rf code/AssbinLoader.h
+rm -rf code/AssimpCExport.cpp
+rm -rf code/AssxmlExporter.h
+rm -rf code/B3DImporter.h
+# rm -rf code/BaseProcess.cpp
+# rm -rf code/BaseProcess.h
+# rm -rf code/Bitmap.cpp
+rm -rf code/BlenderBMesh.cpp
+rm -rf code/BlenderBMesh.h
+rm -rf code/BlenderCustomData.cpp
+rm -rf code/BlenderCustomData.h
+rm -rf code/BlenderIntermediate.h
+rm -rf code/BlenderLoader.h
+rm -rf code/BlenderModifier.h
+rm -rf code/BlenderSceneGen.h
+rm -rf code/BlenderTessellator.h
+rm -rf code/BVHLoader.h
+rm -rf code/C4DImporter.h
+# rm -rf code/CalcTangentsProcess.h
+# rm -rf code/CInterfaceIOWrapper.cpp
+# rm -rf code/CInterfaceIOWrapper.h
+rm -rf code/COBLoader.h
+rm -rf code/COBScene.h
+rm -rf code/ColladaExporter.h
+rm -rf code/ColladaLoader.h
+# rm -rf code/ComputeUVMappingProcess.h
+# rm -rf code/ConvertToLHProcess.h
+# rm -rf code/CreateAnimMesh.cpp
+rm -rf code/CSMLoader.h
+rm -rf code/D3MFExporter.h
+rm -rf code/D3MFImporter.h
+rm -rf code/D3MFOpcPackage.h
+# rm -rf code/DeboneProcess.h
+# rm -rf code/DefaultIOStream.cpp
+# rm -rf code/DefaultIOSystem.cpp
+# rm -rf code/DefaultProgressHandler.h
+# rm -rf code/DropFaceNormalsProcess.cpp
+# rm -rf code/DropFaceNormalsProcess.h
+rm -rf code/DXFHelper.h
+rm -rf code/DXFLoader.h
+# rm -rf code/EmbedTexturesProcess.cpp
+# rm -rf code/EmbedTexturesProcess.h
+# rm -rf code/FBXCommon.h
+# rm -rf code/FBXCompileConfig.h
+# rm -rf code/FBXDeformer.cpp
+# rm -rf code/FBXDocumentUtil.cpp
+# rm -rf code/FBXDocumentUtil.h
+# rm -rf code/FBXExporter.h
+# rm -rf code/FBXExportNode.h
+# rm -rf code/FBXExportProperty.h
+# rm -rf code/FBXImporter.cpp
+# rm -rf code/FBXImporter.h
+# rm -rf code/FBXImportSettings.h
+# rm -rf code/FBXMeshGeometry.h
+# rm -rf code/FBXModel.cpp
+# rm -rf code/FBXNodeAttribute.cpp
+# rm -rf code/FBXParser.h
+# rm -rf code/FBXProperties.cpp
+# rm -rf code/FBXProperties.h
+# rm -rf code/FBXTokenizer.cpp
+# rm -rf code/FBXTokenizer.h
+# rm -rf code/FBXUtil.cpp
+# rm -rf code/FBXUtil.h
+# rm -rf code/FileLogStream.h
+# rm -rf code/FindDegenerates.h
+# rm -rf code/FindInstancesProcess.h
+# rm -rf code/FindInvalidDataProcess.h
+rm -rf code/FIReader.hpp
+# rm -rf code/FixNormalsStep.cpp
+# rm -rf code/FixNormalsStep.h
+# rm -rf code/GenFaceNormalsProcess.cpp
+# rm -rf code/GenFaceNormalsProcess.h
+# rm -rf code/GenVertexNormalsProcess.cpp
+# rm -rf code/GenVertexNormalsProcess.h
+rm -rf code/glTF2Asset.h
+rm -rf code/glTF2Asset.inl
+rm -rf code/glTF2AssetWriter.inl
+rm -rf code/glTF2Exporter.cpp
+rm -rf code/glTF2Importer.cpp
+rm -rf code/glTF2AssetWriter.h
+rm -rf code/glTFAsset.h
+rm -rf code/glTFAsset.inl
+rm -rf code/glTFAssetWriter.inl
+rm -rf code/glTFExporter.cpp
+rm -rf code/glTFImporter.cpp
+rm -rf code/glTF2Exporter.h
+rm -rf code/glTF2Importer.h
+rm -rf code/glTFAssetWriter.h
+rm -rf code/glTFExporter.h
+rm -rf code/glTFImporter.h
+rm -rf code/HalfLifeFileData.h
+rm -rf code/HMPFileData.h
+rm -rf code/HMPLoader.h
+rm -rf code/HMPLoader.cpp
+rm -rf code/IFF.h
+# rm -rf code/Importer.h
+# rm -rf code/ImproveCacheLocality.h
+rm -rf code/IRRLoader.h
+rm -rf code/IRRMeshLoader.h
+rm -rf code/IRRShared.h
+# rm -rf code/JoinVerticesProcess.h
+# rm -rf code/LimitBoneWeightsProcess.cpp
+# rm -rf code/LimitBoneWeightsProcess.h
+rm -rf code/LWSLoader.h
+rm -rf code/makefile.mingw
+# rm -rf code/MakeVerboseFormat.cpp
+# rm -rf code/MakeVerboseFormat.h
+# rm -rf code/MaterialSystem.h
+rm -rf code/MD2FileData.h
+rm -rf code/MD2Loader.h
+rm -rf code/MD2NormalTable.h
+rm -rf code/MD3FileData.h
+rm -rf code/MD3Loader.h
+rm -rf code/MD4FileData.h
+rm -rf code/MD5Loader.h
+rm -rf code/MD5Parser.cpp
+rm -rf code/MDCFileData.h
+rm -rf code/MDCLoader.h
+rm -rf code/MDLDefaultColorMap.h
+# rm -rf code/MMDCpp14.h
+# rm -rf code/MMDImporter.h
+rm -rf code/MS3DLoader.h
+rm -rf code/NDOLoader.h
+rm -rf code/NFFLoader.h
+rm -rf code/ObjExporter.h
+rm -rf code/ObjFileImporter.h
+rm -rf code/ObjFileMtlImporter.h
+rm -rf code/ObjFileParser.h
+rm -rf code/ObjTools.h
+rm -rf code/ObjExporter.cpp
+rm -rf code/ObjFileImporter.cpp
+rm -rf code/ObjFileMtlImporter.cpp
+rm -rf code/ObjFileParser.cpp
+rm -rf code/OFFLoader.h
+rm -rf code/OFFLoader.cpp
+rm -rf code/OgreImporter.cpp
+rm -rf code/OgreImporter.h
+rm -rf code/OgreParsingUtils.h
+rm -rf code/OgreXmlSerializer.h
+rm -rf code/OgreXmlSerializer.cpp
+rm -rf code/OgreBinarySerializer.cpp
+rm -rf code/OpenGEXExporter.cpp
+rm -rf code/OpenGEXExporter.h
+rm -rf code/OpenGEXImporter.h
+rm -rf code/OpenGEXStructs.h
+rm -rf code/OpenGEXImporter.cpp
+# rm -rf code/OptimizeGraph.h
+# rm -rf code/OptimizeMeshes.cpp
+# rm -rf code/OptimizeMeshes.h
+rm -rf code/PlyExporter.h
+rm -rf code/PlyLoader.h
+# rm -rf code/PolyTools.h
+# rm -rf code/PostStepRegistry.cpp
+# rm -rf code/PretransformVertices.h
+rm -rf code/Q3BSPFileData.h
+rm -rf code/Q3BSPFileImporter.h
+rm -rf code/Q3BSPFileParser.cpp
+rm -rf code/Q3BSPFileParser.h
+rm -rf code/Q3BSPZipArchive.cpp
+rm -rf code/Q3BSPZipArchive.h
+rm -rf code/Q3DLoader.h
+rm -rf code/Q3DLoader.cpp
+rm -rf code/Q3BSPFileImporter.cpp
+rm -rf code/RawLoader.h
+# rm -rf code/RemoveComments.cpp
+# rm -rf code/RemoveRedundantMaterials.cpp
+# rm -rf code/RemoveRedundantMaterials.h
+# rm -rf code/RemoveVCProcess.h
+# rm -rf code/ScaleProcess.cpp
+# rm -rf code/ScaleProcess.h
+# rm -rf code/scene.cpp
+# rm -rf code/ScenePreprocessor.cpp
+# rm -rf code/ScenePreprocessor.h
+# rm -rf code/ScenePrivate.h
+# rm -rf code/SGSpatialSort.cpp
+rm -rf code/SIBImporter.h
+rm -rf code/SMDLoader.cpp
+# rm -rf code/simd.cpp
+# rm -rf code/simd.h
+# rm -rf code/SortByPTypeProcess.h
+# rm -rf code/SplitByBoneCountProcess.h
+# rm -rf code/SplitLargeMeshes.h
+# rm -rf code/StdOStreamLogStream.h
+rm -rf code/StepExporter.h
+rm -rf code/StepExporter.cpp
+rm -rf code/STLExporter.cpp
+rm -rf code/STLExporter.h
+rm -rf code/STLLoader.h
+rm -rf code/STLLoader.cpp
+# rm -rf code/TargetAnimation.cpp
+# rm -rf code/TargetAnimation.h
+rm -rf code/TerragenLoader.h
+rm -rf code/TerragenLoader.cpp
+# rm -rf code/TextureTransform.h
+# rm -rf code/TriangulateProcess.h
+rm -rf code/UnrealLoader.h
+# rm -rf code/ValidateDataStructure.h
+# rm -rf code/Version.cpp
+# rm -rf code/VertexTriangleAdjacency.cpp
+# rm -rf code/VertexTriangleAdjacency.h
+# rm -rf code/Win32DebugLogStream.h
+rm -rf code/X3DImporter_Macro.hpp
+rm -rf code/X3DImporter_Metadata.cpp
+rm -rf code/X3DImporter_Networking.cpp
+rm -rf code/X3DImporter_Texturing.cpp
+rm -rf code/X3DImporter_Shape.cpp
+rm -rf code/X3DImporter_Rendering.cpp
+rm -rf code/X3DImporter_Postprocess.cpp
+rm -rf code/X3DImporter_Light.cpp
+rm -rf code/X3DImporter_Group.cpp
+rm -rf code/X3DImporter_Geometry3D.cpp
+rm -rf code/X3DImporter_Geometry2D.cpp
+rm -rf code/X3DImporter.cpp
+rm -rf code/X3DExporter.cpp
+rm -rf code/X3DVocabulary.cpp
+rm -rf code/XFileExporter.h
+rm -rf code/XFileExporter.cpp
+rm -rf code/XFileHelper.h
+rm -rf code/XFileHelper.cpp
+rm -rf code/XFileImporter.h
+rm -rf code/XFileImporter.cpp
+rm -rf code/XFileParser.h
+rm -rf code/XFileParser.cpp
+rm -rf code/XGLLoader.h
+rm -rf code/XGLLoader.cpp
+rm -rf code/Importer
+rm -rf .git
+rm -rf cmake-modules
+rm -rf doc
+rm -rf packaging
+rm -rf port
+rm -rf samples
+rm -rf scripts
+rm -rf test
+rm -rf tools
+rm -rf contrib/zlib
+rm -rf contrib/android-cmake
+rm -rf contrib/gtest
+rm -rf contrib/clipper
+rm -rf contrib/irrXML
+rm -rf contrib/Open3DGC
+rm -rf contrib/openddlparser
+rm -rf contrib/poly2tri
+rm -rf contrib/rapidjson
+rm -rf contrib/unzip
+rm -rf contrib/zip
+rm -rf contrib/stb_image
+rm .travis*
diff --git a/modules/assimp/register_types.cpp b/modules/assimp/register_types.cpp
new file mode 100644
index 0000000000..2e8181372e
--- /dev/null
+++ b/modules/assimp/register_types.cpp
@@ -0,0 +1,59 @@
+/*************************************************************************/
+/* register_types.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 "register_types.h"
+
+#include "editor/editor_node.h"
+#include "editor_scene_importer_assimp.h"
+
+#ifdef TOOLS_ENABLED
+static void _editor_init() {
+ Ref<EditorSceneImporterAssimp> import_assimp;
+ import_assimp.instance();
+ ResourceImporterScene::get_singleton()->add_importer(import_assimp);
+}
+#endif
+
+void register_assimp_types() {
+
+#ifdef TOOLS_ENABLED
+ ClassDB::APIType prev_api = ClassDB::get_current_api();
+ ClassDB::set_current_api(ClassDB::API_EDITOR);
+
+ ClassDB::register_class<EditorSceneImporterAssimp>();
+
+ ClassDB::set_current_api(prev_api);
+
+ EditorNode::add_init_callback(_editor_init);
+#endif
+}
+
+void unregister_assimp_types() {
+}
diff --git a/modules/assimp/register_types.h b/modules/assimp/register_types.h
new file mode 100644
index 0000000000..f841cd26b2
--- /dev/null
+++ b/modules/assimp/register_types.h
@@ -0,0 +1,32 @@
+/*************************************************************************/
+/* register_types.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. */
+/*************************************************************************/
+
+void register_assimp_types();
+void unregister_assimp_types();
diff --git a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
index a4dc61d0bc..1f91349f32 100644
--- a/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
+++ b/modules/bullet/doc_classes/BulletPhysicsDirectBodyState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.1">
+<class name="BulletPhysicsDirectBodyState" inherits="PhysicsDirectBodyState" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/bullet/doc_classes/BulletPhysicsServer.xml b/modules/bullet/doc_classes/BulletPhysicsServer.xml
index 1486936cf4..8adc659b2c 100644
--- a/modules/bullet/doc_classes/BulletPhysicsServer.xml
+++ b/modules/bullet/doc_classes/BulletPhysicsServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.1">
+<class name="BulletPhysicsServer" inherits="PhysicsServer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp
index 1aba31f03d..b590d63167 100644
--- a/modules/bullet/shape_bullet.cpp
+++ b/modules/bullet/shape_bullet.cpp
@@ -510,16 +510,17 @@ void HeightMapShapeBullet::set_data(const Variant &p_data) {
// Compute min and max heights if not specified.
if (!d.has("min_height") && !d.has("max_height")) {
- PoolVector<real_t>::Read r = heights.read();
- int heights_size = heights.size();
+ PoolVector<real_t>::Read r = l_heights.read();
+ int heights_size = l_heights.size();
for (int i = 0; i < heights_size; ++i) {
real_t h = r[i];
- if (h < l_min_height)
+ if (h < l_min_height) {
l_min_height = h;
- else if (h > l_max_height)
+ } else if (h > l_max_height) {
l_max_height = h;
+ }
}
}
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index f274fff3f3..775ec67ba6 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -806,8 +806,8 @@ CSGBrush *CSGMesh::_build_brush() {
uvw[as + j + 1] = uv[1];
uvw[as + j + 2] = uv[2];
- sw[j / 3] = !flat;
- mw[j / 3] = mat;
+ sw[(as + j) / 3] = !flat;
+ mw[(as + j) / 3] = mat;
}
} else {
int as = vertices.size();
@@ -849,8 +849,8 @@ CSGBrush *CSGMesh::_build_brush() {
uvw[as + j + 1] = uv[1];
uvw[as + j + 2] = uv[2];
- sw[j / 3] = !flat;
- mw[j / 3] = mat;
+ sw[(as + j) / 3] = !flat;
+ mw[(as + j) / 3] = mat;
}
}
}
diff --git a/modules/csg/doc_classes/CSGBox.xml b/modules/csg/doc_classes/CSGBox.xml
index 5ec7b5089d..1684850f0a 100644
--- a/modules/csg/doc_classes/CSGBox.xml
+++ b/modules/csg/doc_classes/CSGBox.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGBox" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGBox" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Box shape.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGCombiner.xml b/modules/csg/doc_classes/CSGCombiner.xml
index 69c5df5840..819a4a3a22 100644
--- a/modules/csg/doc_classes/CSGCombiner.xml
+++ b/modules/csg/doc_classes/CSGCombiner.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGCombiner" inherits="CSGShape" category="Core" version="3.1">
+<class name="CSGCombiner" inherits="CSGShape" category="Core" version="3.2">
<brief_description>
A CSG node that allows you to combine other CSG modifiers.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGCylinder.xml b/modules/csg/doc_classes/CSGCylinder.xml
index 92b170ed1f..50a88d6773 100644
--- a/modules/csg/doc_classes/CSGCylinder.xml
+++ b/modules/csg/doc_classes/CSGCylinder.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGCylinder" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGCylinder" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Cylinder shape.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGMesh.xml b/modules/csg/doc_classes/CSGMesh.xml
index 58e2bc1c4b..fc9815d7c0 100644
--- a/modules/csg/doc_classes/CSGMesh.xml
+++ b/modules/csg/doc_classes/CSGMesh.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGMesh" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGMesh" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Mesh shape that uses a mesh resource.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGPolygon.xml b/modules/csg/doc_classes/CSGPolygon.xml
index a33e5557cb..ae75f7e01b 100644
--- a/modules/csg/doc_classes/CSGPolygon.xml
+++ b/modules/csg/doc_classes/CSGPolygon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGPolygon" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGPolygon" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
Extrudes a 2D polygon shape to create a 3D mesh.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGPrimitive.xml b/modules/csg/doc_classes/CSGPrimitive.xml
index 2591bab7e3..502a8230e4 100644
--- a/modules/csg/doc_classes/CSGPrimitive.xml
+++ b/modules/csg/doc_classes/CSGPrimitive.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGPrimitive" inherits="CSGShape" category="Core" version="3.1">
+<class name="CSGPrimitive" inherits="CSGShape" category="Core" version="3.2">
<brief_description>
Base class for CSG primitives.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml
index d304d0179f..ccfc5a04c0 100644
--- a/modules/csg/doc_classes/CSGShape.xml
+++ b/modules/csg/doc_classes/CSGShape.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGShape" inherits="VisualInstance" category="Core" version="3.1">
+<class name="CSGShape" inherits="VisualInstance" category="Core" version="3.2">
<brief_description>
The CSG base class.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGSphere.xml b/modules/csg/doc_classes/CSGSphere.xml
index a0069879cb..088c9f14eb 100644
--- a/modules/csg/doc_classes/CSGSphere.xml
+++ b/modules/csg/doc_classes/CSGSphere.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGSphere" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGSphere" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Sphere shape.
</brief_description>
diff --git a/modules/csg/doc_classes/CSGTorus.xml b/modules/csg/doc_classes/CSGTorus.xml
index 187d71a2fa..946637bd2c 100644
--- a/modules/csg/doc_classes/CSGTorus.xml
+++ b/modules/csg/doc_classes/CSGTorus.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSGTorus" inherits="CSGPrimitive" category="Core" version="3.1">
+<class name="CSGTorus" inherits="CSGPrimitive" category="Core" version="3.2">
<brief_description>
A CSG Torus shape.
</brief_description>
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index c9a7d96ae7..c1bec533dd 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1">
+<class name="NetworkedMultiplayerENet" inherits="NetworkedMultiplayerPeer" category="Core" version="3.2">
<brief_description>
PacketPeer implementation using the ENet library.
</brief_description>
diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp
index 9cd37ac950..8c602e0cba 100644
--- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp
+++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp
@@ -198,6 +198,17 @@ CameraMatrix ARVRInterfaceGDNative::get_projection_for_eye(ARVRInterface::Eyes p
return cm;
}
+unsigned int ARVRInterfaceGDNative::get_external_texture_for_eye(ARVRInterface::Eyes p_eye) {
+
+ ERR_FAIL_COND_V(interface == NULL, 0);
+
+ if ((interface->version.major > 1) || ((interface->version.major) == 1 && (interface->version.minor >= 1))) {
+ return (unsigned int)interface->get_external_texture_for_eye(data, (godot_int)p_eye);
+ } else {
+ return 0;
+ }
+}
+
void ARVRInterfaceGDNative::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
ERR_FAIL_COND(interface == NULL);
diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.h b/modules/gdnative/arvr/arvr_interface_gdnative.h
index 015d0c8a2a..3f966ece51 100644
--- a/modules/gdnative/arvr/arvr_interface_gdnative.h
+++ b/modules/gdnative/arvr/arvr_interface_gdnative.h
@@ -78,6 +78,7 @@ public:
// and a CameraMatrix version to ARVRServer
virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+ virtual unsigned int get_external_texture_for_eye(ARVRInterface::Eyes p_eye);
virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
virtual void process();
diff --git a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
index be86ff0541..afb014d608 100644
--- a/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
+++ b/modules/gdnative/doc_classes/ARVRInterfaceGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.1">
+<class name="ARVRInterfaceGDNative" inherits="ARVRInterface" category="Core" version="3.2">
<brief_description>
GDNative wrapper for an ARVR interface
</brief_description>
diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml
index ca0457623f..e5a59aad07 100644
--- a/modules/gdnative/doc_classes/GDNative.xml
+++ b/modules/gdnative/doc_classes/GDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNative" inherits="Reference" category="Core" version="3.1">
+<class name="GDNative" inherits="Reference" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/GDNativeLibrary.xml b/modules/gdnative/doc_classes/GDNativeLibrary.xml
index 754a6d2514..ba5278d440 100644
--- a/modules/gdnative/doc_classes/GDNativeLibrary.xml
+++ b/modules/gdnative/doc_classes/GDNativeLibrary.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.1">
+<class name="GDNativeLibrary" inherits="Resource" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml b/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
index 4433179726..ba481a6d6e 100644
--- a/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
+++ b/modules/gdnative/doc_classes/MultiplayerPeerGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MultiplayerPeerGDNative" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1">
+<class name="MultiplayerPeerGDNative" inherits="NetworkedMultiplayerPeer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml
index 37d5b79e7a..c50f9eee22 100644
--- a/modules/gdnative/doc_classes/NativeScript.xml
+++ b/modules/gdnative/doc_classes/NativeScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NativeScript" inherits="Script" category="Core" version="3.1">
+<class name="NativeScript" inherits="Script" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/PacketPeerGDNative.xml b/modules/gdnative/doc_classes/PacketPeerGDNative.xml
index 0ae54bc9c7..f4d7d22f5b 100644
--- a/modules/gdnative/doc_classes/PacketPeerGDNative.xml
+++ b/modules/gdnative/doc_classes/PacketPeerGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PacketPeerGDNative" inherits="PacketPeer" category="Core" version="3.1">
+<class name="PacketPeerGDNative" inherits="PacketPeer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/PluginScript.xml b/modules/gdnative/doc_classes/PluginScript.xml
index 1876d06c20..8510708124 100644
--- a/modules/gdnative/doc_classes/PluginScript.xml
+++ b/modules/gdnative/doc_classes/PluginScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="PluginScript" inherits="Script" category="Core" version="3.1">
+<class name="PluginScript" inherits="Script" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml b/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml
index 61a7f60499..8e7f4698ff 100644
--- a/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml
+++ b/modules/gdnative/doc_classes/ResourceFormatLoaderVideoStreamGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceFormatLoaderVideoStreamGDNative" inherits="ResourceFormatLoader" category="Core" version="3.1">
+<class name="ResourceFormatLoaderVideoStreamGDNative" inherits="ResourceFormatLoader" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/StreamPeerGDNative.xml b/modules/gdnative/doc_classes/StreamPeerGDNative.xml
index d86cd2c25a..eddebf4889 100644
--- a/modules/gdnative/doc_classes/StreamPeerGDNative.xml
+++ b/modules/gdnative/doc_classes/StreamPeerGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="StreamPeerGDNative" inherits="StreamPeer" category="Core" version="3.1">
+<class name="StreamPeerGDNative" inherits="StreamPeer" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/doc_classes/VideoStreamGDNative.xml b/modules/gdnative/doc_classes/VideoStreamGDNative.xml
index 20575c768b..d5c5ed7ccf 100644
--- a/modules/gdnative/doc_classes/VideoStreamGDNative.xml
+++ b/modules/gdnative/doc_classes/VideoStreamGDNative.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoStreamGDNative" inherits="VideoStream" category="Core" version="3.1">
+<class name="VideoStreamGDNative" inherits="VideoStream" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/arvr/godot_arvr.h
index 0d14f3743f..321b471d0e 100644
--- a/modules/gdnative/include/arvr/godot_arvr.h
+++ b/modules/gdnative/include/arvr/godot_arvr.h
@@ -42,7 +42,7 @@ extern "C" {
// Use these to populate version in your plugin
#define GODOTVR_API_MAJOR 1
-#define GODOTVR_API_MINOR 0
+#define GODOTVR_API_MINOR 1
typedef struct {
godot_gdnative_api_version version; /* version of our API */
@@ -61,6 +61,8 @@ typedef struct {
void (*fill_projection_for_eye)(void *, godot_real *, godot_int, godot_real, godot_real, godot_real);
void (*commit_for_eye)(void *, godot_int, godot_rid *, godot_rect2 *);
void (*process)(void *);
+ // only in 1.1 onwards
+ godot_int (*get_external_texture_for_eye)(void *, godot_int);
} godot_arvr_interface_gdnative;
void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface);
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index 7eb4294732..4577c7327a 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -323,6 +323,9 @@ List<ClassAPI> generate_c_api_classes() {
arg_type = "Variant";
} else if (arg_info.type == Variant::OBJECT) {
arg_type = arg_info.class_name;
+ if (arg_type == "") {
+ arg_type = Variant::get_type_name(arg_info.type);
+ }
} else {
arg_type = Variant::get_type_name(arg_info.type);
}
diff --git a/modules/gdnative/pluginscript/pluginscript_script.cpp b/modules/gdnative/pluginscript/pluginscript_script.cpp
index 3450a032c5..8dbbd2e4eb 100644
--- a/modules/gdnative/pluginscript/pluginscript_script.cpp
+++ b/modules/gdnative/pluginscript/pluginscript_script.cpp
@@ -34,7 +34,7 @@
#include "pluginscript_instance.h"
#include "pluginscript_script.h"
-#if DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
#define __ASSERT_SCRIPT_REASON "Cannot retrieve pluginscript class for this script, is you code correct ?"
#define ASSERT_SCRIPT_VALID() \
{ \
diff --git a/modules/gdscript/doc_classes/GDScript.xml b/modules/gdscript/doc_classes/GDScript.xml
index 4cefdbd7cb..46796c68eb 100644
--- a/modules/gdscript/doc_classes/GDScript.xml
+++ b/modules/gdscript/doc_classes/GDScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScript" inherits="Script" category="Core" version="3.1">
+<class name="GDScript" inherits="Script" category="Core" version="3.2">
<brief_description>
A script implemented in the GDScript programming language.
</brief_description>
diff --git a/modules/gdscript/doc_classes/GDScriptFunctionState.xml b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
index c205cedef5..f38f39b612 100644
--- a/modules/gdscript/doc_classes/GDScriptFunctionState.xml
+++ b/modules/gdscript/doc_classes/GDScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.1">
+<class name="GDScriptFunctionState" inherits="Reference" category="Core" version="3.2">
<brief_description>
State of a function call after yielding.
</brief_description>
diff --git a/modules/gdscript/doc_classes/GDScriptNativeClass.xml b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
index 90935b5c22..e86b69c31c 100644
--- a/modules/gdscript/doc_classes/GDScriptNativeClass.xml
+++ b/modules/gdscript/doc_classes/GDScriptNativeClass.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.1">
+<class name="GDScriptNativeClass" inherits="Reference" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 4385cf12ad..0676317f6e 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -597,7 +597,7 @@ Error GDScript::reload(bool p_keep_state) {
return err;
}
}
-#if DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
for (const List<GDScriptWarning>::Element *E = parser.get_warnings().front(); E; E = E->next()) {
const GDScriptWarning &warning = E->get();
if (ScriptDebugger::get_singleton()) {
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index ded873c7d3..c67e390e32 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -444,6 +444,7 @@ public:
virtual void get_reserved_words(List<String> *p_words) const;
virtual void get_comment_delimiters(List<String> *p_delimiters) const;
virtual void get_string_delimiters(List<String> *p_delimiters) const;
+ virtual String _get_processed_template(const String &p_template, const String &p_base_class_name) const;
virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const;
virtual bool is_using_templates();
virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index fafc73b7e6..ee0d5ae055 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -44,12 +44,43 @@ void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const
p_delimiters->push_back("#");
}
+
void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("\" \"");
p_delimiters->push_back("' '");
p_delimiters->push_back("\"\"\" \"\"\"");
}
+
+String GDScriptLanguage::_get_processed_template(const String &p_template, const String &p_base_class_name) const {
+
+ String processed_template = p_template;
+
+#ifdef TOOLS_ENABLED
+ if (EDITOR_DEF("text_editor/completion/add_type_hints", false)) {
+ processed_template = processed_template.replace("%INT_TYPE%", ": int");
+ processed_template = processed_template.replace("%STRING_TYPE%", ": String");
+ processed_template = processed_template.replace("%FLOAT_TYPE%", ": float");
+ processed_template = processed_template.replace("%VOID_RETURN%", " -> void");
+ } else {
+ processed_template = processed_template.replace("%INT_TYPE%", "");
+ processed_template = processed_template.replace("%STRING_TYPE%", "");
+ processed_template = processed_template.replace("%FLOAT_TYPE%", "");
+ processed_template = processed_template.replace("%VOID_RETURN%", "");
+ }
+#else
+ processed_template = processed_template.replace("%INT_TYPE%", "");
+ processed_template = processed_template.replace("%STRING_TYPE%", "");
+ processed_template = processed_template.replace("%FLOAT_TYPE%", "");
+ processed_template = processed_template.replace("%VOID_RETURN%", "");
+#endif
+
+ processed_template = processed_template.replace("%BASE%", p_base_class_name);
+ processed_template = processed_template.replace("%TS%", _get_indentation());
+
+ return processed_template;
+}
+
Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const {
String _template = "extends %BASE%\n"
"\n"
@@ -65,27 +96,7 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str
"#func _process(delta%FLOAT_TYPE%)%VOID_RETURN%:\n"
"#%TS%pass\n";
-#ifdef TOOLS_ENABLED
- if (EDITOR_DEF("text_editor/completion/add_type_hints", false)) {
- _template = _template.replace("%INT_TYPE%", ": int");
- _template = _template.replace("%STRING_TYPE%", ": String");
- _template = _template.replace("%FLOAT_TYPE%", ": float");
- _template = _template.replace("%VOID_RETURN%", " -> void");
- } else {
- _template = _template.replace("%INT_TYPE%", "");
- _template = _template.replace("%STRING_TYPE%", "");
- _template = _template.replace("%FLOAT_TYPE%", "");
- _template = _template.replace("%VOID_RETURN%", "");
- }
-#else
- _template = _template.replace("%INT_TYPE%", "");
- _template = _template.replace("%STRING_TYPE%", "");
- _template = _template.replace("%FLOAT_TYPE%", "");
- _template = _template.replace("%VOID_RETURN%", "");
-#endif
-
- _template = _template.replace("%BASE%", p_base_class_name);
- _template = _template.replace("%TS%", _get_indentation());
+ _template = _get_processed_template(_template, p_base_class_name);
Ref<GDScript> script;
script.instance();
@@ -101,10 +112,8 @@ bool GDScriptLanguage::is_using_templates() {
void GDScriptLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {
- String src = p_script->get_source_code();
- src = src.replace("%BASE%", p_base_class_name);
- src = src.replace("%TS%", _get_indentation());
- p_script->set_source_code(src);
+ String _template = _get_processed_template(p_script->get_source_code(), p_base_class_name);
+ p_script->set_source_code(_template);
}
bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const {
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 44d44462ca..4fd136d5cc 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -74,6 +74,7 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
"lerp",
"inverse_lerp",
"range_lerp",
+ "smoothstep",
"dectime",
"randomize",
"randi",
@@ -369,6 +370,13 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
VALIDATE_ARG_NUM(4);
r_ret = Math::range_lerp((double)*p_args[0], (double)*p_args[1], (double)*p_args[2], (double)*p_args[3], (double)*p_args[4]);
} break;
+ case MATH_SMOOTHSTEP: {
+ VALIDATE_ARG_COUNT(3);
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ r_ret = Math::smoothstep((double)*p_args[0], (double)*p_args[1], (double)*p_args[2]);
+ } break;
case MATH_DECTIME: {
VALIDATE_ARG_COUNT(3);
VALIDATE_ARG_NUM(0);
@@ -768,11 +776,30 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
(void)VariantParser::parse(&ss, r_ret, errs, line);
} break;
case VAR_TO_BYTES: {
- VALIDATE_ARG_COUNT(1);
+ bool full_objects = false;
+ if (p_arg_count < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ r_ret = Variant();
+ return;
+ } else if (p_arg_count > 2) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 2;
+ r_ret = Variant();
+ } else if (p_arg_count == 2) {
+ if (p_args[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ r_ret = Variant();
+ return;
+ }
+ full_objects = *p_args[1];
+ }
PoolByteArray barr;
int len;
- Error err = encode_variant(*p_args[0], NULL, len);
+ Error err = encode_variant(*p_args[0], NULL, len, full_objects);
if (err) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
@@ -784,15 +811,35 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
barr.resize(len);
{
PoolByteArray::Write w = barr.write();
- encode_variant(*p_args[0], w.ptr(), len);
+ encode_variant(*p_args[0], w.ptr(), len, full_objects);
}
r_ret = barr;
} break;
case BYTES_TO_VAR: {
- VALIDATE_ARG_COUNT(1);
+ bool allow_objects = false;
+ if (p_arg_count < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ r_ret = Variant();
+ return;
+ } else if (p_arg_count > 2) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 2;
+ r_ret = Variant();
+ } else if (p_arg_count == 2) {
+ if (p_args[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ r_ret = Variant();
+ return;
+ }
+ allow_objects = *p_args[1];
+ }
+
if (p_args[0]->get_type() != Variant::POOL_BYTE_ARRAY) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
+ r_error.argument = 1;
r_error.expected = Variant::POOL_BYTE_ARRAY;
r_ret = Variant();
return;
@@ -802,7 +849,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Variant ret;
{
PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects);
if (err != OK) {
r_ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
@@ -1396,6 +1443,7 @@ bool GDScriptFunctions::is_deterministic(Function p_func) {
case MATH_LERP:
case MATH_INVERSE_LERP:
case MATH_RANGE_LERP:
+ case MATH_SMOOTHSTEP:
case MATH_DECTIME:
case MATH_DEG2RAD:
case MATH_RAD2DEG:
@@ -1579,6 +1627,11 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
mi.return_val.type = Variant::REAL;
return mi;
} break;
+ case MATH_SMOOTHSTEP: {
+ MethodInfo mi("smoothstep", PropertyInfo(Variant::REAL, "from"), PropertyInfo(Variant::REAL, "to"), PropertyInfo(Variant::REAL, "weight"));
+ mi.return_val.type = Variant::REAL;
+ return mi;
+ } break;
case MATH_DECTIME: {
MethodInfo mi("dectime", PropertyInfo(Variant::REAL, "value"), PropertyInfo(Variant::REAL, "amount"), PropertyInfo(Variant::REAL, "step"));
mi.return_val.type = Variant::REAL;
@@ -1805,13 +1858,15 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
} break;
case VAR_TO_BYTES: {
- MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT));
+ MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::BOOL, "full_objects"));
+ mi.default_arguments.push_back(false);
mi.return_val.type = Variant::POOL_BYTE_ARRAY;
return mi;
} break;
case BYTES_TO_VAR: {
- MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"));
+ MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"), PropertyInfo(Variant::BOOL, "allow_objects"));
+ mi.default_arguments.push_back(false);
mi.return_val.type = Variant::NIL;
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
return mi;
diff --git a/modules/gdscript/gdscript_functions.h b/modules/gdscript/gdscript_functions.h
index fcb8f32e54..14bf3d7560 100644
--- a/modules/gdscript/gdscript_functions.h
+++ b/modules/gdscript/gdscript_functions.h
@@ -65,6 +65,7 @@ public:
MATH_LERP,
MATH_INVERSE_LERP,
MATH_RANGE_LERP,
+ MATH_SMOOTHSTEP,
MATH_DECTIME,
MATH_RANDOMIZE,
MATH_RAND,
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index da69181a43..e75b8a14a3 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -777,7 +777,8 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
}
_add_warning(GDScriptWarning::UNASSIGNED_VARIABLE_OP_ASSIGN, -1, identifier.operator String());
}
- } // fallthrough
+ FALLTHROUGH;
+ }
case GDScriptTokenizer::TK_OP_ASSIGN: {
lv->assignments += 1;
lv->usages--; // Assignment is not really usage
@@ -2225,6 +2226,8 @@ GDScriptParser::PatternNode *GDScriptParser::_parse_pattern(bool p_static) {
void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBranchNode *> &p_branches, bool p_static) {
int indent_level = tab_level.back()->get();
+ p_block->has_return = true;
+
while (true) {
while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline())
@@ -2282,8 +2285,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
current_block = p_block;
- if (catch_all && branch->body->has_return) {
- p_block->has_return = true;
+ if (!branch->body->has_return) {
+ p_block->has_return = false;
}
p_branches.push_back(branch);
@@ -3634,7 +3637,8 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
return;
}
- }; //fallthrough to function
+ FALLTHROUGH;
+ }
case GDScriptTokenizer::TK_PR_FUNCTION: {
bool _static = false;
@@ -4084,7 +4088,8 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
break;
}
- }; //fallthrough to use the same
+ FALLTHROUGH;
+ }
case Variant::REAL: {
if (tokenizer->get_token() == GDScriptTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier() == "EASE") {
@@ -4509,6 +4514,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
#ifdef DEBUG_ENABLED
_add_warning(GDScriptWarning::DEPRECATED_KEYWORD, tokenizer->get_token_line(), "slave", "puppet");
#endif
+ FALLTHROUGH;
case GDScriptTokenizer::TK_PR_PUPPET: {
//may be fallthrough from export, ignore if so
@@ -4576,7 +4582,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
continue;
} break;
case GDScriptTokenizer::TK_PR_VAR: {
- //variale declaration and (eventual) initialization
+ // variable declaration and (eventual) initialization
ClassNode::Member member;
@@ -5288,7 +5294,8 @@ String GDScriptParser::DataType::to_string() const {
if (!gds_class.empty()) {
return gds_class;
}
- } // fallthrough
+ FALLTHROUGH;
+ }
case SCRIPT: {
if (is_meta_type) {
return script_type->get_class_name().operator String();
@@ -8044,7 +8051,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (cn->value.get_type() == Variant::STRING) {
break;
}
- } // falthrough
+ FALLTHROUGH;
+ }
default: {
_mark_line_as_safe(statement->line);
_reduce_node_type(statement); // Test for safety anyway
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 8b22d6f085..abc739d645 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -744,7 +744,7 @@ void GDScriptTokenizerText::_advance() {
}
INCPOS(1);
is_node_path = true;
-
+ FALLTHROUGH;
case '\'':
case '"': {
@@ -1199,7 +1199,8 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer)
Variant v;
int len;
- Error err = decode_variant(v, b, total_len, &len);
+ // An object cannot be constant, never decode objects
+ Error err = decode_variant(v, b, total_len, &len, false);
if (err)
return err;
b += len;
@@ -1367,11 +1368,12 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code)
for (Map<int, Variant>::Element *E = rev_constant_map.front(); E; E = E->next()) {
int len;
- Error err = encode_variant(E->get(), NULL, len);
+ // Objects cannot be constant, never encode objects
+ Error err = encode_variant(E->get(), NULL, len, false);
ERR_FAIL_COND_V(err != OK, Vector<uint8_t>());
int pos = buf.size();
buf.resize(pos + len);
- encode_variant(E->get(), &buf.write[pos], len);
+ encode_variant(E->get(), &buf.write[pos], len, false);
}
for (Map<int, uint32_t>::Element *E = rev_line_map.front(); E; E = E->next()) {
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 2ea116d79b..655be4eb20 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GridMap" inherits="Spatial" category="Core" version="3.1">
+<class name="GridMap" inherits="Spatial" category="Core" version="3.2">
<brief_description>
Node for 3D tile-based maps.
</brief_description>
diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
index 359d654433..0a75ad4784 100644
--- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml
+++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.1">
+<class name="MobileVRInterface" inherits="ARVRInterface" category="Core" version="3.2">
<brief_description>
Generic mobile VR implementation
</brief_description>
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index 706949154e..341d57f3e4 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -5,70 +5,6 @@ Import('env_modules')
env_mono = env_modules.Clone()
-# TODO move functions to their own modules
-
-def make_cs_files_header(src, dst, version_dst):
- from compat import byte_to_str
-
- with open(dst, 'w') as header:
- header.write('/* THIS FILE IS GENERATED DO NOT EDIT */\n')
- header.write('#ifndef CS_COMPRESSED_H\n')
- header.write('#define CS_COMPRESSED_H\n\n')
- header.write('#ifdef TOOLS_ENABLED\n\n')
- header.write('#include "core/map.h"\n')
- header.write('#include "core/ustring.h"\n')
- inserted_files = ''
- import os
- latest_mtime = 0
- cs_file_count = 0
- for root, _, files in os.walk(src):
- files = [f for f in files if f.endswith('.cs')]
- for file in files:
- cs_file_count += 1
- filepath = os.path.join(root, file)
- filepath_src_rel = os.path.relpath(filepath, src)
- mtime = os.path.getmtime(filepath)
- latest_mtime = mtime if mtime > latest_mtime else latest_mtime
- with open(filepath, 'rb') as f:
- buf = f.read()
- decomp_size = len(buf)
- import zlib
- buf = zlib.compress(buf)
- name = str(cs_file_count)
- header.write('\n')
- header.write('// ' + filepath_src_rel + '\n')
- header.write('static const int _cs_' + name + '_compressed_size = ' + str(len(buf)) + ';\n')
- header.write('static const int _cs_' + name + '_uncompressed_size = ' + str(decomp_size) + ';\n')
- header.write('static const unsigned char _cs_' + name + '_compressed[] = { ')
- for i, buf_idx in enumerate(range(len(buf))):
- if i > 0:
- header.write(', ')
- header.write(byte_to_str(buf[buf_idx]))
- inserted_files += '\tr_files.insert("' + filepath_src_rel.replace('\\', '\\\\') + '", ' \
- 'CompressedFile(_cs_' + name + '_compressed_size, ' \
- '_cs_' + name + '_uncompressed_size, ' \
- '_cs_' + name + '_compressed));\n'
- header.write(' };\n')
- header.write('\nstruct CompressedFile\n' '{\n'
- '\tint compressed_size;\n' '\tint uncompressed_size;\n' '\tconst unsigned char* data;\n'
- '\n\tCompressedFile(int p_comp_size, int p_uncomp_size, const unsigned char* p_data)\n'
- '\t{\n' '\t\tcompressed_size = p_comp_size;\n' '\t\tuncompressed_size = p_uncomp_size;\n'
- '\t\tdata = p_data;\n' '\t}\n' '\n\tCompressedFile() {}\n' '};\n'
- '\nvoid get_compressed_files(Map<String, CompressedFile>& r_files)\n' '{\n' + inserted_files + '}\n'
- )
- header.write('\n#endif // TOOLS_ENABLED\n')
- header.write('\n#endif // CS_COMPRESSED_H\n')
-
- glue_version = int(latest_mtime) # The latest modified time will do for now
-
- with open(version_dst, 'w') as version_header:
- version_header.write('/* THIS FILE IS GENERATED DO NOT EDIT */\n')
- version_header.write('#ifndef CS_GLUE_VERSION_H\n')
- version_header.write('#define CS_GLUE_VERSION_H\n\n')
- version_header.write('#define CS_GLUE_VERSION UINT32_C(' + str(glue_version) + ')\n')
- version_header.write('\n#endif // CS_GLUE_VERSION_H\n')
-
-
env_mono.add_source_files(env.modules_sources, '*.cpp')
env_mono.add_source_files(env.modules_sources, 'glue/*.cpp')
env_mono.add_source_files(env.modules_sources, 'mono_gd/*.cpp')
@@ -77,7 +13,12 @@ env_mono.add_source_files(env.modules_sources, 'utils/*.cpp')
if env['tools']:
env_mono.add_source_files(env.modules_sources, 'editor/*.cpp')
# NOTE: It is safe to generate this file here, since this is still executed serially
- make_cs_files_header('glue/Managed/Files', 'glue/cs_compressed.gen.h', 'glue/cs_glue_version.gen.h')
+ import build_scripts.make_cs_compressed_header as make_cs_compressed_header
+ make_cs_compressed_header.generate_header(
+ 'glue/Managed/Files',
+ 'glue/cs_compressed.gen.h',
+ 'glue/cs_glue_version.gen.h'
+ )
vars = Variables()
vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True))
@@ -88,273 +29,29 @@ vars.Update(env_mono)
if env_mono['mono_glue']:
env_mono.Append(CPPDEFINES=['MONO_GLUE_ENABLED'])
+ import os.path
+ if not os.path.isfile('glue/mono_glue.gen.cpp'):
+ raise RuntimeError('Missing mono glue sources. Did you forget to generate them?')
+
if env_mono['tools'] or env_mono['target'] != 'release':
env_mono.Append(CPPDEFINES=['GD_MONO_HOT_RELOAD'])
-# Configure TLS checks
+# Configure Thread Local Storage
+
+import build_scripts.tls_configure as tls_configure
-import tls_configure
conf = Configure(env_mono)
tls_configure.configure(conf)
env_mono = conf.Finish()
+# Configure Mono
-# Build GodotSharpTools solution
-
-
-import os
-
-
-def find_nuget_unix():
- import os
-
- if 'NUGET_PATH' in os.environ:
- hint_path = os.environ['NUGET_PATH']
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
- hint_path = os.path.join(hint_path, 'nuget')
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
-
- import os.path
- import sys
-
- hint_dirs = ['/opt/novell/mono/bin']
- if sys.platform == 'darwin':
- hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin', '/usr/local/var/homebrew/linked/mono/bin'] + hint_dirs
-
- for hint_dir in hint_dirs:
- hint_path = os.path.join(hint_dir, 'nuget')
- if os.path.isfile(hint_path):
- return hint_path
- elif os.path.isfile(hint_path + '.exe'):
- return hint_path + '.exe'
-
- for hint_dir in os.environ['PATH'].split(os.pathsep):
- hint_dir = hint_dir.strip('"')
- hint_path = os.path.join(hint_dir, 'nuget')
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
- if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK):
- return hint_path + '.exe'
-
- return None
-
-
-def find_nuget_windows():
- import os
-
- if 'NUGET_PATH' in os.environ:
- hint_path = os.environ['NUGET_PATH']
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
- hint_path = os.path.join(hint_path, 'nuget.exe')
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
-
- import mono_reg_utils as monoreg
-
- mono_root = ''
- bits = env['bits']
-
- if bits == '32':
- if os.getenv('MONO32_PREFIX'):
- mono_root = os.getenv('MONO32_PREFIX')
- else:
- mono_root = monoreg.find_mono_root_dir(bits)
- else:
- if os.getenv('MONO64_PREFIX'):
- mono_root = os.getenv('MONO64_PREFIX')
- else:
- mono_root = monoreg.find_mono_root_dir(bits)
-
- if mono_root:
- mono_bin_dir = os.path.join(mono_root, 'bin')
- nuget_mono = os.path.join(mono_bin_dir, 'nuget.bat')
-
- if os.path.isfile(nuget_mono):
- return nuget_mono
-
- # Standalone NuGet
-
- for hint_dir in os.environ['PATH'].split(os.pathsep):
- hint_dir = hint_dir.strip('"')
- hint_path = os.path.join(hint_dir, 'nuget.exe')
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
-
- return None
-
-
-def find_msbuild_unix(filename):
- import os.path
- import sys
-
- hint_dirs = ['/opt/novell/mono/bin']
- if sys.platform == 'darwin':
- hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin', '/usr/local/var/homebrew/linked/mono/bin'] + hint_dirs
-
- for hint_dir in hint_dirs:
- hint_path = os.path.join(hint_dir, filename)
- if os.path.isfile(hint_path):
- return hint_path
- elif os.path.isfile(hint_path + '.exe'):
- return hint_path + '.exe'
+import build_scripts.mono_configure as mono_configure
- for hint_dir in os.environ['PATH'].split(os.pathsep):
- hint_dir = hint_dir.strip('"')
- hint_path = os.path.join(hint_dir, filename)
- if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
- return hint_path
- if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK):
- return hint_path + '.exe'
+mono_configure.configure(env, env_mono)
- return None
+# Build GodotSharpTools
+import build_scripts.godotsharptools_build as godotsharptools_build
-def find_msbuild_windows():
- import mono_reg_utils as monoreg
-
- mono_root = ''
- bits = env['bits']
-
- if bits == '32':
- if os.getenv('MONO32_PREFIX'):
- mono_root = os.getenv('MONO32_PREFIX')
- else:
- mono_root = monoreg.find_mono_root_dir(bits)
- else:
- if os.getenv('MONO64_PREFIX'):
- mono_root = os.getenv('MONO64_PREFIX')
- else:
- mono_root = monoreg.find_mono_root_dir(bits)
-
- if not mono_root:
- raise RuntimeError('Cannot find mono root directory')
-
- framework_path = os.path.join(mono_root, 'lib', 'mono', '4.5')
- mono_bin_dir = os.path.join(mono_root, 'bin')
- msbuild_mono = os.path.join(mono_bin_dir, 'msbuild.bat')
-
- if os.path.isfile(msbuild_mono):
- # The (Csc/Vbc/Fsc)ToolExe environment variables are required when
- # building with Mono's MSBuild. They must point to the batch files
- # in Mono's bin directory to make sure they are executed with Mono.
- mono_msbuild_env = {
- 'CscToolExe': os.path.join(mono_bin_dir, 'csc.bat'),
- 'VbcToolExe': os.path.join(mono_bin_dir, 'vbc.bat'),
- 'FscToolExe': os.path.join(mono_bin_dir, 'fsharpc.bat')
- }
- return (msbuild_mono, framework_path, mono_msbuild_env)
-
- msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
-
- if msbuild_tools_path:
- return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {})
-
- return None
-
-
-def mono_build_solution(source, target, env):
- import subprocess
- import mono_reg_utils as monoreg
- from shutil import copyfile
-
- sln_path = os.path.abspath(str(source[0]))
- target_path = os.path.abspath(str(target[0]))
-
- framework_path = ''
- msbuild_env = os.environ.copy()
-
- # Needed when running from Developer Command Prompt for VS
- if 'PLATFORM' in msbuild_env:
- del msbuild_env['PLATFORM']
-
- # Find MSBuild
- if os.name == 'nt':
- msbuild_info = find_msbuild_windows()
- if msbuild_info is None:
- raise RuntimeError('Cannot find MSBuild executable')
- msbuild_path = msbuild_info[0]
- framework_path = msbuild_info[1]
- msbuild_env.update(msbuild_info[2])
- else:
- msbuild_path = find_msbuild_unix('msbuild')
- if msbuild_path is None:
- xbuild_fallback = env['xbuild_fallback']
-
- if xbuild_fallback and os.name == 'nt':
- print('Option \'xbuild_fallback\' not supported on Windows')
- xbuild_fallback = False
-
- if xbuild_fallback:
- print('Cannot find MSBuild executable, trying with xbuild')
- print('Warning: xbuild is deprecated')
-
- msbuild_path = find_msbuild_unix('xbuild')
-
- if msbuild_path is None:
- raise RuntimeError('Cannot find xbuild executable')
- else:
- raise RuntimeError('Cannot find MSBuild executable')
-
- print('MSBuild path: ' + msbuild_path)
-
- # Find NuGet
- nuget_path = find_nuget_windows() if os.name == 'nt' else find_nuget_unix()
- if nuget_path is None:
- raise RuntimeError('Cannot find NuGet executable')
-
- print('NuGet path: ' + nuget_path)
-
- # Do NuGet restore
-
- try:
- subprocess.check_call([nuget_path, 'restore', sln_path])
- except subprocess.CalledProcessError:
- raise RuntimeError('GodotSharpTools: NuGet restore failed')
-
- # Build solution
-
- build_config = 'Release'
-
- msbuild_args = [
- msbuild_path,
- sln_path,
- '/p:Configuration=' + build_config,
- ]
-
- if framework_path:
- msbuild_args += ['/p:FrameworkPathOverride=' + framework_path]
-
- try:
- subprocess.check_call(msbuild_args, env=msbuild_env)
- except subprocess.CalledProcessError:
- raise RuntimeError('GodotSharpTools: Build failed')
-
- # Copy files
-
- src_dir = os.path.abspath(os.path.join(sln_path, os.pardir, 'bin', build_config))
- dst_dir = os.path.abspath(os.path.join(target_path, os.pardir))
- asm_file = 'GodotSharpTools.dll'
-
- if not os.path.isdir(dst_dir):
- if os.path.exists(dst_dir):
- raise RuntimeError('Target directory is a file')
- os.makedirs(dst_dir)
-
- copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file))
-
- # Dependencies
- copyfile(os.path.join(src_dir, "DotNet.Glob.dll"), os.path.join(dst_dir, "DotNet.Glob.dll"))
-
-if env['tools']:
- output_dir = Dir('#bin').abspath
- editor_tools_dir = os.path.join(output_dir, 'GodotSharp', 'Tools')
-
- mono_sln_builder = Builder(action=mono_build_solution)
- env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder})
- env_mono.MonoBuildSolution(
- os.path.join(editor_tools_dir, 'GodotSharpTools.dll'),
- 'editor/GodotSharpTools/GodotSharpTools.sln'
- )
+godotsharptools_build.build(env_mono)
diff --git a/modules/mono/build_scripts/__init__.py b/modules/mono/build_scripts/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/modules/mono/build_scripts/__init__.py
diff --git a/modules/mono/build_scripts/godotsharptools_build.py b/modules/mono/build_scripts/godotsharptools_build.py
new file mode 100644
index 0000000000..af3a5cb5c6
--- /dev/null
+++ b/modules/mono/build_scripts/godotsharptools_build.py
@@ -0,0 +1,263 @@
+# Build GodotSharpTools solution
+
+
+import os
+
+from SCons.Script import Builder, Dir
+
+
+def find_nuget_unix():
+ import os
+
+ if 'NUGET_PATH' in os.environ:
+ hint_path = os.environ['NUGET_PATH']
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+ hint_path = os.path.join(hint_path, 'nuget')
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+
+ import os.path
+ import sys
+
+ hint_dirs = ['/opt/novell/mono/bin']
+ if sys.platform == 'darwin':
+ hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin', '/usr/local/var/homebrew/linked/mono/bin'] + hint_dirs
+
+ for hint_dir in hint_dirs:
+ hint_path = os.path.join(hint_dir, 'nuget')
+ if os.path.isfile(hint_path):
+ return hint_path
+ elif os.path.isfile(hint_path + '.exe'):
+ return hint_path + '.exe'
+
+ for hint_dir in os.environ['PATH'].split(os.pathsep):
+ hint_dir = hint_dir.strip('"')
+ hint_path = os.path.join(hint_dir, 'nuget')
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+ if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK):
+ return hint_path + '.exe'
+
+ return None
+
+
+def find_nuget_windows(env):
+ import os
+
+ if 'NUGET_PATH' in os.environ:
+ hint_path = os.environ['NUGET_PATH']
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+ hint_path = os.path.join(hint_path, 'nuget.exe')
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+
+ from . import mono_reg_utils as monoreg
+
+ mono_root = ''
+ bits = env['bits']
+
+ if bits == '32':
+ if os.getenv('MONO32_PREFIX'):
+ mono_root = os.getenv('MONO32_PREFIX')
+ else:
+ mono_root = monoreg.find_mono_root_dir(bits)
+ else:
+ if os.getenv('MONO64_PREFIX'):
+ mono_root = os.getenv('MONO64_PREFIX')
+ else:
+ mono_root = monoreg.find_mono_root_dir(bits)
+
+ if mono_root:
+ mono_bin_dir = os.path.join(mono_root, 'bin')
+ nuget_mono = os.path.join(mono_bin_dir, 'nuget.bat')
+
+ if os.path.isfile(nuget_mono):
+ return nuget_mono
+
+ # Standalone NuGet
+
+ for hint_dir in os.environ['PATH'].split(os.pathsep):
+ hint_dir = hint_dir.strip('"')
+ hint_path = os.path.join(hint_dir, 'nuget.exe')
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+
+ return None
+
+
+def find_msbuild_unix(filename):
+ import os.path
+ import sys
+
+ hint_dirs = ['/opt/novell/mono/bin']
+ if sys.platform == 'darwin':
+ hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current/bin', '/usr/local/var/homebrew/linked/mono/bin'] + hint_dirs
+
+ for hint_dir in hint_dirs:
+ hint_path = os.path.join(hint_dir, filename)
+ if os.path.isfile(hint_path):
+ return hint_path
+ elif os.path.isfile(hint_path + '.exe'):
+ return hint_path + '.exe'
+
+ for hint_dir in os.environ['PATH'].split(os.pathsep):
+ hint_dir = hint_dir.strip('"')
+ hint_path = os.path.join(hint_dir, filename)
+ if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
+ return hint_path
+ if os.path.isfile(hint_path + '.exe') and os.access(hint_path + '.exe', os.X_OK):
+ return hint_path + '.exe'
+
+ return None
+
+
+def find_msbuild_windows(env):
+ from . import mono_reg_utils as monoreg
+
+ mono_root = ''
+ bits = env['bits']
+
+ if bits == '32':
+ if os.getenv('MONO32_PREFIX'):
+ mono_root = os.getenv('MONO32_PREFIX')
+ else:
+ mono_root = monoreg.find_mono_root_dir(bits)
+ else:
+ if os.getenv('MONO64_PREFIX'):
+ mono_root = os.getenv('MONO64_PREFIX')
+ else:
+ mono_root = monoreg.find_mono_root_dir(bits)
+
+ if not mono_root:
+ raise RuntimeError('Cannot find mono root directory')
+
+ framework_path = os.path.join(mono_root, 'lib', 'mono', '4.5')
+ mono_bin_dir = os.path.join(mono_root, 'bin')
+ msbuild_mono = os.path.join(mono_bin_dir, 'msbuild.bat')
+
+ if os.path.isfile(msbuild_mono):
+ # The (Csc/Vbc/Fsc)ToolExe environment variables are required when
+ # building with Mono's MSBuild. They must point to the batch files
+ # in Mono's bin directory to make sure they are executed with Mono.
+ mono_msbuild_env = {
+ 'CscToolExe': os.path.join(mono_bin_dir, 'csc.bat'),
+ 'VbcToolExe': os.path.join(mono_bin_dir, 'vbc.bat'),
+ 'FscToolExe': os.path.join(mono_bin_dir, 'fsharpc.bat')
+ }
+ return (msbuild_mono, framework_path, mono_msbuild_env)
+
+ msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
+
+ if msbuild_tools_path:
+ return (os.path.join(msbuild_tools_path, 'MSBuild.exe'), framework_path, {})
+
+ return None
+
+
+def mono_build_solution(source, target, env):
+ import subprocess
+ from shutil import copyfile
+
+ sln_path = os.path.abspath(str(source[0]))
+ target_path = os.path.abspath(str(target[0]))
+
+ framework_path = ''
+ msbuild_env = os.environ.copy()
+
+ # Needed when running from Developer Command Prompt for VS
+ if 'PLATFORM' in msbuild_env:
+ del msbuild_env['PLATFORM']
+
+ # Find MSBuild
+ if os.name == 'nt':
+ msbuild_info = find_msbuild_windows(env)
+ if msbuild_info is None:
+ raise RuntimeError('Cannot find MSBuild executable')
+ msbuild_path = msbuild_info[0]
+ framework_path = msbuild_info[1]
+ msbuild_env.update(msbuild_info[2])
+ else:
+ msbuild_path = find_msbuild_unix('msbuild')
+ if msbuild_path is None:
+ xbuild_fallback = env['xbuild_fallback']
+
+ if xbuild_fallback and os.name == 'nt':
+ print('Option \'xbuild_fallback\' not supported on Windows')
+ xbuild_fallback = False
+
+ if xbuild_fallback:
+ print('Cannot find MSBuild executable, trying with xbuild')
+ print('Warning: xbuild is deprecated')
+
+ msbuild_path = find_msbuild_unix('xbuild')
+
+ if msbuild_path is None:
+ raise RuntimeError('Cannot find xbuild executable')
+ else:
+ raise RuntimeError('Cannot find MSBuild executable')
+
+ print('MSBuild path: ' + msbuild_path)
+
+ # Find NuGet
+ nuget_path = find_nuget_windows(env) if os.name == 'nt' else find_nuget_unix()
+ if nuget_path is None:
+ raise RuntimeError('Cannot find NuGet executable')
+
+ print('NuGet path: ' + nuget_path)
+
+ # Do NuGet restore
+
+ try:
+ subprocess.check_call([nuget_path, 'restore', sln_path])
+ except subprocess.CalledProcessError:
+ raise RuntimeError('GodotSharpTools: NuGet restore failed')
+
+ # Build solution
+
+ build_config = 'Release'
+
+ msbuild_args = [
+ msbuild_path,
+ sln_path,
+ '/p:Configuration=' + build_config,
+ ]
+
+ if framework_path:
+ msbuild_args += ['/p:FrameworkPathOverride=' + framework_path]
+
+ try:
+ subprocess.check_call(msbuild_args, env=msbuild_env)
+ except subprocess.CalledProcessError:
+ raise RuntimeError('GodotSharpTools: Build failed')
+
+ # Copy files
+
+ src_dir = os.path.abspath(os.path.join(sln_path, os.pardir, 'bin', build_config))
+ dst_dir = os.path.abspath(os.path.join(target_path, os.pardir))
+ asm_file = 'GodotSharpTools.dll'
+
+ if not os.path.isdir(dst_dir):
+ if os.path.exists(dst_dir):
+ raise RuntimeError('Target directory is a file')
+ os.makedirs(dst_dir)
+
+ copyfile(os.path.join(src_dir, asm_file), os.path.join(dst_dir, asm_file))
+
+ # Dependencies
+ copyfile(os.path.join(src_dir, "DotNet.Glob.dll"), os.path.join(dst_dir, "DotNet.Glob.dll"))
+
+def build(env_mono):
+ if not env_mono['tools']:
+ return
+
+ output_dir = Dir('#bin').abspath
+ editor_tools_dir = os.path.join(output_dir, 'GodotSharp', 'Tools')
+
+ mono_sln_builder = Builder(action=mono_build_solution)
+ env_mono.Append(BUILDERS={'MonoBuildSolution': mono_sln_builder})
+ env_mono.MonoBuildSolution(
+ os.path.join(editor_tools_dir, 'GodotSharpTools.dll'),
+ 'editor/GodotSharpTools/GodotSharpTools.sln'
+ )
diff --git a/modules/mono/build_scripts/make_cs_compressed_header.py b/modules/mono/build_scripts/make_cs_compressed_header.py
new file mode 100644
index 0000000000..1f9177cef8
--- /dev/null
+++ b/modules/mono/build_scripts/make_cs_compressed_header.py
@@ -0,0 +1,61 @@
+
+def generate_header(src, dst, version_dst):
+ from compat import byte_to_str
+
+ with open(dst, 'w') as header:
+ header.write('/* THIS FILE IS GENERATED DO NOT EDIT */\n')
+ header.write('#ifndef CS_COMPRESSED_H\n')
+ header.write('#define CS_COMPRESSED_H\n\n')
+ header.write('#ifdef TOOLS_ENABLED\n\n')
+ header.write('#include "core/map.h"\n')
+ header.write('#include "core/ustring.h"\n')
+ inserted_files = ''
+ import os
+ latest_mtime = 0
+ cs_file_count = 0
+ for root, _, files in os.walk(src):
+ files = [f for f in files if f.endswith('.cs')]
+ for file in files:
+ cs_file_count += 1
+ filepath = os.path.join(root, file)
+ filepath_src_rel = os.path.relpath(filepath, src)
+ mtime = os.path.getmtime(filepath)
+ latest_mtime = mtime if mtime > latest_mtime else latest_mtime
+ with open(filepath, 'rb') as f:
+ buf = f.read()
+ decomp_size = len(buf)
+ import zlib
+ buf = zlib.compress(buf)
+ name = str(cs_file_count)
+ header.write('\n')
+ header.write('// ' + filepath_src_rel + '\n')
+ header.write('static const int _cs_' + name + '_compressed_size = ' + str(len(buf)) + ';\n')
+ header.write('static const int _cs_' + name + '_uncompressed_size = ' + str(decomp_size) + ';\n')
+ header.write('static const unsigned char _cs_' + name + '_compressed[] = { ')
+ for i, buf_idx in enumerate(range(len(buf))):
+ if i > 0:
+ header.write(', ')
+ header.write(byte_to_str(buf[buf_idx]))
+ inserted_files += '\tr_files.insert("' + filepath_src_rel.replace('\\', '\\\\') + '", ' \
+ 'CompressedFile(_cs_' + name + '_compressed_size, ' \
+ '_cs_' + name + '_uncompressed_size, ' \
+ '_cs_' + name + '_compressed));\n'
+ header.write(' };\n')
+ header.write('\nstruct CompressedFile\n' '{\n'
+ '\tint compressed_size;\n' '\tint uncompressed_size;\n' '\tconst unsigned char* data;\n'
+ '\n\tCompressedFile(int p_comp_size, int p_uncomp_size, const unsigned char* p_data)\n'
+ '\t{\n' '\t\tcompressed_size = p_comp_size;\n' '\t\tuncompressed_size = p_uncomp_size;\n'
+ '\t\tdata = p_data;\n' '\t}\n' '\n\tCompressedFile() {}\n' '};\n'
+ '\nvoid get_compressed_files(Map<String, CompressedFile>& r_files)\n' '{\n' + inserted_files + '}\n'
+ )
+ header.write('\n#endif // TOOLS_ENABLED\n')
+ header.write('\n#endif // CS_COMPRESSED_H\n')
+
+ glue_version = int(latest_mtime) # The latest modified time will do for now
+
+ with open(version_dst, 'w') as version_header:
+ version_header.write('/* THIS FILE IS GENERATED DO NOT EDIT */\n')
+ version_header.write('#ifndef CS_GLUE_VERSION_H\n')
+ version_header.write('#define CS_GLUE_VERSION_H\n\n')
+ version_header.write('#define CS_GLUE_VERSION UINT32_C(' + str(glue_version) + ')\n')
+ version_header.write('\n#endif // CS_GLUE_VERSION_H\n')
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
new file mode 100644
index 0000000000..160580e116
--- /dev/null
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -0,0 +1,414 @@
+import imp
+import os
+import sys
+import subprocess
+
+from distutils.version import LooseVersion
+from SCons.Script import BoolVariable, Dir, Environment, Variables
+
+if os.name == 'nt':
+ from . import mono_reg_utils as monoreg
+
+
+def find_file_in_dir(directory, files, prefix='', extension=''):
+ if not extension.startswith('.'):
+ extension = '.' + extension
+ for curfile in files:
+ if os.path.isfile(os.path.join(directory, prefix + curfile + extension)):
+ return curfile
+ return ''
+
+
+def copy_file(src_dir, dst_dir, name):
+ from shutil import copyfile
+
+ src_path = os.path.join(src_dir, name)
+ dst_path = os.path.join(dst_dir, name)
+
+ if not os.path.isdir(dst_dir):
+ os.mkdir(dst_dir)
+
+ copyfile(src_path, dst_path)
+
+
+def configure(env, env_mono):
+ envvars = Variables()
+ envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
+ envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False))
+ envvars.Update(env)
+
+ bits = env['bits']
+
+ tools_enabled = env['tools']
+ mono_static = env['mono_static']
+ copy_mono_root = env['copy_mono_root']
+
+ mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
+
+ if env['platform'] == 'windows':
+ mono_root = ''
+
+ if bits == '32':
+ if os.getenv('MONO32_PREFIX'):
+ mono_root = os.getenv('MONO32_PREFIX')
+ elif os.name == 'nt':
+ mono_root = monoreg.find_mono_root_dir(bits)
+ else:
+ if os.getenv('MONO64_PREFIX'):
+ mono_root = os.getenv('MONO64_PREFIX')
+ elif os.name == 'nt':
+ mono_root = monoreg.find_mono_root_dir(bits)
+
+ if not mono_root:
+ raise RuntimeError('Mono installation directory not found')
+
+ print('Found Mono root directory: ' + mono_root)
+
+ mono_version = mono_root_try_find_mono_version(mono_root)
+ configure_for_mono_version(env_mono, mono_version)
+
+ mono_lib_path = os.path.join(mono_root, 'lib')
+
+ env.Append(LIBPATH=mono_lib_path)
+ env_mono.Append(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0'))
+
+ if mono_static:
+ lib_suffix = Environment()['LIBSUFFIX']
+
+ if env.msvc:
+ mono_static_lib_name = 'libmono-static-sgen'
+ else:
+ mono_static_lib_name = 'libmonosgen-2.0'
+
+ if not os.path.isfile(os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix)):
+ raise RuntimeError('Could not find static mono library in: ' + mono_lib_path)
+
+ if env.msvc:
+ env.Append(LINKFLAGS=mono_static_lib_name + lib_suffix)
+
+ env.Append(LINKFLAGS='Mincore' + lib_suffix)
+ env.Append(LINKFLAGS='msvcrt' + lib_suffix)
+ env.Append(LINKFLAGS='LIBCMT' + lib_suffix)
+ env.Append(LINKFLAGS='Psapi' + lib_suffix)
+ else:
+ env.Append(LINKFLAGS=os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix))
+
+ env.Append(LIBS='psapi')
+ env.Append(LIBS='version')
+ else:
+ mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib')
+
+ if not mono_lib_name:
+ raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
+
+ if env.msvc:
+ env.Append(LINKFLAGS=mono_lib_name + Environment()['LIBSUFFIX'])
+ else:
+ env.Append(LIBS=mono_lib_name)
+
+ mono_bin_path = os.path.join(mono_root, 'bin')
+
+ mono_dll_name = find_file_in_dir(mono_bin_path, mono_lib_names, extension='.dll')
+
+ if not mono_dll_name:
+ raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
+
+ copy_file(mono_bin_path, 'bin', mono_dll_name + '.dll')
+ else:
+ is_apple = (sys.platform == 'darwin' or "osxcross" in env)
+
+ sharedlib_ext = '.dylib' if is_apple else '.so'
+
+ mono_root = ''
+ mono_lib_path = ''
+
+ if bits == '32':
+ if os.getenv('MONO32_PREFIX'):
+ mono_root = os.getenv('MONO32_PREFIX')
+ else:
+ if os.getenv('MONO64_PREFIX'):
+ mono_root = os.getenv('MONO64_PREFIX')
+
+ if not mono_root and is_apple:
+ # Try with some known directories under OSX
+ hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current', '/usr/local/var/homebrew/linked/mono']
+ for hint_dir in hint_dirs:
+ if os.path.isdir(hint_dir):
+ mono_root = hint_dir
+ break
+
+ # We can't use pkg-config to link mono statically,
+ # but we can still use it to find the mono root directory
+ if not mono_root and mono_static:
+ mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext)
+ if not mono_root:
+ raise RuntimeError('Building with mono_static=yes, but failed to find the mono prefix with pkg-config. Specify one manually')
+
+ if mono_root:
+ print('Found Mono root directory: ' + mono_root)
+
+ mono_version = mono_root_try_find_mono_version(mono_root)
+ configure_for_mono_version(env_mono, mono_version)
+
+ mono_lib_path = os.path.join(mono_root, 'lib')
+
+ env.Append(LIBPATH=mono_lib_path)
+ env_mono.Append(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0'))
+
+ mono_lib = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension='.a')
+
+ if not mono_lib:
+ raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
+
+ env_mono.Append(CPPFLAGS=['-D_REENTRANT'])
+
+ if mono_static:
+ mono_lib_file = os.path.join(mono_lib_path, 'lib' + mono_lib + '.a')
+
+ if is_apple:
+ env.Append(LINKFLAGS=['-Wl,-force_load,' + mono_lib_file])
+ else:
+ env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive'])
+ else:
+ env.Append(LIBS=[mono_lib])
+
+ if is_apple:
+ env.Append(LIBS=['iconv', 'pthread'])
+ else:
+ env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
+
+ if not mono_static:
+ mono_so_name = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension=sharedlib_ext)
+
+ if not mono_so_name:
+ raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)
+
+ copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
+ else:
+ assert not mono_static
+
+ # TODO: Add option to force using pkg-config
+ print('Mono root directory not found. Using pkg-config instead')
+
+ mono_version = pkgconfig_try_find_mono_version()
+ configure_for_mono_version(env_mono, mono_version)
+
+ env.ParseConfig('pkg-config monosgen-2 --libs')
+ env_mono.ParseConfig('pkg-config monosgen-2 --cflags')
+
+ mono_lib_path = ''
+ mono_so_name = ''
+
+ tmpenv = Environment()
+ tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
+ tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
+
+ for hint_dir in tmpenv['LIBPATH']:
+ name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext)
+ if name_found:
+ mono_lib_path = hint_dir
+ mono_so_name = name_found
+ break
+
+ if not mono_so_name:
+ raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))
+
+ copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
+
+ env.Append(LINKFLAGS='-rdynamic')
+
+ if not tools_enabled:
+ if not mono_root:
+ mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
+
+ make_template_dir(env, mono_root)
+
+ if copy_mono_root:
+ if not mono_root:
+ mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
+
+ if tools_enabled:
+ copy_mono_root_files(env, mono_root)
+ else:
+ print("Ignoring option: 'copy_mono_root'. Only available for builds with 'tools' enabled.")
+
+
+def make_template_dir(env, mono_root):
+ from shutil import rmtree
+
+ platform = env['platform']
+ target = env['target']
+
+ template_dir_name = ''
+
+ if platform in ['windows', 'osx', 'x11']:
+ template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target)
+ else:
+ assert False
+
+ output_dir = Dir('#bin').abspath
+ template_dir = os.path.join(output_dir, template_dir_name)
+
+ template_mono_root_dir = os.path.join(template_dir, 'Mono')
+
+ if os.path.isdir(template_mono_root_dir):
+ rmtree(template_mono_root_dir) # Clean first
+
+ # Copy etc/mono/
+
+ template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono')
+ copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform'])
+
+ # Copy the required shared libraries
+
+ copy_mono_shared_libs(mono_root, template_mono_root_dir, env['platform'])
+
+
+def copy_mono_root_files(env, mono_root):
+ from glob import glob
+ from shutil import copy
+ from shutil import rmtree
+
+ if not mono_root:
+ raise RuntimeError('Mono installation directory not found')
+
+ output_dir = Dir('#bin').abspath
+ editor_mono_root_dir = os.path.join(output_dir, 'GodotSharp', 'Mono')
+
+ if os.path.isdir(editor_mono_root_dir):
+ rmtree(editor_mono_root_dir) # Clean first
+
+ # Copy etc/mono/
+
+ editor_mono_config_dir = os.path.join(editor_mono_root_dir, 'etc', 'mono')
+ copy_mono_etc_dir(mono_root, editor_mono_config_dir, env['platform'])
+
+ # Copy the required shared libraries
+
+ copy_mono_shared_libs(mono_root, editor_mono_root_dir, env['platform'])
+
+ # Copy framework assemblies
+
+ mono_framework_dir = os.path.join(mono_root, 'lib', 'mono', '4.5')
+ mono_framework_facades_dir = os.path.join(mono_framework_dir, 'Facades')
+
+ editor_mono_framework_dir = os.path.join(editor_mono_root_dir, 'lib', 'mono', '4.5')
+ editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, 'Facades')
+
+ if not os.path.isdir(editor_mono_framework_dir):
+ os.makedirs(editor_mono_framework_dir)
+ if not os.path.isdir(editor_mono_framework_facades_dir):
+ os.makedirs(editor_mono_framework_facades_dir)
+
+ for assembly in glob(os.path.join(mono_framework_dir, '*.dll')):
+ copy(assembly, editor_mono_framework_dir)
+ for assembly in glob(os.path.join(mono_framework_facades_dir, '*.dll')):
+ copy(assembly, editor_mono_framework_facades_dir)
+
+
+def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
+ from distutils.dir_util import copy_tree
+ from glob import glob
+ from shutil import copy
+
+ if not os.path.isdir(target_mono_config_dir):
+ os.makedirs(target_mono_config_dir)
+
+ mono_etc_dir = os.path.join(mono_root, 'etc', 'mono')
+ if not os.path.isdir(mono_etc_dir):
+ mono_etc_dir = ''
+ etc_hint_dirs = []
+ if platform != 'windows':
+ etc_hint_dirs += ['/etc/mono', '/usr/local/etc/mono']
+ if 'MONO_CFG_DIR' in os.environ:
+ etc_hint_dirs += [os.path.join(os.environ['MONO_CFG_DIR'], 'mono')]
+ for etc_hint_dir in etc_hint_dirs:
+ if os.path.isdir(etc_hint_dir):
+ mono_etc_dir = etc_hint_dir
+ break
+ if not mono_etc_dir:
+ raise RuntimeError('Mono installation etc directory not found')
+
+ copy_tree(os.path.join(mono_etc_dir, '2.0'), os.path.join(target_mono_config_dir, '2.0'))
+ copy_tree(os.path.join(mono_etc_dir, '4.0'), os.path.join(target_mono_config_dir, '4.0'))
+ copy_tree(os.path.join(mono_etc_dir, '4.5'), os.path.join(target_mono_config_dir, '4.5'))
+ copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig'))
+
+ for file in glob(os.path.join(mono_etc_dir, '*')):
+ if os.path.isfile(file):
+ copy(file, target_mono_config_dir)
+
+
+def copy_mono_shared_libs(mono_root, target_mono_root_dir, platform):
+ from shutil import copy
+
+ if platform == 'windows':
+ target_mono_bin_dir = os.path.join(target_mono_root_dir, 'bin')
+
+ if not os.path.isdir(target_mono_bin_dir):
+ os.makedirs(target_mono_bin_dir)
+
+ copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll'))
+ else:
+ target_mono_lib_dir = os.path.join(target_mono_root_dir, 'lib')
+
+ if not os.path.isdir(target_mono_lib_dir):
+ os.makedirs(target_mono_lib_dir)
+
+ if platform == 'osx':
+ copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.dylib'))
+ elif platform == 'x11':
+ copy(os.path.join(mono_root, 'lib', 'libmono-btls-shared.so'), os.path.join(target_mono_lib_dir, 'libmono-btls-shared.so'))
+ copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.so'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.so'))
+
+
+def configure_for_mono_version(env, mono_version):
+ if mono_version is None:
+ raise RuntimeError('Mono JIT compiler version not found')
+ print('Found Mono JIT compiler version: ' + str(mono_version))
+ if mono_version >= LooseVersion('5.12.0'):
+ env.Append(CPPFLAGS=['-DHAS_PENDING_EXCEPTIONS'])
+
+
+def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext):
+ tmpenv = Environment()
+ tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
+ tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
+ for hint_dir in tmpenv['LIBPATH']:
+ name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext)
+ if name_found and os.path.isdir(os.path.join(hint_dir, '..', 'include', 'mono-2.0')):
+ return os.path.join(hint_dir, '..')
+ return ''
+
+
+def pkgconfig_try_find_mono_version():
+ from compat import decode_utf8
+
+ lines = subprocess.check_output(['pkg-config', 'monosgen-2', '--modversion']).splitlines()
+ greater_version = None
+ for line in lines:
+ try:
+ version = LooseVersion(decode_utf8(line))
+ if greater_version is None or version > greater_version:
+ greater_version = version
+ except ValueError:
+ pass
+ return greater_version
+
+
+def mono_root_try_find_mono_version(mono_root):
+ from compat import decode_utf8
+
+ mono_bin = os.path.join(mono_root, 'bin')
+ if os.path.isfile(os.path.join(mono_bin, 'mono')):
+ mono_binary = os.path.join(mono_bin, 'mono')
+ elif os.path.isfile(os.path.join(mono_bin, 'mono.exe')):
+ mono_binary = os.path.join(mono_bin, 'mono.exe')
+ else:
+ return None
+ output = subprocess.check_output([mono_binary, '--version'])
+ first_line = decode_utf8(output.splitlines()[0])
+ try:
+ return LooseVersion(first_line.split()[len('Mono JIT compiler version'.split())])
+ except (ValueError, IndexError):
+ return None
diff --git a/modules/mono/mono_reg_utils.py b/modules/mono/build_scripts/mono_reg_utils.py
index c8ebb54ded..583708bf07 100644
--- a/modules/mono/mono_reg_utils.py
+++ b/modules/mono/build_scripts/mono_reg_utils.py
@@ -40,7 +40,7 @@ def _reg_open_key_bits(key, subkey, bits):
def _find_mono_in_reg(subkey, bits):
try:
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
- value, regtype = winreg.QueryValueEx(hKey, 'SdkInstallRoot')
+ value = winreg.QueryValueEx(hKey, 'SdkInstallRoot')[0]
return value
except (WindowsError, OSError):
return None
@@ -49,7 +49,7 @@ def _find_mono_in_reg(subkey, bits):
def _find_mono_in_reg_old(subkey, bits):
try:
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
- default_clr, regtype = winreg.QueryValueEx(hKey, 'DefaultCLR')
+ default_clr = winreg.QueryValueEx(hKey, 'DefaultCLR')[0]
if default_clr:
return _find_mono_in_reg(subkey + '\\' + default_clr, bits)
return None
@@ -91,7 +91,13 @@ def find_msbuild_tools_path_reg():
if not val:
raise ValueError('Value of `installationPath` entry is empty')
- return os.path.join(val, "MSBuild\\15.0\\Bin")
+ # Since VS2019, the directory is simply named "Current"
+ msbuild_dir = os.path.join(val, 'MSBuild\\Current\\Bin')
+ if os.path.isdir(msbuild_dir):
+ return msbuild_dir
+
+ # Directory name "15.0" is used in VS 2017
+ return os.path.join(val, 'MSBuild\\15.0\\Bin')
raise ValueError('Cannot find `installationPath` entry')
except ValueError as e:
@@ -106,7 +112,7 @@ def find_msbuild_tools_path_reg():
try:
subkey = r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0'
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
- value, regtype = winreg.QueryValueEx(hKey, 'MSBuildToolsPath')
+ value = winreg.QueryValueEx(hKey, 'MSBuildToolsPath')[0]
return value
except (WindowsError, OSError):
return ''
diff --git a/modules/mono/tls_configure.py b/modules/mono/build_scripts/tls_configure.py
index 622280b00b..622280b00b 100644
--- a/modules/mono/tls_configure.py
+++ b/modules/mono/build_scripts/tls_configure.py
diff --git a/modules/mono/config.py b/modules/mono/config.py
index a81ecfce70..3b2e96765e 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -1,25 +1,12 @@
-
-import imp
-import os
-import sys
-import subprocess
-
-from distutils.version import LooseVersion
-from SCons.Script import BoolVariable, Dir, Environment, File, SCons, Variables
-
-
-monoreg = imp.load_source('mono_reg_utils', 'modules/mono/mono_reg_utils.py')
-
-
def can_build(env, platform):
if platform in ['javascript']:
return False # Not yet supported
return True
-def is_enabled():
- # The module is disabled by default. Use module_mono_enabled=yes to enable it.
- return False
+def configure(env):
+ env.use_ptrcall = True
+ env.add_module_version_string('mono')
def get_doc_classes():
@@ -34,407 +21,6 @@ def get_doc_path():
return 'doc_classes'
-def find_file_in_dir(directory, files, prefix='', extension=''):
- if not extension.startswith('.'):
- extension = '.' + extension
- for curfile in files:
- if os.path.isfile(os.path.join(directory, prefix + curfile + extension)):
- return curfile
- return ''
-
-
-def copy_file(src_dir, dst_dir, name):
- from shutil import copyfile
-
- src_path = os.path.join(src_dir, name)
- dst_path = os.path.join(dst_dir, name)
-
- if not os.path.isdir(dst_dir):
- os.mkdir(dst_dir)
-
- copyfile(src_path, dst_path)
-
-
-def configure(env):
- env.use_ptrcall = True
- env.add_module_version_string('mono')
-
- envvars = Variables()
- envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
- envvars.Add(BoolVariable('copy_mono_root', 'Make a copy of the mono installation directory to bundle with the editor', False))
- envvars.Update(env)
-
- bits = env['bits']
-
- tools_enabled = env['tools']
- mono_static = env['mono_static']
- copy_mono_root = env['copy_mono_root']
-
- mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
-
- if env['platform'] == 'windows':
- mono_root = ''
-
- if bits == '32':
- if os.getenv('MONO32_PREFIX'):
- mono_root = os.getenv('MONO32_PREFIX')
- elif os.name == 'nt':
- mono_root = monoreg.find_mono_root_dir(bits)
- else:
- if os.getenv('MONO64_PREFIX'):
- mono_root = os.getenv('MONO64_PREFIX')
- elif os.name == 'nt':
- mono_root = monoreg.find_mono_root_dir(bits)
-
- if not mono_root:
- raise RuntimeError('Mono installation directory not found')
-
- print('Found Mono root directory: ' + mono_root)
-
- mono_version = mono_root_try_find_mono_version(mono_root)
- configure_for_mono_version(env, mono_version)
-
- mono_lib_path = os.path.join(mono_root, 'lib')
-
- env.Append(LIBPATH=mono_lib_path)
- env.Append(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0'))
-
- if mono_static:
- lib_suffix = Environment()['LIBSUFFIX']
-
- if env.msvc:
- mono_static_lib_name = 'libmono-static-sgen'
- else:
- mono_static_lib_name = 'libmonosgen-2.0'
-
- if not os.path.isfile(os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix)):
- raise RuntimeError('Could not find static mono library in: ' + mono_lib_path)
-
- if env.msvc:
- env.Append(LINKFLAGS=mono_static_lib_name + lib_suffix)
-
- env.Append(LINKFLAGS='Mincore' + lib_suffix)
- env.Append(LINKFLAGS='msvcrt' + lib_suffix)
- env.Append(LINKFLAGS='LIBCMT' + lib_suffix)
- env.Append(LINKFLAGS='Psapi' + lib_suffix)
- else:
- env.Append(LINKFLAGS=os.path.join(mono_lib_path, mono_static_lib_name + lib_suffix))
-
- env.Append(LIBS='psapi')
- env.Append(LIBS='version')
- else:
- mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib')
-
- if not mono_lib_name:
- raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
-
- if env.msvc:
- env.Append(LINKFLAGS=mono_lib_name + Environment()['LIBSUFFIX'])
- else:
- env.Append(LIBS=mono_lib_name)
-
- mono_bin_path = os.path.join(mono_root, 'bin')
-
- mono_dll_name = find_file_in_dir(mono_bin_path, mono_lib_names, extension='.dll')
-
- if not mono_dll_name:
- raise RuntimeError('Could not find mono shared library in: ' + mono_bin_path)
-
- copy_file(mono_bin_path, 'bin', mono_dll_name + '.dll')
- else:
- is_apple = (sys.platform == 'darwin' or "osxcross" in env)
-
- sharedlib_ext = '.dylib' if is_apple else '.so'
-
- mono_root = ''
- mono_lib_path = ''
-
- if bits == '32':
- if os.getenv('MONO32_PREFIX'):
- mono_root = os.getenv('MONO32_PREFIX')
- else:
- if os.getenv('MONO64_PREFIX'):
- mono_root = os.getenv('MONO64_PREFIX')
-
- if not mono_root and is_apple:
- # Try with some known directories under OSX
- hint_dirs = ['/Library/Frameworks/Mono.framework/Versions/Current', '/usr/local/var/homebrew/linked/mono']
- for hint_dir in hint_dirs:
- if os.path.isdir(hint_dir):
- mono_root = hint_dir
- break
-
- # We can't use pkg-config to link mono statically,
- # but we can still use it to find the mono root directory
- if not mono_root and mono_static:
- mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext)
- if not mono_root:
- raise RuntimeError('Building with mono_static=yes, but failed to find the mono prefix with pkg-config. Specify one manually')
-
- if mono_root:
- print('Found Mono root directory: ' + mono_root)
-
- mono_version = mono_root_try_find_mono_version(mono_root)
- configure_for_mono_version(env, mono_version)
-
- mono_lib_path = os.path.join(mono_root, 'lib')
-
- env.Append(LIBPATH=mono_lib_path)
- env.Append(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0'))
-
- mono_lib = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension='.a')
-
- if not mono_lib:
- raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
-
- env.Append(CPPFLAGS=['-D_REENTRANT'])
-
- if mono_static:
- mono_lib_file = os.path.join(mono_lib_path, 'lib' + mono_lib + '.a')
-
- if is_apple:
- env.Append(LINKFLAGS=['-Wl,-force_load,' + mono_lib_file])
- else:
- env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive'])
- else:
- env.Append(LIBS=[mono_lib])
-
- if is_apple:
- env.Append(LIBS=['iconv', 'pthread'])
- else:
- env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
-
- if not mono_static:
- mono_so_name = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension=sharedlib_ext)
-
- if not mono_so_name:
- raise RuntimeError('Could not find mono shared library in: ' + mono_lib_path)
-
- copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
- else:
- assert not mono_static
-
- # TODO: Add option to force using pkg-config
- print('Mono root directory not found. Using pkg-config instead')
-
- mono_version = pkgconfig_try_find_mono_version()
- configure_for_mono_version(env, mono_version)
-
- env.ParseConfig('pkg-config monosgen-2 --cflags --libs')
-
- mono_lib_path = ''
- mono_so_name = ''
-
- tmpenv = Environment()
- tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
- tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
-
- for hint_dir in tmpenv['LIBPATH']:
- name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext)
- if name_found:
- mono_lib_path = hint_dir
- mono_so_name = name_found
- break
-
- if not mono_so_name:
- raise RuntimeError('Could not find mono shared library in: ' + str(tmpenv['LIBPATH']))
-
- copy_file(mono_lib_path, 'bin', 'lib' + mono_so_name + sharedlib_ext)
-
- env.Append(LINKFLAGS='-rdynamic')
-
- if not tools_enabled:
- if not mono_root:
- mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
-
- make_template_dir(env, mono_root)
-
- if copy_mono_root:
- if not mono_root:
- mono_root = subprocess.check_output(['pkg-config', 'mono-2', '--variable=prefix']).decode('utf8').strip()
-
- if tools_enabled:
- copy_mono_root_files(env, mono_root)
- else:
- print("Ignoring option: 'copy_mono_root'. Only available for builds with 'tools' enabled.")
-
-
-def make_template_dir(env, mono_root):
- from shutil import rmtree
-
- platform = env['platform']
- target = env['target']
-
- template_dir_name = ''
-
- if platform in ['windows', 'osx', 'x11']:
- template_dir_name = 'data.mono.%s.%s.%s' % (platform, env['bits'], target)
- else:
- assert False
-
- output_dir = Dir('#bin').abspath
- template_dir = os.path.join(output_dir, template_dir_name)
-
- template_mono_root_dir = os.path.join(template_dir, 'Mono')
-
- if os.path.isdir(template_mono_root_dir):
- rmtree(template_mono_root_dir) # Clean first
-
- # Copy etc/mono/
-
- template_mono_config_dir = os.path.join(template_mono_root_dir, 'etc', 'mono')
- copy_mono_etc_dir(mono_root, template_mono_config_dir, env['platform'])
-
- # Copy the required shared libraries
-
- copy_mono_shared_libs(mono_root, template_mono_root_dir, env['platform'])
-
-
-def copy_mono_root_files(env, mono_root):
- from glob import glob
- from shutil import copy
- from shutil import rmtree
-
- if not mono_root:
- raise RuntimeError('Mono installation directory not found')
-
- output_dir = Dir('#bin').abspath
- editor_mono_root_dir = os.path.join(output_dir, 'GodotSharp', 'Mono')
-
- if os.path.isdir(editor_mono_root_dir):
- rmtree(editor_mono_root_dir) # Clean first
-
- # Copy etc/mono/
-
- editor_mono_config_dir = os.path.join(editor_mono_root_dir, 'etc', 'mono')
- copy_mono_etc_dir(mono_root, editor_mono_config_dir, env['platform'])
-
- # Copy the required shared libraries
-
- copy_mono_shared_libs(mono_root, editor_mono_root_dir, env['platform'])
-
- # Copy framework assemblies
-
- mono_framework_dir = os.path.join(mono_root, 'lib', 'mono', '4.5')
- mono_framework_facades_dir = os.path.join(mono_framework_dir, 'Facades')
-
- editor_mono_framework_dir = os.path.join(editor_mono_root_dir, 'lib', 'mono', '4.5')
- editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, 'Facades')
-
- if not os.path.isdir(editor_mono_framework_dir):
- os.makedirs(editor_mono_framework_dir)
- if not os.path.isdir(editor_mono_framework_facades_dir):
- os.makedirs(editor_mono_framework_facades_dir)
-
- for assembly in glob(os.path.join(mono_framework_dir, '*.dll')):
- copy(assembly, editor_mono_framework_dir)
- for assembly in glob(os.path.join(mono_framework_facades_dir, '*.dll')):
- copy(assembly, editor_mono_framework_facades_dir)
-
-
-def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
- from distutils.dir_util import copy_tree
- from glob import glob
- from shutil import copy
-
- if not os.path.isdir(target_mono_config_dir):
- os.makedirs(target_mono_config_dir)
-
- mono_etc_dir = os.path.join(mono_root, 'etc', 'mono')
- if not os.path.isdir(mono_etc_dir):
- mono_etc_dir = ''
- etc_hint_dirs = []
- if platform != 'windows':
- etc_hint_dirs += ['/etc/mono', '/usr/local/etc/mono']
- if 'MONO_CFG_DIR' in os.environ:
- etc_hint_dirs += [os.path.join(os.environ['MONO_CFG_DIR'], 'mono')]
- for etc_hint_dir in etc_hint_dirs:
- if os.path.isdir(etc_hint_dir):
- mono_etc_dir = etc_hint_dir
- break
- if not mono_etc_dir:
- raise RuntimeError('Mono installation etc directory not found')
-
- copy_tree(os.path.join(mono_etc_dir, '2.0'), os.path.join(target_mono_config_dir, '2.0'))
- copy_tree(os.path.join(mono_etc_dir, '4.0'), os.path.join(target_mono_config_dir, '4.0'))
- copy_tree(os.path.join(mono_etc_dir, '4.5'), os.path.join(target_mono_config_dir, '4.5'))
- copy_tree(os.path.join(mono_etc_dir, 'mconfig'), os.path.join(target_mono_config_dir, 'mconfig'))
-
- for file in glob(os.path.join(mono_etc_dir, '*')):
- if os.path.isfile(file):
- copy(file, target_mono_config_dir)
-
-
-def copy_mono_shared_libs(mono_root, target_mono_root_dir, platform):
- from shutil import copy
-
- if platform == 'windows':
- target_mono_bin_dir = os.path.join(target_mono_root_dir, 'bin')
-
- if not os.path.isdir(target_mono_bin_dir):
- os.makedirs(target_mono_bin_dir)
-
- copy(os.path.join(mono_root, 'bin', 'MonoPosixHelper.dll'), os.path.join(target_mono_bin_dir, 'MonoPosixHelper.dll'))
- else:
- target_mono_lib_dir = os.path.join(target_mono_root_dir, 'lib')
-
- if not os.path.isdir(target_mono_lib_dir):
- os.makedirs(target_mono_lib_dir)
-
- if platform == 'osx':
- copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.dylib'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.dylib'))
- elif platform == 'x11':
- copy(os.path.join(mono_root, 'lib', 'libmono-btls-shared.so'), os.path.join(target_mono_lib_dir, 'libmono-btls-shared.so'))
- copy(os.path.join(mono_root, 'lib', 'libMonoPosixHelper.so'), os.path.join(target_mono_lib_dir, 'libMonoPosixHelper.so'))
-
-
-def configure_for_mono_version(env, mono_version):
- if mono_version is None:
- raise RuntimeError('Mono JIT compiler version not found')
- print('Found Mono JIT compiler version: ' + str(mono_version))
- if mono_version >= LooseVersion('5.12.0'):
- env.Append(CPPFLAGS=['-DHAS_PENDING_EXCEPTIONS'])
-
-
-def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext):
- tmpenv = Environment()
- tmpenv.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
- tmpenv.ParseConfig('pkg-config monosgen-2 --libs-only-L')
- for hint_dir in tmpenv['LIBPATH']:
- name_found = find_file_in_dir(hint_dir, mono_lib_names, prefix='lib', extension=sharedlib_ext)
- if name_found and os.path.isdir(os.path.join(hint_dir, '..', 'include', 'mono-2.0')):
- return os.path.join(hint_dir, '..')
- return ''
-
-
-def pkgconfig_try_find_mono_version():
- from compat import decode_utf8
-
- lines = subprocess.check_output(['pkg-config', 'monosgen-2', '--modversion']).splitlines()
- greater_version = None
- for line in lines:
- try:
- version = LooseVersion(decode_utf8(line))
- if greater_version is None or version > greater_version:
- greater_version = version
- except ValueError:
- pass
- return greater_version
-
-
-def mono_root_try_find_mono_version(mono_root):
- from compat import decode_utf8
-
- mono_bin = os.path.join(mono_root, 'bin')
- if os.path.isfile(os.path.join(mono_bin, 'mono')):
- mono_binary = os.path.join(mono_bin, 'mono')
- elif os.path.isfile(os.path.join(mono_bin, 'mono.exe')):
- mono_binary = os.path.join(mono_bin, 'mono.exe')
- else:
- return None
- output = subprocess.check_output([mono_binary, '--version'])
- first_line = decode_utf8(output.splitlines()[0])
- try:
- return LooseVersion(first_line.split()[len('Mono JIT compiler version'.split())])
- except (ValueError, IndexError):
- return None
+def is_enabled():
+ # The module is disabled by default. Use module_mono_enabled=yes to enable it.
+ return False
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index e33b238f45..5f97069485 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -571,7 +571,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec
MonoException *exc = NULL;
- MonoArray *frames = invoke_method_thunk(CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames), p_stack_trace, (MonoObject **)&exc);
+ MonoArray *frames = invoke_method_thunk(CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames), p_stack_trace, &exc);
if (exc) {
GDMonoUtils::debug_print_unhandled_exception(exc);
@@ -595,7 +595,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObjec
MonoString *file_name;
int file_line_num;
MonoString *method_decl;
- invoke_method_thunk(get_sf_info, frame, &file_name, &file_line_num, &method_decl, (MonoObject **)&exc);
+ invoke_method_thunk(get_sf_info, frame, &file_name, &file_line_num, &method_decl, &exc);
if (exc) {
GDMonoUtils::debug_print_unhandled_exception(exc);
@@ -625,7 +625,7 @@ void CSharpLanguage::frame() {
if (task_scheduler) {
MonoException *exc = NULL;
- invoke_method_thunk(CACHED_METHOD_THUNK(GodotTaskScheduler, Activate), task_scheduler, (MonoObject **)&exc);
+ invoke_method_thunk(CACHED_METHOD_THUNK(GodotTaskScheduler, Activate), task_scheduler, &exc);
if (exc) {
GDMonoUtils::debug_unhandled_exception(exc);
@@ -1577,7 +1577,7 @@ MonoObject *CSharpInstance::_internal_new_managed() {
// Search the constructor first, to fail with an error if it's not found before allocating anything else.
GDMonoMethod *ctor = script->script_class->get_method(CACHED_STRING_NAME(dotctor), 0);
if (ctor == NULL) {
- ERR_PRINTS("Cannot create script instance because the class does not define a default constructor: " + script->get_path());
+ ERR_PRINTS("Cannot create script instance because the class does not define a parameterless constructor: " + script->get_path());
ERR_EXPLAIN("Constructor not found");
ERR_FAIL_V(NULL);
@@ -1966,7 +1966,7 @@ bool CSharpScript::_update_exports() {
GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0);
if (ctor == NULL) {
- ERR_PRINTS("Cannot construct temporary MonoObject because the class does not define a default constructor: " + get_path());
+ ERR_PRINTS("Cannot construct temporary MonoObject because the class does not define a parameterless constructor: " + get_path());
ERR_EXPLAIN("Constructor not found");
ERR_FAIL_V(NULL);
@@ -2166,7 +2166,8 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_
CRASH_NOW();
}
- Variant::Type variant_type = GDMonoMarshal::managed_to_variant_type(type);
+ GDMonoMarshal::ExportInfo export_info;
+ Variant::Type variant_type = GDMonoMarshal::managed_to_variant_type(type, &export_info);
if (!p_member->has_attribute(CACHED_CLASS(ExportAttribute))) {
r_prop_info = PropertyInfo(variant_type, name.operator String(), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE);
@@ -2191,6 +2192,7 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_
ERR_PRINTS("Unknown type of exported member: " + p_class->get_full_name() + "." + name.operator String());
return false;
} else if (variant_type == Variant::INT && type.type_encoding == MONO_TYPE_VALUETYPE && mono_class_is_enum(type.type_class->get_mono_ptr())) {
+ // TODO: Move to ExportInfo?
variant_type = Variant::INT;
hint = PROPERTY_HINT_ENUM;
@@ -2257,6 +2259,11 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_
hint = PROPERTY_HINT_RESOURCE_TYPE;
hint_string = NATIVE_GDMONOCLASS_NAME(field_native_class);
+ } else if (variant_type == Variant::ARRAY && export_info.array.element_type != Variant::NIL) {
+ hint = PROPERTY_HINT_TYPE_STRING;
+ hint_string = itos(export_info.array.element_type) + ":";
+ } else if (variant_type == Variant::DICTIONARY && export_info.dictionary.key_type != Variant::NIL && export_info.dictionary.value_type != Variant::NIL) {
+ // TODO: There is no hint for this yet
} else {
hint = PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr));
hint_string = CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr);
@@ -2460,7 +2467,7 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount);
if (ctor == NULL) {
if (p_argcount == 0) {
- ERR_PRINTS("Cannot create script instance because the class does not define a default constructor: " + get_path());
+ ERR_PRINTS("Cannot create script instance because the class does not define a parameterless constructor: " + get_path());
}
ERR_EXPLAIN("Constructor not found");
diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml
index 082bc30fd8..a821713d0d 100644
--- a/modules/mono/doc_classes/@C#.xml
+++ b/modules/mono/doc_classes/@C#.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="@C#" category="Core" version="3.1">
+<class name="@C#" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml
index a1f7399653..7f22388132 100644
--- a/modules/mono/doc_classes/CSharpScript.xml
+++ b/modules/mono/doc_classes/CSharpScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="CSharpScript" inherits="Script" category="Core" version="3.1">
+<class name="CSharpScript" inherits="Script" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml
index 921c1ca825..21835e639c 100644
--- a/modules/mono/doc_classes/GodotSharp.xml
+++ b/modules/mono/doc_classes/GodotSharp.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="GodotSharp" inherits="Object" category="Core" version="3.1">
+<class name="GodotSharp" inherits="Object" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 35a89956a8..cb4eb46052 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -100,7 +100,7 @@
#define BINDINGS_GENERATOR_VERSION UINT32_C(8)
-const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
+const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n");
bool BindingsGenerator::verbose_output = false;
@@ -277,7 +277,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else if (code_tag) {
xml_output.append("[");
pos = brk_pos + 1;
- } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ")) {
+ } else if (tag.begins_with("method ") || tag.begins_with("member ") || tag.begins_with("signal ") || tag.begins_with("enum ") || tag.begins_with("constant ")) {
String link_target = tag.substr(tag.find(" ") + 1, tag.length());
String link_tag = tag.substr(0, tag.find(" "));
@@ -386,6 +386,97 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
xml_output.append(link_target);
xml_output.append("</c>");
}
+ } else if (link_tag == "const") {
+ if (!target_itype || !target_itype->is_object_type) {
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ if (target_itype) {
+ OS::get_singleton()->print("Cannot resolve constant reference for non-Godot.Object type in documentation: %s\n", link_target.utf8().get_data());
+ } else {
+ OS::get_singleton()->print("Cannot resolve type from constant reference in documentation: %s\n", link_target.utf8().get_data());
+ }
+ }
+
+ // TODO Map what we can
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ } else if (!target_itype && target_cname == name_cache.type_at_GlobalScope) {
+ String target_name = (String)target_cname;
+
+ // Try to find as a global constant
+ const ConstantInterface *target_iconst = find_constant_by_name(target_name, global_constants);
+
+ if (target_iconst) {
+ // Found global constant
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE "." BINDINGS_GLOBAL_SCOPE_CLASS ".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ // Try to find as global enum constant
+ const EnumInterface *target_ienum = NULL;
+
+ for (const List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
+ target_ienum = &E->get();
+ target_iconst = find_constant_by_name(target_name, target_ienum->constants);
+ if (target_iconst)
+ break;
+ }
+
+ if (target_iconst) {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_ienum->cname);
+ xml_output.append(".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ ERR_PRINTS("Cannot resolve global constant reference in documentation: " + link_target);
+
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ }
+ }
+ } else {
+ String target_name = (String)target_cname;
+
+ // Try to find the constant in the current class
+ const ConstantInterface *target_iconst = find_constant_by_name(target_name, target_itype->constants);
+
+ if (target_iconst) {
+ // Found constant in current class
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_itype->proxy_name);
+ xml_output.append(".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ // Try to find as enum constant in the current class
+ const EnumInterface *target_ienum = NULL;
+
+ for (const List<EnumInterface>::Element *E = target_itype->enums.front(); E; E = E->next()) {
+ target_ienum = &E->get();
+ target_iconst = find_constant_by_name(target_name, target_ienum->constants);
+ if (target_iconst)
+ break;
+ }
+
+ if (target_iconst) {
+ xml_output.append("<see cref=\"" BINDINGS_NAMESPACE ".");
+ xml_output.append(target_itype->proxy_name);
+ xml_output.append(".");
+ xml_output.append(target_ienum->cname);
+ xml_output.append(".");
+ xml_output.append(target_iconst->proxy_name);
+ xml_output.append("\"/>");
+ } else {
+ ERR_PRINTS("Cannot resolve constant reference in documentation: " + link_target);
+
+ xml_output.append("<c>");
+ xml_output.append(link_target);
+ xml_output.append("</c>");
+ }
+ }
+ }
}
pos = brk_end + 1;
@@ -414,7 +505,7 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
} else if (tag == "Nil") {
xml_output.append("<see langword=\"null\"/>");
} else if (tag.begins_with("@")) {
- // @Global Scope, @GDScript, etc
+ // @GlobalScope, @GDScript, etc
xml_output.append("<c>");
xml_output.append(tag);
xml_output.append("</c>");
@@ -2406,6 +2497,7 @@ void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, Arg
r_iarg.default_argument = "null";
break;
}
+ FALLTHROUGH;
case Variant::DICTIONARY:
case Variant::_RID:
r_iarg.default_argument = "new %s()";
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 7eaebeabbd..42071f9c0d 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -497,6 +497,7 @@ class BindingsGenerator {
StringName type_Object;
StringName type_Reference;
StringName type_String;
+ StringName type_at_GlobalScope;
StringName enum_Error;
NameCache() {
@@ -509,6 +510,7 @@ class BindingsGenerator {
type_Object = StaticCString::create("Object");
type_Reference = StaticCString::create("Reference");
type_String = StaticCString::create("String");
+ type_at_GlobalScope = StaticCString::create("@GlobalScope");
enum_Error = StaticCString::create("Error");
}
@@ -527,6 +529,15 @@ class BindingsGenerator {
return NULL;
}
+ const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
+ for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) {
+ if (E->get().name == p_name)
+ return &E->get();
+ }
+
+ return NULL;
+ }
+
inline String get_unique_sig(const TypeInterface &p_type) {
if (p_type.is_reference)
return "Ref";
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index 921b9f987b..9d42528927 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -502,11 +502,11 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
String settings_hint_str = "Disabled";
-#ifdef WINDOWS_ENABLED
+#if defined(WINDOWS_ENABLED)
settings_hint_str += ",MonoDevelop,Visual Studio Code";
-#elif OSX_ENABLED
+#elif defined(OSX_ENABLED)
settings_hint_str += ",Visual Studio,MonoDevelop,Visual Studio Code";
-#elif UNIX_ENABLED
+#elif defined(UNIX_ENABLED)
settings_hint_str += ",MonoDevelop,Visual Studio Code";
#endif
diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h
index cf0d2aec84..d9523c384c 100644
--- a/modules/mono/editor/godotsharp_editor.h
+++ b/modules/mono/editor/godotsharp_editor.h
@@ -81,15 +81,15 @@ public:
enum ExternalEditor {
EDITOR_NONE,
-#ifdef WINDOWS_ENABLED
+#if defined(WINDOWS_ENABLED)
//EDITOR_VISUALSTUDIO, // TODO
EDITOR_MONODEVELOP,
EDITOR_VSCODE
-#elif OSX_ENABLED
+#elif defined(OSX_ENABLED)
EDITOR_VISUALSTUDIO_MAC,
EDITOR_MONODEVELOP,
EDITOR_VSCODE
-#elif UNIX_ENABLED
+#elif defined(UNIX_ENABLED)
EDITOR_MONODEVELOP,
EDITOR_VSCODE
#endif
diff --git a/modules/mono/glue/Managed/Files/Array.cs b/modules/mono/glue/Managed/Files/Array.cs
index 1ee64f3b71..2277c7bf18 100644
--- a/modules/mono/glue/Managed/Files/Array.cs
+++ b/modules/mono/glue/Managed/Files/Array.cs
@@ -28,7 +28,7 @@ namespace Godot.Collections
}
}
- public class Array : IList<object>, ICollection<object>, IEnumerable<object>, IDisposable
+ public class Array : IList, IDisposable
{
ArraySafeHandle safeHandle;
bool disposed = false;
@@ -38,6 +38,14 @@ namespace Godot.Collections
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
}
+ public Array(IEnumerable collection) : this()
+ {
+ if (collection == null)
+ throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
+
+ MarshalUtils.EnumerableToArray(collection, GetPtr());
+ }
+
internal Array(ArraySafeHandle handle)
{
safeHandle = handle;
@@ -56,6 +64,13 @@ namespace Godot.Collections
return safeHandle.DangerousGetHandle();
}
+ public Error Resize(int newSize)
+ {
+ return godot_icall_Array_Resize(GetPtr(), newSize);
+ }
+
+ // IDisposable
+
public void Dispose()
{
if (disposed)
@@ -70,62 +85,55 @@ namespace Godot.Collections
disposed = true;
}
+ // IList
+
+ public bool IsReadOnly => false;
+
+ public bool IsFixedSize => false;
+
public object this[int index]
{
- get
- {
- return godot_icall_Array_At(GetPtr(), index);
- }
- set
- {
- godot_icall_Array_SetAt(GetPtr(), index, value);
- }
+ get => godot_icall_Array_At(GetPtr(), index);
+ set => godot_icall_Array_SetAt(GetPtr(), index, value);
}
- public int Count
- {
- get
- {
- return godot_icall_Array_Count(GetPtr());
- }
- }
+ public int Add(object value) => godot_icall_Array_Add(GetPtr(), value);
- public bool IsReadOnly
- {
- get
- {
- return false;
- }
- }
+ public bool Contains(object value) => godot_icall_Array_Contains(GetPtr(), value);
- public void Add(object item)
- {
- godot_icall_Array_Add(GetPtr(), item);
- }
+ public void Clear() => godot_icall_Array_Clear(GetPtr());
- public void Clear()
- {
- godot_icall_Array_Clear(GetPtr());
- }
+ public int IndexOf(object value) => godot_icall_Array_IndexOf(GetPtr(), value);
- public bool Contains(object item)
- {
- return godot_icall_Array_Contains(GetPtr(), item);
- }
+ public void Insert(int index, object value) => godot_icall_Array_Insert(GetPtr(), index, value);
+
+ public void Remove(object value) => godot_icall_Array_Remove(GetPtr(), value);
+
+ public void RemoveAt(int index) => godot_icall_Array_RemoveAt(GetPtr(), index);
+
+ // ICollection
+
+ public int Count => godot_icall_Array_Count(GetPtr());
+
+ public object SyncRoot => this;
- public void CopyTo(object[] array, int arrayIndex)
+ public bool IsSynchronized => false;
+
+ public void CopyTo(System.Array array, int index)
{
if (array == null)
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
- if (arrayIndex < 0)
- throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
// Internal call may throw ArgumentException
- godot_icall_Array_CopyTo(GetPtr(), array, arrayIndex);
+ godot_icall_Array_CopyTo(GetPtr(), array, index);
}
- public IEnumerator<object> GetEnumerator()
+ // IEnumerable
+
+ public IEnumerator GetEnumerator()
{
int count = Count;
@@ -135,36 +143,6 @@ namespace Godot.Collections
}
}
- public int IndexOf(object item)
- {
- return godot_icall_Array_IndexOf(GetPtr(), item);
- }
-
- public void Insert(int index, object item)
- {
- godot_icall_Array_Insert(GetPtr(), index, item);
- }
-
- public bool Remove(object item)
- {
- return godot_icall_Array_Remove(GetPtr(), item);
- }
-
- public void RemoveAt(int index)
- {
- godot_icall_Array_RemoveAt(GetPtr(), index);
- }
-
- public Error Resize(int newSize)
- {
- return godot_icall_Array_Resize(GetPtr(), newSize);
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_Array_Ctor();
@@ -184,7 +162,7 @@ namespace Godot.Collections
internal extern static int godot_icall_Array_Count(IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_Add(IntPtr ptr, object item);
+ internal extern static int godot_icall_Array_Add(IntPtr ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Array_Clear(IntPtr ptr);
@@ -193,7 +171,7 @@ namespace Godot.Collections
internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, object[] array, int arrayIndex);
+ internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item);
@@ -231,6 +209,14 @@ namespace Godot.Collections
objectArray = new Array();
}
+ public Array(IEnumerable<T> collection)
+ {
+ if (collection == null)
+ throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
+
+ objectArray = new Array(collection);
+ }
+
public Array(Array array)
{
objectArray = array;
@@ -246,11 +232,23 @@ namespace Godot.Collections
objectArray = new Array(handle);
}
+ internal IntPtr GetPtr()
+ {
+ return objectArray.GetPtr();
+ }
+
public static explicit operator Array(Array<T> from)
{
return from.objectArray;
}
+ public Error Resize(int newSize)
+ {
+ return objectArray.Resize(newSize);
+ }
+
+ // IList<T>
+
public T this[int index]
{
get
@@ -263,6 +261,23 @@ namespace Godot.Collections
}
}
+ public int IndexOf(T item)
+ {
+ return objectArray.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ objectArray.Insert(index, item);
+ }
+
+ public void RemoveAt(int index)
+ {
+ objectArray.RemoveAt(index);
+ }
+
+ // ICollection<T>
+
public int Count
{
get
@@ -317,6 +332,13 @@ namespace Godot.Collections
}
}
+ public bool Remove(T item)
+ {
+ return Array.godot_icall_Array_Remove(GetPtr(), item);
+ }
+
+ // IEnumerable<T>
+
public IEnumerator<T> GetEnumerator()
{
int count = objectArray.Count;
@@ -327,39 +349,9 @@ namespace Godot.Collections
}
}
- public int IndexOf(T item)
- {
- return objectArray.IndexOf(item);
- }
-
- public void Insert(int index, T item)
- {
- objectArray.Insert(index, item);
- }
-
- public bool Remove(T item)
- {
- return objectArray.Remove(item);
- }
-
- public void RemoveAt(int index)
- {
- objectArray.RemoveAt(index);
- }
-
- public Error Resize(int newSize)
- {
- return objectArray.Resize(newSize);
- }
-
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
-
- internal IntPtr GetPtr()
- {
- return objectArray.GetPtr();
- }
}
}
diff --git a/modules/mono/glue/Managed/Files/Dictionary.cs b/modules/mono/glue/Managed/Files/Dictionary.cs
index fb4521065f..af1782b79a 100644
--- a/modules/mono/glue/Managed/Files/Dictionary.cs
+++ b/modules/mono/glue/Managed/Files/Dictionary.cs
@@ -29,9 +29,7 @@ namespace Godot.Collections
}
public class Dictionary :
- IDictionary<object, object>,
- ICollection<KeyValuePair<object, object>>,
- IEnumerable<KeyValuePair<object, object>>,
+ IDictionary,
IDisposable
{
DictionarySafeHandle safeHandle;
@@ -42,6 +40,14 @@ namespace Godot.Collections
safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
}
+ public Dictionary(IDictionary dictionary) : this()
+ {
+ if (dictionary == null)
+ throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
+
+ MarshalUtils.IDictionaryToDictionary(dictionary, GetPtr());
+ }
+
internal Dictionary(DictionarySafeHandle handle)
{
safeHandle = handle;
@@ -74,19 +80,9 @@ namespace Godot.Collections
disposed = true;
}
- public object this[object key]
- {
- get
- {
- return godot_icall_Dictionary_GetValue(GetPtr(), key);
- }
- set
- {
- godot_icall_Dictionary_SetValue(GetPtr(), key, value);
- }
- }
+ // IDictionary
- public ICollection<object> Keys
+ public ICollection Keys
{
get
{
@@ -95,7 +91,7 @@ namespace Godot.Collections
}
}
- public ICollection<object> Values
+ public ICollection Values
{
get
{
@@ -104,97 +100,97 @@ namespace Godot.Collections
}
}
- public int Count
- {
- get
- {
- return godot_icall_Dictionary_Count(GetPtr());
- }
- }
+ public bool IsFixedSize => false;
- public bool IsReadOnly
- {
- get
- {
- return false;
- }
- }
+ public bool IsReadOnly => false;
- public void Add(object key, object value)
+ public object this[object key]
{
- godot_icall_Dictionary_Add(GetPtr(), key, value);
+ get => godot_icall_Dictionary_GetValue(GetPtr(), key);
+ set => godot_icall_Dictionary_SetValue(GetPtr(), key, value);
}
- public void Add(KeyValuePair<object, object> item)
- {
- Add(item.Key, item.Value);
- }
+ public void Add(object key, object value) => godot_icall_Dictionary_Add(GetPtr(), key, value);
- public void Clear()
- {
- godot_icall_Dictionary_Clear(GetPtr());
- }
+ public void Clear() => godot_icall_Dictionary_Clear(GetPtr());
- public bool Contains(KeyValuePair<object, object> item)
- {
- return godot_icall_Dictionary_Contains(GetPtr(), item.Key, item.Value);
- }
+ public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(GetPtr(), key);
- public bool ContainsKey(object key)
- {
- return godot_icall_Dictionary_ContainsKey(GetPtr(), key);
- }
+ public IDictionaryEnumerator GetEnumerator() => new DictionaryEnumerator(this);
+
+ public void Remove(object key) => godot_icall_Dictionary_RemoveKey(GetPtr(), key);
+
+ // ICollection
+
+ public object SyncRoot => this;
- public void CopyTo(KeyValuePair<object, object>[] array, int arrayIndex)
+ public bool IsSynchronized => false;
+
+ public int Count => godot_icall_Dictionary_Count(GetPtr());
+
+ public void CopyTo(System.Array array, int index)
{
- // TODO 3 internal calls, can reduce to 1
+ // TODO Can be done with single internal call
+
+ if (array == null)
+ throw new ArgumentNullException(nameof(array), "Value cannot be null.");
+
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
+
Array keys = (Array)Keys;
Array values = (Array)Values;
int count = Count;
+ if (array.Length < (index + count))
+ throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
+
for (int i = 0; i < count; i++)
{
- // TODO 2 internal calls, can reduce to 1
- array[arrayIndex] = new KeyValuePair<object, object>(keys[i], values[i]);
- arrayIndex++;
+ array.SetValue(new DictionaryEntry(keys[i], values[i]), index);
+ index++;
}
}
- public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
+ // IEnumerable
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ private class DictionaryEnumerator : IDictionaryEnumerator
{
- // TODO 3 internal calls, can reduce to 1
- Array keys = (Array)Keys;
- Array values = (Array)Values;
- int count = Count;
+ Array keys;
+ Array values;
+ int count;
+ int index = -1;
- for (int i = 0; i < count; i++)
+ public DictionaryEnumerator(Dictionary dictionary)
{
- // TODO 2 internal calls, can reduce to 1
- yield return new KeyValuePair<object, object>(keys[i], values[i]);
+ // TODO 3 internal calls, can reduce to 1
+ keys = (Array)dictionary.Keys;
+ values = (Array)dictionary.Values;
+ count = dictionary.Count;
}
- }
- public bool Remove(object key)
- {
- return godot_icall_Dictionary_RemoveKey(GetPtr(), key);
- }
+ public object Current => Entry;
- public bool Remove(KeyValuePair<object, object> item)
- {
- return godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
- }
+ public DictionaryEntry Entry =>
+ // TODO 2 internal calls, can reduce to 1
+ new DictionaryEntry(keys[index], values[index]);
- public bool TryGetValue(object key, out object value)
- {
- object retValue;
- bool found = godot_icall_Dictionary_TryGetValue(GetPtr(), key, out retValue);
- value = found ? retValue : default(object);
- return found;
- }
+ public object Key => Entry.Key;
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
+ public object Value => Entry.Value;
+
+ public bool MoveNext()
+ {
+ index++;
+ return index < count;
+ }
+
+ public void Reset()
+ {
+ index = -1;
+ }
}
[MethodImpl(MethodImplOptions.InternalCall)]
@@ -250,9 +246,7 @@ namespace Godot.Collections
}
public class Dictionary<TKey, TValue> :
- IDictionary<TKey, TValue>,
- ICollection<KeyValuePair<TKey, TValue>>,
- IEnumerable<KeyValuePair<TKey, TValue>>
+ IDictionary<TKey, TValue>
{
Dictionary objectDict;
@@ -269,6 +263,23 @@ namespace Godot.Collections
objectDict = new Dictionary();
}
+ public Dictionary(IDictionary<TKey, TValue> dictionary)
+ {
+ objectDict = new Dictionary();
+
+ if (dictionary == null)
+ throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
+
+ // TODO: Can be optimized
+
+ IntPtr godotDictionaryPtr = GetPtr();
+
+ foreach (KeyValuePair<TKey, TValue> entry in dictionary)
+ {
+ Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value);
+ }
+ }
+
public Dictionary(Dictionary dictionary)
{
objectDict = dictionary;
@@ -289,6 +300,13 @@ namespace Godot.Collections
return from.objectDict;
}
+ internal IntPtr GetPtr()
+ {
+ return objectDict.GetPtr();
+ }
+
+ // IDictionary<TKey, TValue>
+
public TValue this[TKey key]
{
get
@@ -319,6 +337,31 @@ namespace Godot.Collections
}
}
+ public void Add(TKey key, TValue value)
+ {
+ objectDict.Add(key, value);
+ }
+
+ public bool ContainsKey(TKey key)
+ {
+ return objectDict.Contains(key);
+ }
+
+ public bool Remove(TKey key)
+ {
+ return Dictionary.godot_icall_Dictionary_RemoveKey(GetPtr(), key);
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ object retValue;
+ bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out retValue, valTypeEncoding, valTypeClass);
+ value = found ? (TValue)retValue : default(TValue);
+ return found;
+ }
+
+ // ICollection<KeyValuePair<TKey, TValue>>
+
public int Count
{
get
@@ -335,11 +378,6 @@ namespace Godot.Collections
}
}
- public void Add(TKey key, TValue value)
- {
- objectDict.Add(key, value);
- }
-
public void Add(KeyValuePair<TKey, TValue> item)
{
objectDict.Add(item.Key, item.Value);
@@ -355,18 +393,22 @@ namespace Godot.Collections
return objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
}
- public bool ContainsKey(TKey key)
- {
- return objectDict.ContainsKey(key);
- }
-
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
+ if (array == null)
+ throw new ArgumentNullException(nameof(array), "Value cannot be null.");
+
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
+
// TODO 3 internal calls, can reduce to 1
Array<TKey> keys = (Array<TKey>)Keys;
Array<TValue> values = (Array<TValue>)Values;
int count = Count;
+ if (array.Length < (arrayIndex + count))
+ throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
+
for (int i = 0; i < count; i++)
{
// TODO 2 internal calls, can reduce to 1
@@ -375,6 +417,13 @@ namespace Godot.Collections
}
}
+ public bool Remove(KeyValuePair<TKey, TValue> item)
+ {
+ return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value); ;
+ }
+
+ // IEnumerable<KeyValuePair<TKey, TValue>>
+
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
// TODO 3 internal calls, can reduce to 1
@@ -389,32 +438,9 @@ namespace Godot.Collections
}
}
- public bool Remove(TKey key)
- {
- return objectDict.Remove(key);
- }
-
- public bool Remove(KeyValuePair<TKey, TValue> item)
- {
- return objectDict.Remove(new KeyValuePair<object, object>(item.Key, item.Value));
- }
-
- public bool TryGetValue(TKey key, out TValue value)
- {
- object retValue;
- bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out retValue, valTypeEncoding, valTypeClass);
- value = found ? (TValue)retValue : default(TValue);
- return found;
- }
-
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
-
- internal IntPtr GetPtr()
- {
- return objectDict.GetPtr();
- }
}
}
diff --git a/modules/mono/glue/Managed/Files/GD.cs b/modules/mono/glue/Managed/Files/GD.cs
index 3afaf5d08b..d968f8a78f 100644
--- a/modules/mono/glue/Managed/Files/GD.cs
+++ b/modules/mono/glue/Managed/Files/GD.cs
@@ -13,12 +13,12 @@ namespace Godot
{
public static partial class GD
{
- public static object Bytes2Var(byte[] bytes)
+ public static object Bytes2Var(byte[] bytes, bool allow_objects = false)
{
- return godot_icall_GD_bytes2var(bytes);
+ return godot_icall_GD_bytes2var(bytes, allow_objects);
}
- public static object Convert(object what, int type)
+ public static object Convert(object what, Variant.Type type)
{
return godot_icall_GD_convert(what, type);
}
@@ -186,9 +186,9 @@ namespace Godot
return godot_icall_GD_type_exists(type);
}
- public static byte[] Var2Bytes(object var)
+ public static byte[] Var2Bytes(object var, bool full_objects = false)
{
- return godot_icall_GD_var2bytes(var);
+ return godot_icall_GD_var2bytes(var, full_objects);
}
public static string Var2Str(object var)
@@ -197,10 +197,10 @@ namespace Godot
}
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_GD_bytes2var(byte[] bytes);
+ internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allow_objects);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static object godot_icall_GD_convert(object what, int type);
+ internal extern static object godot_icall_GD_convert(object what, Variant.Type type);
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static int godot_icall_GD_hash(object var);
@@ -251,7 +251,7 @@ namespace Godot
internal extern static bool godot_icall_GD_type_exists(string type);
[MethodImpl(MethodImplOptions.InternalCall)]
- internal extern static byte[] godot_icall_GD_var2bytes(object what);
+ internal extern static byte[] godot_icall_GD_var2bytes(object what, bool full_objects);
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static string godot_icall_GD_var2str(object var);
diff --git a/modules/mono/glue/Managed/Files/MarshalUtils.cs b/modules/mono/glue/Managed/Files/MarshalUtils.cs
index f7699a15bf..7e72b0edb5 100644
--- a/modules/mono/glue/Managed/Files/MarshalUtils.cs
+++ b/modules/mono/glue/Managed/Files/MarshalUtils.cs
@@ -1,18 +1,68 @@
using System;
-using Godot.Collections;
+using System.Collections;
namespace Godot
{
+ using Array = Godot.Collections.Array;
+ using Dictionary = Godot.Collections.Dictionary;
+
static class MarshalUtils
{
- static bool IsArrayGenericType(Type type)
+ static bool TypeIsGenericArray(Type type)
{
- return type.GetGenericTypeDefinition() == typeof(Array<>);
+ return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>);
+ }
+
+ static bool TypeIsGenericDictionary(Type type)
+ {
+ return type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
+ }
+
+ static void ArrayGetElementType(Type type, out Type elementType)
+ {
+ elementType = type.GetGenericArguments()[0];
+ }
+
+ static void DictionaryGetKeyValueTypes(Type type, out Type keyType, out Type valueType)
+ {
+ var genericArgs = type.GetGenericArguments();
+
+ keyType = genericArgs[0];
+ valueType = genericArgs[1];
+ }
+
+ // TODO Add support for IEnumerable<T> and IDictionary<TKey, TValue>
+ // TODO: EnumerableToArray and IDictionaryToDictionary can be optimized
+
+ internal static void EnumerableToArray(IEnumerable enumerable, IntPtr godotArrayPtr)
+ {
+ if (enumerable is ICollection collection)
+ {
+ int count = collection.Count;
+
+ object[] tempArray = new object[count];
+ collection.CopyTo(tempArray, 0);
+
+ for (int i = 0; i < count; i++)
+ {
+ Array.godot_icall_Array_Add(godotArrayPtr, tempArray[i]);
+ }
+ }
+ else
+ {
+ foreach (object element in enumerable)
+ {
+ Array.godot_icall_Array_Add(godotArrayPtr, element);
+ }
+ }
}
- static bool IsDictionaryGenericType(Type type)
+ internal static void IDictionaryToDictionary(IDictionary dictionary, IntPtr godotDictionaryPtr)
{
- return type.GetGenericTypeDefinition() == typeof(Dictionary<, >);
+ foreach (DictionaryEntry entry in dictionary)
+ {
+ Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value);
+ }
}
}
}
diff --git a/modules/mono/glue/Managed/Files/Mathf.cs b/modules/mono/glue/Managed/Files/Mathf.cs
index 5f5de12959..a064278237 100644
--- a/modules/mono/glue/Managed/Files/Mathf.cs
+++ b/modules/mono/glue/Managed/Files/Mathf.cs
@@ -261,6 +261,16 @@ namespace Godot
return (real_t)Math.Sinh(s);
}
+ public static real_t SmoothStep(real_t from, real_t to, real_t weight)
+ {
+ if (IsEqualApprox(from, to))
+ {
+ return from;
+ }
+ real_t x = Clamp((weight - from) / (to - from), (real_t)0.0, (real_t)1.0);
+ return x * x * (3 - 2 * x);
+ }
+
public static real_t Sqrt(real_t s)
{
return (real_t)Math.Sqrt(s);
diff --git a/modules/mono/glue/Managed/Files/Vector2.cs b/modules/mono/glue/Managed/Files/Vector2.cs
index 73a3252fdb..908162ec45 100644
--- a/modules/mono/glue/Managed/Files/Vector2.cs
+++ b/modules/mono/glue/Managed/Files/Vector2.cs
@@ -132,6 +132,11 @@ namespace Godot
(-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
}
+ public Vector2 DirectionTo(Vector2 b)
+ {
+ return new Vector2(b.x - x, b.y - y).Normalized();
+ }
+
public real_t DistanceSquaredTo(Vector2 to)
{
return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y);
diff --git a/modules/mono/glue/Managed/Files/Vector3.cs b/modules/mono/glue/Managed/Files/Vector3.cs
index f6ff27989d..0c96d346a9 100644
--- a/modules/mono/glue/Managed/Files/Vector3.cs
+++ b/modules/mono/glue/Managed/Files/Vector3.cs
@@ -126,6 +126,11 @@ namespace Godot
);
}
+ public Vector3 DirectionTo(Vector3 b)
+ {
+ return new Vector3(b.x - x, b.y - y, b.z - z).Normalized();
+ }
+
public real_t DistanceSquaredTo(Vector3 b)
{
return (b - this).LengthSquared();
diff --git a/modules/mono/glue/Managed/IgnoredFiles/Variant.cs b/modules/mono/glue/Managed/IgnoredFiles/Variant.cs
new file mode 100644
index 0000000000..802140b062
--- /dev/null
+++ b/modules/mono/glue/Managed/IgnoredFiles/Variant.cs
@@ -0,0 +1,11 @@
+
+namespace Godot
+{
+ public static class Variant
+ {
+ public enum Type
+ {
+
+ }
+ }
+}
diff --git a/modules/mono/glue/arguments_vector.h b/modules/mono/glue/arguments_vector.h
index cb558235d8..8c0f308c15 100644
--- a/modules/mono/glue/arguments_vector.h
+++ b/modules/mono/glue/arguments_vector.h
@@ -39,6 +39,7 @@ struct ArgumentsVector {
private:
T pool[POOL_SIZE];
T *_ptr;
+ int size;
ArgumentsVector();
ArgumentsVector(const ArgumentsVector &);
@@ -48,11 +49,18 @@ public:
T &get(int p_idx) { return _ptr[p_idx]; }
void set(int p_idx, const T &p_value) { _ptr[p_idx] = p_value; }
- explicit ArgumentsVector(int size) {
- if (size <= POOL_SIZE) {
+ explicit ArgumentsVector(int p_size) :
+ size(p_size) {
+ if (p_size <= POOL_SIZE) {
_ptr = pool;
} else {
- _ptr = memnew_arr(T, size);
+ _ptr = memnew_arr(T, p_size);
+ }
+ }
+
+ ~ArgumentsVector() {
+ if (size > POOL_SIZE) {
+ memdelete_arr(_ptr);
}
}
};
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index b690de0d20..7f367fa095 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -192,7 +192,7 @@ MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoStrin
*r_result = GDMonoMarshal::variant_to_mono_object(result);
- return error.error == OK;
+ return error.error == Variant::CallError::CALL_OK;
}
MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result) {
diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp
index 1aad1c53bc..84c3f354d8 100644
--- a/modules/mono/glue/collections_glue.cpp
+++ b/modules/mono/glue/collections_glue.cpp
@@ -73,8 +73,9 @@ int godot_icall_Array_Count(Array *ptr) {
return ptr->size();
}
-void godot_icall_Array_Add(Array *ptr, MonoObject *item) {
+int godot_icall_Array_Add(Array *ptr, MonoObject *item) {
ptr->append(GDMonoMarshal::mono_object_to_variant(item));
+ return ptr->size();
}
void godot_icall_Array_Clear(Array *ptr) {
diff --git a/modules/mono/glue/collections_glue.h b/modules/mono/glue/collections_glue.h
index 85a2e243a2..69768500d8 100644
--- a/modules/mono/glue/collections_glue.h
+++ b/modules/mono/glue/collections_glue.h
@@ -51,7 +51,7 @@ void godot_icall_Array_SetAt(Array *ptr, int index, MonoObject *value);
int godot_icall_Array_Count(Array *ptr);
-void godot_icall_Array_Add(Array *ptr, MonoObject *item);
+int godot_icall_Array_Add(Array *ptr, MonoObject *item);
void godot_icall_Array_Clear(Array *ptr);
diff --git a/modules/mono/glue/gd_glue.cpp b/modules/mono/glue/gd_glue.cpp
index af022dae81..d756131ac9 100644
--- a/modules/mono/glue/gd_glue.cpp
+++ b/modules/mono/glue/gd_glue.cpp
@@ -41,11 +41,11 @@
#include "../mono_gd/gd_mono_utils.h"
-MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes) {
+MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects) {
Variant ret;
PoolByteArray varr = GDMonoMarshal::mono_array_to_PoolByteArray(p_bytes);
PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, p_allow_objects);
if (err != OK) {
ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
}
@@ -187,19 +187,19 @@ void godot_icall_GD_pushwarning(MonoString *p_str) {
WARN_PRINTS(GDMonoMarshal::mono_string_to_godot(p_str));
}
-MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var) {
+MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects) {
Variant var = GDMonoMarshal::mono_object_to_variant(p_var);
PoolByteArray barr;
int len;
- Error err = encode_variant(var, NULL, len);
+ Error err = encode_variant(var, NULL, len, p_full_objects);
ERR_EXPLAIN("Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
ERR_FAIL_COND_V(err != OK, NULL);
barr.resize(len);
{
PoolByteArray::Write w = barr.write();
- encode_variant(var, w.ptr(), len);
+ encode_variant(var, w.ptr(), len, p_full_objects);
}
return GDMonoMarshal::PoolByteArray_to_mono_array(barr);
diff --git a/modules/mono/glue/gd_glue.h b/modules/mono/glue/gd_glue.h
index 2632639169..910979aae3 100644
--- a/modules/mono/glue/gd_glue.h
+++ b/modules/mono/glue/gd_glue.h
@@ -35,7 +35,7 @@
#include "../mono_gd/gd_mono_marshal.h"
-MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes);
+MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects);
MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type);
@@ -71,7 +71,7 @@ MonoObject *godot_icall_GD_str2var(MonoString *p_str);
MonoBoolean godot_icall_GD_type_exists(MonoString *p_type);
-MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var);
+MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects);
MonoString *godot_icall_GD_var2str(MonoObject *p_var);
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index bba7df2c6a..48bea4addf 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -212,7 +212,7 @@ void GDMono::initialize() {
String config_dir;
#ifdef TOOLS_ENABLED
-#ifdef WINDOWS_ENABLED
+#if defined(WINDOWS_ENABLED)
mono_reg_info = MonoRegUtils::find_mono();
if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) {
@@ -222,7 +222,7 @@ void GDMono::initialize() {
if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) {
config_dir = mono_reg_info.config_dir;
}
-#elif OSX_ENABLED
+#elif defined(OSX_ENABLED)
const char *c_assembly_rootdir = mono_assembly_getrootdir();
const char *c_config_dir = mono_get_config_dir();
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index 92324d73f9..4342f46109 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -55,7 +55,8 @@ String GDMonoClass::get_full_name() const {
}
MonoType *GDMonoClass::get_mono_type() {
- // Care, you cannot compare MonoType pointers
+ // Careful, you cannot compare two MonoType*.
+ // There is mono_metadata_type_equal, how is this different from comparing two MonoClass*?
return get_mono_type(mono_class);
}
@@ -260,6 +261,11 @@ bool GDMonoClass::has_fetched_method_unknown_params(const StringName &p_name) {
return get_fetched_method_unknown_params(p_name) != NULL;
}
+bool GDMonoClass::implements_interface(GDMonoClass *p_interface) {
+
+ return mono_class_implements_interface(mono_class, p_interface->get_mono_ptr());
+}
+
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) {
MethodKey key = MethodKey(p_name, p_params_count);
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index 4af909450e..249422b844 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -135,6 +135,8 @@ public:
void fetch_attributes();
void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base);
+ bool implements_interface(GDMonoClass *p_interface);
+
GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0);
GDMonoMethod *get_method(MonoMethod *p_raw_method);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name);
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 5e9d4db122..9779797d1a 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -313,6 +313,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
break;
}
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
+ mono_field_set_value(p_object, mono_field, managed);
+ break;
+ }
+
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
+ mono_field_set_value(p_object, mono_field, managed);
+ break;
+ }
+
ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + type_class->get_name());
ERR_FAIL();
} break;
@@ -422,8 +434,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
MonoException *exc = NULL;
- GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
- MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
+ MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_dict) {
@@ -434,8 +446,8 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
exc = NULL;
- GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
- MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
+ MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_array) {
@@ -443,6 +455,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
mono_field_set_value(p_object, mono_field, managed);
break;
}
+
+ if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
+ mono_field_set_value(p_object, mono_field, managed);
+ break;
+ }
+
+ if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
+ mono_field_set_value(p_object, mono_field, managed);
+ break;
+ }
} break;
default: {
diff --git a/modules/mono/mono_gd/gd_mono_header.h b/modules/mono/mono_gd/gd_mono_header.h
index dd8c047386..d7962eac8b 100644
--- a/modules/mono/mono_gd/gd_mono_header.h
+++ b/modules/mono/mono_gd/gd_mono_header.h
@@ -35,24 +35,12 @@
class GDMonoAssembly;
class GDMonoClass;
-class IMonoClassMember;
class GDMonoField;
-class GDMonoProperty;
class GDMonoMethod;
+class GDMonoProperty;
-struct ManagedType {
- int type_encoding;
- GDMonoClass *type_class;
-
- ManagedType() :
- type_encoding(0),
- type_class(NULL) {
- }
+class IMonoClassMember;
- ManagedType(int p_type_encoding, GDMonoClass *p_type_class) :
- type_encoding(p_type_encoding),
- type_class(p_type_class) {
- }
-};
+#include "managed_type.h"
#endif // GD_MONO_HEADER_H
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index 7fe8ae608a..de4f3650bd 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -35,7 +35,7 @@
namespace GDMonoMarshal {
-Variant::Type managed_to_variant_type(const ManagedType &p_type) {
+Variant::Type managed_to_variant_type(const ManagedType &p_type, ExportInfo *r_export_info) {
switch (p_type.type_encoding) {
case MONO_TYPE_BOOLEAN:
return Variant::BOOL;
@@ -156,26 +156,66 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
if (CACHED_CLASS(Array) == type_class) {
return Variant::ARRAY;
}
+
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ return Variant::DICTIONARY;
+ }
+
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ return Variant::ARRAY;
+ }
} break;
case MONO_TYPE_GENERICINST: {
MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, p_type.type_class->get_mono_type());
MonoException *exc = NULL;
- GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
- MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
+ MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_dict) {
+ if (r_export_info) {
+ MonoReflectionType *key_reftype;
+ MonoReflectionType *value_reftype;
+
+ exc = NULL;
+ invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes),
+ reftype, &key_reftype, &value_reftype, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+
+ r_export_info->dictionary.key_type = managed_to_variant_type(ManagedType::from_reftype(key_reftype));
+ r_export_info->dictionary.value_type = managed_to_variant_type(ManagedType::from_reftype(value_reftype));
+ }
+
return Variant::DICTIONARY;
}
exc = NULL;
- GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
- MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
+ MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_array) {
+ if (r_export_info) {
+ MonoReflectionType *elem_reftype;
+
+ exc = NULL;
+ invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType),
+ reftype, &elem_reftype, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+
+ r_export_info->array.element_type = managed_to_variant_type(ManagedType::from_reftype(elem_reftype));
+ }
+
+ return Variant::ARRAY;
+ }
+
+ if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ return Variant::DICTIONARY;
+ }
+
+ if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
return Variant::ARRAY;
}
} break;
@@ -453,6 +493,14 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
if (CACHED_CLASS(Array) == type_class) {
return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
}
+
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
+ }
+
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
+ }
} break;
case MONO_TYPE_OBJECT: {
// Variant
@@ -548,8 +596,8 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, p_type.type_class->get_mono_type());
MonoException *exc = NULL;
- GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
- MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
+ MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_dict) {
@@ -557,13 +605,21 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
}
exc = NULL;
- GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
- MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
+ MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_array) {
return GDMonoUtils::create_managed_from(p_var->operator Array(), p_type.type_class);
}
+
+ if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
+ }
+
+ if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
+ }
} break;
} break;
}
@@ -577,15 +633,9 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
if (!p_obj)
return Variant();
- GDMonoClass *tclass = GDMono::get_singleton()->get_class(mono_object_get_class(p_obj));
- ERR_FAIL_COND_V(!tclass, Variant());
+ ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj));
- MonoType *raw_type = tclass->get_mono_type();
-
- ManagedType type;
-
- type.type_encoding = mono_type_get_type(raw_type);
- type.type_class = tclass;
+ ERR_FAIL_COND_V(!type.type_class, Variant());
switch (type.type_encoding) {
case MONO_TYPE_BOOLEAN:
@@ -717,17 +767,33 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
if (CACHED_CLASS(Array) == type_class) {
MonoException *exc = NULL;
- Array *ptr = invoke_method_thunk(CACHED_METHOD_THUNK(Array, GetPtr), p_obj, (MonoObject **)&exc);
+ Array *ptr = invoke_method_thunk(CACHED_METHOD_THUNK(Array, GetPtr), p_obj, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return ptr ? Variant(*ptr) : Variant();
}
if (CACHED_CLASS(Dictionary) == type_class) {
MonoException *exc = NULL;
- Dictionary *ptr = invoke_method_thunk(CACHED_METHOD_THUNK(Dictionary, GetPtr), p_obj, (MonoObject **)&exc);
+ Dictionary *ptr = invoke_method_thunk(CACHED_METHOD_THUNK(Dictionary, GetPtr), p_obj, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return ptr ? Variant(*ptr) : Variant();
}
+
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ Dictionary dict;
+ MonoException *exc = NULL;
+ invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, IDictionaryToDictionary), p_obj, &dict, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+ return dict;
+ }
+
+ if (type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ Array array;
+ MonoException *exc = NULL;
+ invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, EnumerableToArray), p_obj, &array, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+ return array;
+ }
} break;
case MONO_TYPE_GENERICINST: {
@@ -735,8 +801,8 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
MonoException *exc = NULL;
- GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
- MonoBoolean is_dict = invoke_method_thunk(type_is_dict, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericDictionary type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary);
+ MonoBoolean is_dict = invoke_method_thunk(type_is_dict, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_dict) {
@@ -748,8 +814,8 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
exc = NULL;
- GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
- MonoBoolean is_array = invoke_method_thunk(type_is_array, (MonoObject *)reftype, (MonoObject **)&exc);
+ GDMonoUtils::TypeIsGenericArray type_is_array = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray);
+ MonoBoolean is_array = invoke_method_thunk(type_is_array, reftype, &exc);
UNLIKELY_UNHANDLED_EXCEPTION(exc);
if (is_array) {
@@ -758,6 +824,22 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
UNLIKELY_UNHANDLED_EXCEPTION(exc);
return *unbox<Array *>(ret);
}
+
+ if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
+ Dictionary dict;
+ exc = NULL;
+ invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, IDictionaryToDictionary), p_obj, &dict, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+ return dict;
+ }
+
+ if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
+ Array array;
+ exc = NULL;
+ invoke_method_thunk(CACHED_METHOD_THUNK(MarshalUtils, EnumerableToArray), p_obj, &array, &exc);
+ UNLIKELY_UNHANDLED_EXCEPTION(exc);
+ return array;
+ }
} break;
}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 4f86e02f87..4a73f9e3e6 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -32,6 +32,7 @@
#define GDMONOMARSHAL_H
#include "core/variant.h"
+
#include "gd_mono.h"
#include "gd_mono_utils.h"
@@ -56,7 +57,25 @@ T unbox(MonoObject *p_obj) {
#define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x)
#define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x)
-Variant::Type managed_to_variant_type(const ManagedType &p_type);
+// FIXME: Made this struct in a hurry. It could be done differently.
+struct ExportInfo {
+ struct ArrayInfo {
+ Variant::Type element_type;
+
+ ArrayInfo() :
+ element_type(Variant::NIL) {}
+ } array;
+ struct DictionaryInfo {
+ Variant::Type key_type;
+ Variant::Type value_type;
+
+ DictionaryInfo() :
+ key_type(Variant::NIL),
+ value_type(Variant::NIL) {}
+ } dictionary;
+};
+
+Variant::Type managed_to_variant_type(const ManagedType &p_type, ExportInfo *r_export_info = NULL);
// String
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 6cc1c8afc2..429d4f68d9 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -63,6 +63,7 @@ MonoCache mono_cache;
#define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
#define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val)
#define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
+#define CACHE_PROPERTY_AND_CHECK(m_class, m_property, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.property_##m_class##_##m_property, m_val)
void MonoCache::clear_members() {
@@ -81,6 +82,9 @@ void MonoCache::clear_members() {
class_String = NULL;
class_IntPtr = NULL;
+ class_System_Collections_IEnumerable = NULL;
+ class_System_Collections_IDictionary = NULL;
+
#ifdef DEBUG_ENABLED
class_System_Diagnostics_StackTrace = NULL;
methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL;
@@ -143,12 +147,17 @@ void MonoCache::clear_members() {
methodthunk_GodotObject_Dispose = NULL;
methodthunk_Array_GetPtr = NULL;
methodthunk_Dictionary_GetPtr = NULL;
- methodthunk_MarshalUtils_IsArrayGenericType = NULL;
- methodthunk_MarshalUtils_IsDictionaryGenericType = NULL;
methodthunk_SignalAwaiter_SignalCallback = NULL;
methodthunk_SignalAwaiter_FailureCallback = NULL;
methodthunk_GodotTaskScheduler_Activate = NULL;
+ methodthunk_MarshalUtils_TypeIsGenericArray = NULL;
+ methodthunk_MarshalUtils_TypeIsGenericDictionary = NULL;
+ methodthunk_MarshalUtils_ArrayGetElementType = NULL;
+ methodthunk_MarshalUtils_DictionaryGetKeyValueTypes = NULL;
+ methodthunk_MarshalUtils_EnumerableToArray = NULL;
+ methodthunk_MarshalUtils_IDictionaryToDictionary = NULL;
+
task_scheduler_handle = Ref<MonoGCHandle>();
}
@@ -178,6 +187,9 @@ void update_corlib_cache() {
CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
+ CACHE_CLASS_AND_CHECK(System_Collections_IEnumerable, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IEnumerable"));
+ CACHE_CLASS_AND_CHECK(System_Collections_IDictionary, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IDictionary"));
+
#ifdef DEBUG_ENABLED
CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace"));
CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_thunk("GetFrames"));
@@ -242,12 +254,17 @@ void update_godot_api_cache() {
CACHE_METHOD_THUNK_AND_CHECK(GodotObject, Dispose, (GodotObject_Dispose)CACHED_CLASS(GodotObject)->get_method_thunk("Dispose", 0));
CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array)->get_method_thunk("GetPtr", 0));
CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)->get_method_thunk("GetPtr", 0));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsArrayGenericType, (IsArrayGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsArrayGenericType", 1));
- CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsDictionaryGenericType, (IsDictionaryGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsDictionaryGenericType", 1));
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("SignalCallback", 1));
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("FailureCallback", 0));
CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method_thunk("Activate", 0));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, (TypeIsGenericArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericArray", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericDictionary, (TypeIsGenericDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("TypeIsGenericDictionary", 1));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, EnumerableToArray, (EnumerableToArray)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("EnumerableToArray", 2));
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IDictionaryToDictionary, (IDictionaryToDictionary)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IDictionaryToDictionary", 2));
+
#ifdef DEBUG_ENABLED
CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method_thunk("GetStackFrameInfo", 4));
#endif
@@ -712,7 +729,7 @@ uint64_t unbox_enum_value(MonoObject *p_boxed, MonoType *p_enum_basetype, bool &
}
void dispose(MonoObject *p_mono_object, MonoException **r_exc) {
- invoke_method_thunk(CACHED_METHOD_THUNK(GodotObject, Dispose), p_mono_object, (MonoObject **)r_exc);
+ invoke_method_thunk(CACHED_METHOD_THUNK(GodotObject, Dispose), p_mono_object, r_exc);
}
} // namespace GDMonoUtils
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
index e88bf1ced9..87610e286c 100644
--- a/modules/mono/mono_gd/gd_mono_utils.h
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -49,18 +49,21 @@
namespace GDMonoUtils {
-typedef void (*GodotObject_Dispose)(MonoObject *, MonoObject **);
-typedef Array *(*Array_GetPtr)(MonoObject *, MonoObject **);
-typedef Dictionary *(*Dictionary_GetPtr)(MonoObject *, MonoObject **);
-typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray *, MonoObject **);
-typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
-typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
-typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **);
-typedef MonoBoolean (*IsArrayGenericType)(MonoObject *, MonoObject **);
-typedef MonoBoolean (*IsDictionaryGenericType)(MonoObject *, MonoObject **);
-typedef MonoBoolean (*IsArrayGenericType)(MonoObject *, MonoObject **);
-typedef MonoBoolean (*IsDictionaryGenericType)(MonoObject *, MonoObject **);
-typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoObject **);
+typedef void (*GodotObject_Dispose)(MonoObject *, MonoException **);
+typedef Array *(*Array_GetPtr)(MonoObject *, MonoException **);
+typedef Dictionary *(*Dictionary_GetPtr)(MonoObject *, MonoException **);
+typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray *, MonoException **);
+typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoException **);
+typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoException **);
+typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoException **);
+typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoException **);
+
+typedef MonoBoolean (*TypeIsGenericArray)(MonoReflectionType *, MonoException **);
+typedef MonoBoolean (*TypeIsGenericDictionary)(MonoReflectionType *, MonoException **);
+typedef MonoBoolean (*ArrayGetElementType)(MonoReflectionType *, MonoReflectionType **, MonoException **);
+typedef MonoBoolean (*DictionaryGetKeyValueTypes)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **);
+typedef void (*EnumerableToArray)(MonoObject *, Array *, MonoException **);
+typedef void (*IDictionaryToDictionary)(MonoObject *, Dictionary *, MonoException **);
struct MonoCache {
@@ -83,6 +86,9 @@ struct MonoCache {
GDMonoClass *class_String;
GDMonoClass *class_IntPtr;
+ GDMonoClass *class_System_Collections_IEnumerable;
+ GDMonoClass *class_System_Collections_IDictionary;
+
#ifdef DEBUG_ENABLED
GDMonoClass *class_System_Diagnostics_StackTrace;
StackTrace_GetFrames methodthunk_System_Diagnostics_StackTrace_GetFrames;
@@ -146,12 +152,17 @@ struct MonoCache {
GodotObject_Dispose methodthunk_GodotObject_Dispose;
Array_GetPtr methodthunk_Array_GetPtr;
Dictionary_GetPtr methodthunk_Dictionary_GetPtr;
- IsArrayGenericType methodthunk_MarshalUtils_IsArrayGenericType;
- IsDictionaryGenericType methodthunk_MarshalUtils_IsDictionaryGenericType;
SignalAwaiter_SignalCallback methodthunk_SignalAwaiter_SignalCallback;
SignalAwaiter_FailureCallback methodthunk_SignalAwaiter_FailureCallback;
GodotTaskScheduler_Activate methodthunk_GodotTaskScheduler_Activate;
+ TypeIsGenericArray methodthunk_MarshalUtils_TypeIsGenericArray;
+ TypeIsGenericDictionary methodthunk_MarshalUtils_TypeIsGenericDictionary;
+ ArrayGetElementType methodthunk_MarshalUtils_ArrayGetElementType;
+ DictionaryGetKeyValueTypes methodthunk_MarshalUtils_DictionaryGetKeyValueTypes;
+ EnumerableToArray methodthunk_MarshalUtils_EnumerableToArray;
+ IDictionaryToDictionary methodthunk_MarshalUtils_IDictionaryToDictionary;
+
Ref<MonoGCHandle> task_scheduler_handle;
bool corlib_cache_updated;
@@ -255,6 +266,7 @@ void dispose(MonoObject *p_mono_object, MonoException **r_exc);
#define CACHED_FIELD(m_class, m_field) (GDMonoUtils::mono_cache.field_##m_class##_##m_field)
#define CACHED_METHOD(m_class, m_method) (GDMonoUtils::mono_cache.method_##m_class##_##m_method)
#define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method)
+#define CACHED_PROPERTY(m_class, m_property) (GDMonoUtils::mono_cache.property_##m_class##_##m_property)
#ifdef REAL_T_IS_DOUBLE
#define REAL_T_MONOCLASS CACHED_CLASS_RAW(double)
diff --git a/modules/mono/mono_gd/managed_type.cpp b/modules/mono/mono_gd/managed_type.cpp
new file mode 100644
index 0000000000..9f736b71cd
--- /dev/null
+++ b/modules/mono/mono_gd/managed_type.cpp
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* managed_type.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 "managed_type.h"
+
+#include "gd_mono.h"
+#include "gd_mono_class.h"
+
+ManagedType ManagedType::from_class(GDMonoClass *p_class) {
+ return ManagedType(mono_type_get_type(p_class->get_mono_type()), p_class);
+}
+
+ManagedType ManagedType::from_class(MonoClass *p_mono_class) {
+ GDMonoClass *tclass = GDMono::get_singleton()->get_class(p_mono_class);
+ ERR_FAIL_COND_V(!tclass, ManagedType());
+
+ return ManagedType(mono_type_get_type(tclass->get_mono_type()), tclass);
+}
+
+ManagedType ManagedType::from_type(MonoType *p_mono_type) {
+ MonoClass *mono_class = mono_class_from_mono_type(p_mono_type);
+ GDMonoClass *tclass = GDMono::get_singleton()->get_class(mono_class);
+ ERR_FAIL_COND_V(!tclass, ManagedType());
+
+ return ManagedType(mono_type_get_type(p_mono_type), tclass);
+}
+
+ManagedType ManagedType::from_reftype(MonoReflectionType *p_mono_reftype) {
+ MonoType *mono_type = mono_reflection_type_get_type(p_mono_reftype);
+ return from_type(mono_type);
+}
diff --git a/modules/mono/mono_gd/managed_type.h b/modules/mono/mono_gd/managed_type.h
new file mode 100644
index 0000000000..a537e56aea
--- /dev/null
+++ b/modules/mono/mono_gd/managed_type.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* managed_type.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 MANAGED_TYPE_H
+#define MANAGED_TYPE_H
+
+#include <mono/metadata/object.h>
+
+#include "gd_mono_header.h"
+
+struct ManagedType {
+ int type_encoding;
+ GDMonoClass *type_class;
+
+ static ManagedType from_class(GDMonoClass *p_class);
+ static ManagedType from_class(MonoClass *p_mono_class);
+ static ManagedType from_type(MonoType *p_mono_type);
+ static ManagedType from_reftype(MonoReflectionType *p_mono_reftype);
+
+ ManagedType() :
+ type_encoding(0),
+ type_class(NULL) {
+ }
+
+ ManagedType(int p_type_encoding, GDMonoClass *p_type_class) :
+ type_encoding(p_type_encoding),
+ type_class(p_type_class) {
+ }
+};
+
+#endif // MANAGED_TYPE_H
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 5051d83694..5d37e8212f 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -100,7 +100,7 @@ Variant SignalAwaiterHandle::_signal_callback(const Variant **p_args, int p_argc
MonoException *exc = NULL;
GD_MONO_BEGIN_RUNTIME_INVOKE;
- invoke_method_thunk(CACHED_METHOD_THUNK(SignalAwaiter, SignalCallback), get_target(), signal_args, (MonoObject **)&exc);
+ invoke_method_thunk(CACHED_METHOD_THUNK(SignalAwaiter, SignalCallback), get_target(), signal_args, &exc);
GD_MONO_END_RUNTIME_INVOKE;
if (exc) {
@@ -132,7 +132,7 @@ SignalAwaiterHandle::~SignalAwaiterHandle() {
if (awaiter) {
MonoException *exc = NULL;
GD_MONO_BEGIN_RUNTIME_INVOKE;
- invoke_method_thunk(CACHED_METHOD_THUNK(SignalAwaiter, FailureCallback), awaiter, (MonoObject **)&exc);
+ invoke_method_thunk(CACHED_METHOD_THUNK(SignalAwaiter, FailureCallback), awaiter, &exc);
GD_MONO_END_RUNTIME_INVOKE;
if (exc) {
diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp
index d7f9b22c31..98aeadc8c8 100644
--- a/modules/mono/utils/mono_reg_utils.cpp
+++ b/modules/mono/utils/mono_reg_utils.cpp
@@ -202,9 +202,9 @@ String find_msbuild_tools_path() {
}
// Since VS2019, the directory is simply named "Current"
- String msBuildDirectory = val + "MSBuild\\Current\\Bin";
- if (DirAccess::exists(msBuildDirectory)) {
- return msBuildDirectory;
+ String msbuild_dir = val + "MSBuild\\Current\\Bin";
+ if (DirAccess::exists(msbuild_dir)) {
+ return msbuild_dir;
}
// Directory name "15.0" is used in VS 2017
diff --git a/modules/mono/utils/thread_local.h b/modules/mono/utils/thread_local.h
index 276db8830b..488cc2619a 100644
--- a/modules/mono/utils/thread_local.h
+++ b/modules/mono/utils/thread_local.h
@@ -39,7 +39,7 @@
#error Platform or compiler not supported
#endif
-#ifdef __GNUC__
+#if defined(__GNUC__)
#ifdef HAVE_GCC___THREAD
#define _THREAD_LOCAL_(m_t) __thread m_t
@@ -47,7 +47,7 @@
#define USE_CUSTOM_THREAD_LOCAL
#endif
-#elif _MSC_VER
+#elif defined(_MSC_VER)
#ifdef HAVE_DECLSPEC_THREAD
#define _THREAD_LOCAL_(m_t) __declspec(thread) m_t
diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml
index a91114b2f7..25f104b221 100644
--- a/modules/opensimplex/doc_classes/NoiseTexture.xml
+++ b/modules/opensimplex/doc_classes/NoiseTexture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="NoiseTexture" inherits="Texture" category="Core" version="3.1">
+<class name="NoiseTexture" inherits="Texture" category="Core" version="3.2">
<brief_description>
[OpenSimplexNoise] filled texture.
</brief_description>
diff --git a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
index 31f13f341c..b5bc35df69 100644
--- a/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
+++ b/modules/opensimplex/doc_classes/OpenSimplexNoise.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OpenSimplexNoise" inherits="Resource" category="Core" version="3.1">
+<class name="OpenSimplexNoise" inherits="Resource" category="Core" version="3.2">
<brief_description>
Noise generator based on Open Simplex.
</brief_description>
diff --git a/modules/opensimplex/open_simplex_noise.cpp b/modules/opensimplex/open_simplex_noise.cpp
index b2d6b5e718..3a3a698e5c 100644
--- a/modules/opensimplex/open_simplex_noise.cpp
+++ b/modules/opensimplex/open_simplex_noise.cpp
@@ -173,6 +173,7 @@ void OpenSimplexNoise::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_image", "width", "height"), &OpenSimplexNoise::get_image);
ClassDB::bind_method(D_METHOD("get_seamless_image", "size"), &OpenSimplexNoise::get_seamless_image);
+ ClassDB::bind_method(D_METHOD("get_noise_1d", "x"), &OpenSimplexNoise::get_noise_1d);
ClassDB::bind_method(D_METHOD("get_noise_2d", "x", "y"), &OpenSimplexNoise::get_noise_2d);
ClassDB::bind_method(D_METHOD("get_noise_3d", "x", "y", "z"), &OpenSimplexNoise::get_noise_3d);
ClassDB::bind_method(D_METHOD("get_noise_4d", "x", "y", "z", "w"), &OpenSimplexNoise::get_noise_4d);
@@ -187,6 +188,11 @@ void OpenSimplexNoise::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "lacunarity", PROPERTY_HINT_RANGE, "0.1,4.0,0.01"), "set_lacunarity", "get_lacunarity");
}
+float OpenSimplexNoise::get_noise_1d(float x) {
+
+ return get_noise_2d(x, 1.0);
+}
+
float OpenSimplexNoise::get_noise_2d(float x, float y) {
x /= period;
diff --git a/modules/opensimplex/open_simplex_noise.h b/modules/opensimplex/open_simplex_noise.h
index ac4c6e361f..96885f5893 100644
--- a/modules/opensimplex/open_simplex_noise.h
+++ b/modules/opensimplex/open_simplex_noise.h
@@ -73,6 +73,7 @@ public:
Ref<Image> get_image(int p_width, int p_height);
Ref<Image> get_seamless_image(int p_size);
+ float get_noise_1d(float x);
float get_noise_2d(float x, float y);
float get_noise_3d(float x, float y, float z);
float get_noise_4d(float x, float y, float z, float w);
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index aa656c575a..b72144c679 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -220,10 +220,15 @@ if env['builtin_opus']:
]
env_opus.Append(CPPPATH=[thirdparty_dir + "/" + dir for dir in thirdparty_include_paths])
- if env["platform"] == "android" or env["platform"] == "iphone":
- if ("arch" in env and env["arch"] == "arm") or ("android_arch" in env and env["android_arch"] in ["armv6", "armv7"]):
+ if env["platform"] == "android":
+ if ("android_arch" in env and env["android_arch"] in ["armv6", "armv7"]):
env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
- elif ("arch" in env and env["arch"] == "arm64") or ("android_arch" in env and env["android_arch"] == "arm64v8"):
+ elif ("android_arch" in env and env["android_arch"] == "arm64v8"):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+ elif env["platform"] == "iphone":
+ if ("arch" in env and env["arch"] == "arm"):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ elif ("arch" in env and env["arch"] == "arm64"):
env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
env_thirdparty = env_opus.Clone()
diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml
index 75e8903ff8..20857572f3 100644
--- a/modules/regex/doc_classes/RegEx.xml
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegEx" inherits="Reference" category="Core" version="3.1">
+<class name="RegEx" inherits="Reference" category="Core" version="3.2">
<brief_description>
Class for searching text for patterns using regular expressions.
</brief_description>
diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml
index 3d070d2786..9efec91bdc 100644
--- a/modules/regex/doc_classes/RegExMatch.xml
+++ b/modules/regex/doc_classes/RegExMatch.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RegExMatch" inherits="Reference" category="Core" version="3.1">
+<class name="RegExMatch" inherits="Reference" category="Core" version="3.2">
<brief_description>
Contains the results of a regex search.
</brief_description>
diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
index e2281babf7..574ff1ff2a 100644
--- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
+++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.1">
+<class name="AudioStreamOGGVorbis" inherits="AudioStream" category="Core" version="3.2">
<brief_description>
OGG Vorbis audio stream driver.
</brief_description>
diff --git a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
index 018f4734ec..ade485e717 100644
--- a/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
+++ b/modules/stb_vorbis/doc_classes/ResourceImporterOGGVorbis.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.1">
+<class name="ResourceImporterOGGVorbis" inherits="ResourceImporter" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/theora/doc_classes/VideoStreamTheora.xml b/modules/theora/doc_classes/VideoStreamTheora.xml
index e7c4727332..2bd8ad862f 100644
--- a/modules/theora/doc_classes/VideoStreamTheora.xml
+++ b/modules/theora/doc_classes/VideoStreamTheora.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.1">
+<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp
index e69d9a0ae3..bd84a28c84 100644
--- a/modules/tinyexr/image_loader_tinyexr.cpp
+++ b/modules/tinyexr/image_loader_tinyexr.cpp
@@ -107,22 +107,31 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
}
}
- if (idxR == -1) {
- ERR_PRINT("TinyEXR: R channel not found.");
- // @todo { free exr_image }
- return ERR_FILE_CORRUPT;
- }
+ if (exr_header.num_channels == 1) {
+ // Grayscale channel only.
+ idxR = 0;
+ idxG = 0;
+ idxB = 0;
+ idxA = 0;
+ } else {
+ // Assume RGB(A)
+ if (idxR == -1) {
+ ERR_PRINT("TinyEXR: R channel not found.");
+ // @todo { free exr_image }
+ return ERR_FILE_CORRUPT;
+ }
- if (idxG == -1) {
- ERR_PRINT("TinyEXR: G channel not found.")
- // @todo { free exr_image }
- return ERR_FILE_CORRUPT;
- }
+ if (idxG == -1) {
+ ERR_PRINT("TinyEXR: G channel not found.")
+ // @todo { free exr_image }
+ return ERR_FILE_CORRUPT;
+ }
- if (idxB == -1) {
- ERR_PRINT("TinyEXR: B channel not found.")
- // @todo { free exr_image }
- return ERR_FILE_CORRUPT;
+ if (idxB == -1) {
+ ERR_PRINT("TinyEXR: B channel not found.")
+ // @todo { free exr_image }
+ return ERR_FILE_CORRUPT;
+ }
}
// EXR image data loaded, now parse it into Godot-friendly image data
diff --git a/modules/upnp/doc_classes/UPNP.xml b/modules/upnp/doc_classes/UPNP.xml
index b98327c60d..0f967c993b 100644
--- a/modules/upnp/doc_classes/UPNP.xml
+++ b/modules/upnp/doc_classes/UPNP.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UPNP" inherits="Reference" category="Core" version="3.1">
+<class name="UPNP" inherits="Reference" category="Core" version="3.2">
<brief_description>
UPNP network functions.
</brief_description>
diff --git a/modules/upnp/doc_classes/UPNPDevice.xml b/modules/upnp/doc_classes/UPNPDevice.xml
index 9de8042daf..c9b695a651 100644
--- a/modules/upnp/doc_classes/UPNPDevice.xml
+++ b/modules/upnp/doc_classes/UPNPDevice.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="UPNPDevice" inherits="Reference" category="Core" version="3.1">
+<class name="UPNPDevice" inherits="Reference" category="Core" version="3.2">
<brief_description>
UPNP device.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScript.xml b/modules/visual_script/doc_classes/VisualScript.xml
index 70849c5a80..f4a9bc68e6 100644
--- a/modules/visual_script/doc_classes/VisualScript.xml
+++ b/modules/visual_script/doc_classes/VisualScript.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScript" inherits="Script" category="Core" version="3.1">
+<class name="VisualScript" inherits="Script" category="Core" version="3.2">
<brief_description>
A script implemented in the Visual Script programming environment.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
index 5ec155fbc6..ce49cdf3a0 100644
--- a/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBasicTypeConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptBasicTypeConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node representing a constant from the base types.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
index 3a1d773058..104a90059e 100644
--- a/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
+++ b/modules/visual_script/doc_classes/VisualScriptBuiltinFunc.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptBuiltinFunc" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node used to call built-in functions.
</brief_description>
@@ -204,7 +204,14 @@
<constant name="COLORN" value="62" enum="BuiltinFunc">
Return the [Color] with the given name and alpha ranging from 0 to 1. Note: names are defined in color_names.inc.
</constant>
- <constant name="FUNC_MAX" value="63" enum="BuiltinFunc">
+ <constant name="MATH_SMOOTHSTEP" value="63" enum="BuiltinFunc">
+ Return a number smoothly interpolated between the first two inputs, based on the third input. Similar to [code]MATH_LERP[/code], but interpolates faster at the beginning and slower at the end. Using Hermite interpolation formula:
+ [codeblock]
+ var t = clamp((weight - from) / (to - from), 0.0, 1.0)
+ return t * t * (3.0 - 2.0 * t)
+ [/codeblock]
+ </constant>
+ <constant name="FUNC_MAX" value="64" enum="BuiltinFunc">
The maximum value the [member function] property can have.
</constant>
</constants>
diff --git a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
index dc9044e9ed..32b5924cdc 100644
--- a/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptClassConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptClassConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a constant from a given class.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptComment.xml b/modules/visual_script/doc_classes/VisualScriptComment.xml
index a4a890ea8a..990e0ecb85 100644
--- a/modules/visual_script/doc_classes/VisualScriptComment.xml
+++ b/modules/visual_script/doc_classes/VisualScriptComment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptComment" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node used to annotate the script.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptCondition.xml b/modules/visual_script/doc_classes/VisualScriptCondition.xml
index a7b1028c0c..94c075205d 100644
--- a/modules/visual_script/doc_classes/VisualScriptCondition.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCondition.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptCondition" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node which branches the flow.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptConstant.xml b/modules/visual_script/doc_classes/VisualScriptConstant.xml
index ed633c4135..0fc4e87db4 100644
--- a/modules/visual_script/doc_classes/VisualScriptConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a contant's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptConstructor.xml b/modules/visual_script/doc_classes/VisualScriptConstructor.xml
index 14c44c6970..05fc3f318d 100644
--- a/modules/visual_script/doc_classes/VisualScriptConstructor.xml
+++ b/modules/visual_script/doc_classes/VisualScriptConstructor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptConstructor" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node which calls a base type constructor.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
index ff3ed66e81..0ad4e7c1f5 100644
--- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptCustomNode" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A scripted Visual Script node.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
index d3158df357..b933a25f1d 100644
--- a/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
+++ b/modules/visual_script/doc_classes/VisualScriptDeconstruct.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptDeconstruct" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node which deconstructs a base type instance into its parts.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptEditor.xml b/modules/visual_script/doc_classes/VisualScriptEditor.xml
index fc49cfc07b..be4606b57c 100644
--- a/modules/visual_script/doc_classes/VisualScriptEditor.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEditor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.1">
+<class name="VisualScriptEditor" inherits="Object" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
index 4bb05525bd..3282269811 100644
--- a/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEmitSignal.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptEmitSignal" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Emits a specified signal.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
index 93d7ce3516..3e52fb818c 100644
--- a/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
+++ b/modules/visual_script/doc_classes/VisualScriptEngineSingleton.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptEngineSingleton" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
A Visual Script node returning a singleton from [@GlobalScope]
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptExpression.xml b/modules/visual_script/doc_classes/VisualScriptExpression.xml
index 343e83cb55..4760685bfb 100644
--- a/modules/visual_script/doc_classes/VisualScriptExpression.xml
+++ b/modules/visual_script/doc_classes/VisualScriptExpression.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptExpression" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunction.xml b/modules/visual_script/doc_classes/VisualScriptFunction.xml
index ec8e955cf7..dc021196cd 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptFunction" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
index f6116cf539..e978437542 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionCall.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptFunctionCall" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
index c75dd0cdbc..a5e15b8da2 100644
--- a/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
+++ b/modules/visual_script/doc_classes/VisualScriptFunctionState.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.1">
+<class name="VisualScriptFunctionState" inherits="Reference" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
index 9d43204f02..2d609ed262 100644
--- a/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptGlobalConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptGlobalConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
index 73c1f47e1a..16499e9ec9 100644
--- a/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptIndexGet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
index 652c29a9ac..06844ac4ae 100644
--- a/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIndexSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptIndexSet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptInputAction.xml b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
index ab4c23012b..01887e0764 100644
--- a/modules/visual_script/doc_classes/VisualScriptInputAction.xml
+++ b/modules/visual_script/doc_classes/VisualScriptInputAction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptInputAction" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptIterator.xml b/modules/visual_script/doc_classes/VisualScriptIterator.xml
index 7090621bd7..496c24dee4 100644
--- a/modules/visual_script/doc_classes/VisualScriptIterator.xml
+++ b/modules/visual_script/doc_classes/VisualScriptIterator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptIterator" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Steps through items in a given input.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
index 5c8ee6453c..cd7286b59b 100644
--- a/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVar.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptLocalVar" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a local variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
index f2e6c48907..f8fe2f4b6b 100644
--- a/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptLocalVarSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptLocalVarSet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Changes a local variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
index d456e880b7..733b48203d 100644
--- a/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
+++ b/modules/visual_script/doc_classes/VisualScriptMathConstant.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptMathConstant" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Commonly used mathematical constants.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptNode.xml b/modules/visual_script/doc_classes/VisualScriptNode.xml
index 941a0cd91a..86bd469d5c 100644
--- a/modules/visual_script/doc_classes/VisualScriptNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.1">
+<class name="VisualScriptNode" inherits="Resource" category="Core" version="3.2">
<brief_description>
A node which is part of a [VisualScript].
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptOperator.xml b/modules/visual_script/doc_classes/VisualScriptOperator.xml
index e60d50c977..d722477653 100644
--- a/modules/visual_script/doc_classes/VisualScriptOperator.xml
+++ b/modules/visual_script/doc_classes/VisualScriptOperator.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptOperator" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptPreload.xml b/modules/visual_script/doc_classes/VisualScriptPreload.xml
index 5a2886ccac..b811252c42 100644
--- a/modules/visual_script/doc_classes/VisualScriptPreload.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPreload.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptPreload" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Creates a new [Resource] or loads one from the filesystem.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
index 60cc8fdd4f..7f652b7012 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertyGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptPropertyGet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
index 8f29e9d152..ef9938c6a7 100644
--- a/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPropertySet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptPropertySet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
index f6300e03f0..2a5c56cf69 100644
--- a/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
+++ b/modules/visual_script/doc_classes/VisualScriptResourcePath.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptResourcePath" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptReturn.xml b/modules/visual_script/doc_classes/VisualScriptReturn.xml
index 0ca3e3b612..7daddc7639 100644
--- a/modules/visual_script/doc_classes/VisualScriptReturn.xml
+++ b/modules/visual_script/doc_classes/VisualScriptReturn.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptReturn" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Exits a function and returns an optional value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
index 7704eaba04..8604a0f5eb 100644
--- a/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSceneNode.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSceneNode" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Node reference.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
index 2c2af9262d..72a2faaa78 100644
--- a/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSceneTree.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSceneTree" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSelect.xml b/modules/visual_script/doc_classes/VisualScriptSelect.xml
index 0731fc77e1..c87f77ea65 100644
--- a/modules/visual_script/doc_classes/VisualScriptSelect.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSelect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSelect" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Chooses between two input values.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSelf.xml b/modules/visual_script/doc_classes/VisualScriptSelf.xml
index 61a73e104c..42c75e56a6 100644
--- a/modules/visual_script/doc_classes/VisualScriptSelf.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSelf.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSelf" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Outputs a reference to the current instance.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSequence.xml b/modules/visual_script/doc_classes/VisualScriptSequence.xml
index c71e068045..c26c72dd50 100644
--- a/modules/visual_script/doc_classes/VisualScriptSequence.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSequence.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSequence" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Executes a series of Sequence ports.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSubCall.xml b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
index 46aeebab9c..712b4ed09b 100644
--- a/modules/visual_script/doc_classes/VisualScriptSubCall.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSubCall.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSubCall" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptSwitch.xml b/modules/visual_script/doc_classes/VisualScriptSwitch.xml
index a00811a29b..0053733b34 100644
--- a/modules/visual_script/doc_classes/VisualScriptSwitch.xml
+++ b/modules/visual_script/doc_classes/VisualScriptSwitch.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptSwitch" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Branches program flow based on a given input's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
index 0bdc4ce89d..85b3980e21 100644
--- a/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
+++ b/modules/visual_script/doc_classes/VisualScriptTypeCast.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptTypeCast" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
index 06178a399d..27bf223aac 100644
--- a/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableGet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptVariableGet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Gets a variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
index 5969f25060..c55c72d55e 100644
--- a/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
+++ b/modules/visual_script/doc_classes/VisualScriptVariableSet.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptVariableSet" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Changes a variable's value.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptWhile.xml b/modules/visual_script/doc_classes/VisualScriptWhile.xml
index b9e7f6a553..b7ed56e7d2 100644
--- a/modules/visual_script/doc_classes/VisualScriptWhile.xml
+++ b/modules/visual_script/doc_classes/VisualScriptWhile.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptWhile" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
Conditional loop.
</brief_description>
diff --git a/modules/visual_script/doc_classes/VisualScriptYield.xml b/modules/visual_script/doc_classes/VisualScriptYield.xml
index c4698f746a..5aa0f76a55 100644
--- a/modules/visual_script/doc_classes/VisualScriptYield.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYield.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptYield" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
index b67e4ab1b8..8e3b2aec1d 100644
--- a/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
+++ b/modules/visual_script/doc_classes/VisualScriptYieldSignal.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.1">
+<class name="VisualScriptYieldSignal" inherits="VisualScriptNode" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp
index 9f2d1a49c0..c2ce5f0bf5 100644
--- a/modules/visual_script/visual_script_builtin_funcs.cpp
+++ b/modules/visual_script/visual_script_builtin_funcs.cpp
@@ -102,6 +102,7 @@ const char *VisualScriptBuiltinFunc::func_name[VisualScriptBuiltinFunc::FUNC_MAX
"var2bytes",
"bytes2var",
"color_named",
+ "smoothstep",
};
VisualScriptBuiltinFunc::BuiltinFunc VisualScriptBuiltinFunc::find_function(const String &p_string) {
@@ -183,10 +184,10 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
case TEXT_PRINTRAW:
case VAR_TO_STR:
case STR_TO_VAR:
- case VAR_TO_BYTES:
- case BYTES_TO_VAR:
case TYPE_EXISTS:
return 1;
+ case VAR_TO_BYTES:
+ case BYTES_TO_VAR:
case MATH_ATAN2:
case MATH_FMOD:
case MATH_FPOSMOD:
@@ -204,6 +205,7 @@ int VisualScriptBuiltinFunc::get_func_argument_count(BuiltinFunc p_func) {
return 2;
case MATH_LERP:
case MATH_INVERSE_LERP:
+ case MATH_SMOOTHSTEP:
case MATH_DECTIME:
case MATH_WRAP:
case MATH_WRAPF:
@@ -337,6 +339,14 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
else
return PropertyInfo(Variant::REAL, "ostop");
} break;
+ case MATH_SMOOTHSTEP: {
+ if (p_idx == 0)
+ return PropertyInfo(Variant::REAL, "from");
+ else if (p_idx == 1)
+ return PropertyInfo(Variant::REAL, "to");
+ else
+ return PropertyInfo(Variant::REAL, "weight");
+ } break;
case MATH_DECTIME: {
if (p_idx == 0)
return PropertyInfo(Variant::REAL, "value");
@@ -491,12 +501,18 @@ PropertyInfo VisualScriptBuiltinFunc::get_input_value_port_info(int p_idx) const
return PropertyInfo(Variant::STRING, "string");
} break;
case VAR_TO_BYTES: {
- return PropertyInfo(Variant::NIL, "var");
+ if (p_idx == 0)
+ return PropertyInfo(Variant::NIL, "var");
+ else
+ return PropertyInfo(Variant::BOOL, "full_objects");
} break;
case BYTES_TO_VAR: {
- return PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes");
+ if (p_idx == 0)
+ return PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes");
+ else
+ return PropertyInfo(Variant::BOOL, "allow_objects");
} break;
case COLORN: {
@@ -563,6 +579,7 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
case MATH_LERP:
case MATH_INVERSE_LERP:
case MATH_RANGE_LERP:
+ case MATH_SMOOTHSTEP:
case MATH_DECTIME: {
t = Variant::REAL;
@@ -655,11 +672,15 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons
} break;
case VAR_TO_BYTES: {
- t = Variant::POOL_BYTE_ARRAY;
+ if (p_idx == 0)
+ t = Variant::POOL_BYTE_ARRAY;
+ else
+ t = Variant::BOOL;
} break;
case BYTES_TO_VAR: {
-
+ if (p_idx == 1)
+ t = Variant::BOOL;
} break;
case COLORN: {
t = Variant::COLOR;
@@ -889,6 +910,12 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
VALIDATE_ARG_NUM(4);
*r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]);
} break;
+ case VisualScriptBuiltinFunc::MATH_SMOOTHSTEP: {
+ VALIDATE_ARG_NUM(0);
+ VALIDATE_ARG_NUM(1);
+ VALIDATE_ARG_NUM(2);
+ *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]);
+ } break;
case VisualScriptBuiltinFunc::MATH_DECTIME: {
VALIDATE_ARG_NUM(0);
@@ -1192,9 +1219,16 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
} break;
case VisualScriptBuiltinFunc::VAR_TO_BYTES: {
+ if (p_inputs[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ return;
+ }
PoolByteArray barr;
int len;
- Error err = encode_variant(*p_inputs[0], NULL, len);
+ bool full_objects = *p_inputs[1];
+ Error err = encode_variant(*p_inputs[0], NULL, len, full_objects);
if (err) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
@@ -1206,7 +1240,7 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
barr.resize(len);
{
PoolByteArray::Write w = barr.write();
- encode_variant(*p_inputs[0], w.ptr(), len);
+ encode_variant(*p_inputs[0], w.ptr(), len, full_objects);
}
*r_return = barr;
} break;
@@ -1216,15 +1250,21 @@ void VisualScriptBuiltinFunc::exec_func(BuiltinFunc p_func, const Variant **p_in
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
r_error.expected = Variant::POOL_BYTE_ARRAY;
-
+ return;
+ }
+ if (p_inputs[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
return;
}
PoolByteArray varr = *p_inputs[0];
+ bool allow_objects = *p_inputs[1];
Variant ret;
{
PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects);
if (err != OK) {
r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format.");
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
@@ -1356,6 +1396,7 @@ void VisualScriptBuiltinFunc::_bind_methods() {
BIND_ENUM_CONSTANT(VAR_TO_BYTES);
BIND_ENUM_CONSTANT(BYTES_TO_VAR);
BIND_ENUM_CONSTANT(COLORN);
+ BIND_ENUM_CONSTANT(MATH_SMOOTHSTEP);
BIND_ENUM_CONSTANT(FUNC_MAX);
}
@@ -1410,6 +1451,7 @@ void register_visual_script_builtin_func_node() {
VisualScriptLanguage::singleton->add_register_func("functions/built_in/lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_LERP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/inverse_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_INVERSE_LERP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/range_lerp", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANGE_LERP>);
+ VisualScriptLanguage::singleton->add_register_func("functions/built_in/smoothstep", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_SMOOTHSTEP>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/dectime", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_DECTIME>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/randomize", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RANDOMIZE>);
VisualScriptLanguage::singleton->add_register_func("functions/built_in/rand", create_builtin_func_node<VisualScriptBuiltinFunc::MATH_RAND>);
diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h
index 2d8454ddd4..50854c16b1 100644
--- a/modules/visual_script/visual_script_builtin_funcs.h
+++ b/modules/visual_script/visual_script_builtin_funcs.h
@@ -101,6 +101,7 @@ public:
VAR_TO_BYTES,
BYTES_TO_VAR,
COLORN,
+ MATH_SMOOTHSTEP,
FUNC_MAX
};
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 7e54891d97..6e7e566206 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -579,7 +579,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
if (gnode->is_comment())
sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode");
- Color c = sbf->get_border_color(MARGIN_TOP);
+ Color c = sbf->get_border_color();
c.a = 1;
if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) {
Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0);
@@ -3054,10 +3054,10 @@ void VisualScriptEditor::_notification(int p_what) {
Ref<StyleBoxFlat> sb = tm->get_stylebox("frame", "GraphNode");
if (!sb.is_null()) {
Ref<StyleBoxFlat> frame_style = sb->duplicate();
- Color c = sb->get_border_color(MARGIN_TOP);
+ Color c = sb->get_border_color();
Color cn = E->get().second;
cn.a = c.a;
- frame_style->set_border_color_all(cn);
+ frame_style->set_border_color(cn);
node_styles[E->get().first] = frame_style;
}
}
diff --git a/modules/webm/doc_classes/VideoStreamWebm.xml b/modules/webm/doc_classes/VideoStreamWebm.xml
index c02a7a8016..33dff0e93b 100644
--- a/modules/webm/doc_classes/VideoStreamWebm.xml
+++ b/modules/webm/doc_classes/VideoStreamWebm.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.1">
+<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.2">
<brief_description>
</brief_description>
<description>
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index ffb6d40e30..cb85fe864d 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketClient" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1">
+<class name="WebSocketClient" inherits="WebSocketMultiplayerPeer" category="Core" version="3.2">
<brief_description>
A WebSocket client implementation
</brief_description>
diff --git a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
index 1a841f85ed..139480c31f 100644
--- a/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
+++ b/modules/websocket/doc_classes/WebSocketMultiplayerPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" category="Core" version="3.1">
+<class name="WebSocketMultiplayerPeer" inherits="NetworkedMultiplayerPeer" category="Core" version="3.2">
<brief_description>
Base class for WebSocket server and client.
</brief_description>
diff --git a/modules/websocket/doc_classes/WebSocketPeer.xml b/modules/websocket/doc_classes/WebSocketPeer.xml
index 5dda012899..3b3692dd87 100644
--- a/modules/websocket/doc_classes/WebSocketPeer.xml
+++ b/modules/websocket/doc_classes/WebSocketPeer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketPeer" inherits="PacketPeer" category="Core" version="3.1">
+<class name="WebSocketPeer" inherits="PacketPeer" category="Core" version="3.2">
<brief_description>
A class representing a specific WebSocket connection.
</brief_description>
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 2932bf782a..4740bd6dcf 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="WebSocketServer" inherits="WebSocketMultiplayerPeer" category="Core" version="3.1">
+<class name="WebSocketServer" inherits="WebSocketMultiplayerPeer" category="Core" version="3.2">
<brief_description>
A WebSocket server implementation
</brief_description>
diff --git a/modules/websocket/packet_buffer.h b/modules/websocket/packet_buffer.h
index 47786a87a6..057fecfb56 100644
--- a/modules/websocket/packet_buffer.h
+++ b/modules/websocket/packet_buffer.h
@@ -59,7 +59,7 @@ public:
ERR_FAIL_V(ERR_OUT_OF_MEMORY);
}
#else
- ERR_FAIL_COND_V(p_payload && _payload.space_left() < p_size, ERR_OUT_OF_MEMORY);
+ ERR_FAIL_COND_V(p_payload && (uint32_t)_payload.space_left() < p_size, ERR_OUT_OF_MEMORY);
ERR_FAIL_COND_V(p_info && _packets.space_left() < 1, ERR_OUT_OF_MEMORY);
#endif