summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--SConstruct49
-rw-r--r--core/SCsub4
-rw-r--r--core/error_macros.h6
-rw-r--r--core/io/file_access_buffered_fa.h8
-rw-r--r--core/io/file_access_compressed.cpp13
-rw-r--r--core/io/file_access_compressed.h2
-rw-r--r--core/io/file_access_encrypted.cpp10
-rw-r--r--core/io/file_access_encrypted.h2
-rw-r--r--core/io/file_access_memory.h2
-rw-r--r--core/io/file_access_network.cpp10
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/file_access_pack.h2
-rw-r--r--core/io/file_access_zip.h2
-rw-r--r--core/math/camera_matrix.cpp8
-rw-r--r--core/math/camera_matrix.h1
-rw-r--r--core/os/dir_access.cpp2
-rw-r--r--core/os/file_access.cpp23
-rw-r--r--core/os/file_access.h7
-rw-r--r--core/os/os.h4
-rw-r--r--core/string_builder.h4
-rw-r--r--core/translation.cpp15
-rw-r--r--core/translation.h2
-rw-r--r--core/ustring.cpp25
-rw-r--r--core/ustring.h5
-rw-r--r--core/variant_call.cpp15
-rw-r--r--core/variant_parser.cpp3
-rw-r--r--doc/classes/@GDScript.xml2
-rw-r--r--doc/classes/ARVRAnchor.xml2
-rw-r--r--doc/classes/ARVRInterface.xml2
-rw-r--r--doc/classes/ARVRServer.xml2
-rw-r--r--doc/classes/AnimatedSprite.xml2
-rw-r--r--doc/classes/AnimatedSprite3D.xml2
-rw-r--r--doc/classes/Animation.xml2
-rw-r--r--doc/classes/AnimationNode.xml8
-rw-r--r--doc/classes/AnimationPlayer.xml2
-rw-r--r--doc/classes/Array.xml6
-rw-r--r--doc/classes/AudioStreamPlayer3D.xml5
-rw-r--r--doc/classes/BaseButton.xml2
-rw-r--r--doc/classes/BitMap.xml6
-rw-r--r--doc/classes/Camera.xml20
-rw-r--r--doc/classes/CanvasItem.xml4
-rw-r--r--doc/classes/ClassDB.xml8
-rw-r--r--doc/classes/CollisionPolygon.xml2
-rw-r--r--doc/classes/Control.xml2
-rw-r--r--doc/classes/Curve2D.xml2
-rw-r--r--doc/classes/Curve3D.xml2
-rw-r--r--doc/classes/Dictionary.xml6
-rw-r--r--doc/classes/DynamicFont.xml6
-rw-r--r--doc/classes/EditorFileSystem.xml2
-rw-r--r--doc/classes/EditorInspectorPlugin.xml16
-rw-r--r--doc/classes/EditorPlugin.xml4
-rw-r--r--doc/classes/EditorProperty.xml39
-rw-r--r--doc/classes/EditorSpatialGizmo.xml2
-rw-r--r--doc/classes/EditorSpatialGizmoPlugin.xml2
-rw-r--r--doc/classes/Environment.xml2
-rw-r--r--doc/classes/GraphEdit.xml2
-rw-r--r--doc/classes/GraphNode.xml4
-rw-r--r--doc/classes/HTTPClient.xml4
-rw-r--r--doc/classes/Image.xml4
-rw-r--r--doc/classes/Input.xml4
-rw-r--r--doc/classes/ItemList.xml2
-rw-r--r--doc/classes/KinematicBody.xml4
-rw-r--r--doc/classes/KinematicBody2D.xml4
-rw-r--r--doc/classes/Label.xml2
-rw-r--r--doc/classes/MeshTexture.xml26
-rw-r--r--doc/classes/MultiMesh.xml2
-rw-r--r--doc/classes/Node2D.xml4
-rw-r--r--doc/classes/NodePath.xml4
-rw-r--r--doc/classes/Object.xml4
-rw-r--r--doc/classes/Performance.xml40
-rw-r--r--doc/classes/Plane.xml4
-rw-r--r--doc/classes/PoolByteArray.xml7
-rw-r--r--doc/classes/ProjectSettings.xml208
-rw-r--r--doc/classes/ResourceFormatSaver.xml2
-rw-r--r--doc/classes/ResourcePreloader.xml2
-rw-r--r--doc/classes/SceneTree.xml2
-rw-r--r--doc/classes/Skeleton.xml6
-rw-r--r--doc/classes/SphereMesh.xml2
-rw-r--r--doc/classes/StreamPeerSSL.xml2
-rw-r--r--doc/classes/StyleBoxFlat.xml2
-rw-r--r--doc/classes/TCP_Server.xml2
-rw-r--r--doc/classes/TabContainer.xml2
-rw-r--r--doc/classes/Tabs.xml2
-rw-r--r--doc/classes/TextEdit.xml10
-rw-r--r--doc/classes/Thread.xml2
-rw-r--r--doc/classes/VehicleBody.xml4
-rw-r--r--doc/classes/VehicleWheel.xml6
-rw-r--r--doc/classes/VisualInstance.xml12
-rw-r--r--doc/classes/VisualServer.xml25
-rw-r--r--doc/classes/bool.xml6
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp1
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp11
-rw-r--r--drivers/unix/file_access_unix.cpp21
-rw-r--r--drivers/unix/file_access_unix.h4
-rw-r--r--drivers/unix/os_unix.cpp35
-rw-r--r--drivers/unix/os_unix.h2
-rw-r--r--drivers/windows/file_access_windows.cpp10
-rw-r--r--drivers/windows/file_access_windows.h2
-rw-r--r--drivers/xaudio2/SCsub2
-rw-r--r--editor/code_editor.cpp43
-rw-r--r--editor/collada/collada.cpp3
-rw-r--r--editor/connections_dialog.cpp8
-rw-r--r--editor/editor_audio_buses.cpp4
-rw-r--r--editor/editor_file_dialog.cpp10
-rw-r--r--editor/editor_inspector.cpp12
-rw-r--r--editor/editor_node.cpp153
-rw-r--r--editor/editor_node.h22
-rw-r--r--editor/editor_run_native.cpp19
-rw-r--r--editor/editor_settings.cpp1
-rw-r--r--editor/editor_sub_scene.cpp6
-rw-r--r--editor/export_template_manager.cpp113
-rw-r--r--editor/export_template_manager.h3
-rw-r--r--editor/icons/icon_bucket.svg86
-rw-r--r--editor/import/editor_import_collada.cpp2
-rw-r--r--editor/inspector_dock.cpp3
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp11
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp29
-rw-r--r--editor/plugins/animation_state_machine_editor.h2
-rw-r--r--editor/plugins/animation_tree_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp13
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp9
-rw-r--r--editor/plugins/script_editor_plugin.cpp49
-rw-r--r--editor/plugins/script_editor_plugin.h1
-rw-r--r--editor/plugins/script_text_editor.cpp173
-rw-r--r--editor/plugins/script_text_editor.h24
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp41
-rw-r--r--editor/plugins/spatial_editor_plugin.h6
-rw-r--r--editor/plugins/text_editor.cpp10
-rw-r--r--editor/plugins/theme_editor_plugin.cpp223
-rw-r--r--editor/plugins/theme_editor_plugin.h7
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp138
-rw-r--r--editor/plugins/tile_map_editor_plugin.h13
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp39
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp123
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h6
-rw-r--r--editor/progress_dialog.cpp3
-rw-r--r--editor/project_export.cpp19
-rw-r--r--editor/project_export.h6
-rw-r--r--editor/scene_tree_dock.cpp14
-rw-r--r--editor/spatial_editor_gizmos.cpp67
-rw-r--r--main/performance.cpp22
-rw-r--r--main/performance.h3
-rw-r--r--methods.py72
-rw-r--r--modules/assimp/editor_scene_importer_assimp.cpp4
-rw-r--r--modules/bmp/image_loader_bmp.cpp62
-rw-r--r--modules/bmp/image_loader_bmp.h22
-rw-r--r--modules/bullet/SCsub2
-rw-r--r--modules/bullet/rigid_body_bullet.cpp2
-rw-r--r--modules/csg/csg_shape.cpp24
-rw-r--r--modules/csg/csg_shape.h8
-rw-r--r--modules/csg/doc_classes/CSGCylinder.xml4
-rw-r--r--modules/csg/doc_classes/CSGMesh.xml2
-rw-r--r--modules/csg/doc_classes/CSGPolygon.xml6
-rw-r--r--modules/csg/doc_classes/CSGShape.xml4
-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/enet/networked_multiplayer_enet.cpp16
-rw-r--r--modules/etc/SCsub2
-rw-r--r--modules/freetype/SCsub6
-rw-r--r--modules/gdnative/videodecoder/video_stream_gdnative.cpp2
-rw-r--r--modules/gdscript/gdscript_editor.cpp2
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp2
-rw-r--r--modules/mono/editor/bindings_generator.cpp703
-rw-r--r--modules/mono/editor/bindings_generator.h11
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp2
-rw-r--r--modules/opensimplex/doc_classes/NoiseTexture.xml2
-rw-r--r--modules/opus/SCsub12
-rw-r--r--modules/recast/navigation_mesh_editor_plugin.cpp4
-rw-r--r--modules/svg/SCsub2
-rw-r--r--modules/theora/SCsub2
-rw-r--r--modules/vhacd/SCsub2
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml2
-rw-r--r--modules/visual_script/visual_script_editor.cpp2
-rw-r--r--modules/webm/SCsub2
-rw-r--r--modules/webm/libvpx/SCsub4
-rw-r--r--modules/websocket/SCsub2
-rw-r--r--modules/xatlas_unwrap/SCsub12
-rw-r--r--platform/android/SCsub108
-rw-r--r--platform/android/detect.py48
-rw-r--r--platform/android/export/export.cpp403
-rw-r--r--platform/android/file_access_android.h2
-rw-r--r--platform/android/file_access_jandroid.h2
-rw-r--r--platform/android/java/AndroidManifest.xml (renamed from platform/android/AndroidManifest.xml.template)19
-rw-r--r--platform/android/java/build.gradle (renamed from platform/android/build.gradle.template)59
-rw-r--r--platform/haiku/detect.py2
-rw-r--r--platform/iphone/detect.py15
-rw-r--r--platform/osx/detect.py16
-rw-r--r--platform/osx/export/export.cpp2
-rw-r--r--platform/server/detect.py8
-rw-r--r--platform/uwp/detect.py27
-rw-r--r--platform/windows/detect.py19
-rw-r--r--platform/windows/os_windows.cpp35
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--platform/x11/detect.py22
-rw-r--r--platform/x11/os_x11.cpp38
-rw-r--r--scene/2d/animated_sprite.cpp3
-rw-r--r--scene/2d/light_2d.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp3
-rw-r--r--scene/3d/audio_stream_player_3d.cpp6
-rw-r--r--scene/3d/audio_stream_player_3d.h1
-rw-r--r--scene/3d/camera.cpp46
-rw-r--r--scene/3d/camera.h8
-rw-r--r--scene/3d/collision_shape.cpp28
-rw-r--r--scene/3d/collision_shape.h4
-rw-r--r--scene/3d/cpu_particles.cpp1
-rw-r--r--scene/3d/physics_body.cpp3
-rw-r--r--scene/3d/vehicle_body.cpp2
-rw-r--r--scene/3d/visual_instance.cpp8
-rw-r--r--scene/3d/visual_instance.h2
-rw-r--r--scene/animation/animation_tree.cpp8
-rw-r--r--scene/gui/base_button.cpp2
-rw-r--r--scene/gui/line_edit.cpp16
-rw-r--r--scene/gui/popup_menu.cpp2
-rw-r--r--scene/gui/rich_text_label.cpp14
-rw-r--r--scene/gui/text_edit.cpp138
-rw-r--r--scene/gui/text_edit.h22
-rw-r--r--scene/gui/tree.cpp1
-rw-r--r--scene/main/http_request.cpp2
-rw-r--r--scene/main/node.cpp9
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/resources/box_shape.cpp1
-rw-r--r--scene/resources/capsule_shape.cpp1
-rw-r--r--scene/resources/concave_polygon_shape.cpp1
-rw-r--r--scene/resources/convex_polygon_shape.cpp2
-rw-r--r--scene/resources/curve.cpp2
-rw-r--r--scene/resources/cylinder_shape.cpp1
-rw-r--r--scene/resources/default_theme/default_theme.cpp2
-rw-r--r--scene/resources/multimesh.cpp14
-rw-r--r--scene/resources/multimesh.h4
-rw-r--r--scene/resources/plane_shape.cpp1
-rw-r--r--scene/resources/ray_shape.cpp2
-rw-r--r--scene/resources/shape.cpp5
-rw-r--r--scene/resources/shape.h2
-rw-r--r--scene/resources/sphere_shape.cpp1
-rw-r--r--scene/resources/visual_shader.cpp3
-rw-r--r--servers/audio/audio_rb_resampler.cpp6
-rw-r--r--servers/audio/effects/audio_effect_record.cpp2
-rw-r--r--servers/physics/space_sw.cpp6
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp2
-rw-r--r--servers/physics_2d/space_2d_sw.cpp8
-rw-r--r--servers/visual/visual_server_canvas.cpp16
-rw-r--r--servers/visual/visual_server_canvas.h4
-rw-r--r--servers/visual/visual_server_raster.h1
-rw-r--r--servers/visual/visual_server_scene.cpp25
-rw-r--r--servers/visual/visual_server_scene.h6
-rw-r--r--servers/visual/visual_server_wrap_mt.h1
-rw-r--r--servers/visual_server.cpp1
-rw-r--r--servers/visual_server.h1
-rw-r--r--thirdparty/README.md2
-rw-r--r--thirdparty/assimp/code/FBXConverter.cpp35
-rw-r--r--thirdparty/assimp/code/FBXConverter.h20
-rw-r--r--thirdparty/assimp/code/FBXMaterial.cpp32
-rw-r--r--thirdparty/assimp/code/FBXUtil.cpp44
-rw-r--r--thirdparty/assimp/code/FBXUtil.h15
-rw-r--r--thirdparty/assimp/code/Version.cpp2
-rw-r--r--thirdparty/assimp/include/assimp/material.h1
258 files changed, 3438 insertions, 1444 deletions
diff --git a/.gitignore b/.gitignore
index 6acab19251..2697507adb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,13 +8,10 @@ doc/_build/
*.bc
# Android specific
-platform/android/java/build.gradle
platform/android/java/.gradle
platform/android/java/.gradletasknamecache
platform/android/java/local.properties
platform/android/java/project.properties
-platform/android/java/build.gradle
-platform/android/java/AndroidManifest.xml
platform/android/java/libs/*
platform/android/java/assets
platform/android/java/.idea/*
diff --git a/SConstruct b/SConstruct
index 78d77d1b7a..e943f8dc04 100644
--- a/SConstruct
+++ b/SConstruct
@@ -66,20 +66,6 @@ if 'TERM' in os.environ:
env_base['ENV']['TERM'] = os.environ['TERM']
env_base.AppendENVPath('PATH', os.getenv('PATH'))
env_base.AppendENVPath('PKG_CONFIG_PATH', os.getenv('PKG_CONFIG_PATH'))
-env_base.android_maven_repos = []
-env_base.android_flat_dirs = []
-env_base.android_dependencies = []
-env_base.android_gradle_plugins = []
-env_base.android_gradle_classpath = []
-env_base.android_java_dirs = []
-env_base.android_res_dirs = []
-env_base.android_asset_dirs = []
-env_base.android_aidl_dirs = []
-env_base.android_jni_dirs = []
-env_base.android_default_config = []
-env_base.android_manifest_chunk = ""
-env_base.android_permission_chunk = ""
-env_base.android_appattributes_chunk = ""
env_base.disabled_modules = []
env_base.use_ptrcall = False
env_base.split_drivers = False
@@ -87,20 +73,6 @@ env_base.split_modules = False
env_base.module_version_string = ""
env_base.msvc = False
-env_base.__class__.android_add_maven_repository = methods.android_add_maven_repository
-env_base.__class__.android_add_flat_dir = methods.android_add_flat_dir
-env_base.__class__.android_add_dependency = methods.android_add_dependency
-env_base.__class__.android_add_java_dir = methods.android_add_java_dir
-env_base.__class__.android_add_res_dir = methods.android_add_res_dir
-env_base.__class__.android_add_asset_dir = methods.android_add_asset_dir
-env_base.__class__.android_add_aidl_dir = methods.android_add_aidl_dir
-env_base.__class__.android_add_jni_dir = methods.android_add_jni_dir
-env_base.__class__.android_add_default_config = methods.android_add_default_config
-env_base.__class__.android_add_to_manifest = methods.android_add_to_manifest
-env_base.__class__.android_add_to_permissions = methods.android_add_to_permissions
-env_base.__class__.android_add_to_attributes = methods.android_add_to_attributes
-env_base.__class__.android_add_gradle_plugin = methods.android_add_gradle_plugin
-env_base.__class__.android_add_gradle_classpath = methods.android_add_gradle_classpath
env_base.__class__.disable_module = methods.disable_module
env_base.__class__.add_module_version_string = methods.add_module_version_string
@@ -189,8 +161,8 @@ opts.Add("CXX", "C++ compiler")
opts.Add("CC", "C compiler")
opts.Add("LINK", "Linker")
opts.Add("CCFLAGS", "Custom flags for both the C and C++ compilers")
-opts.Add("CXXFLAGS", "Custom flags for the C++ compiler")
opts.Add("CFLAGS", "Custom flags for the C compiler")
+opts.Add("CXXFLAGS", "Custom flags for the C++ compiler")
opts.Add("LINKFLAGS", "Custom flags for the linker")
# add platform specific options
@@ -299,17 +271,18 @@ if selected_platform in platform_list:
CCFLAGS = env.get('CCFLAGS', '')
env['CCFLAGS'] = ''
-
env.Append(CCFLAGS=str(CCFLAGS).split())
CFLAGS = env.get('CFLAGS', '')
env['CFLAGS'] = ''
-
env.Append(CFLAGS=str(CFLAGS).split())
+ CXXFLAGS = env.get('CXXFLAGS', '')
+ env['CXXFLAGS'] = ''
+ env.Append(CXXFLAGS=str(CXXFLAGS).split())
+
LINKFLAGS = env.get('LINKFLAGS', '')
env['LINKFLAGS'] = ''
-
env.Append(LINKFLAGS=str(LINKFLAGS).split())
flag_list = platform_flags[selected_platform]
@@ -347,11 +320,19 @@ if selected_platform in platform_list:
if (env["warnings"] == 'extra'):
# FIXME: enable -Wclobbered once #26351 is fixed
+ # FIXME: enable -Wlogical-op and -Wduplicated-branches once #27594 is merged
# Note: enable -Wimplicit-fallthrough for Clang (already part of -Wextra for GCC)
# once we switch to C++11 or later (necessary for our FALLTHROUGH macro).
- env.Append(CCFLAGS=['-Wall', '-Wextra', '-Wno-unused-parameter'] + all_plus_warnings + shadow_local_warning)
+ env.Append(CCFLAGS=['-Wall', '-Wextra', '-Wno-unused-parameter']
+ + all_plus_warnings + shadow_local_warning)
+ env.Append(CXXFLAGS=['-Wctor-dtor-privacy', '-Wnon-virtual-dtor'])
if methods.using_gcc(env):
- env['CCFLAGS'] += ['-Wno-clobbered']
+ env.Append(CCFLAGS=['-Wno-clobbered', '-Walloc-zero',
+ '-Wduplicated-cond', '-Wstringop-overflow=4'])
+ env.Append(CXXFLAGS=['-Wnoexcept', '-Wplacement-new=1'])
+ version = methods.get_compiler_version(env)
+ if version != None and version[0] >= '9':
+ env.Append(CCFLAGS=['-Wattribute-alias=2'])
elif (env["warnings"] == 'all'):
env.Append(CCFLAGS=['-Wall'] + shadow_local_warning)
elif (env["warnings"] == 'moderate'):
diff --git a/core/SCsub b/core/SCsub
index 00d0bcac24..d5be74a64f 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -129,10 +129,10 @@ if env['builtin_zstd']:
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
env_thirdparty.Append(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
- env_thirdparty.Append(CCFLAGS="-DZSTD_STATIC_LINKING_ONLY")
+ env_thirdparty.Append(CPPFLAGS="-DZSTD_STATIC_LINKING_ONLY")
env.Append(CPPPATH=thirdparty_zstd_dir)
# Also needed in main env includes will trigger warnings
- env.Append(CCFLAGS="-DZSTD_STATIC_LINKING_ONLY")
+ env.Append(CPPFLAGS="-DZSTD_STATIC_LINKING_ONLY")
env_thirdparty.add_source_files(env.core_sources, thirdparty_zstd_sources)
diff --git a/core/error_macros.h b/core/error_macros.h
index ca5ccd24cf..78e29551d4 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -86,7 +86,7 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
#define _FNL __FILE__ ":"
-/** An index has failed if m_index<0 or m_index >=m_size, the function exists */
+/** An index has failed if m_index<0 or m_index >=m_size, the function exits */
extern bool _err_error_exists;
@@ -140,7 +140,7 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
-/** An index has failed if m_index<0 or m_index >=m_size, the function exists.
+/** An index has failed if m_index<0 or m_index >=m_size, the function exits.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
@@ -154,7 +154,7 @@ extern bool _err_error_exists;
_err_error_exists = false; \
} while (0); // (*)
-/** An index has failed if m_index >=m_size, the function exists.
+/** An index has failed if m_index >=m_size, the function exits.
* This function returns an error value, if returning Error, please select the most
* appropriate error condition from error_macros.h
*/
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index be960fbc25..24b40cbce8 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -143,6 +143,14 @@ public:
return f._get_modified_time(p_file);
}
+ virtual uint32_t _get_unix_permissions(const String &p_file) {
+ return f._get_unix_permissions(p_file);
+ }
+
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+ return f._set_unix_permissions(p_file, p_permissions);
+ }
+
FileAccessBufferedFA(){
};
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index b268d5c710..6c4310a572 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -373,6 +373,19 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
return 0;
}
+uint32_t FileAccessCompressed::_get_unix_permissions(const String &p_file) {
+ if (f)
+ return f->_get_unix_permissions(p_file);
+ return 0;
+}
+
+Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+ if (f) {
+ return f->_set_unix_permissions(p_file, p_permissions);
+ }
+ return FAILED;
+}
+
FileAccessCompressed::FileAccessCompressed() :
cmode(Compression::MODE_ZSTD),
writing(false),
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index f408b1bc29..773fed6a3a 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -91,6 +91,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
FileAccessCompressed();
virtual ~FileAccessCompressed();
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 6ad68dd74d..3cf6908961 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -301,6 +301,16 @@ uint64_t FileAccessEncrypted::_get_modified_time(const String &p_file) {
return 0;
}
+uint32_t FileAccessEncrypted::_get_unix_permissions(const String &p_file) {
+
+ return 0;
+}
+
+Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+ return FAILED;
+}
+
FileAccessEncrypted::FileAccessEncrypted() {
file = NULL;
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index e77d62a9f4..d779a150ac 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -79,6 +79,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
FileAccessEncrypted();
~FileAccessEncrypted();
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 73952133c1..4db7811aaa 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -70,6 +70,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
FileAccessMemory();
};
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 501a21a50d..722e62c54e 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -497,6 +497,16 @@ uint64_t FileAccessNetwork::_get_modified_time(const String &p_file) {
return exists_modtime;
}
+uint32_t FileAccessNetwork::_get_unix_permissions(const String &p_file) {
+ //could be implemented, not sure if worth it
+ return 0;
+}
+
+Error FileAccessNetwork::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+ return FAILED;
+}
+
void FileAccessNetwork::configure() {
GLOBAL_DEF("network/remote_fs/page_size", 65536);
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 5bbf7588c7..073b75a37b 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -159,6 +159,8 @@ public:
virtual bool file_exists(const String &p_path); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
static void configure();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index a90672ce26..a21dd7d22d 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -142,6 +142,8 @@ class FileAccessPack : public FileAccess {
FileAccess *f;
virtual Error _open(const String &p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
public:
virtual void close();
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index fc8f85c07b..217176c0af 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -112,6 +112,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; } // todo
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
FileAccessZip(const String &p_path, const PackedData::PackedFile &p_file);
~FileAccessZip();
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index caf08c7379..f615cc8c65 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -210,6 +210,14 @@ void CameraMatrix::set_frustum(real_t p_left, real_t p_right, real_t p_bottom, r
te[15] = 0;
}
+void CameraMatrix::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov) {
+ if (!p_flip_fov) {
+ p_size *= p_aspect;
+ }
+
+ set_frustum(-p_size / 2 + p_offset.x, +p_size / 2 + p_offset.x, -p_size / p_aspect / 2 + p_offset.y, +p_size / p_aspect / 2 + p_offset.y, p_near, p_far);
+}
+
real_t CameraMatrix::get_z_far() const {
const real_t *matrix = (const real_t *)this->matrix;
diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h
index 015588a8cb..3bcf48f5da 100644
--- a/core/math/camera_matrix.h
+++ b/core/math/camera_matrix.h
@@ -61,6 +61,7 @@ struct CameraMatrix {
void set_orthogonal(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_znear, real_t p_zfar);
void set_orthogonal(real_t p_size, real_t p_aspect, real_t p_znear, real_t p_zfar, bool p_flip_fov = false);
void set_frustum(real_t p_left, real_t p_right, real_t p_bottom, real_t p_top, real_t p_near, real_t p_far);
+ void set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, real_t p_near, real_t p_far, bool p_flip_fov = false);
static real_t get_fovy(real_t p_fovx, real_t p_aspect) {
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 2c1c655175..d81c30f33a 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -330,7 +330,7 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
if (err == OK && p_chmod_flags != -1) {
fdst->close();
- err = fdst->_chmod(p_to, p_chmod_flags);
+ err = FileAccess::set_unix_permissions(p_to, p_chmod_flags);
// If running on a platform with no chmod support (i.e., Windows), don't fail
if (err == ERR_UNAVAILABLE)
err = OK;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 4be1364278..079f51bada 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -507,6 +507,29 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
return mt;
}
+uint32_t FileAccess::get_unix_permissions(const String &p_file) {
+
+ if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file))
+ return 0;
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V(!fa, 0);
+
+ uint32_t mt = fa->_get_unix_permissions(p_file);
+ memdelete(fa);
+ return mt;
+}
+
+Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+ FileAccess *fa = create_for_path(p_file);
+ ERR_FAIL_COND_V(!fa, ERR_CANT_CREATE);
+
+ Error err = fa->_set_unix_permissions(p_file, p_permissions);
+ memdelete(fa);
+ return err;
+}
+
void FileAccess::store_string(const String &p_string) {
if (p_string.length() == 0)
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 9df2a5cade..4930eae35a 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -56,6 +56,9 @@ public:
bool endian_swap;
bool real_is_double;
+ virtual uint32_t _get_unix_permissions(const String &p_file) = 0;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) = 0;
+
protected:
String fix_path(const String &p_path) const;
virtual Error _open(const String &p_path, int p_mode_flags) = 0; ///< open a file
@@ -148,14 +151,14 @@ public:
virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
- virtual Error _chmod(const String &p_path, int p_mod) { return ERR_UNAVAILABLE; }
-
static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static FileAccess *create_for_path(const String &p_path);
static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static CreateFunc get_create_func(AccessType p_access);
static bool exists(const String &p_name); ///< return true if a file exists
static uint64_t get_modified_time(const String &p_file);
+ static uint32_t get_unix_permissions(const String &p_file);
+ static Error set_unix_permissions(const String &p_file, uint32_t p_permissions);
static void set_backup_save(bool p_enable) { backup_save = p_enable; };
static bool is_backup_save_enabled() { return backup_save; };
diff --git a/core/os/os.h b/core/os/os.h
index 12012fba80..4ae8a354e5 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -45,6 +45,8 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+class Mutex;
+
class OS {
static OS *singleton;
@@ -260,7 +262,7 @@ public:
virtual int get_low_processor_usage_mode_sleep_usec() const;
virtual String get_executable_path() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false) = 0;
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL) = 0;
virtual Error kill(const ProcessID &p_pid) = 0;
virtual int get_process_id() const;
diff --git a/core/string_builder.h b/core/string_builder.h
index 40d70e8f45..0c4985d230 100644
--- a/core/string_builder.h
+++ b/core/string_builder.h
@@ -70,6 +70,10 @@ public:
return appended_strings.size();
}
+ _FORCE_INLINE_ uint32_t get_string_length() const {
+ return string_length;
+ }
+
String as_string() const;
_FORCE_INLINE_ operator String() const {
diff --git a/core/translation.cpp b/core/translation.cpp
index 6921f1d9f1..afbc639eaa 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -968,6 +968,19 @@ String TranslationServer::get_locale_name(const String &p_locale) const {
return locale_name_map[p_locale];
}
+Array TranslationServer::get_loaded_locales() const {
+ Array locales;
+ for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
+
+ const Ref<Translation> &t = E->get();
+ String l = t->get_locale();
+
+ locales.push_back(l);
+ }
+
+ return locales;
+}
+
Vector<String> TranslationServer::get_all_locales() {
Vector<String> locales;
@@ -1168,6 +1181,8 @@ void TranslationServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation);
ClassDB::bind_method(D_METHOD("clear"), &TranslationServer::clear);
+
+ ClassDB::bind_method(D_METHOD("get_loaded_locales"), &TranslationServer::get_loaded_locales);
}
void TranslationServer::load_translations() {
diff --git a/core/translation.h b/core/translation.h
index b12bad0d72..d172b9ecf2 100644
--- a/core/translation.h
+++ b/core/translation.h
@@ -94,6 +94,8 @@ public:
String get_locale_name(const String &p_locale) const;
+ Array get_loaded_locales() const;
+
void add_translation(const Ref<Translation> &p_translation);
void remove_translation(const Ref<Translation> &p_translation);
diff --git a/core/ustring.cpp b/core/ustring.cpp
index d60bd16921..78feddb229 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -123,6 +123,31 @@ const char *CharString::get_data() const {
return "";
}
+CharString &CharString::operator=(const char *p_cstr) {
+
+ copy_from(p_cstr);
+ return *this;
+}
+
+void CharString::copy_from(const char *p_cstr) {
+
+ if (!p_cstr) {
+ resize(0);
+ return;
+ }
+
+ size_t len = strlen(p_cstr);
+
+ if (len == 0) {
+ resize(0);
+ return;
+ }
+
+ resize(len + 1); // include terminating null char
+
+ strcpy(ptrw(), p_cstr);
+}
+
void String::copy_from(const char *p_cstr) {
if (!p_cstr) {
diff --git a/core/ustring.h b/core/ustring.h
index 85103057df..e2e62874d6 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -101,12 +101,17 @@ public:
_cowdata._ref(p_str._cowdata);
return *this;
}
+ _FORCE_INLINE_ CharString(const char *p_cstr) { copy_from(p_cstr); }
+ CharString &operator=(const char *p_cstr);
bool operator<(const CharString &p_right) const;
CharString &operator+=(char p_char);
int length() const { return size() ? size() - 1 : 0; }
const char *get_data() const;
operator const char *() const { return get_data(); };
+
+protected:
+ void copy_from(const char *p_cstr);
};
typedef wchar_t CharType;
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 143b07418e..f9f73b4e51 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -36,6 +36,7 @@
#include "core/object.h"
#include "core/os/os.h"
#include "core/script_language.h"
+#include "thirdparty/misc/sha256.h"
typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args);
typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args);
@@ -587,6 +588,19 @@ struct _VariantCall {
r_ret = decompressed;
}
+ static void _call_PoolByteArray_sha256_string(Variant &r_ret, Variant &p_self, const Variant **p_args) {
+ PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem);
+ PoolByteArray::Read r = ba->read();
+ String s;
+ unsigned char hash[32];
+ sha256_context sha256;
+ sha256_init(&sha256);
+ sha256_hash(&sha256, (unsigned char *)r.ptr(), ba->size());
+ sha256_done(&sha256, hash);
+ s = String::hex_encode_buffer(hash, 32);
+ r_ret = s;
+ }
+
VCALL_LOCALMEM0R(PoolByteArray, size);
VCALL_LOCALMEM2(PoolByteArray, set);
VCALL_LOCALMEM1R(PoolByteArray, get);
@@ -1733,6 +1747,7 @@ void register_variant_methods() {
ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray());
ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray());
+ ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, sha256_string, varray());
ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0));
ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0));
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 6377197282..d7371b0434 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1542,6 +1542,9 @@ Error VariantParser::parse_tag_assign_eof(Stream *p_stream, int &line, String &r
} else if (c != '=') {
what += String::chr(c);
} else {
+ if (p_stream->is_utf8()) {
+ what.parse_utf8(what.ascii(true).get_data());
+ }
r_assign = what;
Token token;
get_token(p_stream, token, line, r_err_str);
diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml
index e31d815063..29bf9b62ce 100644
--- a/doc/classes/@GDScript.xml
+++ b/doc/classes/@GDScript.xml
@@ -92,7 +92,7 @@
<argument index="0" name="condition" type="bool">
</argument>
<description>
- Assert that the [code]condition[/code] is true. If the [code]condition[/code] is false a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always true.
+ Assert that the [code]condition[/code] is [code]true[/code] . If the [code]condition[/code] is [code]false[/code] a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always [code]true[/code].
[codeblock]
# Speed should always be between 0 and 20
speed = -10
diff --git a/doc/classes/ARVRAnchor.xml b/doc/classes/ARVRAnchor.xml
index 092d5e2916..91f44151fa 100644
--- a/doc/classes/ARVRAnchor.xml
+++ b/doc/classes/ARVRAnchor.xml
@@ -22,7 +22,7 @@
<return type="bool">
</return>
<description>
- Returns true if the anchor is being tracked and false if no anchor with this id is currently known.
+ Returns [code]true[/code] if the anchor is being tracked and [code]false[/code] if no anchor with this id is currently known.
</description>
</method>
<method name="get_mesh" qualifiers="const">
diff --git a/doc/classes/ARVRInterface.xml b/doc/classes/ARVRInterface.xml
index bb03c50be9..11084fb98e 100644
--- a/doc/classes/ARVRInterface.xml
+++ b/doc/classes/ARVRInterface.xml
@@ -53,7 +53,7 @@
<return type="bool">
</return>
<description>
- Returns true if the current output of this interface is in stereo.
+ Returns [code]true[/code] if the current output of this interface is in stereo.
</description>
</method>
<method name="uninitialize">
diff --git a/doc/classes/ARVRServer.xml b/doc/classes/ARVRServer.xml
index b828d45cbe..6f5a76943f 100644
--- a/doc/classes/ARVRServer.xml
+++ b/doc/classes/ARVRServer.xml
@@ -54,7 +54,7 @@
<return type="int">
</return>
<description>
- Get the number of interfaces currently registered with the AR/VR server. If your game supports multiple AR/VR platforms, you can look through the available interface, and either present the user with a selection or simply try an initialize each interface and use the first one that returns true.
+ Get the number of interfaces currently registered with the AR/VR server. If your game supports multiple AR/VR platforms, you can look through the available interface, and either present the user with a selection or simply try an initialize each interface and use the first one that returns [code]true[/code].
</description>
</method>
<method name="get_interfaces" qualifiers="const">
diff --git a/doc/classes/AnimatedSprite.xml b/doc/classes/AnimatedSprite.xml
index a5202dc612..2d4dd0e4b2 100644
--- a/doc/classes/AnimatedSprite.xml
+++ b/doc/classes/AnimatedSprite.xml
@@ -13,7 +13,7 @@
<return type="bool">
</return>
<description>
- Return true if an animation if currently being played.
+ Return [code]true[/code] if an animation if currently being played.
</description>
</method>
<method name="play">
diff --git a/doc/classes/AnimatedSprite3D.xml b/doc/classes/AnimatedSprite3D.xml
index 1607a2e105..4c6868d807 100644
--- a/doc/classes/AnimatedSprite3D.xml
+++ b/doc/classes/AnimatedSprite3D.xml
@@ -13,7 +13,7 @@
<return type="bool">
</return>
<description>
- Return true if an animation if currently being played.
+ Return [code]true[/code] if an animation if currently being played.
</description>
</method>
<method name="play">
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 23227c7404..af3abed256 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -438,7 +438,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return true if the given track is imported. Else, return false.
+ Return [code]true[/code] if the given track is imported. Else, return [code]false[/code].
</description>
</method>
<method name="track_move_down">
diff --git a/doc/classes/AnimationNode.xml b/doc/classes/AnimationNode.xml
index 7ce4aae4fd..e61fe374fa 100644
--- a/doc/classes/AnimationNode.xml
+++ b/doc/classes/AnimationNode.xml
@@ -52,7 +52,7 @@
<argument index="5" name="optimize" type="bool" default="true">
</argument>
<description>
- Blend an input. This is only useful for nodes created for an [AnimationNodeBlendTree]. Time is a delta, unless "seek" is true, in which case it is absolute. A filter mode may be optionally passed.
+ Blend an input. This is only useful for nodes created for an [AnimationNodeBlendTree]. Time is a delta, unless "seek" is [code]true[/code], in which case it is absolute. A filter mode may be optionally passed.
</description>
</method>
<method name="blend_node">
@@ -144,7 +144,7 @@
<return type="String">
</return>
<description>
- Return true whether you want the blend tree editor to display filter editing on this node.
+ Return [code]true[/code] whether you want the blend tree editor to display filter editing on this node.
</description>
</method>
<method name="is_path_filtered" qualifiers="const">
@@ -153,7 +153,7 @@
<argument index="0" name="path" type="NodePath">
</argument>
<description>
- Return true wether a given path is filtered.
+ Return [code]true[/code] wether a given path is filtered.
</description>
</method>
<method name="process" qualifiers="virtual">
@@ -164,7 +164,7 @@
<argument index="1" name="seek" type="bool">
</argument>
<description>
- Called when a custom node is processed. The argument "time" is relative, unless "seek" is true (in which case it is absolute).
+ Called when a custom node is processed. The argument "time" is relative, unless "seek" is [code]true[/code] (in which case it is absolute).
Here, call the [method blend_input], [method blend_node] or [method blend_animation] functions.
You can also use [method get_parameter] and [method set_parameter] to modify local memory.
This function returns the time left for the current animation to finish (if unsure, just pass the value from the main blend being called).
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index 509285cdb8..5ea993f83d 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -142,7 +142,7 @@
<argument index="3" name="from_end" type="bool" default="false">
</argument>
<description>
- Play the animation with key [code]name[/code]. Custom speed and blend times can be set. If custom speed is negative (-1), 'from_end' being true can play the animation backwards.
+ Play the animation with key [code]name[/code]. Custom speed and blend times can be set. If custom speed is negative (-1), 'from_end' being [code]true[/code] can play the animation backwards.
If the animation has been paused by [code]stop(true)[/code] it will be resumed. Calling [code]play()[/code] without arguments will also resume the animation.
</description>
</method>
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 73ca6ab5b3..ecafc3514c 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -103,7 +103,7 @@
<argument index="1" name="before" type="bool" default="True">
</argument>
<description>
- Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a before specifier can be passed. If false, the returned index comes after all existing entries of the value in the array. Note that calling bsearch on an unsorted array results in unexpected behavior.
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search. Optionally, a before specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array. Note that calling bsearch on an unsorted array results in unexpected behavior.
</description>
</method>
<method name="bsearch_custom">
@@ -118,7 +118,7 @@
<argument index="3" name="before" type="bool" default="True">
</argument>
<description>
- Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search and a custom comparison method. Optionally, a before specifier can be passed. If false, the returned index comes after all existing entries of the value in the array. The custom method receives two arguments (an element from the array and the value searched for) and must return true if the first argument is less than the second, and return false otherwise. Note that calling bsearch on an unsorted array results in unexpected behavior.
+ Finds the index of an existing value (or the insertion index that maintains sorting order, if the value is not yet present in the array) using binary search and a custom comparison method. Optionally, a before specifier can be passed. If [code]false[/code], the returned index comes after all existing entries of the value in the array. The custom method receives two arguments (an element from the array and the value searched for) and must return [code]true[/code] if the first argument is less than the second, and return [code]false[/code] otherwise. Note that calling bsearch on an unsorted array results in unexpected behavior.
</description>
</method>
<method name="clear">
@@ -312,7 +312,7 @@
<argument index="1" name="func" type="String">
</argument>
<description>
- Sorts the array using a custom method. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise.
+ Sorts the array using a custom method. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return [code]true[/code] if the first argument is less than the second, and return [code]false[/code] otherwise.
[b]Note:[/b] you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior.
[codeblock]
class MyCustomSorter:
diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml
index 6083372b72..2bd3ac1eaa 100644
--- a/doc/classes/AudioStreamPlayer3D.xml
+++ b/doc/classes/AudioStreamPlayer3D.xml
@@ -60,7 +60,7 @@
Amount how much the filter affects the loudness, in dB.
</member>
<member name="attenuation_model" type="int" setter="set_attenuation_model" getter="get_attenuation_model" enum="AudioStreamPlayer3D.AttenuationModel">
- Decides if audio should get quieter with distance linearly, quadratically or logarithmically.
+ Decides if audio should get quieter with distance linearly, quadratically, logarithmically, or not be affected by distance, effectively disabling attenuation.
</member>
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled">
If [code]true[/code], audio plays when added to scene tree. Default value: [code]false[/code].
@@ -124,6 +124,9 @@
<constant name="ATTENUATION_LOGARITHMIC" value="2" enum="AttenuationModel">
Logarithmic dampening of loudness according to distance.
</constant>
+ <constant name="ATTENUATION_DISABLED" value="3" enum="AttenuationModel">
+ No dampening of loudness according to distance.
+ </constant>
<constant name="OUT_OF_RANGE_MIX" value="0" enum="OutOfRangeMode">
Mix this audio in, even when it's out of range.
</constant>
diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml
index 3c8d4ea0d8..08be3ed0f4 100644
--- a/doc/classes/BaseButton.xml
+++ b/doc/classes/BaseButton.xml
@@ -36,7 +36,7 @@
<return type="bool">
</return>
<description>
- Return true if the mouse has entered the button and has not left it yet.
+ Return [code]true[/code] if the mouse has entered the button and has not left it yet.
</description>
</method>
</methods>
diff --git a/doc/classes/BitMap.xml b/doc/classes/BitMap.xml
index 2e4aaed099..7f03c22b70 100644
--- a/doc/classes/BitMap.xml
+++ b/doc/classes/BitMap.xml
@@ -15,7 +15,7 @@
<argument index="0" name="size" type="Vector2">
</argument>
<description>
- Creates a bitmap with the specified size, filled with false.
+ Creates a bitmap with the specified size, filled with [code]false[/code].
</description>
</method>
<method name="create_from_image_alpha">
@@ -26,7 +26,7 @@
<argument index="1" name="threshold" type="float" default="0.1">
</argument>
<description>
- Creates a bitmap that matches the given image dimensions, every element of the bitmap is set to false if the alpha value of the image at that position is equal to [code]threshold[/code] or less, and true in other case.
+ Creates a bitmap that matches the given image dimensions, every element of the bitmap is set to [code]false[/code] if the alpha value of the image at that position is equal to [code]threshold[/code] or less, and [code]true[/code] in other case.
</description>
</method>
<method name="get_bit" qualifiers="const">
@@ -49,7 +49,7 @@
<return type="int">
</return>
<description>
- Returns the amount of bitmap elements that are set to true.
+ Returns the amount of bitmap elements that are set to [code]true[/code].
</description>
</method>
<method name="grow_mask">
diff --git a/doc/classes/Camera.xml b/doc/classes/Camera.xml
index 2716bee0f3..014df2b72a 100644
--- a/doc/classes/Camera.xml
+++ b/doc/classes/Camera.xml
@@ -15,7 +15,7 @@
<argument index="0" name="enable_next" type="bool" default="true">
</argument>
<description>
- If this is the current Camera, remove it from being current. If [code]enable_next[/code] is true, request to make the next Camera current, if any.
+ If this is the current Camera, remove it from being current. If [code]enable_next[/code] is [code]true[/code], request to make the next Camera current, if any.
</description>
</method>
<method name="get_camera_transform" qualifiers="const">
@@ -101,6 +101,20 @@
<description>
</description>
</method>
+ <method name="set_frustum">
+ <return type="void">
+ </return>
+ <argument index="0" name="size" type="float">
+ </argument>
+ <argument index="1" name="offset" type="Vector2">
+ </argument>
+ <argument index="2" name="z_near" type="float">
+ </argument>
+ <argument index="3" name="z_far" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_orthogonal">
<return type="void">
</return>
@@ -156,6 +170,8 @@
<member name="fov" type="float" setter="set_fov" getter="get_fov">
The camera's field of view angle (in degrees). Only applicable in perspective mode. Since [member keep_aspect] locks one axis, [code]fov[/code] sets the other axis' field of view angle.
</member>
+ <member name="frustum_offset" type="Vector2" setter="set_frustum_offset" getter="get_frustum_offset">
+ </member>
<member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset">
The horizontal (X) offset of the Camera viewport.
</member>
@@ -182,6 +198,8 @@
<constant name="PROJECTION_ORTHOGONAL" value="1" enum="Projection">
Orthogonal Projection (objects remain the same size on the screen no matter how far away they are).
</constant>
+ <constant name="PROJECTION_FRUSTUM" value="2" enum="Projection">
+ </constant>
<constant name="KEEP_WIDTH" value="0" enum="KeepAspect">
Preserves the horizontal aspect ratio.
</constant>
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index f3e598c17d..82a5679172 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -97,6 +97,10 @@
</argument>
<argument index="2" name="normal_map" type="Texture" default="null">
</argument>
+ <argument index="3" name="transform" type="Transform2D" default="Transform2D( 1, 0, 0, 1, 0, 0 )">
+ </argument>
+ <argument index="4" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
+ </argument>
<description>
</description>
</method>
diff --git a/doc/classes/ClassDB.xml b/doc/classes/ClassDB.xml
index a37dd28d72..b029c85409 100644
--- a/doc/classes/ClassDB.xml
+++ b/doc/classes/ClassDB.xml
@@ -15,7 +15,7 @@
<argument index="0" name="class" type="String">
</argument>
<description>
- Returns true if you can instance objects from the specified 'class', false in other case.
+ Returns [code]true[/code] if you can instance objects from the specified 'class', [code]false[/code] in other case.
</description>
</method>
<method name="class_exists" qualifiers="const">
@@ -66,7 +66,7 @@
<argument index="1" name="no_inheritance" type="bool" default="false">
</argument>
<description>
- Returns an array with all the methods of 'class' or its ancestry if 'no_inheritance' is false. Every element of the array is a [Dictionary] with the following keys: args, default_args, flags, id, name, return: (class_name, hint, hint_string, name, type, usage).
+ Returns an array with all the methods of 'class' or its ancestry if 'no_inheritance' is [code]false[/code]. Every element of the array is a [Dictionary] with the following keys: args, default_args, flags, id, name, return: (class_name, hint, hint_string, name, type, usage).
</description>
</method>
<method name="class_get_property" qualifiers="const">
@@ -88,7 +88,7 @@
<argument index="1" name="no_inheritance" type="bool" default="false">
</argument>
<description>
- Returns an array with all the properties of 'class' or its ancestry if 'no_inheritance' is false.
+ Returns an array with all the properties of 'class' or its ancestry if 'no_inheritance' is [code]false[/code].
</description>
</method>
<method name="class_get_signal" qualifiers="const">
@@ -110,7 +110,7 @@
<argument index="1" name="no_inheritance" type="bool" default="false">
</argument>
<description>
- Returns an array with all the signals of 'class' or its ancestry if 'no_inheritance' is false. Every element of the array is a [Dictionary] as described in [method class_get_signal].
+ Returns an array with all the signals of 'class' or its ancestry if 'no_inheritance' is [code]false[/code]. Every element of the array is a [Dictionary] as described in [method class_get_signal].
</description>
</method>
<method name="class_has_integer_constant" qualifiers="const">
diff --git a/doc/classes/CollisionPolygon.xml b/doc/classes/CollisionPolygon.xml
index c40c8a82c3..85eb17cae7 100644
--- a/doc/classes/CollisionPolygon.xml
+++ b/doc/classes/CollisionPolygon.xml
@@ -15,7 +15,7 @@
Length that the resulting collision extends in either direction perpendicular to its polygon.
</member>
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled">
- If true, no collision will be produced.
+ If [code]true[/code], no collision will be produced.
</member>
<member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon">
Array of vertices which define the polygon. Note that the returned value is a copy of the original. Methods which mutate the size or properties of the return value will not impact the original polygon. To change properties of the polygon, assign it to a temporary variable and make changes before reassigning the [code]polygon[/code] member.
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 224efeb3f5..f7fbdf08ed 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -682,7 +682,7 @@
Controls whether the control will be able to receive mouse button input events through [method _gui_input] and how these events should be handled. Also controls whether the control can receive the [signal mouse_entered], and [signal mouse_exited] signals. See the constants to learn what each does.
</member>
<member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents">
- Enables whether rendering of children should be clipped to this control's rectangle. If true, parts of a child which would be visibly outside of this control's rectangle will not be rendered.
+ Enables whether rendering of children should be clipped to this control's rectangle. If [code]true[/code], parts of a child which would be visibly outside of this control's rectangle will not be rendered.
</member>
<member name="rect_global_position" type="Vector2" setter="set_global_position" getter="get_global_position">
The node's global position, relative to the world (usually to the top-left corner of the window).
diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml
index d4aaa24b8c..3631711a8f 100644
--- a/doc/classes/Curve2D.xml
+++ b/doc/classes/Curve2D.xml
@@ -122,7 +122,7 @@
</argument>
<description>
Returns a point within the curve at position [code]offset[/code], where [code]offset[/code] is measured as a pixel distance along the curve.
- To do that, it finds the two cached points where the [code]offset[/code] lies between, then interpolates the values. This interpolation is cubic if [code]cubic[/code] is set to true, or linear if set to false.
+ To do that, it finds the two cached points where the [code]offset[/code] lies between, then interpolates the values. This interpolation is cubic if [code]cubic[/code] is set to [code]true[/code], or linear if set to [code]false[/code].
Cubic interpolation tends to follow the curves better, but linear is faster (and often, precise enough).
</description>
</method>
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 1d9761407d..7fda8aaa93 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -146,7 +146,7 @@
</argument>
<description>
Returns a point within the curve at position [code]offset[/code], where [code]offset[/code] is measured as a pixel distance along the curve.
- To do that, it finds the two cached points where the [code]offset[/code] lies between, then interpolates the values. This interpolation is cubic if [code]cubic[/code] is set to true, or linear if set to false.
+ To do that, it finds the two cached points where the [code]offset[/code] lies between, then interpolates the values. This interpolation is cubic if [code]cubic[/code] is set to [code]true[/code], or linear if set to [code]false[/code].
Cubic interpolation tends to follow the curves better, but linear is faster (and often, precise enough).
</description>
</method>
diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml
index b0a3b1ac75..f47649363e 100644
--- a/doc/classes/Dictionary.xml
+++ b/doc/classes/Dictionary.xml
@@ -38,7 +38,7 @@
<return type="bool">
</return>
<description>
- Return true if the dictionary is empty.
+ Return [code]true[/code] if the dictionary is empty.
</description>
</method>
<method name="erase">
@@ -67,7 +67,7 @@
<argument index="0" name="key" type="Variant">
</argument>
<description>
- Return true if the dictionary has a given key.
+ Return [code]true[/code] if the dictionary has a given key.
</description>
</method>
<method name="has_all">
@@ -76,7 +76,7 @@
<argument index="0" name="keys" type="Array">
</argument>
<description>
- Return true if the dictionary has all of the keys in the given array.
+ Return [code]true[/code] if the dictionary has all of the keys in the given array.
</description>
</method>
<method name="hash">
diff --git a/doc/classes/DynamicFont.xml b/doc/classes/DynamicFont.xml
index 99ba5143e3..5fdc1ebb75 100644
--- a/doc/classes/DynamicFont.xml
+++ b/doc/classes/DynamicFont.xml
@@ -5,6 +5,12 @@
</brief_description>
<description>
DynamicFont renders vector font files (such as TTF or OTF) dynamically at runtime instead of using a prerendered texture atlas like [BitmapFont]. This trades the faster loading time of [BitmapFont]s for the ability to change font parameters like size and spacing during runtime. [DynamicFontData] is used for referencing the font file paths.
+ [codeblock]
+ var dynamic_font = DynamicFont.new()
+ dynamic_font.font_data = load("res://BarlowCondensed-Bold.ttf")
+ dynamic_font.size = 64
+ $"Label".set("custom_fonts/font", dynamic_font)
+ [/codeblock]
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/EditorFileSystem.xml b/doc/classes/EditorFileSystem.xml
index f110183081..531af4c4e0 100644
--- a/doc/classes/EditorFileSystem.xml
+++ b/doc/classes/EditorFileSystem.xml
@@ -45,7 +45,7 @@
<return type="bool">
</return>
<description>
- Return true of the filesystem is being scanned.
+ Return [code]true[/code] of the filesystem is being scanned.
</description>
</method>
<method name="scan">
diff --git a/doc/classes/EditorInspectorPlugin.xml b/doc/classes/EditorInspectorPlugin.xml
index 49efee49f4..f2dcd2177c 100644
--- a/doc/classes/EditorInspectorPlugin.xml
+++ b/doc/classes/EditorInspectorPlugin.xml
@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorInspectorPlugin" inherits="Reference" category="Core" version="3.2">
<brief_description>
+ Plugin for adding custom property editors on inspector.
</brief_description>
<description>
+ This plugins allows adding custom property editors to [EditorInspector].
+ Plugins are registered via [method EditorPlugin.add_inspector_plugin].
+ When an object is edited, the [method can_handle] function is called and must return true if the object type is supported.
+ If supported, the function [method parse_begin] will be called, allowing to place custom controls at the beginning of the class.
+ Subsequently, the [method parse_category] and [method parse_property] are called for every category and property. They offer the ability to add custom controls to the inspector too.
+ Finally [method parse_end] will be called.
+ On each of these calls, the "add" functions can be called.
</description>
<tutorials>
</tutorials>
@@ -13,6 +21,7 @@
<argument index="0" name="control" type="Control">
</argument>
<description>
+ Add a custom control, not necesarily a property editor.
</description>
</method>
<method name="add_property_editor">
@@ -23,6 +32,7 @@
<argument index="1" name="editor" type="Control">
</argument>
<description>
+ Add a property editor, this must inherit [EditorProperty].
</description>
</method>
<method name="add_property_editor_for_multiple_properties">
@@ -35,6 +45,7 @@
<argument index="2" name="editor" type="Control">
</argument>
<description>
+ Add am editor that allows modifying multiple properties, this must inherit [EditorProperty].
</description>
</method>
<method name="can_handle" qualifiers="virtual">
@@ -43,6 +54,7 @@
<argument index="0" name="object" type="Object">
</argument>
<description>
+ Return true if this object can be handled by this plugin.
</description>
</method>
<method name="parse_begin" qualifiers="virtual">
@@ -51,6 +63,7 @@
<argument index="0" name="object" type="Object">
</argument>
<description>
+ Called to allow adding controls at the beginning of the list.
</description>
</method>
<method name="parse_category" qualifiers="virtual">
@@ -61,12 +74,14 @@
<argument index="1" name="category" type="String">
</argument>
<description>
+ Called to allow adding controls at the beginning of the category.
</description>
</method>
<method name="parse_end" qualifiers="virtual">
<return type="void">
</return>
<description>
+ Called to allow adding controls at the end of the list.
</description>
</method>
<method name="parse_property" qualifiers="virtual">
@@ -85,6 +100,7 @@
<argument index="5" name="usage" type="int">
</argument>
<description>
+ Called to allow adding property specific editors to the inspector. Usually these inherit [EditorProperty]
</description>
</method>
</methods>
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 829563c8ac..7981c90f86 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -292,14 +292,14 @@
<argument index="0" name="object" type="Object">
</argument>
<description>
- Implement this function if your plugin edits a specific type of object (Resource or Node). If you return true, then you will get the functions [method EditorPlugin.edit] and [method EditorPlugin.make_visible] called when the editor requests them. If you have declared the methods [method forward_canvas_gui_input] and [method forward_spatial_gui_input] these will be called too.
+ Implement this function if your plugin edits a specific type of object (Resource or Node). If you return [code]true[/code], then you will get the functions [method EditorPlugin.edit] and [method EditorPlugin.make_visible] called when the editor requests them. If you have declared the methods [method forward_canvas_gui_input] and [method forward_spatial_gui_input] these will be called too.
</description>
</method>
<method name="has_main_screen" qualifiers="virtual">
<return type="bool">
</return>
<description>
- Return true if this is a main screen editor plugin (it goes in the workspaces selector together with '2D', '3D', and 'Script').
+ Return [code]true[/code] if this is a main screen editor plugin (it goes in the workspaces selector together with '2D', '3D', and 'Script').
</description>
</method>
<method name="hide_bottom_panel">
diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml
index 2fd7f18461..735c270279 100644
--- a/doc/classes/EditorProperty.xml
+++ b/doc/classes/EditorProperty.xml
@@ -1,12 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorProperty" inherits="Container" category="Core" version="3.2">
<brief_description>
+ Custom control to edit properties for adding into the inspector
</brief_description>
<description>
+ This control allows property editing for one or multiple properties into [EditorInspector]. It is added via [EditorInspectorPlugin].
</description>
<tutorials>
</tutorials>
<methods>
+ <method name="add_focusable">
+ <return type="void">
+ </return>
+ <argument index="0" name="control" type="Control">
+ </argument>
+ <description>
+ If any of the controls added can gain keyboard focus, add it here. This ensures that focus will be restored if the inspector is refreshed.
+ </description>
+ </method>
<method name="emit_changed">
<return type="void">
</return>
@@ -19,45 +30,65 @@
<argument index="3" name="changing" type="bool" default="false">
</argument>
<description>
+ If one (or many properties) changed, this must be called. "Field" is used in case your editor can modify fields separately (as an example, Vector3.x). The "changing" argument avoids the editor requesting this property to be refreshed (leave as false if unsure).
</description>
</method>
<method name="get_edited_object">
<return type="Object">
</return>
<description>
+ Get the edited object.
</description>
</method>
<method name="get_edited_property">
<return type="String">
</return>
<description>
+ Get the edited property. If your editor is for a single property (added via [method EditorInspectorPlugin.parse_property]), then this will return it..
</description>
</method>
<method name="get_tooltip_text" qualifiers="const">
<return type="String">
</return>
<description>
+ Override if you want to allow a custom tooltip over your property.
+ </description>
+ </method>
+ <method name="set_bottom_editor">
+ <return type="void">
+ </return>
+ <argument index="0" name="editor" type="Control">
+ </argument>
+ <description>
+ Add controls with this function if you want them on the bottom (below the label).
</description>
</method>
<method name="update_property" qualifiers="virtual">
<return type="void">
</return>
<description>
+ When this virtual function is called, you must update your editor.
</description>
</method>
</methods>
<members>
<member name="checkable" type="bool" setter="set_checkable" getter="is_checkable">
+ Used by the inspector, set when property is checkable.
</member>
<member name="checked" type="bool" setter="set_checked" getter="is_checked">
+ Used by the inspector, when the property is checked.
</member>
<member name="draw_red" type="bool" setter="set_draw_red" getter="is_draw_red">
+ Used by the inspector, when the property must draw with error color.
</member>
<member name="keying" type="bool" setter="set_keying" getter="is_keying">
+ Used by the inspector, when the property can add keys for animation/
</member>
<member name="label" type="String" setter="set_label" getter="get_label">
+ Set this property to change the label (if you want to show one)
</member>
<member name="read_only" type="bool" setter="set_read_only" getter="is_read_only">
+ Used by the inspector, when the property is read-only.
</member>
</members>
<signals>
@@ -67,6 +98,7 @@
<argument index="1" name="value" type="Array">
</argument>
<description>
+ Emit yourself if you want multiple properties modified at the same time. Do not use if added via [method EditorInspectorPlugin.parse_property]
</description>
</signal>
<signal name="object_id_selected">
@@ -75,6 +107,7 @@
<argument index="1" name="id" type="int">
</argument>
<description>
+ Used by sub-inspectors. Emit if what was selected was an Object ID.
</description>
</signal>
<signal name="property_changed">
@@ -83,6 +116,7 @@
<argument index="1" name="value" type="Nil">
</argument>
<description>
+ Do not emit this manually, use the [method emit_changed] method instead.
</description>
</signal>
<signal name="property_checked">
@@ -91,12 +125,14 @@
<argument index="1" name="bool" type="String">
</argument>
<description>
+ Used internally, when a property was checked.
</description>
</signal>
<signal name="property_keyed">
<argument index="0" name="property" type="String">
</argument>
<description>
+ Emit if you want to add this value as an animation key (check keying being enabled first).
</description>
</signal>
<signal name="property_keyed_with_value">
@@ -105,6 +141,7 @@
<argument index="1" name="value" type="Nil">
</argument>
<description>
+ Emit if you want to key a property with a single value.
</description>
</signal>
<signal name="resource_selected">
@@ -113,6 +150,7 @@
<argument index="1" name="resource" type="Resource">
</argument>
<description>
+ If you want a sub-resource to be edited, emit this signal with the resource.
</description>
</signal>
<signal name="selected">
@@ -121,6 +159,7 @@
<argument index="1" name="focusable_idx" type="int">
</argument>
<description>
+ Internal, used when selected.
</description>
</signal>
</signals>
diff --git a/doc/classes/EditorSpatialGizmo.xml b/doc/classes/EditorSpatialGizmo.xml
index 58d04e2bbf..da7fee1cf7 100644
--- a/doc/classes/EditorSpatialGizmo.xml
+++ b/doc/classes/EditorSpatialGizmo.xml
@@ -97,7 +97,7 @@
</argument>
<description>
Commit a handle being edited (handles must have been previously added by [method add_handles]).
- If the cancel parameter is true, an option to restore the edited value to the original is provided.
+ If the cancel parameter is [code]true[/code], an option to restore the edited value to the original is provided.
</description>
</method>
<method name="get_handle_name" qualifiers="virtual">
diff --git a/doc/classes/EditorSpatialGizmoPlugin.xml b/doc/classes/EditorSpatialGizmoPlugin.xml
index 8700c1cff9..40d6376ca3 100644
--- a/doc/classes/EditorSpatialGizmoPlugin.xml
+++ b/doc/classes/EditorSpatialGizmoPlugin.xml
@@ -25,7 +25,7 @@
<return type="bool">
</return>
<description>
- Override this method to define whether the gizmo can be hidden or not. Defaults to true.
+ Override this method to define whether the gizmo can be hidden or not. Defaults to [code]true[/code].
</description>
</method>
<method name="commit_handle" qualifiers="virtual">
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 17fdc59c6f..5f8dc552d7 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -28,7 +28,7 @@
Global contrast value of the rendered scene (default value is 1).
</member>
<member name="adjustment_enabled" type="bool" setter="set_adjustment_enable" getter="is_adjustment_enabled">
- Enables the adjustment_* options provided by this resource. If false, adjustments modifications will have no effect on the rendered scene.
+ Enables the adjustment_* options provided by this resource. If [code]false[/code], adjustments modifications will have no effect on the rendered scene.
</member>
<member name="adjustment_saturation" type="float" setter="set_adjustment_saturation" getter="get_adjustment_saturation">
Global color saturation value of the rendered scene (default value is 1).
diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index 86504b2c98..145cd243bc 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -101,7 +101,7 @@
<argument index="3" name="to_port" type="int">
</argument>
<description>
- Return true if the 'from_port' slot of 'from' GraphNode is connected to the 'to_port' slot of 'to' GraphNode.
+ Return [code]true[/code] if the 'from_port' slot of 'from' GraphNode is connected to the 'to_port' slot of 'to' GraphNode.
</description>
</method>
<method name="is_valid_connection_type" qualifiers="const">
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index 845fc35a7a..4d6f3180d0 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -135,7 +135,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return true if left (input) slot 'idx' is enabled. False otherwise.
+ Return [code]true[/code] if left (input) slot 'idx' is enabled, [code]false[/code] otherwise.
</description>
</method>
<method name="is_slot_enabled_right" qualifiers="const">
@@ -144,7 +144,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return true if right (output) slot 'idx' is enabled. False otherwise.
+ Return [code]true[/code] if right (output) slot 'idx' is enabled, [code]false[/code] otherwise.
</description>
</method>
<method name="set_slot">
diff --git a/doc/classes/HTTPClient.xml b/doc/classes/HTTPClient.xml
index 13e018f88f..8ae0120a34 100644
--- a/doc/classes/HTTPClient.xml
+++ b/doc/classes/HTTPClient.xml
@@ -295,7 +295,7 @@
HTTP status code [code]303 See Other[/code]. The server is redirecting the user agent to a different resource, as indicated by a URI in the Location header field, which is intended to provide an indirect response to the original request.
</constant>
<constant name="RESPONSE_NOT_MODIFIED" value="304" enum="ResponseCode">
- HTTP status code [code]304 Not Modified[/code]. A conditional GET or HEAD request has been received and would have resulted in a 200 OK response if it were not for the fact that the condition evaluated to false.
+ HTTP status code [code]304 Not Modified[/code]. A conditional GET or HEAD request has been received and would have resulted in a 200 OK response if it were not for the fact that the condition evaluated to [code]false[/code].
</constant>
<constant name="RESPONSE_USE_PROXY" value="305" enum="ResponseCode">
HTTP status code [code]305 Use Proxy[/code]. Deprecated. Do not use.
@@ -346,7 +346,7 @@
HTTP status code [code]411 Length Required[/code]. The server refuses to accept the request without a defined Content-Length header.
</constant>
<constant name="RESPONSE_PRECONDITION_FAILED" value="412" enum="ResponseCode">
- HTTP status code [code]412 Precondition Failed[/code]. One or more conditions given in the request header fields evaluated to false when tested on the server.
+ HTTP status code [code]412 Precondition Failed[/code]. One or more conditions given in the request header fields evaluated to [code]false[/code] when tested on the server.
</constant>
<constant name="RESPONSE_REQUEST_ENTITY_TOO_LARGE" value="413" enum="ResponseCode">
HTTP status code [code]413 Entity Too Large[/code]. The server is refusing to process a request because the request payload is larger than the server is willing or able to process.
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 2abc3af8c5..641bd64599 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -123,7 +123,7 @@
<argument index="3" name="format" type="int" enum="Image.Format">
</argument>
<description>
- Creates an empty image of given size and format. See [code]FORMAT_*[/code] constants. If [code]use_mipmaps[/code] is true then generate mipmaps for this image. See the [code]generate_mipmaps[/code] method.
+ Creates an empty image of given size and format. See [code]FORMAT_*[/code] constants. If [code]use_mipmaps[/code] is [code]true[/code] then generate mipmaps for this image. See the [code]generate_mipmaps[/code] method.
</description>
</method>
<method name="create_from_data">
@@ -140,7 +140,7 @@
<argument index="4" name="data" type="PoolByteArray">
</argument>
<description>
- Creates a new image of given size and format. See [code]FORMAT_*[/code] constants. Fills the image with the given raw data. If [code]use_mipmaps[/code] is true then generate mipmaps for this image. See the [code]generate_mipmaps[/code] method.
+ Creates a new image of given size and format. See [code]FORMAT_*[/code] constants. Fills the image with the given raw data. If [code]use_mipmaps[/code] is [code]true[/code] then generate mipmaps for this image. See the [code]generate_mipmaps[/code] method.
</description>
</method>
<method name="crop">
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index 4aff5dd62b..319f84b8d2 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -203,7 +203,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Returns [code]true[/code] when the user starts pressing the action event, meaning it's true only on the frame that the user pressed down the button.
+ Returns [code]true[/code] when the user starts pressing the action event, meaning it's [code]true[/code] only on the frame that the user pressed down the button.
This is useful for code that needs to run only once when an action is pressed, instead of every frame while it's pressed.
</description>
</method>
@@ -213,7 +213,7 @@
<argument index="0" name="action" type="String">
</argument>
<description>
- Returns [code]true[/code] when the user stops pressing the action event, meaning it's true only on the frame that the user released the button.
+ Returns [code]true[/code] when the user stops pressing the action event, meaning it's [code]true[/code] only on the frame that the user released the button.
</description>
</method>
<method name="is_action_pressed" qualifiers="const">
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index 1cfd9e03f7..663eeda77a 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -32,7 +32,7 @@
</argument>
<description>
Adds an item to the item list with specified text. Specify an icon of null for a list item with no icon.
- If selectable is true the list item will be selectable.
+ If selectable is [code]true[/code] the list item will be selectable.
</description>
</method>
<method name="clear">
diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml
index dae549125f..8ea3d8c188 100644
--- a/doc/classes/KinematicBody.xml
+++ b/doc/classes/KinematicBody.xml
@@ -91,10 +91,10 @@
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody] or [RigidBody], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.
[code]linear_velocity[/code] is the velocity vector (typically meters per second). Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
[code]floor_normal[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector3(0, 0, 0)[/code], everything is considered a wall. This is useful for topdown games.
- If [code]stop_on_slope[/code] is true, body will not slide on slopes if you include gravity in [code]linear_velocity[/code].
+ If [code]stop_on_slope[/code] is [code]true[/code], body will not slide on slopes if you include gravity in [code]linear_velocity[/code].
If the body collides, it will change direction a maximum of [code]max_slides[/code] times before it stops.
[code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
- If [code]infinite_inertia[/code] is true, body will be able to push [RigidBody] nodes, but it won't also detect any collisions with them. When false, it will interact with [RigidBody] nodes like with [StaticBody].
+ If [code]infinite_inertia[/code] is [code]true[/code], body will be able to push [RigidBody] nodes, but it won't also detect any collisions with them. If [code]false[/code] it will interact with [RigidBody] nodes like with [StaticBody].
Returns the [code]linear_velocity[/code] vector, rotated and/or scaled if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
</description>
</method>
diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml
index b41b5412d7..05a8129cc5 100644
--- a/doc/classes/KinematicBody2D.xml
+++ b/doc/classes/KinematicBody2D.xml
@@ -95,10 +95,10 @@
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.
[code]linear_velocity[/code] is the velocity vector in pixels per second. Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
[code]floor_normal[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.
- If [code]stop_on_slope[/code] is true, body will not slide on slopes when you include gravity in [code]linear_velocity[/code] and the body is standing still.
+ If [code]stop_on_slope[/code] is [code]true[/code], body will not slide on slopes when you include gravity in [code]linear_velocity[/code] and the body is standing still.
If the body collides, it will change direction a maximum of [code]max_slides[/code] times before it stops.
[code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees.
- If [code]infinite_inertia[/code] is true, body will be able to push [RigidBody2D] nodes, but it won't also detect any collisions with them. When false, it will interact with [RigidBody2D] nodes like with [StaticBody2D].
+ If [code]infinite_inertia[/code] is [code]true[/code], body will be able to push [RigidBody2D] nodes, but it won't also detect any collisions with them. If [code]false[/code] it will interact with [RigidBody2D] nodes like with [StaticBody2D].
Returns the [code]linear_velocity[/code] vector, rotated and/or scaled if a slide collision occurred. To get detailed information about collisions that occurred, use [method get_slide_collision].
</description>
</method>
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index 955fe6f822..8d52cae186 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -44,7 +44,7 @@
Controls the text's horizontal align. Supports left, center, right, and fill, or justify. Set it to one of the [code]ALIGN_*[/code] constants.
</member>
<member name="autowrap" type="bool" setter="set_autowrap" getter="has_autowrap">
- If [code]true[/code], wraps the text inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. Default: false.
+ If [code]true[/code], wraps the text inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. Default: [code]false[/code].
</member>
<member name="clip_text" type="bool" setter="set_clip_text" getter="is_clipping_text">
If [code]true[/code], the Label only shows the text that fits inside its bounding rectangle. It also lets you scale the node down freely.
diff --git a/doc/classes/MeshTexture.xml b/doc/classes/MeshTexture.xml
new file mode 100644
index 0000000000..d305cca482
--- /dev/null
+++ b/doc/classes/MeshTexture.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="MeshTexture" inherits="Texture" category="Core" version="3.2">
+ <brief_description>
+ Simple texture that uses a mesh to draw itself.
+ </brief_description>
+ <description>
+ Simple texture that uses a mesh to draw itself. It's limited because flags can't be changed and region drawing is not supported.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ </methods>
+ <members>
+ <member name="base_texture" type="Texture" setter="set_base_texture" getter="get_base_texture">
+ Set the base texture that the Mesh will use to draw.
+ </member>
+ <member name="image_size" type="Vector2" setter="set_image_size" getter="get_image_size">
+ Set the size of the image, needed for reference.
+ </member>
+ <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
+ Set the mesh used to draw. It must be a mesh using 2D vertices.
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml
index 723ba7ea2b..7148871e8c 100644
--- a/doc/classes/MultiMesh.xml
+++ b/doc/classes/MultiMesh.xml
@@ -116,6 +116,8 @@
<member name="transform_format" type="int" setter="set_transform_format" getter="get_transform_format" enum="MultiMesh.TransformFormat">
Format of transform used to transform mesh, either 2D or 3D.
</member>
+ <member name="visible_instance_count" type="int" setter="set_visible_instance_count" getter="get_visible_instance_count">
+ </member>
</members>
<constants>
<constant name="TRANSFORM_2D" value="0" enum="TransformFormat">
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index 14299cdcba..1b97f3267f 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -63,7 +63,7 @@
<argument index="1" name="scaled" type="bool" default="false">
</argument>
<description>
- Applies a local translation on the node's X axis based on the [method Node._process]'s [code]delta[/code]. If [code]scaled[/code] is false, normalizes the movement.
+ Applies a local translation on the node's X axis based on the [method Node._process]'s [code]delta[/code]. If [code]scaled[/code] is [code]false[/code], normalizes the movement.
</description>
</method>
<method name="move_local_y">
@@ -74,7 +74,7 @@
<argument index="1" name="scaled" type="bool" default="false">
</argument>
<description>
- Applies a local translation on the node's Y axis based on the [method Node._process]'s [code]delta[/code]. If [code]scaled[/code] is false, normalizes the movement.
+ Applies a local translation on the node's Y axis based on the [method Node._process]'s [code]delta[/code]. If [code]scaled[/code] is [code]false[/code], normalizes the movement.
</description>
</method>
<method name="rotate">
diff --git a/doc/classes/NodePath.xml b/doc/classes/NodePath.xml
index 4c682f1266..73739ba79a 100644
--- a/doc/classes/NodePath.xml
+++ b/doc/classes/NodePath.xml
@@ -68,14 +68,14 @@
<return type="bool">
</return>
<description>
- Return true if the node path is absolute (not relative).
+ Return [code]true[/code] if the node path is absolute (not relative).
</description>
</method>
<method name="is_empty">
<return type="bool">
</return>
<description>
- Return true if the node path is empty.
+ Return [code]true[/code] if the node path is empty.
</description>
</method>
</methods>
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 4724cb9270..4fe43814d1 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -344,7 +344,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- If set to true, signal emission is blocked.
+ If set to [code]true[/code], signal emission is blocked.
</description>
</method>
<method name="set_deferred">
@@ -373,7 +373,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Define whether the object can translate strings (with calls to [method tr]). Default is true.
+ Define whether the object can translate strings (with calls to [method tr]). Default is [code]true[/code].
</description>
</method>
<method name="set_meta">
diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml
index 881e4a9d82..3860511615 100644
--- a/doc/classes/Performance.xml
+++ b/doc/classes/Performance.xml
@@ -55,58 +55,60 @@
Number of resources currently used.
</constant>
<constant name="OBJECT_NODE_COUNT" value="10" enum="Monitor">
- Number of nodes currently instanced. This also includes the root node, as well as any nodes not in the scene tree.
+ Number of nodes currently instanced in the scene tree. This also includes the root node.
</constant>
- <constant name="RENDER_OBJECTS_IN_FRAME" value="11" enum="Monitor">
+ <constant name="OBJECT_ORPHAN_NODE_COUNT" value="11" enum="Monitor">
+ </constant>
+ <constant name="RENDER_OBJECTS_IN_FRAME" value="12" enum="Monitor">
3D objects drawn per frame.
</constant>
- <constant name="RENDER_VERTICES_IN_FRAME" value="12" enum="Monitor">
+ <constant name="RENDER_VERTICES_IN_FRAME" value="13" enum="Monitor">
Vertices drawn per frame. 3D only.
</constant>
- <constant name="RENDER_MATERIAL_CHANGES_IN_FRAME" value="13" enum="Monitor">
+ <constant name="RENDER_MATERIAL_CHANGES_IN_FRAME" value="14" enum="Monitor">
Material changes per frame. 3D only
</constant>
- <constant name="RENDER_SHADER_CHANGES_IN_FRAME" value="14" enum="Monitor">
+ <constant name="RENDER_SHADER_CHANGES_IN_FRAME" value="15" enum="Monitor">
Shader changes per frame. 3D only.
</constant>
- <constant name="RENDER_SURFACE_CHANGES_IN_FRAME" value="15" enum="Monitor">
+ <constant name="RENDER_SURFACE_CHANGES_IN_FRAME" value="16" enum="Monitor">
Render surface changes per frame. 3D only.
</constant>
- <constant name="RENDER_DRAW_CALLS_IN_FRAME" value="16" enum="Monitor">
+ <constant name="RENDER_DRAW_CALLS_IN_FRAME" value="17" enum="Monitor">
Draw calls per frame. 3D only.
</constant>
- <constant name="RENDER_VIDEO_MEM_USED" value="17" enum="Monitor">
+ <constant name="RENDER_VIDEO_MEM_USED" value="18" enum="Monitor">
Video memory used. Includes both texture and vertex memory.
</constant>
- <constant name="RENDER_TEXTURE_MEM_USED" value="18" enum="Monitor">
+ <constant name="RENDER_TEXTURE_MEM_USED" value="19" enum="Monitor">
Texture memory used.
</constant>
- <constant name="RENDER_VERTEX_MEM_USED" value="19" enum="Monitor">
+ <constant name="RENDER_VERTEX_MEM_USED" value="20" enum="Monitor">
Vertex memory used.
</constant>
- <constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="20" enum="Monitor">
+ <constant name="RENDER_USAGE_VIDEO_MEM_TOTAL" value="21" enum="Monitor">
</constant>
- <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="21" enum="Monitor">
+ <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="22" enum="Monitor">
Number of active [RigidBody2D] nodes in the game.
</constant>
- <constant name="PHYSICS_2D_COLLISION_PAIRS" value="22" enum="Monitor">
+ <constant name="PHYSICS_2D_COLLISION_PAIRS" value="23" enum="Monitor">
Number of collision pairs in the 2D physics engine.
</constant>
- <constant name="PHYSICS_2D_ISLAND_COUNT" value="23" enum="Monitor">
+ <constant name="PHYSICS_2D_ISLAND_COUNT" value="24" enum="Monitor">
Number of islands in the 2D physics engine.
</constant>
- <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="24" enum="Monitor">
+ <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="25" enum="Monitor">
Number of active [RigidBody] and [VehicleBody] nodes in the game.
</constant>
- <constant name="PHYSICS_3D_COLLISION_PAIRS" value="25" enum="Monitor">
+ <constant name="PHYSICS_3D_COLLISION_PAIRS" value="26" enum="Monitor">
Number of collision pairs in the 3D physics engine.
</constant>
- <constant name="PHYSICS_3D_ISLAND_COUNT" value="26" enum="Monitor">
+ <constant name="PHYSICS_3D_ISLAND_COUNT" value="27" enum="Monitor">
Number of islands in the 3D physics engine.
</constant>
- <constant name="AUDIO_OUTPUT_LATENCY" value="27" enum="Monitor">
+ <constant name="AUDIO_OUTPUT_LATENCY" value="28" enum="Monitor">
</constant>
- <constant name="MONITOR_MAX" value="28" enum="Monitor">
+ <constant name="MONITOR_MAX" value="29" enum="Monitor">
</constant>
</constants>
</class>
diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml
index df76b45f9f..a5e5c7022f 100644
--- a/doc/classes/Plane.xml
+++ b/doc/classes/Plane.xml
@@ -80,7 +80,7 @@
<argument index="1" name="epsilon" type="float" default="0.00001">
</argument>
<description>
- Returns true if "point" is inside the plane (by a very minimum threshold).
+ Returns [code]true[/code] if "point" is inside the plane (by a very minimum threshold).
</description>
</method>
<method name="intersect_3">
@@ -122,7 +122,7 @@
<argument index="0" name="point" type="Vector3">
</argument>
<description>
- Returns true if "point" is located above the plane.
+ Returns [code]true[/code] if "point" is located above the plane.
</description>
</method>
<method name="normalized">
diff --git a/doc/classes/PoolByteArray.xml b/doc/classes/PoolByteArray.xml
index 67419377e8..f46cb243d7 100644
--- a/doc/classes/PoolByteArray.xml
+++ b/doc/classes/PoolByteArray.xml
@@ -112,6 +112,13 @@
Change the byte at the given index.
</description>
</method>
+ <method name="sha256_string">
+ <return type="String">
+ </return>
+ <description>
+ Return SHA256 string of the PoolByteArray.
+ </description>
+ </method>
<method name="size">
<return type="int">
</return>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index a1558c186b..46a4a70a9b 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -4,7 +4,7 @@
Contains global variables accessible from everywhere.
</brief_description>
<description>
- Contains global variables accessible from everywhere. Use "ProjectSettings.get_setting(variable)", "ProjectSettings.set_setting(variable,value)" or "ProjectSettings.has_setting(variable)" to access them. Variables stored in project.godot are also loaded into ProjectSettings, making this object very useful for reading custom game configuration options.
+ Contains global variables accessible from everywhere. Use [method get_setting], [method set_setting] or [method has_setting] to access them. Variables stored in [code]project.godot[/code] are also loaded into ProjectSettings, making this object very useful for reading custom game configuration options.
</description>
<tutorials>
</tutorials>
@@ -15,7 +15,7 @@
<argument index="0" name="hint" type="Dictionary">
</argument>
<description>
- Add a custom property info to a property. The dictionary must contain: name:[String](the name of the property) and type:[int](see TYPE_* in [@GlobalScope]), and optionally hint:[int](see PROPERTY_HINT_* in [@GlobalScope]), hint_string:[String].
+ Adds a custom property info to a property. The dictionary must contain: name:[String](the property's name) and type:[int](see TYPE_* in [@GlobalScope]), and optionally hint:[int](see PROPERTY_HINT_* in [@GlobalScope]), hint_string:[String].
Example:
[codeblock]
ProjectSettings.set("category/property_name", 0)
@@ -37,7 +37,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Clear the whole configuration (not recommended, may break things).
+ Clears the whole configuration (not recommended, may break things).
</description>
</method>
<method name="get_order" qualifiers="const">
@@ -46,7 +46,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Return the order of a configuration value (influences when saved to the config file).
+ Returns the order of a configuration value (influences when saved to the config file).
</description>
</method>
<method name="get_setting" qualifiers="const">
@@ -63,7 +63,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Convert a localized path (res://) to a full native OS path.
+ Converts a localized path ([code]res://[/code]) to a full native OS path.
</description>
</method>
<method name="has_setting" qualifiers="const">
@@ -72,7 +72,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Return true if a configuration value is present.
+ Returns [code]true[/code] if a configuration value is present.
</description>
</method>
<method name="load_resource_pack">
@@ -81,7 +81,7 @@
<argument index="0" name="pack" type="String">
</argument>
<description>
- Loads the contents of the .pck or .zip file specified by [code]pack[/code] into the resource filesystem (res://). Returns true on success.
+ Loads the contents of the .pck or .zip file specified by [code]pack[/code] into the resource filesystem ([code]res://[/code]). Returns [code]true[/code] on success.
Note: If a file from [code]pack[/code] shares the same path as a file already in the resource filesystem, any attempts to load that file will use the file from [code]pack[/code].
</description>
</method>
@@ -91,7 +91,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Convert a path to a localized path (res:// path).
+ Convert a path to a localized path ([code]res://[/code] path).
</description>
</method>
<method name="property_can_revert">
@@ -100,7 +100,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Returns true if the specified property exists and its initial value differs from the current value.
+ Returns [code]true[/code] if the specified property exists and its initial value differs from the current value.
</description>
</method>
<method name="property_get_revert">
@@ -109,14 +109,14 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Returns the initial value of the specified property. Returns null if the property does not exist.
+ Returns the specified property's initial value. Returns [code]null[/code] if the property does not exist.
</description>
</method>
<method name="save">
<return type="int" enum="Error">
</return>
<description>
- Saves the configuration to the project.godot file.
+ Saves the configuration to the [code]project.godot[/code] file.
</description>
</method>
<method name="save_custom">
@@ -146,7 +146,7 @@
<argument index="1" name="position" type="int">
</argument>
<description>
- Set the order of a configuration value (influences when saved to the config file).
+ Sets the order of a configuration value (influences when saved to the config file).
</description>
</method>
<method name="set_setting">
@@ -168,62 +168,64 @@
Background color for the boot splash.
</member>
<member name="application/boot_splash/fullsize" type="bool" setter="" getter="">
- Scale the boot splash image to the full window length when engine starts (will leave it as default pixel size otherwise).
+ If [code]true[/code], scale the boot splash image to the full window length when engine starts. If [code]false[/code], the engine will leave it at the default pixel size.
</member>
<member name="application/boot_splash/image" type="String" setter="" getter="">
- Path to an image used for boot splash.
+ Path to an image used as the boot splash.
</member>
<member name="application/config/custom_user_dir_name" type="String" setter="" getter="">
- This user directory is used for storing persistent data ([code]user://[/code] filesystem). By default (no custom name defined), [code]user://[/code] resolves to a project-specific folder in Godot's own configuration folder (see [method OS.get_user_data_dir]). If a custom directory name is defined, this name will be used instead and appended to the system-specific user data directory (same parent folder as the Godot configuration folder documented in [method OS.get_user_data_dir]).
+ This user directory is used for storing persistent data ([code]user://[/code] filesystem). If left empty, [code]user://[/code] resolves to a project-specific folder in Godot's own configuration folder (see [method OS.get_user_data_dir]). If a custom directory name is defined, this name will be used instead and appended to the system-specific user data directory (same parent folder as the Godot configuration folder documented in [method OS.get_user_data_dir]).
The [member application/config/use_custom_user_dir] setting must be enabled for this to take effect.
</member>
<member name="application/config/icon" type="String" setter="" getter="">
- Icon used for the project, set when project loads. Exporters will use this icon when possible to.
+ Icon used for the project, set when project loads. Exporters will also use this icon when possible.
</member>
<member name="application/config/name" type="String" setter="" getter="">
- Name of the project. It is used from both project manager and by the exporters. Overriding this as name.locale allows setting it in multiple languages.
+ The project's name. It is used both by the Project Manager and by exporters. The project name can be translated by translating its value in localization files.
</member>
<member name="application/config/project_settings_override" type="String" setter="" getter="">
Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code].
</member>
<member name="application/config/use_custom_user_dir" type="bool" setter="" getter="">
- Allow the project to save to its own custom user dir (see [member application/config/custom_user_dir_name]). This setting only works for desktop platforms. A name must be set in the [member application/config/custom_user_dir_name] setting for this to take effect.
+ If [code]true[/code], the project will save user data to its own user directory (see [member application/config/custom_user_dir_name]). This setting is only effective on desktop platforms. A name must be set in the [member application/config/custom_user_dir_name] setting for this to take effect. If [code]false[/code], the project will save user data to [code](OS user data directory)/Godot/app_userdata/(project name)[/code].
</member>
<member name="application/run/disable_stderr" type="bool" setter="" getter="">
- Disable printing to stderr on exported build.
+ If [code]true[/code], disables printing to standard error in an exported build.
</member>
<member name="application/run/disable_stdout" type="bool" setter="" getter="">
- Disable printing to stdout on exported build.
+ If [code]true[/code], disables printing to standard output in an exported build.
</member>
<member name="application/run/frame_delay_msec" type="int" setter="" getter="">
- Force a delay between frames in the main loop. This may be useful if you plan to disable vsync.
+ Forces a delay between frames in the main loop (in milliseconds). This may be useful if you plan to disable vertical synchronization.
</member>
<member name="application/run/low_processor_mode" type="bool" setter="" getter="">
- Turn on low processor mode. This setting only works on desktops. The screen is not redrawn if nothing changes visually. This is meant for writing applications and editors, but is pretty useless (and can hurt performance) on games.
+ If [code]true[/code], enables low-processor usage mode. This setting only works on desktop platforms. The screen is not redrawn if nothing changes visually. This is meant for writing applications and editors, but is pretty useless (and can hurt performance) in most games.
</member>
<member name="application/run/low_processor_mode_sleep_usec" type="int" setter="" getter="">
- Amount of sleeping between frames when the low_processor_mode is enabled. This effectively reduces CPU usage when this mode is enabled.
+ Amount of sleeping between frames when the low-processor usage mode is enabled (in microseconds). Higher values will result in lower CPU usage.
</member>
<member name="application/run/main_scene" type="String" setter="" getter="">
Path to the main scene file that will be loaded when the project runs.
</member>
<member name="audio/channel_disable_threshold_db" type="float" setter="" getter="">
- Audio buses will disable automatically when sound goes below a given DB threshold for a given time. This saves CPU as effects assigned to that bus will no longer do any processing.
+ Audio buses will disable automatically when sound goes below a given dB threshold for a given time. This saves CPU as effects assigned to that bus will no longer do any processing.
</member>
<member name="audio/channel_disable_time" type="float" setter="" getter="">
- Audio buses will disable automatically when sound goes below a given DB threshold for a given time. This saves CPU as effects assigned to that bus will no longer do any processing.
+ Audio buses will disable automatically when sound goes below a given dB threshold for a given time. This saves CPU as effects assigned to that bus will no longer do any processing.
</member>
<member name="audio/default_bus_layout" type="String" setter="" getter="">
</member>
<member name="audio/driver" type="String" setter="" getter="">
+ Specifies the audio driver to use. This setting is platform-dependent as each platform supports different audio drivers. If left empty, the default audio driver will be used.
</member>
<member name="audio/enable_audio_input" type="bool" setter="" getter="">
- This option should be enabled if project works with microphone.
+ If [code]true[/code], microphone input will be allowed. This requires appropriate permissions to be set when exporting to Android or iOS.
</member>
<member name="audio/mix_rate" type="int" setter="" getter="">
- Mix rate used for audio. In general, it's better to not touch this and leave it to the host operating system.
+ Mixing rate used for audio. In general, it's better to not touch this and leave it to the host operating system.
</member>
<member name="audio/output_latency" type="int" setter="" getter="">
+ Output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware.
</member>
<member name="audio/video_delay_compensation_ms" type="int" setter="" getter="">
Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing.
@@ -232,75 +234,105 @@
Default compression level for gzip. Affects compressed scenes and resources.
</member>
<member name="compression/formats/zlib/compression_level" type="int" setter="" getter="">
- Default compression level for zlib. Affects compressed scenes and resources.
+ Default compression level for Zlib. Affects compressed scenes and resources.
</member>
<member name="compression/formats/zstd/compression_level" type="int" setter="" getter="">
- Default compression level for zstd. Affects compressed scenes and resources.
+ Default compression level for Zstandard. Affects compressed scenes and resources.
</member>
<member name="compression/formats/zstd/long_distance_matching" type="bool" setter="" getter="">
- Enable long distance matching in zstd.
+ Enables long-distance matching in Zstandard.
</member>
<member name="compression/formats/zstd/window_log_size" type="int" setter="" getter="">
</member>
<member name="debug/gdscript/completion/autocomplete_setters_and_getters" type="bool" setter="" getter="">
+ If [code]true[/code], displays getters and setters in autocompletion results in the script editor. This setting is meant to be used when porting old projects (Godot 2), as using member variables is the preferred style from Godot 3 onwards.
</member>
<member name="debug/gdscript/warnings/constant_used_as_function" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a constant is used as a function.
</member>
<member name="debug/gdscript/warnings/deprecated_keyword" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when deprecated keywords such as [code]slave[/code] are used.
</member>
<member name="debug/gdscript/warnings/enable" type="bool" setter="" getter="">
+ If [code]true[/code], enables specific GDScript warnings (see [code]debug/gdscript/warnings/*[/code] settings). If [code]false[/code], disables all GDScript warnings.
</member>
<member name="debug/gdscript/warnings/function_conflicts_constant" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a function is declared with the same name as a constant.
</member>
<member name="debug/gdscript/warnings/function_conflicts_variable" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a function is declared with the same name as a variable. This will turn into an error in a future version when first-class functions become supported in GDScript.
</member>
<member name="debug/gdscript/warnings/function_may_yield" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a function assigned to a variable may yield and return a function state instead of a value.
</member>
<member name="debug/gdscript/warnings/function_used_as_property" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when using a function as if it was a property.
</member>
<member name="debug/gdscript/warnings/incompatible_ternary" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a ternary operator may emit values with incompatible types.
</member>
<member name="debug/gdscript/warnings/integer_division" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when dividing an integer by another integer (the decimal part will be discarded).
</member>
<member name="debug/gdscript/warnings/narrowing_conversion" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when passing a floating-point value to a function that expects an integer (it will be converted and lose precision).
</member>
<member name="debug/gdscript/warnings/property_used_as_function" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when using a property as if it was a function.
</member>
<member name="debug/gdscript/warnings/return_value_discarded" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when calling a function without using its return value (by assigning it to a variable or using it as a function argument). Such return values are sometimes used to denote possible errors using the [Error] type.
</member>
<member name="debug/gdscript/warnings/shadowed_variable" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when defining a local or subclass member variable that would shadow a variable at an upper level (such as a member variable).
</member>
<member name="debug/gdscript/warnings/standalone_expression" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when calling an expression that has no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
</member>
<member name="debug/gdscript/warnings/treat_warnings_as_errors" type="bool" setter="" getter="">
+ If [code]true[/code], all warnings will be reported as if they were errors.
</member>
<member name="debug/gdscript/warnings/unassigned_variable" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when using a variable that wasn't previously assigned.
</member>
<member name="debug/gdscript/warnings/unassigned_variable_op_assign" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when assigning a variable using an assignment operator like [code]+=[/code] if the variable wasn't previously assigned.
</member>
<member name="debug/gdscript/warnings/unreachable_code" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when unreachable code is detected (such as after a [code]return[/code] statement that will always be executed).
</member>
<member name="debug/gdscript/warnings/unsafe_call_argument" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when using an expression whose type may not be compatible with the function parameter expected.
</member>
<member name="debug/gdscript/warnings/unsafe_cast" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when performing an unsafe cast.
</member>
<member name="debug/gdscript/warnings/unsafe_method_access" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when calling a method whose presence is not guaranteed at compile-time in the class.
</member>
<member name="debug/gdscript/warnings/unsafe_property_access" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when accessing a property whose presence is not guaranteed at compile-time in the class.
</member>
<member name="debug/gdscript/warnings/unused_argument" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a function parameter is unused.
</member>
<member name="debug/gdscript/warnings/unused_class_variable" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a member variable is unused.
</member>
<member name="debug/gdscript/warnings/unused_signal" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a signal is unused.
</member>
<member name="debug/gdscript/warnings/unused_variable" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a local variable is unused.
</member>
<member name="debug/gdscript/warnings/variable_conflicts_function" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when a variable is declared with the same name as a function. This will turn into an error in a future version when first-class functions become supported in GDScript.
</member>
<member name="debug/gdscript/warnings/void_assignment" type="bool" setter="" getter="">
+ If [code]true[/code], enables warnings when assigning the result of a function that returns [code]void[/code] to a variable.
</member>
<member name="debug/settings/crash_handler/message" type="String" setter="" getter="">
+ Message to be displayed before the backtrace when the engine crashes.
</member>
<member name="debug/settings/fps/force_fps" type="int" setter="" getter="">
</member>
@@ -311,34 +343,34 @@
Maximum amount of functions per frame allowed when profiling.
</member>
<member name="debug/settings/stdout/print_fps" type="bool" setter="" getter="">
- Print frames per second to stdout. Not very useful in general.
+ Print frames per second to standard output every second.
</member>
<member name="debug/settings/stdout/verbose_stdout" type="bool" setter="" getter="">
- Print more information to stdout when running. It shows info such as memory leaks, which scenes and resources are being loaded, etc.
+ Print more information to standard output when running. It displays information such as memory leaks, which scenes and resources are being loaded, etc.
</member>
<member name="debug/settings/visual_script/max_call_stack" type="int" setter="" getter="">
Maximum call stack in visual scripting, to avoid infinite recursion.
</member>
<member name="display/mouse_cursor/custom_image" type="String" setter="" getter="">
- Custom image for the mouse cursor.
+ Custom image for the mouse cursor (limited to 256x256).
</member>
<member name="display/mouse_cursor/custom_image_hotspot" type="Vector2" setter="" getter="">
Hotspot for the custom mouse cursor image.
</member>
<member name="display/mouse_cursor/tooltip_position_offset" type="Vector2" setter="" getter="">
- Position offset for tooltips, relative to the hotspot of the mouse cursor.
+ Position offset for tooltips, relative to the mouse cursor's hotspot.
</member>
<member name="display/window/dpi/allow_hidpi" type="bool" setter="" getter="">
- Allow HiDPI display on Windows and OSX. On Desktop Linux, this can't be enabled or disabled.
+ If [code]true[/code], allows HiDPI display on Windows and macOS. This setting has no effect on desktop Linux, as DPI-awareness fallbacks are not supported there.
</member>
<member name="display/window/energy_saving/keep_screen_on" type="bool" setter="" getter="">
- Force keep the screen on, so the screensaver does not take over. Works on Desktop and Mobile.
+ If [code]true[/code], keeps the screen on (even in case of inactivity), so the screensaver does not take over. Works on desktop and mobile platforms.
</member>
<member name="display/window/handheld/orientation" type="String" setter="" getter="">
- Default orientation for cell phone or tablet.
+ Default orientation on mobile devices.
</member>
<member name="display/window/per_pixel_transparency/allowed" type="bool" setter="" getter="">
- Allow per pixel transparency in a Desktop window. This affects performance if not needed, so leave it off.
+ If [code]true[/code], allows per-pixel transparency in a desktop window. This affects performance if not needed, so leave it on [code]false[/code] unless you need it.
</member>
<member name="display/window/per_pixel_transparency/enabled" type="bool" setter="" getter="">
</member>
@@ -357,19 +389,19 @@
Set the main window height. On desktop, this is the default window size. Stretch mode settings use this also as a reference when enabled.
</member>
<member name="display/window/size/resizable" type="bool" setter="" getter="">
- Allow the window to be resizable by default.
+ Allows the window to be resizable by default.
</member>
<member name="display/window/size/test_height" type="int" setter="" getter="">
- Test a different height for the window. The main use for this is to test with stretch modes.
+ If greater than zero, uses a different height for the window when running from the editor. The main use for this is to test with stretch modes.
</member>
<member name="display/window/size/test_width" type="int" setter="" getter="">
- Test a different width for the window. The main use for this is to test with stretch modes.
+ If greater than zero, uses a different width for the window when running from the editor. The main use for this is to test with stretch modes.
</member>
<member name="display/window/size/width" type="int" setter="" getter="">
- Set the main window width. On desktop, this is the default window size. Stretch mode settings use this also as a reference when enabled.
+ Sets the main window width. On desktop platforms, this is the default window size. Stretch mode settings use this also as a reference when enabled.
</member>
<member name="display/window/vsync/use_vsync" type="bool" setter="" getter="">
- Use VSync. Don't be stupid, don't turn this off.
+ If [code]true[/code], enables vertical synchronization. This eliminates tearing that may appear in moving scenes, at the cost of higher input latency and stuttering at lower framerates. If [code]false[/code], vertical synchronization will be disabled, however, many platforms will enforce it regardless (such as mobile platforms and HTML5).
</member>
<member name="editor/active" type="bool" setter="" getter="">
Internal editor setting, don't touch.
@@ -377,22 +409,22 @@
<member name="gui/common/default_scroll_deadzone" type="int" setter="" getter="">
</member>
<member name="gui/common/swap_ok_cancel" type="bool" setter="" getter="">
- Enable swap OK and Cancel buttons on dialogs. This is because Windows/MacOS/Desktop Linux may use them in different order, so the GUI swaps them depending on the host OS. Disable this behavior by turning this setting off.
+ If [code]true[/code], swaps OK and Cancel buttons in dialogs on Windows and UWP to follow interface conventions.
</member>
<member name="gui/theme/custom" type="String" setter="" getter="">
Use a custom theme resource, set a path to it here.
</member>
<member name="gui/theme/custom_font" type="String" setter="" getter="">
- USe a custom default font resource, set a path to it here.
+ Use a custom default font resource, set a path to it here.
</member>
<member name="gui/theme/use_hidpi" type="bool" setter="" getter="">
- Make sure the theme used works with hidpi.
+ If [code]true[/code], makes sure the theme used works with HiDPI.
</member>
<member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="">
- Timer setting for incremental search in Tree, IntemList, etc. controls.
+ Timer setting for incremental search in Tree, IntemList, etc. controls (in milliseconds).
</member>
<member name="gui/timers/text_edit_idle_detect_sec" type="float" setter="" getter="">
- Timer for detecting idle in the editor.
+ Timer for detecting idle in the editor (in seconds).
</member>
<member name="input/ui_accept" type="Dictionary" setter="" getter="">
</member>
@@ -421,8 +453,10 @@
<member name="input/ui_up" type="Dictionary" setter="" getter="">
</member>
<member name="input_devices/pointing/emulate_mouse_from_touch" type="bool" setter="" getter="">
+ If [code]true[/code], sends mouse input events when tapping or swiping on the touchscreen.
</member>
<member name="input_devices/pointing/emulate_touch_from_mouse" type="bool" setter="" getter="">
+ If [code]true[/code], sends touch input events when clicking or dragging the mouse.
</member>
<member name="layer_names/2d_physics/layer_1" type="String" setter="" getter="">
</member>
@@ -585,23 +619,25 @@
<member name="layer_names/3d_render/layer_9" type="String" setter="" getter="">
</member>
<member name="locale/fallback" type="String" setter="" getter="">
+ The locale to fall back to if a translation isn't available in a given language. If left empty, [code]en[/code] (English) will be used.
</member>
<member name="locale/test" type="String" setter="" getter="">
+ If non-empty, this locale will be used when running the project from the editor.
</member>
<member name="logging/file_logging/enable_file_logging" type="bool" setter="" getter="">
- Log all output to a file.
+ If [code]true[/code], logs all output to files.
</member>
<member name="logging/file_logging/log_path" type="String" setter="" getter="">
- Path to logs withint he project. Using an [code]user://[/code] based path is recommended.
+ Path to logs within the project. Using an [code]user://[/code] path is recommended.
</member>
<member name="logging/file_logging/max_log_files" type="int" setter="" getter="">
- Amount of log files (used for rotation).
+ Specifies the maximum amount of log files allowed (used for rotation).
</member>
<member name="memory/limits/message_queue/max_size_kb" type="int" setter="" getter="">
Godot uses a message queue to defer some function calls. If you run out of space on it (you will see an error), you can increase the size here.
</member>
<member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="">
- This is used by servers when used in multi threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number.
+ This is used by servers when used in multi-threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number.
</member>
<member name="network/limits/debugger_stdout/max_chars_per_second" type="int" setter="" getter="">
Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
@@ -613,7 +649,7 @@
Maximum amount of messages allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>
<member name="network/limits/packet_peer_stream/max_buffer_po2" type="int" setter="" getter="">
- Default size of packet peer stream for deserializing godot data. Over this size, data is dropped.
+ Default size of packet peer stream for deserializing Godot data. Over this size, data is dropped.
</member>
<member name="network/limits/websocket_client/max_in_buffer_kb" type="int" setter="" getter="">
</member>
@@ -632,13 +668,13 @@
<member name="network/limits/websocket_server/max_out_packets" type="int" setter="" getter="">
</member>
<member name="network/remote_fs/page_read_ahead" type="int" setter="" getter="">
- Amount of read ahead used by remote filesystem. Improves latency.
+ Amount of read ahead used by remote filesystem. Higher values decrease the effects of latency at the cost of higher bandwidth usage.
</member>
<member name="network/remote_fs/page_size" type="int" setter="" getter="">
- Page size used by remote filesystem.
+ Page size used by remote filesystem (in bytes).
</member>
<member name="node/name_casing" type="int" setter="" getter="">
- When creating nodes names automatically, set the type of casing in this project. This is mostly an editor setting.
+ When creating node names automatically, set the type of casing in this project. This is mostly an editor setting.
</member>
<member name="node/name_num_separator" type="int" setter="" getter="">
What to use to separate node name from number. This is mostly an editor setting.
@@ -646,20 +682,21 @@
<member name="physics/2d/physics_engine" type="String" setter="" getter="">
</member>
<member name="physics/2d/thread_model" type="int" setter="" getter="">
- Set whether physics is run on the main thread or a separate one. Running the server on a thread increases performance, but restricts API Access to only physics process.
+ Sets whether physics is run on the main thread or a separate one. Running the server on a thread increases performance, but restricts API access to only physics process.
</member>
<member name="physics/3d/active_soft_world" type="bool" setter="" getter="">
</member>
<member name="physics/3d/physics_engine" type="String" setter="" getter="">
+ Sets which physics engine to use.
</member>
<member name="physics/common/physics_fps" type="int" setter="" getter="">
Frames per second used in the physics. Physics always needs a fixed amount of frames per second.
</member>
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="">
- Fix to improve physics jitter, specially on monitors where refresh rate is different than physics FPS.
+ Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
</member>
<member name="rendering/environment/default_clear_color" type="Color" setter="" getter="">
- Default background clear color. Overridable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method VisualServer.set_default_clear_color].
+ Default background clear color. Overriddable per [Viewport] using its [Environment]. See [member Environment.background_mode] and [member Environment.background_color] in particular. To change this default color programmatically, use [method VisualServer.set_default_clear_color].
</member>
<member name="rendering/limits/buffers/blend_shape_max_buffer_size_kb" type="int" setter="" getter="">
Max buffer size for blend shapes. Any blend shape bigger than this will not work.
@@ -674,68 +711,70 @@
Max buffer size for drawing immediate objects (ImmediateGeometry nodes). Nodes using more than this size will not work.
</member>
<member name="rendering/limits/rendering/max_renderable_elements" type="int" setter="" getter="">
- Max amount of elements renderable in a frame. If more than this are visible per frame, they will be dropped. Keep in mind elements refer to mesh surfaces and not mesh themselves.
+ Max amount of elements renderable in a frame. If more than this are visible per frame, they will be dropped. Keep in mind elements refer to mesh surfaces and not meshes themselves.
</member>
<member name="rendering/limits/time/time_rollover_secs" type="float" setter="" getter="">
- Shaders have a time variable that constantly increases. At some point it needs to be rolled back to zero to avoid numerical errors on shader animations. This setting specifies when.
+ Shaders have a time variable that constantly increases. At some point, it needs to be rolled back to zero to avoid precision errors on shader animations. This setting specifies when (in seconds).
</member>
<member name="rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround" type="bool" setter="" getter="">
- Some Nvidia GPU drivers have a bug, which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to https://github.com/godotengine/godot/issues/9913 for details.
- If [code]true[/code], this option enables a "safe" code path for such Nvidia GPUs, at the cost of performance. This option only impacts the GLES2 rendering backend (so the bug stays if you use GLES3), and only desktop platforms. Default value: [code]false[/code].
+ Some NVIDIA GPU drivers have a bug which produces flickering issues for the [code]draw_rect[/code] method, especially as used in [TileMap]. Refer to [url]https://github.com/godotengine/godot/issues/9913[/url] for details.
+ If [code]true[/code], this option enables a "safe" code path for such NVIDIA GPUs at the cost of performance. This option only impacts the GLES2 rendering backend (so the bug stays if you use GLES3), and only desktop platforms.
</member>
<member name="rendering/quality/2d/use_pixel_snap" type="bool" setter="" getter="">
- Force snapping of polygons to pixels in 2D rendering. May help in some pixel art styles.
+ If [code]true[/code], forces snapping of polygons to pixels in 2D rendering. May help in some pixel art styles.
</member>
<member name="rendering/quality/depth_prepass/disable_for_vendors" type="String" setter="" getter="">
Disable depth pre-pass for some GPU vendors (usually mobile), as their architecture already does this.
</member>
<member name="rendering/quality/depth_prepass/enable" type="bool" setter="" getter="">
- Do a previous depth pass before rendering materials. This increases performance in scenes with high overdraw, when complex materials and lighting are used.
+ If [code]true[/code], performs a previous depth pass before rendering materials. This increases performance in scenes with high overdraw, when complex materials and lighting are used.
</member>
<member name="rendering/quality/directional_shadow/size" type="int" setter="" getter="">
- Size in pixels of the directional shadow.
+ The directional shadow's size in pixels. Higher values will result in sharper shadows, at the cost of performance.
</member>
<member name="rendering/quality/directional_shadow/size.mobile" type="int" setter="" getter="">
</member>
<member name="rendering/quality/driver/driver_name" type="String" setter="" getter="">
- Name of the configured video driver ("GLES2" or "GLES3").
- Note that the backend in use can be overridden at runtime via the [code]--video-driver[/code] command line argument, or by the [member rendering/quality/driver/fallback_to_gles2] option if the target system does not support GLES3 and falls back to GLES2. In such cases, this property is not updated, so use [method OS.get_current_video_driver] to query it at runtime.
+ The video driver to use ("GLES2" or "GLES3").
+ Note that the backend in use can be overridden at runtime via the [code]--video-driver[/code] command line argument, or by the [member rendering/quality/driver/fallback_to_gles2] option if the target system does not support GLES3 and falls back to GLES2. In such cases, this property is not updated, so use [method OS.get_current_video_driver] to query it at run-time.
</member>
<member name="rendering/quality/driver/fallback_to_gles2" type="bool" setter="" getter="">
- Whether to allow falling back to the GLES2 driver if the GLES3 driver is not supported. Default value: [code]false[/code].
- Note that the two video drivers are not drop-in replacements for each other, so a game designed for GLES3 might not work properly when falling back to GLES2. In particular, some features of the GLES3 backend are not available in GLES2. Enabling this setting also means that both ETC and ETC2 VRAM-compressed textures will be exported on Android and iOS, increasing the size of the game data pack.
+ If [code]true[/code], allows falling back to the GLES2 driver if the GLES3 driver is not supported.
+ Note that the two video drivers are not drop-in replacements for each other, so a game designed for GLES3 might not work properly when falling back to GLES2. In particular, some features of the GLES3 backend are not available in GLES2. Enabling this setting also means that both ETC and ETC2 VRAM-compressed textures will be exported on Android and iOS, increasing the data pack's size.
</member>
<member name="rendering/quality/filters/anisotropic_filter_level" type="int" setter="" getter="">
- Maximum Anisotropic filter level used for textures when anisotropy enabled.
+ Maximum anisotropic filter level used for textures with anisotropy enabled. Higher values will result in sharper textures when viewed from oblique angles, at the cost of performance. Only power-of-two values are valid (2, 4, 8, 16).
</member>
<member name="rendering/quality/filters/use_nearest_mipmap_filter" type="bool" setter="" getter="">
- Force to use nearest mipmap filtering when using mipmaps. This may increase performance in mobile as less memory bandwidth is used.
+ If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used.
</member>
<member name="rendering/quality/intended_usage/framebuffer_allocation" type="int" setter="" getter="">
- Strategy used for framebuffer allocation. The simpler it is, the less memory it uses (but the least features it supports).
+ Strategy used for framebuffer allocation. The simpler it is, the less resources it uses (but the less features it supports).
</member>
<member name="rendering/quality/intended_usage/framebuffer_allocation.mobile" type="int" setter="" getter="">
</member>
<member name="rendering/quality/reflections/high_quality_ggx" type="bool" setter="" getter="">
- For reflection probes and panorama backgrounds (sky), use a high amount of samples to create ggx blurred versions (used for roughness).
+ If [code]true[/code], uses a high amount of samples to create blurred variants of reflection probes and panorama backgrounds (sky). Those blurred variants are used by rough materials.
</member>
<member name="rendering/quality/reflections/high_quality_ggx.mobile" type="bool" setter="" getter="">
</member>
<member name="rendering/quality/reflections/texture_array_reflections" type="bool" setter="" getter="">
- For reflection probes and panorama backgrounds (sky), use a texture array instead of mipmaps. This reduces jitter noise on reflections, but costs more performance and memory.
+ If [code]true[/code], uses texture arrays instead of mipmaps for reflection probes and panorama backgrounds (sky). This reduces jitter noise on reflections, but costs more performance and memory.
</member>
<member name="rendering/quality/reflections/texture_array_reflections.mobile" type="bool" setter="" getter="">
</member>
<member name="rendering/quality/shading/force_blinn_over_ggx" type="bool" setter="" getter="">
+ If [code]true[/code], uses faster but lower-quality Blinn model to generate blurred reflections instead of the GGX model.
</member>
<member name="rendering/quality/shading/force_blinn_over_ggx.mobile" type="bool" setter="" getter="">
</member>
<member name="rendering/quality/shading/force_lambert_over_burley" type="bool" setter="" getter="">
+ If [code]true[/code], uses faster but lower-quality Lambert material lighting model instead of Burley.
</member>
<member name="rendering/quality/shading/force_lambert_over_burley.mobile" type="bool" setter="" getter="">
</member>
<member name="rendering/quality/shading/force_vertex_shading" type="bool" setter="" getter="">
- Force vertex shading for all rendering. This can increase performance a lot, but also reduces quality immensely. Can work to optimize on very low end mobile.
+ If [code]true[/code], forces vertex shading for all rendering. This can increase performance a lot, but also reduces quality immensely. Can be used to optimize performance on low-end mobile devices.
</member>
<member name="rendering/quality/shading/force_vertex_shading.mobile" type="bool" setter="" getter="">
</member>
@@ -752,12 +791,12 @@
Subdivision quadrant size for shadow mapping. See shadow mapping documentation.
</member>
<member name="rendering/quality/shadow_atlas/size" type="int" setter="" getter="">
- Size for shadow atlas (used for point and omni lights). See documentation.
+ Size for shadow atlas (used for OmniLights and SpotLights). See documentation.
</member>
<member name="rendering/quality/shadow_atlas/size.mobile" type="int" setter="" getter="">
</member>
<member name="rendering/quality/shadows/filter_mode" type="int" setter="" getter="">
- Shadow filter mode. The more complex the filter, the more memory bandwidth required.
+ Shadow filter mode. Higher-quality settings result in smoother shadows that flicker less when moving. "Disabled" is the fastest option, but also has the lowest quality. "PCF5" is smoother but is also slower. "PCF13" is the smoothest option, but is also the slowest.
</member>
<member name="rendering/quality/shadows/filter_mode.mobile" type="int" setter="" getter="">
</member>
@@ -773,24 +812,25 @@
Weight subsurface scattering samples. Helps to avoid reading samples from unrelated parts of the screen.
</member>
<member name="rendering/quality/voxel_cone_tracing/high_quality" type="bool" setter="" getter="">
- Use high quality voxel cone tracing (looks better, but requires a higher end GPU).
+ Use high-quality voxel cone tracing. This results in better-looking reflections, but is much more expensive on the GPU.
</member>
<member name="rendering/threads/thread_model" type="int" setter="" getter="">
- Thread model for rendering. Rendering on a thread can vastly improve performance, but syncinc to the main thread can cause a bit more jitter.
+ Thread model for rendering. Rendering on a thread can vastly improve performance, but synchronizing to the main thread can cause a bit more jitter.
</member>
<member name="rendering/vram_compression/import_bptc" type="bool" setter="" getter="">
+ If [code]true[/code], the texture importer will import VRAM-compressed textures using the BPTC algorithm. This texture compression algorithm is only supported on desktop platforms, and only when using the GLES3 renderer.
</member>
<member name="rendering/vram_compression/import_etc" type="bool" setter="" getter="">
- If the project uses this compression (usually low end mobile), texture importer will import these.
+ If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression algorithm. This algorithm doesn't support alpha channels in textures.
</member>
<member name="rendering/vram_compression/import_etc2" type="bool" setter="" getter="">
- If the project uses this compression (usually high end mobile), texture importer will import these.
+ If [code]true[/code], the texture importer will import VRAM-compressed textures using the Ericsson Texture Compression 2 algorithm. This texture compression algorithm is only supported when using the GLES3 renderer.
</member>
<member name="rendering/vram_compression/import_pvrtc" type="bool" setter="" getter="">
- If the project uses this compression (usually iOS), texture importer will import these.
+ If [code]true[/code], the texture importer will import VRAM-compressed textures using the PowerVR Texture Compression algorithm. This texture compression algorithm is only supported on iOS.
</member>
<member name="rendering/vram_compression/import_s3tc" type="bool" setter="" getter="">
- If the project uses this compression (usually Desktop and Consoles), texture importer will import these.
+ If [code]true[/code], the texture importer will import VRAM-compressed textures using the S3 Texture Compression algorithm. This algorithm is only supported on desktop platforms and consoles.
</member>
<member name="script" type="Script" setter="" getter="">
</member>
diff --git a/doc/classes/ResourceFormatSaver.xml b/doc/classes/ResourceFormatSaver.xml
index 79a813bcb5..caa05dce26 100644
--- a/doc/classes/ResourceFormatSaver.xml
+++ b/doc/classes/ResourceFormatSaver.xml
@@ -25,7 +25,7 @@
<argument index="0" name="resource" type="Resource">
</argument>
<description>
- Returns true if the given resource object can be saved by this saver.
+ Returns [code]true[/code] if the given resource object can be saved by this saver.
</description>
</method>
<method name="save" qualifiers="virtual">
diff --git a/doc/classes/ResourcePreloader.xml b/doc/classes/ResourcePreloader.xml
index d9e2466182..d6c635b6eb 100644
--- a/doc/classes/ResourcePreloader.xml
+++ b/doc/classes/ResourcePreloader.xml
@@ -42,7 +42,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Returns true if the preloader contains a resource associated to [code]name[/code].
+ Returns [code]true[/code] if the preloader contains a resource associated to [code]name[/code].
</description>
</method>
<method name="remove_resource">
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index b9199194cd..0b1f659da3 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -61,7 +61,7 @@
<argument index="1" name="pause_mode_process" type="bool" default="true">
</argument>
<description>
- Returns a [SceneTreeTimer] which will [signal SceneTreeTimer.timeout] after the given time in seconds elapsed in this SceneTree. If [code]pause_mode_process[/code] is set to false, pausing the SceneTree will also pause the timer.
+ Returns a [SceneTreeTimer] which will [signal SceneTreeTimer.timeout] after the given time in seconds elapsed in this SceneTree. If [code]pause_mode_process[/code] is set to [code]false[/code], pausing the SceneTree will also pause the timer.
Commonly used to create a one-shot delay timer as in the following example:
[codeblock]
func some_function():
diff --git a/doc/classes/Skeleton.xml b/doc/classes/Skeleton.xml
index 4377cf52c3..8fab778a48 100644
--- a/doc/classes/Skeleton.xml
+++ b/doc/classes/Skeleton.xml
@@ -134,6 +134,12 @@
<description>
</description>
</method>
+ <method name="localize_rests">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="physical_bones_add_collision_exception">
<return type="void">
</return>
diff --git a/doc/classes/SphereMesh.xml b/doc/classes/SphereMesh.xml
index 01f6ee027e..0124d8a4b0 100644
--- a/doc/classes/SphereMesh.xml
+++ b/doc/classes/SphereMesh.xml
@@ -15,7 +15,7 @@
Full height of the sphere. Defaults to 2.0.
</member>
<member name="is_hemisphere" type="bool" setter="set_is_hemisphere" getter="get_is_hemisphere">
- Determines whether a full sphere or a hemisphere is created. Attention: To get a regular hemisphere the height and radius of the sphere have to equal. Defaults to false.
+ Determines whether a full sphere or a hemisphere is created. Attention: To get a regular hemisphere the height and radius of the sphere have to equal. Defaults to [code]false[/code].
</member>
<member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments">
Number of radial segments on the sphere. Defaults to 64.
diff --git a/doc/classes/StreamPeerSSL.xml b/doc/classes/StreamPeerSSL.xml
index 07a21a0b57..f7fd36ed58 100644
--- a/doc/classes/StreamPeerSSL.xml
+++ b/doc/classes/StreamPeerSSL.xml
@@ -28,7 +28,7 @@
<argument index="2" name="for_hostname" type="String" default="&quot;&quot;">
</argument>
<description>
- Connect to a peer using an underlying [StreamPeer] "stream", when "validate_certs" is true, [StreamPeerSSL] will validate that the certificate presented by the peer matches the "for_hostname".
+ Connect to a peer using an underlying [StreamPeer] "stream", when "validate_certs" is [code]true[/code], [StreamPeerSSL] will validate that the certificate presented by the peer matches the "for_hostname".
</description>
</method>
<method name="disconnect_from_stream">
diff --git a/doc/classes/StyleBoxFlat.xml b/doc/classes/StyleBoxFlat.xml
index 884b52459b..ffee7366a3 100644
--- a/doc/classes/StyleBoxFlat.xml
+++ b/doc/classes/StyleBoxFlat.xml
@@ -94,7 +94,7 @@
The background color of the stylebox.
</member>
<member name="border_blend" type="bool" setter="set_border_blend" getter="get_border_blend">
- When set to true, the border will fade into the background color.
+ When set to [code]true[/code], the border will fade into the background color.
</member>
<member name="border_color" type="Color" setter="set_border_color" getter="get_border_color">
Sets the color of the border.
diff --git a/doc/classes/TCP_Server.xml b/doc/classes/TCP_Server.xml
index 2780e39067..ac9b33bc34 100644
--- a/doc/classes/TCP_Server.xml
+++ b/doc/classes/TCP_Server.xml
@@ -13,7 +13,7 @@
<return type="bool">
</return>
<description>
- Return true if a connection is available for taking.
+ Return [code]true[/code] if a connection is available for taking.
</description>
</method>
<method name="listen">
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index e1260ba44e..06299d65b6 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -100,7 +100,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
- If [code]disabled[/code] is false, hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title].
+ If [code]disabled[/code] is [code]false[/code], hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title].
</description>
</method>
<method name="set_tab_icon">
diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml
index 6e61f62f43..8c7d657b4a 100644
--- a/doc/classes/Tabs.xml
+++ b/doc/classes/Tabs.xml
@@ -135,7 +135,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
- If [code]disabled[/code] is false, hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title].
+ If [code]disabled[/code] is [code]false[/code], hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title].
</description>
</method>
<method name="set_tab_icon">
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index c55d4d6960..1817055bab 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -245,7 +245,7 @@
<return type="bool">
</return>
<description>
- Return true if the selection is active.
+ Return [code]true[/code] if the selection is active.
</description>
</method>
<method name="menu_option">
@@ -418,6 +418,14 @@
Emitted when the cursor changes.
</description>
</signal>
+ <signal name="info_clicked">
+ <argument index="0" name="row" type="int">
+ </argument>
+ <argument index="1" name="info" type="String">
+ </argument>
+ <description>
+ </description>
+ </signal>
<signal name="request_completion">
<description>
</description>
diff --git a/doc/classes/Thread.xml b/doc/classes/Thread.xml
index d1d19d91d7..ff8221fed3 100644
--- a/doc/classes/Thread.xml
+++ b/doc/classes/Thread.xml
@@ -20,7 +20,7 @@
<return type="bool">
</return>
<description>
- Returns true if this [Thread] is currently active. An active [Thread] cannot start work on a new method but can be joined with [method wait_to_finish].
+ Returns [code]true[/code] if this [Thread] is currently active. An active [Thread] cannot start work on a new method but can be joined with [method wait_to_finish].
</description>
</method>
<method name="start">
diff --git a/doc/classes/VehicleBody.xml b/doc/classes/VehicleBody.xml
index 81d853090c..ab821aafdc 100644
--- a/doc/classes/VehicleBody.xml
+++ b/doc/classes/VehicleBody.xml
@@ -16,11 +16,11 @@
Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidBody.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking.
</member>
<member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force">
- Accelerates the vehicle by applying an engine force. The vehicle is only speed up if the wheels that have [member VehicleWheel.use_as_traction] set to true and are in contact with a surface. The [member RigidBody.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. Note that the simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears.
+ Accelerates the vehicle by applying an engine force. The vehicle is only speed up if the wheels that have [member VehicleWheel.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidBody.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. Note that the simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears.
A negative value will result in the vehicle reversing.
</member>
<member name="steering" type="float" setter="set_steering" getter="get_steering">
- The steering angle for the vehicle. Setting this to a non-zero value will result in the vehicle turning when it's moving. Wheels that have [member VehicleWheel.use_as_steering] set to true will automatically be rotated.
+ The steering angle for the vehicle. Setting this to a non-zero value will result in the vehicle turning when it's moving. Wheels that have [member VehicleWheel.use_as_steering] set to [code]true[/code] will automatically be rotated.
</member>
</members>
<constants>
diff --git a/doc/classes/VehicleWheel.xml b/doc/classes/VehicleWheel.xml
index 6a507d630c..f8dac82cb5 100644
--- a/doc/classes/VehicleWheel.xml
+++ b/doc/classes/VehicleWheel.xml
@@ -20,7 +20,7 @@
<return type="bool">
</return>
<description>
- Returns true if this wheel is in contact with a surface.
+ Returns [code]true[/code] if this wheel is in contact with a surface.
</description>
</method>
</methods>
@@ -41,10 +41,10 @@
This is the distance the suspension can travel. As Godot measures are in meters keep this setting relatively low. Try a value between 0.1 and 0.3 depending on the type of car .
</member>
<member name="use_as_steering" type="bool" setter="set_use_as_steering" getter="is_used_as_steering">
- If true this wheel will be turned when the car steers.
+ If [code]true[/code] this wheel will be turned when the car steers.
</member>
<member name="use_as_traction" type="bool" setter="set_use_as_traction" getter="is_used_as_traction">
- If true this wheel transfers engine force to the ground to propel the vehicle forward.
+ If [code]true[/code] this wheel transfers engine force to the ground to propel the vehicle forward.
</member>
<member name="wheel_friction_slip" type="float" setter="set_friction_slip" getter="get_friction_slip">
This determines how much grip this wheel has. It is combined with the friction setting of the surface the wheel is in contact with. 0.0 means no grip, 1.0 is normal grip. For a drift car setup, try setting the grip of the rear wheels slightly lower than the front wheels, or use a lower value to simulate tire wear.
diff --git a/doc/classes/VisualInstance.xml b/doc/classes/VisualInstance.xml
index 381679f8bb..59f0a531dd 100644
--- a/doc/classes/VisualInstance.xml
+++ b/doc/classes/VisualInstance.xml
@@ -14,6 +14,18 @@
Returns the [AABB] (also known as the bounding box) for this VisualInstance.
</description>
</method>
+ <method name="get_base" qualifiers="const">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_instance" qualifiers="const">
+ <return type="RID">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_layer_mask_bit" qualifiers="const">
<return type="bool">
</return>
diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml
index 0030795a6b..87bf0b79b6 100644
--- a/doc/classes/VisualServer.xml
+++ b/doc/classes/VisualServer.xml
@@ -66,6 +66,22 @@
<description>
</description>
</method>
+ <method name="camera_set_frustum">
+ <return type="void">
+ </return>
+ <argument index="0" name="camera" type="RID">
+ </argument>
+ <argument index="1" name="size" type="float">
+ </argument>
+ <argument index="2" name="offset" type="Vector2">
+ </argument>
+ <argument index="3" name="z_near" type="float">
+ </argument>
+ <argument index="4" name="z_far" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="camera_set_orthogonal">
<return type="void">
</return>
@@ -173,12 +189,15 @@
</argument>
<argument index="1" name="mesh" type="RID">
</argument>
- <argument index="2" name="texture" type="RID">
+ <argument index="2" name="texture" type="Transform2D">
</argument>
- <argument index="3" name="normal_map" type="RID">
+ <argument index="3" name="normal_map" type="Color">
+ </argument>
+ <argument index="4" name="arg4" type="RID">
+ </argument>
+ <argument index="5" name="arg5" type="RID">
</argument>
<description>
- Adds a [Mesh] to the [CanvasItem]'s draw commands. Only affects its aabb at the moment.
</description>
</method>
<method name="canvas_item_add_multimesh">
diff --git a/doc/classes/bool.xml b/doc/classes/bool.xml
index 15e4146ef4..9ed029a500 100644
--- a/doc/classes/bool.xml
+++ b/doc/classes/bool.xml
@@ -15,7 +15,7 @@
<argument index="0" name="from" type="int">
</argument>
<description>
- Cast an [int] value to a boolean value, this method will return true if called with an integer value different to 0 and false in other case.
+ Cast an [int] value to a boolean value, this method will return [code]true[/code] if called with an integer value different to 0 and [code]false[/code] in other case.
</description>
</method>
<method name="bool">
@@ -24,7 +24,7 @@
<argument index="0" name="from" type="float">
</argument>
<description>
- Cast a [float] value to a boolean value, this method will return true if called with a floating point value different to 0 and false in other case.
+ Cast a [float] value to a boolean value, this method will return [code]true[/code] if called with a floating point value different to 0 and [code]false[/code] in other case.
</description>
</method>
<method name="bool">
@@ -33,7 +33,7 @@
<argument index="0" name="from" type="String">
</argument>
<description>
- Cast a [String] value to a boolean value, this method will return true if called with a non empty string and false in other case. Examples: [code]bool('False')[/code] returns true, [code]bool('')[/code]. returns false
+ Cast a [String] value to a boolean value, this method will return [code]true[/code] if called with a non empty string and [code]false[/code] in other case. Examples: [code]bool('False')[/code] returns [code]true[/code], [code]bool('')[/code] returns [code]false[/code].
</description>
</method>
</methods>
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index e790d5b031..9f1425189c 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -480,7 +480,6 @@ RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
rpi->current_resolution = 0;
rpi->dirty = true;
- rpi->last_pass = 0;
rpi->index = 0;
for (int i = 0; i < 6; i++) {
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 56a6c51460..9aec348291 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1061,12 +1061,11 @@ void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe, RID p_b
if (p_data.is_valid()) {
RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data);
ERR_FAIL_COND(!gipd);
- if (gipd) {
- gipi->tex_cache = gipd->tex_id;
- gipi->cell_size_cache.x = 1.0 / gipd->width;
- gipi->cell_size_cache.y = 1.0 / gipd->height;
- gipi->cell_size_cache.z = 1.0 / gipd->depth;
- }
+
+ gipi->tex_cache = gipd->tex_id;
+ gipi->cell_size_cache.x = 1.0 / gipd->width;
+ gipi->cell_size_cache.y = 1.0 / gipd->height;
+ gipi->cell_size_cache.z = 1.0 / gipd->depth;
}
}
void RasterizerSceneGLES3::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) {
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 6e045817bc..a285b3b65f 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -293,8 +293,25 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
};
}
-Error FileAccessUnix::_chmod(const String &p_path, int p_mod) {
- int err = chmod(p_path.utf8().get_data(), p_mod);
+uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
+
+ String file = fix_path(p_file);
+ struct stat flags;
+ int err = stat(file.utf8().get_data(), &flags);
+
+ if (!err) {
+ return flags.st_mode & 0x7FF; //only permissions
+ } else {
+ ERR_EXPLAIN("Failed to get unix permissions for: " + p_file);
+ ERR_FAIL_V(0);
+ };
+}
+
+Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+
+ String file = fix_path(p_file);
+
+ int err = chmod(file.utf8().get_data(), p_permissions);
if (!err) {
return OK;
}
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 6405589b4d..2a369048a4 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -85,8 +85,8 @@ public:
virtual bool file_exists(const String &p_path); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
-
- virtual Error _chmod(const String &p_path, int p_mod);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
FileAccessUnix();
virtual ~FileAccessUnix();
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 2778590658..25cdc8d8a0 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -119,15 +119,6 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
return 0;
}
-// Very simple signal handler to reap processes where ::execute was called with
-// !p_blocking
-void handle_sigchld(int sig) {
- int saved_errno = errno;
- while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {
- }
- errno = saved_errno;
-}
-
void OS_Unix::initialize_core() {
#ifdef NO_THREADS
@@ -155,14 +146,6 @@ void OS_Unix::initialize_core() {
#endif
_setup_clock();
-
- struct sigaction sa;
- sa.sa_handler = &handle_sigchld;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
- if (sigaction(SIGCHLD, &sa, 0) == -1) {
- perror("ERROR sigaction() failed:");
- }
}
void OS_Unix::finalize_core() {
@@ -293,7 +276,7 @@ uint64_t OS_Unix::get_ticks_usec() const {
return longtime;
}
-Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
+Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
@@ -320,11 +303,17 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
char buf[65535];
+
while (fgets(buf, 65535, f)) {
+ if (p_pipe_mutex) {
+ p_pipe_mutex->lock();
+ }
(*r_pipe) += buf;
+ if (p_pipe_mutex) {
+ p_pipe_mutex->unlock();
+ }
}
-
int rv = pclose(f);
if (r_exitcode)
*r_exitcode = rv;
@@ -337,6 +326,13 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
if (pid == 0) {
// is child
+
+ if (!p_blocking) {
+ // For non blocking calls, create a new session-ID so parent won't wait for it.
+ // This ensures the process won't go zombie at end.
+ setsid();
+ }
+
Vector<CharString> cs;
cs.push_back(p_path.utf8());
for (int i = 0; i < p_arguments.size(); i++)
@@ -359,6 +355,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
waitpid(pid, &status, 0);
if (r_exitcode)
*r_exitcode = WEXITSTATUS(status);
+
} else {
if (r_child_id)
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 09ab4aa1d8..6a05877a8c 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -89,7 +89,7 @@ public:
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false);
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL);
virtual Error kill(const ProcessID &p_pid);
virtual int get_process_id() const;
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index c4c5e0d709..c13300d09f 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -339,6 +339,16 @@ uint64_t FileAccessWindows::_get_modified_time(const String &p_file) {
}
}
+uint32_t FileAccessWindows::_get_unix_permissions(const String &p_file) {
+ ERR_PRINT("Windows does not support unix permissions");
+ return 0;
+}
+
+Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
+ ERR_PRINT("Windows does not support unix permissions");
+ return FAILED;
+}
+
FileAccessWindows::FileAccessWindows() :
f(NULL),
flags(0),
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 35b1f0b2d8..2848ed5279 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -80,6 +80,8 @@ public:
virtual bool file_exists(const String &p_name); ///< return true if a file exists
uint64_t _get_modified_time(const String &p_file);
+ virtual uint32_t _get_unix_permissions(const String &p_file);
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
FileAccessWindows();
virtual ~FileAccessWindows();
diff --git a/drivers/xaudio2/SCsub b/drivers/xaudio2/SCsub
index 3dca95b429..dfc877b6f5 100644
--- a/drivers/xaudio2/SCsub
+++ b/drivers/xaudio2/SCsub
@@ -3,5 +3,5 @@
Import('env')
env.add_source_files(env.drivers_sources, "*.cpp")
-env.Append(CXXFLAGS=['-DXAUDIO2_ENABLED'])
+env.Append(CPPFLAGS=['-DXAUDIO2_ENABLED'])
env.Append(LINKFLAGS=['xaudio2_8.lib'])
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 134384c167..a9ec776693 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -768,6 +768,7 @@ void CodeTextEditor::update_editor_settings() {
text_editor->set_hiding_enabled(EditorSettings::get_singleton()->get("text_editor/line_numbers/code_folding"));
text_editor->set_draw_fold_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/code_folding"));
text_editor->set_wrap_enabled(EditorSettings::get_singleton()->get("text_editor/line_numbers/word_wrap"));
+ text_editor->set_draw_info_gutter(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_info_gutter"));
text_editor->cursor_set_block_mode(EditorSettings::get_singleton()->get("text_editor/cursor/block_caret"));
text_editor->set_smooth_scroll_enabled(EditorSettings::get_singleton()->get("text_editor/open_scripts/smooth_scrolling"));
text_editor->set_v_scroll_speed(EditorSettings::get_singleton()->get("text_editor/open_scripts/v_scroll_speed"));
@@ -1180,17 +1181,57 @@ Variant CodeTextEditor::get_edit_state() {
Dictionary state;
state["scroll_position"] = text_editor->get_v_scroll();
+ state["h_scroll_position"] = text_editor->get_h_scroll();
state["column"] = text_editor->cursor_get_column();
state["row"] = text_editor->cursor_get_line();
+ state["selection"] = get_text_edit()->is_selection_active();
+ if (get_text_edit()->is_selection_active()) {
+ state["selection_from_line"] = text_editor->get_selection_from_line();
+ state["selection_from_column"] = text_editor->get_selection_from_column();
+ state["selection_to_line"] = text_editor->get_selection_to_line();
+ state["selection_to_column"] = text_editor->get_selection_to_column();
+ }
+
+ state["folded_lines"] = text_editor->get_folded_lines();
+ state["breakpoints"] = text_editor->get_breakpoints_array();
+
+ state["syntax_highlighter"] = TTR("Standard");
+ SyntaxHighlighter *syntax_highlighter = text_editor->_get_syntax_highlighting();
+ if (syntax_highlighter) {
+ state["syntax_highlighter"] = syntax_highlighter->get_name();
+ }
+
return state;
}
void CodeTextEditor::set_edit_state(const Variant &p_state) {
Dictionary state = p_state;
- text_editor->cursor_set_column(state["column"]);
+
+ /* update the row first as it sets the column to 0 */
text_editor->cursor_set_line(state["row"]);
+ text_editor->cursor_set_column(state["column"]);
text_editor->set_v_scroll(state["scroll_position"]);
+ text_editor->set_h_scroll(state["h_scroll_position"]);
+
+ if (state.has("selection")) {
+ text_editor->select(state["selection_from_line"], state["selection_from_column"], state["selection_to_line"], state["selection_to_column"]);
+ }
+
+ if (state.has("folded_lines")) {
+ Vector<int> folded_lines = state["folded_lines"];
+ for (int i = 0; i < folded_lines.size(); i++) {
+ text_editor->fold_line(folded_lines[i]);
+ }
+ }
+
+ if (state.has("breakpoints")) {
+ Array breakpoints = state["breakpoints"];
+ for (int i = 0; i < breakpoints.size(); i++) {
+ text_editor->set_line_as_breakpoint(breakpoints[i], true);
+ }
+ }
+
text_editor->grab_focus();
}
diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp
index 94a37a3118..e9040b9d3e 100644
--- a/editor/collada/collada.cpp
+++ b/editor/collada/collada.cpp
@@ -2256,8 +2256,7 @@ void Collada::_merge_skeletons2(VisualScene *p_vscene) {
Node *node = state.scene_map[name];
ERR_CONTINUE(node->type != Node::TYPE_JOINT);
- if (node->type != Node::TYPE_JOINT)
- continue;
+
NodeSkeleton *sk = NULL;
while (node && !sk) {
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 685c5de76c..03a71f3248 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -141,6 +141,9 @@ void ConnectDialog::_tree_node_selected() {
Node *current = tree->get_selected();
+ if (!current)
+ return;
+
dst_path = source->get_path_to(current);
get_ok()->set_disabled(false);
}
@@ -309,6 +312,7 @@ void ConnectDialog::popup_dialog(const String &p_for_signal, bool p_advanced) {
advanced->set_pressed(p_advanced);
from_signal->set_text(p_for_signal);
error_label->add_color_override("font_color", get_color("error_color", "Editor"));
+ vbc_right->set_visible(p_advanced);
if (p_advanced) {
@@ -330,7 +334,7 @@ void ConnectDialog::popup_dialog(const String &p_for_signal, bool p_advanced) {
}
void ConnectDialog::_advanced_pressed() {
- vbc_right->set_visible(advanced->is_pressed());
+
popup_dialog(from_signal->get_text(), advanced->is_pressed());
}
@@ -414,7 +418,7 @@ ConnectDialog::ConnectDialog() {
advanced = memnew(CheckBox);
dstm_hb->add_child(advanced);
- advanced->set_text(TTR("Advanced.."));
+ advanced->set_text(TTR("Advanced..."));
advanced->connect("pressed", this, "_advanced_pressed");
/*
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index 49d40e6d90..2beb0153f4 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -756,7 +756,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
add_child(vb);
set_v_size_flags(SIZE_EXPAND_FILL);
- set_custom_minimum_size(Size2(100, 0) * EDSCALE);
+ set_custom_minimum_size(Size2(110, 0) * EDSCALE);
track_name = memnew(LineEdit);
track_name->connect("text_entered", this, "_name_changed");
@@ -1394,7 +1394,7 @@ void EditorAudioMeterNotches::_notification(int p_what) {
}
void EditorAudioMeterNotches::_draw_audio_notches() {
- Ref<Font> font = get_font("source", "EditorFonts");
+ Ref<Font> font = get_font("font", "Label");
float font_height = font->get_height();
for (uint8_t i = 0; i < notches.size(); i++) {
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index e6a6d9e6a6..724b821267 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -233,8 +233,8 @@ void EditorFileDialog::_file_entered(const String &p_file) {
void EditorFileDialog::_save_confirm_pressed() {
String f = dir_access->get_current_dir().plus_file(file->get_text());
_save_to_recent();
- emit_signal("file_selected", f);
hide();
+ emit_signal("file_selected", f);
}
void EditorFileDialog::_post_popup() {
@@ -343,8 +343,8 @@ void EditorFileDialog::_action_pressed() {
if (files.size()) {
_save_to_recent();
- emit_signal("files_selected", files);
hide();
+ emit_signal("files_selected", files);
}
return;
@@ -354,8 +354,8 @@ void EditorFileDialog::_action_pressed() {
if ((mode == MODE_OPEN_ANY || mode == MODE_OPEN_FILE) && dir_access->file_exists(f)) {
_save_to_recent();
- emit_signal("file_selected", f);
hide();
+ emit_signal("file_selected", f);
} else if (mode == MODE_OPEN_ANY || mode == MODE_OPEN_DIR) {
String path = dir_access->get_current_dir();
@@ -374,8 +374,8 @@ void EditorFileDialog::_action_pressed() {
}
_save_to_recent();
- emit_signal("dir_selected", path);
hide();
+ emit_signal("dir_selected", path);
}
if (mode == MODE_SAVE_FILE) {
@@ -441,8 +441,8 @@ void EditorFileDialog::_action_pressed() {
} else {
_save_to_recent();
- emit_signal("file_selected", f);
hide();
+ emit_signal("file_selected", f);
}
}
}
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index f1f68a14de..b0a1331b2e 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -211,12 +211,14 @@ void EditorProperty::_notification(int p_what) {
}
int ofs = 0;
+ int text_limit = text_size;
+
if (checkable) {
Ref<Texture> checkbox;
if (checked)
- checkbox = get_icon("checked", "CheckBox");
+ checkbox = get_icon("GuiChecked", "EditorIcons");
else
- checkbox = get_icon("unchecked", "CheckBox");
+ checkbox = get_icon("GuiUnchecked", "EditorIcons");
Color color2(1, 1, 1);
if (check_hover) {
@@ -228,12 +230,11 @@ void EditorProperty::_notification(int p_what) {
draw_texture(checkbox, check_rect.position, color2);
ofs += get_constant("hseparator", "Tree");
ofs += checkbox->get_width();
+ text_limit -= ofs;
} else {
check_rect = Rect2();
}
- int text_limit = text_size;
-
if (can_revert) {
Ref<Texture> reload_icon = get_icon("ReloadSmall", "EditorIcons");
text_limit -= reload_icon->get_width() + get_constant("hseparator", "Tree") * 2;
@@ -804,6 +805,9 @@ void EditorProperty::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tooltip_text"), &EditorProperty::get_tooltip_text);
+ ClassDB::bind_method(D_METHOD("add_focusable", "control"), &EditorProperty::add_focusable);
+ ClassDB::bind_method(D_METHOD("set_bottom_editor", "editor"), &EditorProperty::set_bottom_editor);
+
ClassDB::bind_method(D_METHOD("emit_changed", "property", "value", "field", "changing"), &EditorProperty::emit_changed, DEFVAL(StringName()), DEFVAL(false));
ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label");
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index b729de2e2f..fe52e7eb7e 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -47,6 +47,7 @@
#include "core/translation.h"
#include "core/version.h"
#include "main/input_default.h"
+#include "main/main.h"
#include "scene/resources/packed_scene.h"
#include "servers/physics_2d_server.h"
@@ -1973,6 +1974,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
if (scene_idx != -1)
_discard_changes();
+ save_layout();
break;
}
@@ -2270,6 +2272,23 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir());
} break;
+ case FILE_INSTALL_ANDROID_SOURCE: {
+
+ if (p_confirmed) {
+ export_template_manager->install_android_template();
+ } else {
+ if (DirAccess::exists("res://android/build")) {
+ remove_android_build_template->popup_centered_minsize();
+ } else if (export_template_manager->can_install_android_template()) {
+ install_android_build_template->popup_centered_minsize();
+ } else {
+ custom_build_manage_templates->popup_centered_minsize();
+ }
+ }
+ } break;
+ case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: {
+ OS::get_singleton()->shell_open(String("file://") + ProjectSettings::get_singleton()->get_resource_path().plus_file("android"));
+ } break;
case FILE_QUIT:
case RUN_PROJECT_MANAGER: {
@@ -2523,6 +2542,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) {
void EditorNode::_exit_editor() {
exiting = true;
resource_preview->stop(); //stop early to avoid crashes
+ _save_docks();
get_tree()->quit();
}
@@ -4629,19 +4649,53 @@ void EditorNode::remove_tool_menu_item(const String &p_name) {
void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path());
- DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ _add_dropped_files_recursive(p_files, to_path);
+
+ EditorFileSystem::get_singleton()->scan_changes();
+}
+
+void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, String to_path) {
+
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Vector<String> just_copy = String("ttf,otf").split(",");
+
for (int i = 0; i < p_files.size(); i++) {
String from = p_files[i];
+ String to = to_path.plus_file(from.get_file());
+
+ if (dir->dir_exists(from)) {
+
+ Vector<String> sub_files;
+
+ DirAccessRef sub_dir = DirAccess::open(from);
+ sub_dir->list_dir_begin();
+
+ String next_file = sub_dir->get_next();
+ while (next_file != "") {
+ if (next_file == "." || next_file == "..") {
+ next_file = sub_dir->get_next();
+ continue;
+ }
+
+ sub_files.push_back(from.plus_file(next_file));
+ next_file = sub_dir->get_next();
+ }
+
+ if (!sub_files.empty()) {
+ dir->make_dir(to);
+ _add_dropped_files_recursive(sub_files, to);
+ }
+
+ continue;
+ }
+
if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) == -1)) {
continue;
}
- String to = to_path.plus_file(from.get_file());
dir->copy(from, to);
}
- EditorFileSystem::get_singleton()->scan_changes();
}
void EditorNode::_file_access_close_error_notify(const String &p_str) {
@@ -5009,6 +5063,68 @@ void EditorNode::_print_handler(void *p_this, const String &p_string, bool p_err
en->log->add_message(p_string, p_error ? EditorLog::MSG_TYPE_ERROR : EditorLog::MSG_TYPE_STD);
}
+static void _execute_thread(void *p_ud) {
+
+ EditorNode::ExecuteThreadArgs *eta = (EditorNode::ExecuteThreadArgs *)p_ud;
+ Error err = OS::get_singleton()->execute(eta->path, eta->args, true, NULL, &eta->output, &eta->exitcode, true, eta->execute_output_mutex);
+ print_verbose("Thread exit status: " + itos(eta->exitcode));
+ if (err != OK) {
+ eta->exitcode = err;
+ }
+
+ eta->done = true;
+}
+
+int EditorNode::execute_and_show_output(const String &p_title, const String &p_path, const List<String> &p_arguments, bool p_close_on_ok, bool p_close_on_errors) {
+
+ execute_output_dialog->set_title(p_title);
+ execute_output_dialog->get_ok()->set_disabled(true);
+ execute_outputs->clear();
+ execute_outputs->set_scroll_follow(true);
+ execute_output_dialog->popup_centered_ratio();
+
+ ExecuteThreadArgs eta;
+ eta.path = p_path;
+ eta.args = p_arguments;
+ eta.execute_output_mutex = Mutex::create();
+ eta.exitcode = 255;
+ eta.done = false;
+
+ int prev_len = 0;
+
+ eta.execute_output_thread = Thread::create(_execute_thread, &eta);
+
+ ERR_FAIL_COND_V(!eta.execute_output_thread, 0);
+
+ while (!eta.done) {
+ eta.execute_output_mutex->lock();
+ if (prev_len != eta.output.length()) {
+ String to_add = eta.output.substr(prev_len, eta.output.length());
+ prev_len = eta.output.length();
+ execute_outputs->add_text(to_add);
+ Main::iteration();
+ }
+ eta.execute_output_mutex->unlock();
+ OS::get_singleton()->delay_usec(1000);
+ }
+
+ Thread::wait_to_finish(eta.execute_output_thread);
+ memdelete(eta.execute_output_thread);
+ memdelete(eta.execute_output_mutex);
+ execute_outputs->add_text("\nExit Code: " + itos(eta.exitcode));
+
+ if (p_close_on_errors && eta.exitcode != 0) {
+ execute_output_dialog->hide();
+ }
+ if (p_close_on_ok && eta.exitcode == 0) {
+ execute_output_dialog->hide();
+ }
+
+ execute_output_dialog->get_ok()->set_disabled(false);
+
+ return eta.exitcode;
+}
+
EditorNode::EditorNode() {
Input::get_singleton()->set_use_accumulated_input(true);
@@ -5583,12 +5699,13 @@ EditorNode::EditorNode() {
tool_menu = memnew(PopupMenu);
tool_menu->set_name("Tools");
tool_menu->connect("index_pressed", this, "_tool_menu_option");
+ p->add_separator();
p->add_child(tool_menu);
p->add_submenu_item(TTR("Tools"), "Tools");
- tool_menu->add_shortcut(ED_SHORTCUT("editor/orphan_resource_explorer", TTR("Orphan Resource Explorer")), TOOLS_ORPHAN_RESOURCES);
+ tool_menu->add_item(TTR("Orphan Resource Explorer"), TOOLS_ORPHAN_RESOURCES);
+ tool_menu->add_item(TTR("Open Project Data Folder"), RUN_PROJECT_DATA_FOLDER);
p->add_separator();
-
- p->add_shortcut(ED_SHORTCUT("editor/open_project_data_folder", TTR("Open Project Data Folder")), RUN_PROJECT_DATA_FOLDER);
+ p->add_item(TTR("Install Android Build Template"), FILE_INSTALL_ANDROID_SOURCE);
p->add_separator();
#ifdef OSX_ENABLED
@@ -5935,6 +6052,24 @@ EditorNode::EditorNode() {
save_confirmation->connect("confirmed", this, "_menu_confirm_current");
save_confirmation->connect("custom_action", this, "_discard_changes");
+ custom_build_manage_templates = memnew(ConfirmationDialog);
+ custom_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates."));
+ custom_build_manage_templates->get_ok()->set_text(TTR("Manage Templates"));
+ custom_build_manage_templates->connect("confirmed", this, "_menu_option", varray(SETTINGS_MANAGE_EXPORT_TEMPLATES));
+ gui_base->add_child(custom_build_manage_templates);
+
+ install_android_build_template = memnew(ConfirmationDialog);
+ install_android_build_template->set_text(TTR("This will install the Android project for custom builds.\nNote that, in order to use it, it needs to be enabled per export preset."));
+ install_android_build_template->get_ok()->set_text(TTR("Install"));
+ install_android_build_template->connect("confirmed", this, "_menu_confirm_current");
+ gui_base->add_child(install_android_build_template);
+
+ remove_android_build_template = memnew(ConfirmationDialog);
+ remove_android_build_template->set_text(TTR("Android build template is already installed and it won't be overwritten.\nRemove the \"build\" directory manually before attempting this operation again."));
+ remove_android_build_template->get_ok()->set_text(TTR("Show in File Manager"));
+ remove_android_build_template->connect("confirmed", this, "_menu_option", varray(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES));
+ gui_base->add_child(remove_android_build_template);
+
file_templates = memnew(EditorFileDialog);
file_templates->set_title(TTR("Import Templates From ZIP File"));
@@ -6149,6 +6284,12 @@ EditorNode::EditorNode() {
load_error_dialog->set_title(TTR("Load Errors"));
gui_base->add_child(load_error_dialog);
+ execute_outputs = memnew(RichTextLabel);
+ execute_output_dialog = memnew(AcceptDialog);
+ execute_output_dialog->add_child(execute_outputs);
+ execute_output_dialog->set_title(TTR(""));
+ gui_base->add_child(execute_output_dialog);
+
EditorFileSystem::get_singleton()->connect("sources_changed", this, "_sources_changed");
EditorFileSystem::get_singleton()->connect("filesystem_changed", this, "_fs_changed");
EditorFileSystem::get_singleton()->connect("resources_reimported", this, "_resources_reimported");
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 5ed0bd4ac3..a06708eb54 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -112,6 +112,16 @@ public:
DOCK_SLOT_MAX
};
+ struct ExecuteThreadArgs {
+ String path;
+ List<String> args;
+ String output;
+ Thread *execute_output_thread;
+ Mutex *execute_output_mutex;
+ int exitcode;
+ volatile bool done;
+ };
+
private:
enum {
HISTORY_SIZE = 64
@@ -130,6 +140,8 @@ private:
FILE_IMPORT_SUBSCENE,
FILE_EXPORT_PROJECT,
FILE_EXPORT_MESH_LIBRARY,
+ FILE_INSTALL_ANDROID_SOURCE,
+ FILE_EXPLORE_ANDROID_BUILD_TEMPLATES,
FILE_EXPORT_TILESET,
FILE_SAVE_OPTIMIZED,
FILE_OPEN_RECENT,
@@ -267,6 +279,9 @@ private:
RichTextLabel *load_errors;
AcceptDialog *load_error_dialog;
+ RichTextLabel *execute_outputs;
+ AcceptDialog *execute_output_dialog;
+
Ref<Theme> theme;
PopupMenu *recent_scenes;
@@ -290,6 +305,10 @@ private:
PopupMenu *editor_layouts;
EditorNameDialog *layout_dialog;
+ ConfirmationDialog *custom_build_manage_templates;
+ ConfirmationDialog *install_android_build_template;
+ ConfirmationDialog *remove_android_build_template;
+
EditorSettingsDialog *settings_config_dialog;
RunSettingsDialog *run_settings_dialog;
ProjectSettingsEditor *project_settings;
@@ -470,6 +489,7 @@ private:
void _update_recent_scenes();
void _open_recent_scene(int p_idx);
void _dropped_files(const Vector<String> &p_files, int p_screen);
+ void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path);
String _recent_scene;
void _exit_editor();
@@ -799,6 +819,8 @@ public:
void update_keying() const { inspector_dock->update_keying(); };
bool has_scenes_in_session();
+ int execute_and_show_output(const String &p_title, const String &p_path, const List<String> &p_arguments, bool p_close_on_ok = true, bool p_close_on_errors = false);
+
EditorNode();
~EditorNode();
void get_singleton(const char *arg1, bool arg2);
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 06cadca1c0..b73cda6008 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -56,7 +56,7 @@ void EditorRunNative::_notification(int p_what) {
small_icon->create_from_image(im, 0);
MenuButton *mb = memnew(MenuButton);
mb->get_popup()->connect("id_pressed", this, "_run_native", varray(i));
- //mb->connect("pressed", this, "_run_native", varray(-1, i));
+ mb->connect("pressed", this, "_run_native", varray(-1, i));
mb->set_icon(small_icon);
add_child(mb);
menus[i] = mb;
@@ -82,10 +82,14 @@ void EditorRunNative::_notification(int p_what) {
} else {
mb->get_popup()->clear();
mb->show();
- mb->set_tooltip(TTR("Select device from the list"));
- for (int i = 0; i < dc; i++) {
- mb->get_popup()->add_icon_item(get_icon("Play", "EditorIcons"), eep->get_device_name(i));
- mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() - 1, eep->get_device_info(i).strip_edges());
+ if (dc == 1) {
+ mb->set_tooltip(eep->get_device_name(0) + "\n\n" + eep->get_device_info(0).strip_edges());
+ } else {
+ mb->set_tooltip("Select device from the list");
+ for (int i = 0; i < dc; i++) {
+ mb->get_popup()->add_icon_item(get_icon("Play", "EditorIcons"), eep->get_device_name(i));
+ mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() - 1, eep->get_device_info(i).strip_edges());
+ }
}
}
}
@@ -99,14 +103,15 @@ void EditorRunNative::_run_native(int p_idx, int p_platform) {
Ref<EditorExportPlatform> eep = EditorExport::get_singleton()->get_export_platform(p_platform);
ERR_FAIL_COND(eep.is_null());
- /*if (p_idx == -1) {
+
+ if (p_idx == -1) {
if (eep->get_device_count() == 1) {
menus[p_platform]->get_popup()->hide();
p_idx = 0;
} else {
return;
}
- }*/
+ }
Ref<EditorExportPreset> preset;
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index f54c51940f..54bd9cae20 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -429,6 +429,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/line_numbers/show_line_numbers", true);
_initial_set("text_editor/line_numbers/line_numbers_zero_padded", false);
_initial_set("text_editor/line_numbers/show_breakpoint_gutter", true);
+ _initial_set("text_editor/line_numbers/show_info_gutter", true);
_initial_set("text_editor/line_numbers/code_folding", true);
_initial_set("text_editor/line_numbers/word_wrap", false);
_initial_set("text_editor/line_numbers/show_line_length_guideline", false);
diff --git a/editor/editor_sub_scene.cpp b/editor/editor_sub_scene.cpp
index e4807a37c6..987033b123 100644
--- a/editor/editor_sub_scene.cpp
+++ b/editor/editor_sub_scene.cpp
@@ -73,8 +73,8 @@ void EditorSubScene::_notification(int p_what) {
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- if (!is_visible_in_tree()) {
- }
+ if (is_visible() && scene == NULL)
+ _path_browse();
}
}
@@ -232,7 +232,7 @@ EditorSubScene::EditorSubScene() {
hb->add_child(path);
path->set_h_size_flags(SIZE_EXPAND_FILL);
Button *b = memnew(Button);
- b->set_text(" .. ");
+ b->set_text(TTR("Browse"));
hb->add_child(b);
b->connect("pressed", this, "_path_browse");
vb->add_margin_child(TTR("Scene Path:"), hb);
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 97ccfb0db1..aa2a03510d 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -308,7 +308,8 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
p->step(TTR("Importing:") + " " + file, fc);
}
- FileAccess *f = FileAccess::open(template_path.plus_file(file), FileAccess::WRITE);
+ String to_write = template_path.plus_file(file);
+ FileAccess *f = FileAccess::open(to_write, FileAccess::WRITE);
if (!f) {
ret = unzGoToNextFile(pkg);
@@ -320,6 +321,10 @@ bool ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_
memdelete(f);
+#ifndef WINDOWS_ENABLED
+ FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
+#endif
+
ret = unzGoToNextFile(pkg);
fc++;
}
@@ -541,6 +546,112 @@ void ExportTemplateManager::_notification(int p_what) {
}
}
+bool ExportTemplateManager::can_install_android_template() {
+
+ return FileAccess::exists(EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG).plus_file("android_source.zip"));
+}
+
+Error ExportTemplateManager::install_android_template() {
+
+ DirAccessRef da = DirAccess::open("res://");
+ ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+ //make android dir (if it does not exist)
+
+ da->make_dir("android");
+ {
+ //add an empty .gdignore file to avoid scan
+ FileAccessRef f = FileAccess::open("res://android/.gdignore", FileAccess::WRITE);
+ ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+ f->store_line("");
+ f->close();
+ }
+ {
+ //add version, to ensure building wont work if template and Godot version are mismatch
+ FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::WRITE);
+ ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+ f->store_line(VERSION_FULL_CONFIG);
+ f->close();
+ }
+
+ Error err = da->make_dir_recursive("android/build");
+ ERR_FAIL_COND_V(err != OK, err);
+
+ String source_zip = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG).plus_file("android_source.zip");
+ ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN);
+
+ FileAccess *src_f = NULL;
+ zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+
+ unzFile pkg = unzOpen2(source_zip.utf8().get_data(), &io);
+ ERR_EXPLAIN("Android sources not in zip format");
+ ERR_FAIL_COND_V(!pkg, ERR_CANT_OPEN);
+
+ int ret = unzGoToFirstFile(pkg);
+
+ int total_files = 0;
+ //count files
+ while (ret == UNZ_OK) {
+ total_files++;
+ ret = unzGoToNextFile(pkg);
+ }
+
+ ret = unzGoToFirstFile(pkg);
+ //decompress files
+ ProgressDialog::get_singleton()->add_task("uncompress", TTR("Uncompressing Android Build Sources"), total_files);
+
+ Set<String> dirs_tested;
+
+ int idx = 0;
+ while (ret == UNZ_OK) {
+
+ //get filename
+ unz_file_info info;
+ char fname[16384];
+ ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, NULL, 0, NULL, 0);
+
+ String name = fname;
+
+ String base_dir = name.get_base_dir();
+
+ if (!name.ends_with("/")) {
+ Vector<uint8_t> data;
+ data.resize(info.uncompressed_size);
+
+ //read
+ unzOpenCurrentFile(pkg);
+ unzReadCurrentFile(pkg, data.ptrw(), data.size());
+ unzCloseCurrentFile(pkg);
+
+ if (!dirs_tested.has(base_dir)) {
+ da->make_dir_recursive(String("android/build").plus_file(base_dir));
+ dirs_tested.insert(base_dir);
+ }
+
+ String to_write = String("res://android/build").plus_file(name);
+ FileAccess *f = FileAccess::open(to_write, FileAccess::WRITE);
+ if (f) {
+ f->store_buffer(data.ptr(), data.size());
+ memdelete(f);
+#ifndef WINDOWS_ENABLED
+ FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
+#endif
+ } else {
+ ERR_PRINTS("Cant uncompress file: " + to_write);
+ }
+ }
+
+ ProgressDialog::get_singleton()->task_step("uncompress", name, idx);
+
+ idx++;
+ ret = unzGoToNextFile(pkg);
+ }
+
+ ProgressDialog::get_singleton()->end_task("uncompress");
+ unzClose(pkg);
+
+ return OK;
+}
+
void ExportTemplateManager::_bind_methods() {
ClassDB::bind_method("_download_template", &ExportTemplateManager::_download_template);
diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h
index 2edd3db6d7..608830c990 100644
--- a/editor/export_template_manager.h
+++ b/editor/export_template_manager.h
@@ -84,6 +84,9 @@ protected:
static void _bind_methods();
public:
+ bool can_install_android_template();
+ Error install_android_template();
+
void popup_manager();
ExportTemplateManager();
diff --git a/editor/icons/icon_bucket.svg b/editor/icons/icon_bucket.svg
new file mode 100644
index 0000000000..4a5df39e93
--- /dev/null
+++ b/editor/icons/icon_bucket.svg
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ version="1.1"
+ viewBox="0 0 16 16"
+ id="svg6"
+ sodipodi:docname="icon_bucket.svg"
+ inkscape:version="0.92.2 2405546, 2018-03-11">
+ <metadata
+ id="metadata12">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs10" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1876"
+ inkscape:window-height="1574"
+ id="namedview8"
+ showgrid="true"
+ inkscape:snap-bbox="true"
+ inkscape:bbox-paths="false"
+ inkscape:bbox-nodes="false"
+ inkscape:snap-bbox-edge-midpoints="false"
+ inkscape:snap-bbox-midpoints="true"
+ inkscape:snap-intersection-paths="true"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-nodes="false"
+ inkscape:snap-others="false"
+ inkscape:zoom="16"
+ inkscape:cx="-4.3713942"
+ inkscape:cy="-1.9091903"
+ inkscape:window-x="4"
+ inkscape:window-y="20"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="g4">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4524" />
+ </sodipodi:namedview>
+ <g
+ transform="translate(0 -1036.4)"
+ id="g4">
+ <g
+ id="g4576"
+ transform="matrix(0.53348552,0.53348552,-0.53348552,0.53348552,561.06065,484.40406)"
+ style="stroke-width:1.32544696">
+ <path
+ id="path2"
+ transform="translate(0,1036.4)"
+ d="M 2,1 C 1.4477645,1.0001 1.0000523,1.4477 1,2 V 3.5 H 3.8847656 A 1.4999877,1.5 0 0 1 5,3 1.4999877,1.5 0 0 1 6.5,4.5 1.4999877,1.5 0 0 1 5,6 1.4999877,1.5 0 0 1 3.8847656,5.5 H 1 V 7 H -0.26953125 -2 c -0.5522769,0 -0.999989,-0.4477 -1,-1 1.1e-5,-0.5523 0.4477231,-1 1,-1 h 3 2.5878906 0.546875 A 1,1 0 0 0 5,5.5 1,1 0 0 0 6,4.5 1,1 0 0 0 5,3.5 1,1 0 0 0 4.1367188,4 H 3.5878906 1 -2 c -1.1045647,0 -1.9999933,0.8954285 -2,2 6.7e-6,1.1045715 0.8954353,2 2,2 h 3 v 6 c 7.35e-5,0.5523 0.4477232,0.9999 1,1 h 8 c 0.552235,-10e-5 0.999947,-0.4477 1,-1 V 1 Z"
+ style="color:#000000;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;text-orientation:mixed;dominant-baseline:auto;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000000;fill:#e0e0e0;stroke-width:1.32544696;color-rendering:auto;image-rendering:auto;shape-rendering:auto"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cczcc"
+ inkscape:connector-curvature="0"
+ id="path4526"
+ d="m 12,1038.4 c 0.707107,3.5356 0.707107,3.5356 1.414213,4.2427 0.707107,0.7071 2.121321,0.7071 2.828428,0 0.707106,-0.7071 0.707106,-2.1213 0,-2.8284 C 15.535534,1039.1071 15.535534,1039.1071 12,1038.4 Z"
+ style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.32544696px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ </g>
+</svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 44eaf3d9ef..e152827c63 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -1614,8 +1614,6 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
continue;
}
- ERR_CONTINUE(xform_idx == -1);
-
Vector<float> data = at.get_value_at_time(snapshots[i]);
ERR_CONTINUE(data.empty());
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index d711c1717d..8a2393ff60 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -130,8 +130,7 @@ void InspectorDock::_menu_option(int p_option) {
ERR_FAIL_INDEX(idx, methods.size());
String name = methods[idx].name;
- if (current)
- current->call(name);
+ current->call(name);
}
}
}
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index 4a4e7f25b8..1afd7df049 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -481,6 +481,17 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event)
if (edited_point.valid() && (wip_active || (mm->get_button_mask() & BUTTON_MASK_LEFT))) {
Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)));
+
+ //Move the point in a single axis. Should only work when editing a polygon and while holding shift.
+ if (mode == MODE_EDIT && mm->get_shift()) {
+ Vector2 old_point = pre_move_edit.get(selected_point.vertex);
+ if (ABS(cpoint.x - old_point.x) > ABS(cpoint.y - old_point.y)) {
+ cpoint.y = old_point.y;
+ } else {
+ cpoint.x = old_point.x;
+ }
+ }
+
edited_point = PosVertex(edited_point, cpoint);
if (!wip_active) {
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index cb3e5a8129..f06b4b2828 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -874,9 +874,9 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() {
}
to.y = from.y;
- float len = MAX(0.0001, playback->get_current_length());
+ float len = MAX(0.0001, current_length);
- float pos = CLAMP(playback->get_current_play_pos(), 0, len);
+ float pos = CLAMP(play_pos, 0, len);
float c = pos / len;
Color fg = get_color("font_color", "Label");
Color bg = fg;
@@ -1011,7 +1011,8 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
bool is_playing = false;
StringName current_node;
StringName blend_from_node;
- float play_pos = 0;
+ play_pos = 0;
+ current_length = 0;
if (playback.is_valid()) {
tp = playback->get_travel_path();
@@ -1019,6 +1020,7 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
current_node = playback->get_current_node();
blend_from_node = playback->get_blend_from_node();
play_pos = playback->get_current_play_pos();
+ current_length = playback->get_current_length();
}
{
@@ -1046,6 +1048,27 @@ void AnimationNodeStateMachineEditor::_notification(int p_what) {
state_machine_play_pos->update();
}
+ {
+ if (current_node != StringName() && state_machine->has_node(current_node)) {
+
+ String next = current_node;
+ Ref<AnimationNodeStateMachine> anodesm = state_machine->get_node(next);
+ Ref<AnimationNodeStateMachinePlayback> current_node_playback;
+
+ while (anodesm.is_valid()) {
+ current_node_playback = AnimationTreeEditor::get_singleton()->get_tree()->get(AnimationTreeEditor::get_singleton()->get_base_path() + next + "/playback");
+ next += "/" + current_node_playback->get_current_node();
+ anodesm = anodesm->get_node(current_node_playback->get_current_node());
+ }
+
+ // when current_node is a state machine, use playback of current_node to set play_pos
+ if (current_node_playback.is_valid()) {
+ play_pos = current_node_playback->get_current_play_pos();
+ current_length = current_node_playback->get_current_length();
+ }
+ }
+ }
+
if (last_play_pos != play_pos) {
last_play_pos = play_pos;
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index 1c4c06090a..8b0a5a0b00 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -160,6 +160,8 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
StringName last_current_node;
Vector<StringName> last_travel_path;
float last_play_pos;
+ float play_pos;
+ float current_length;
float error_time;
String error_text;
diff --git a/editor/plugins/animation_tree_player_editor_plugin.cpp b/editor/plugins/animation_tree_player_editor_plugin.cpp
index e21ae4834d..f5d21ffb26 100644
--- a/editor/plugins/animation_tree_player_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_player_editor_plugin.cpp
@@ -840,7 +840,7 @@ void AnimationTreePlayerEditor::_gui_input(Ref<InputEvent> p_event) {
click_motion = Point2(mm->get_position().x, mm->get_position().y);
update();
}
- if ((mm->get_button_mask() & 4 || Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+ if (mm->get_button_mask() & 4 || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x);
v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 386bc1738e..0dfb53b34a 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -175,7 +175,7 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const
Ref<Image> overlay = get_icon("PlayOverlay", "EditorIcons")->get_data();
Ref<Image> thumbnail = p_image->get_data();
thumbnail = thumbnail->duplicate();
- Point2 overlay_pos = Point2((thumbnail->get_width() - overlay->get_width()) / 2, (thumbnail->get_height() - overlay->get_height()) / 2);
+ Point2 overlay_pos = Point2((thumbnail->get_width() - overlay->get_width() / 2) / 2, (thumbnail->get_height() - overlay->get_height() / 2) / 2);
// Overlay and thumbnail need the same format for `blend_rect` to work.
thumbnail->convert(Image::FORMAT_RGBA8);
@@ -310,15 +310,20 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() {
description = memnew(RichTextLabel);
description->connect("meta_clicked", this, "_link_click");
+ description->set_custom_minimum_size(Size2(440 * EDSCALE, 300 * EDSCALE));
desc_bg->add_child(description);
+ VBoxContainer *previews_vbox = memnew(VBoxContainer);
+ hbox->add_child(previews_vbox);
+ previews_vbox->add_constant_override("separation", 15 * EDSCALE);
+
preview = memnew(TextureRect);
preview->set_custom_minimum_size(Size2(640 * EDSCALE, 345 * EDSCALE));
- hbox->add_child(preview);
+ previews_vbox->add_child(preview);
previews_bg = memnew(PanelContainer);
- vbox->add_child(previews_bg);
- previews_bg->set_custom_minimum_size(Size2(0, 101 * EDSCALE));
+ previews_vbox->add_child(previews_bg);
+ previews_bg->set_custom_minimum_size(Size2(640 * EDSCALE, 101 * EDSCALE));
previews = memnew(ScrollContainer);
previews_bg->add_child(previews);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 66f7b932a2..e5228ff1e7 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -84,7 +84,6 @@ public:
container = memnew(VBoxContainer);
add_child(container);
- //set_child_rect(container);
child_container = memnew(GridContainer);
child_container->set_columns(3);
@@ -99,12 +98,14 @@ public:
grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
grid_offset_x->set_suffix("px");
+ grid_offset_x->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_offset_x);
grid_offset_y = memnew(SpinBox);
grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
grid_offset_y->set_suffix("px");
+ grid_offset_y->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_offset_y);
label = memnew(Label);
@@ -116,12 +117,14 @@ public:
grid_step_x->set_min(0.01);
grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
grid_step_x->set_suffix("px");
+ grid_step_x->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_step_x);
grid_step_y = memnew(SpinBox);
grid_step_y->set_min(0.01);
grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
grid_step_y->set_suffix("px");
+ grid_step_y->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(grid_step_y);
container->add_child(memnew(HSeparator));
@@ -139,6 +142,7 @@ public:
rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
rotation_offset->set_suffix("deg");
+ rotation_offset->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(rotation_offset);
label = memnew(Label);
@@ -150,6 +154,7 @@ public:
rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
rotation_step->set_suffix("deg");
+ rotation_step->set_h_size_flags(SIZE_EXPAND_FILL);
child_container->add_child(rotation_step);
}
@@ -1858,7 +1863,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
}
// Confirm the move (only if it was moved)
- if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT && (drag_type == DRAG_MOVE)) {
+ if (b.is_valid() && !b->is_pressed() && b->get_button_index() == BUTTON_LEFT) {
if (transform.affine_inverse().xform(b->get_position()) != drag_from) {
_commit_canvas_item_state(drag_selection, TTR("Move CanvasItem"), true);
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index d7d4cec07d..03287b8cf9 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1801,6 +1801,16 @@ void ScriptEditor::_update_script_names() {
_update_script_colors();
}
+void ScriptEditor::_update_script_connections() {
+ for (int i = 0; i < tab_container->get_child_count(); i++) {
+ ScriptTextEditor *ste = Object::cast_to<ScriptTextEditor>(tab_container->get_child(i));
+ if (!ste) {
+ continue;
+ }
+ ste->_update_connected_methods();
+ }
+}
+
Ref<TextFile> ScriptEditor::_load_text_file(const String &p_path, Error *r_error) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
@@ -2203,6 +2213,7 @@ void ScriptEditor::_tree_changed() {
waiting_update_names = true;
call_deferred("_update_script_names");
+ call_deferred("_update_script_connections");
}
void ScriptEditor::_script_split_dragged(float) {
@@ -2482,22 +2493,39 @@ void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) {
for (int i = 0; i < scripts.size(); i++) {
String path = scripts[i];
+
+ Dictionary script_info = scripts[i];
+ if (!script_info.empty()) {
+ path = script_info["path"];
+ }
+
if (!FileAccess::exists(path))
continue;
if (extensions.find(path.get_extension())) {
Ref<Script> scr = ResourceLoader::load(path);
- if (scr.is_valid()) {
- edit(scr);
+ if (!scr.is_valid()) {
+ continue;
+ }
+ if (!edit(scr)) {
+ continue;
+ }
+ } else {
+ Error error;
+ Ref<TextFile> text_file = _load_text_file(path, &error);
+ if (error != OK || !text_file.is_valid()) {
+ continue;
+ }
+ if (!edit(text_file)) {
continue;
}
}
- Error error;
- Ref<TextFile> text_file = _load_text_file(path, &error);
- if (error == OK && text_file.is_valid()) {
- edit(text_file);
- continue;
+ if (!script_info.empty()) {
+ ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(tab_container->get_tab_count() - 1));
+ if (se) {
+ se->set_edit_state(script_info["state"]);
+ }
}
}
@@ -2537,7 +2565,11 @@ void ScriptEditor::get_window_layout(Ref<ConfigFile> p_layout) {
if (!path.is_resource_file())
continue;
- scripts.push_back(path);
+ Dictionary script_info;
+ script_info["path"] = path;
+ script_info["state"] = se->get_edit_state();
+
+ scripts.push_back(script_info);
}
EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(i));
@@ -2856,6 +2888,7 @@ void ScriptEditor::_bind_methods() {
ClassDB::bind_method("_autosave_scripts", &ScriptEditor::_autosave_scripts);
ClassDB::bind_method("_editor_settings_changed", &ScriptEditor::_editor_settings_changed);
ClassDB::bind_method("_update_script_names", &ScriptEditor::_update_script_names);
+ ClassDB::bind_method("_update_script_connections", &ScriptEditor::_update_script_connections);
ClassDB::bind_method("_tree_changed", &ScriptEditor::_tree_changed);
ClassDB::bind_method("_members_overview_selected", &ScriptEditor::_members_overview_selected);
ClassDB::bind_method("_help_overview_selected", &ScriptEditor::_help_overview_selected);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 954b014935..f13308dec7 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -333,6 +333,7 @@ class ScriptEditor : public PanelContainer {
void _update_members_overview();
void _toggle_members_overview_alpha_sort(bool p_alphabetic_sort);
void _update_script_names();
+ void _update_script_connections();
bool _sort_list_on_update;
void _members_overview_selected(int p_idx);
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index c586985957..46b2e8a5f8 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -35,6 +35,76 @@
#include "editor/editor_settings.h"
#include "editor/script_editor_debugger.h"
+void ConnectionInfoDialog::ok_pressed() {
+}
+
+void ConnectionInfoDialog::popup_connections(String p_method, Vector<Node *> p_nodes) {
+ method->set_text(p_method);
+
+ tree->clear();
+ TreeItem *root = tree->create_item();
+
+ for (int i = 0; i < p_nodes.size(); i++) {
+ List<Connection> all_connections;
+ p_nodes[i]->get_signals_connected_to_this(&all_connections);
+
+ for (List<Connection>::Element *E = all_connections.front(); E; E = E->next()) {
+ Connection connection = E->get();
+
+ if (connection.method != p_method) {
+ continue;
+ }
+
+ TreeItem *node_item = tree->create_item(root);
+
+ node_item->set_text(0, Object::cast_to<Node>(connection.source)->get_name());
+ node_item->set_icon(0, EditorNode::get_singleton()->get_object_icon(connection.source, "Node"));
+ node_item->set_selectable(0, false);
+ node_item->set_editable(0, false);
+
+ node_item->set_text(1, connection.signal);
+ node_item->set_icon(1, get_parent_control()->get_icon("Slot", "EditorIcons"));
+ node_item->set_selectable(1, false);
+ node_item->set_editable(1, false);
+
+ node_item->set_text(2, Object::cast_to<Node>(connection.target)->get_name());
+ node_item->set_icon(2, EditorNode::get_singleton()->get_object_icon(connection.target, "Node"));
+ node_item->set_selectable(2, false);
+ node_item->set_editable(2, false);
+ }
+ }
+
+ popup_centered(Size2(400, 300) * EDSCALE);
+}
+
+ConnectionInfoDialog::ConnectionInfoDialog() {
+ set_title(TTR("Connections to method:"));
+
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ vbc->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, 8 * EDSCALE);
+ vbc->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -8 * EDSCALE);
+ vbc->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -8 * EDSCALE);
+ add_child(vbc);
+
+ method = memnew(Label);
+ method->set_align(Label::ALIGN_CENTER);
+ vbc->add_child(method);
+
+ tree = memnew(Tree);
+ tree->set_columns(3);
+ tree->set_hide_root(true);
+ tree->set_column_titles_visible(true);
+ tree->set_column_title(0, TTR("Source"));
+ tree->set_column_title(1, TTR("Signal"));
+ tree->set_column_title(2, TTR("Target"));
+ vbc->add_child(tree);
+ tree->set_v_size_flags(SIZE_EXPAND_FILL);
+ tree->set_allow_rmb_select(true);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
Vector<String> ScriptTextEditor::get_functions() {
String errortxt;
@@ -320,7 +390,6 @@ void ScriptTextEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY:
_load_theme_settings();
- _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("script_text_editor", "syntax_highlighter", 0));
break;
}
}
@@ -365,6 +434,14 @@ Variant ScriptTextEditor::get_edit_state() {
void ScriptTextEditor::set_edit_state(const Variant &p_state) {
code_editor->set_edit_state(p_state);
+
+ Dictionary state = p_state;
+ if (state.has("syntax_highlighter")) {
+ int idx = highlighter_menu->get_item_idx_from_text(state["syntax_highlighter"]);
+ if (idx >= 0) {
+ _change_syntax_highlighter(idx);
+ }
+ }
}
void ScriptTextEditor::_convert_case(CodeTextEditor::CaseStyle p_case) {
@@ -463,9 +540,32 @@ void ScriptTextEditor::_validate_script() {
functions.push_back(E->get());
}
}
+ _update_connected_methods();
- code_editor->set_warning_nb(warnings.size());
+ code_editor->set_warning_nb(missing_connections.size() + warnings.size());
warnings_panel->clear();
+
+ // add missing connections
+ Node *base = get_tree()->get_edited_scene_root();
+ if (base && missing_connections.size() > 0) {
+ warnings_panel->push_table(1);
+ for (List<Connection>::Element *E = missing_connections.front(); E; E = E->next()) {
+ Connection connection = E->get();
+
+ String base_path = base->get_name();
+ String source_path = base == connection.source ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.source)));
+ String target_path = base == connection.target ? base_path : base_path + "/" + String(base->get_path_to(Object::cast_to<Node>(connection.target)));
+
+ warnings_panel->push_cell();
+ warnings_panel->push_color(warnings_panel->get_color("warning_color", "Editor"));
+ warnings_panel->add_text(vformat(TTR("Missing connected method '%s' for signal '%s' from node '%s' to node '%s'"), connection.method, connection.signal, source_path, target_path));
+ warnings_panel->pop(); // Color
+ warnings_panel->pop(); // Cell
+ }
+ warnings_panel->pop(); // Table
+ }
+
+ // add script warnings
warnings_panel->push_table(3);
for (List<ScriptLanguage::Warning>::Element *E = warnings.front(); E; E = E->next()) {
ScriptLanguage::Warning w = E->get();
@@ -519,6 +619,27 @@ void ScriptTextEditor::_validate_script() {
emit_signal("edited_script_changed");
}
+static Vector<Node *> _find_all_node_for_script(Node *p_base, Node *p_current, const Ref<Script> &p_script) {
+
+ Vector<Node *> nodes;
+
+ if (p_current->get_owner() != p_base && p_base != p_current) {
+ return nodes;
+ }
+
+ Ref<Script> c = p_current->get_script();
+ if (c == p_script) {
+ nodes.push_back(p_current);
+ }
+
+ for (int i = 0; i < p_current->get_child_count(); i++) {
+ Vector<Node *> found = _find_all_node_for_script(p_base, p_current->get_child(i), p_script);
+ nodes.append_array(found);
+ }
+
+ return nodes;
+}
+
static Node *_find_node_for_script(Node *p_base, Node *p_current, const Ref<Script> &p_script) {
if (p_current->get_owner() != p_base && p_base != p_current)
@@ -714,6 +835,47 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
}
}
+void ScriptTextEditor::_update_connected_methods() {
+ TextEdit *text_edit = code_editor->get_text_edit();
+ text_edit->clear_info_icons();
+ missing_connections.clear();
+
+ Node *base = get_tree()->get_edited_scene_root();
+ if (!base) {
+ return;
+ }
+
+ Vector<Node *> nodes = _find_all_node_for_script(base, base, script);
+ for (int i = 0; i < nodes.size(); i++) {
+ List<Connection> connections;
+ nodes[i]->get_signals_connected_to_this(&connections);
+
+ for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
+ Connection connection = E->get();
+ if (!(connection.flags & CONNECT_PERSIST)) {
+ continue;
+ }
+
+ int line = script->get_language()->find_function(connection.method, text_edit->get_text());
+ if (line < 0) {
+ missing_connections.push_back(connection);
+ continue;
+ }
+ text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method);
+ }
+ }
+}
+
+void ScriptTextEditor::_lookup_connections(int p_row, String p_method) {
+ Node *base = get_tree()->get_edited_scene_root();
+ if (!base) {
+ return;
+ }
+
+ Vector<Node *> nodes = _find_all_node_for_script(base, base, script);
+ connection_info_dialog->popup_connections(p_method, nodes);
+}
+
void ScriptTextEditor::_edit_option(int p_op) {
TextEdit *tx = code_editor->get_text_edit();
@@ -1026,7 +1188,6 @@ void ScriptTextEditor::_change_syntax_highlighter(int p_idx) {
}
// highlighter_menu->set_item_checked(p_idx, true);
set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
- EditorSettings::get_singleton()->set_project_metadata("script_text_editor", "syntax_highlighter", p_idx);
}
void ScriptTextEditor::_bind_methods() {
@@ -1034,6 +1195,8 @@ void ScriptTextEditor::_bind_methods() {
ClassDB::bind_method("_validate_script", &ScriptTextEditor::_validate_script);
ClassDB::bind_method("_load_theme_settings", &ScriptTextEditor::_load_theme_settings);
ClassDB::bind_method("_breakpoint_toggled", &ScriptTextEditor::_breakpoint_toggled);
+ ClassDB::bind_method("_lookup_connections", &ScriptTextEditor::_lookup_connections);
+ ClassDB::bind_method("_update_connected_methods", &ScriptTextEditor::_update_connected_methods);
ClassDB::bind_method("_change_syntax_highlighter", &ScriptTextEditor::_change_syntax_highlighter);
ClassDB::bind_method("_edit_option", &ScriptTextEditor::_edit_option);
ClassDB::bind_method("_goto_line", &ScriptTextEditor::_goto_line);
@@ -1366,6 +1529,7 @@ ScriptTextEditor::ScriptTextEditor() {
code_editor->set_code_complete_func(_code_complete_scripts, this);
code_editor->get_text_edit()->connect("breakpoint_toggled", this, "_breakpoint_toggled");
code_editor->get_text_edit()->connect("symbol_lookup", this, "_lookup_symbol");
+ code_editor->get_text_edit()->connect("info_clicked", this, "_lookup_connections");
code_editor->set_v_size_flags(SIZE_EXPAND_FILL);
warnings_panel = memnew(RichTextLabel);
@@ -1486,6 +1650,9 @@ ScriptTextEditor::ScriptTextEditor() {
goto_line_dialog = memnew(GotoLineDialog);
add_child(goto_line_dialog);
+ connection_info_dialog = memnew(ConnectionInfoDialog);
+ add_child(connection_info_dialog);
+
code_editor->get_text_edit()->set_drag_forwarding(this);
}
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index b081a31c18..4edb1c3c67 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -32,8 +32,25 @@
#define SCRIPT_TEXT_EDITOR_H
#include "scene/gui/color_picker.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
#include "script_editor_plugin.h"
+class ConnectionInfoDialog : public AcceptDialog {
+
+ GDCLASS(ConnectionInfoDialog, AcceptDialog);
+
+ Label *method;
+ Tree *tree;
+
+ virtual void ok_pressed();
+
+public:
+ void popup_connections(String p_method, Vector<Node *> p_nodes);
+
+ ConnectionInfoDialog();
+};
+
class ScriptTextEditor : public ScriptEditorBase {
GDCLASS(ScriptTextEditor, ScriptEditorBase);
@@ -45,6 +62,8 @@ class ScriptTextEditor : public ScriptEditorBase {
Vector<String> functions;
+ List<Connection> missing_connections;
+
Vector<String> member_keywords;
HBoxContainer *edit_hb;
@@ -56,6 +75,7 @@ class ScriptTextEditor : public ScriptEditorBase {
GotoLineDialog *goto_line_dialog;
ScriptEditorQuickOpen *quick_open;
+ ConnectionInfoDialog *connection_info_dialog;
PopupPanel *color_panel;
ColorPicker *color_picker;
@@ -144,6 +164,8 @@ protected:
void _goto_line(int p_line) { goto_line(p_line); }
void _lookup_symbol(const String &p_symbol, int p_row, int p_column);
+ void _lookup_connections(int p_row, String p_method);
+
void _convert_case(CodeTextEditor::CaseStyle p_case);
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
@@ -151,6 +173,8 @@ protected:
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
public:
+ void _update_connected_methods();
+
virtual void add_syntax_highlighter(SyntaxHighlighter *p_highlighter);
virtual void set_syntax_highlighter(SyntaxHighlighter *p_highlighter);
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 321b136c3b..47f00dc480 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -1850,7 +1850,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!sp)
continue;
- emit_signal("transform_key_request", sp, "", sp->get_transform());
+ spatial_editor->emit_signal("transform_key_request", sp, "", sp->get_transform());
}
set_message(TTR("Animation Key Inserted."));
@@ -5686,11 +5686,11 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
snap_dialog_vbc->add_margin_child(TTR("Translate Snap:"), snap_translate);
snap_rotate = memnew(LineEdit);
- snap_rotate->set_text("5");
+ snap_rotate->set_text("15");
snap_dialog_vbc->add_margin_child(TTR("Rotate Snap (deg.):"), snap_rotate);
snap_scale = memnew(LineEdit);
- snap_scale->set_text("5");
+ snap_scale->set_text("10");
snap_dialog_vbc->add_margin_child(TTR("Scale Snap (%):"), snap_scale);
/* SETTINGS DIALOG */
@@ -5848,6 +5848,39 @@ Vector3 SpatialEditor::snap_point(Vector3 p_target, Vector3 p_start) const {
return p_target;
}
+float SpatialEditor::get_translate_snap() const {
+ float snap_value;
+ if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ snap_value = snap_translate->get_text().to_double() / 10.0;
+ } else {
+ snap_value = snap_translate->get_text().to_double();
+ }
+
+ return snap_value;
+}
+
+float SpatialEditor::get_rotate_snap() const {
+ float snap_value;
+ if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ snap_value = snap_rotate->get_text().to_double() / 3.0;
+ } else {
+ snap_value = snap_rotate->get_text().to_double();
+ }
+
+ return snap_value;
+}
+
+float SpatialEditor::get_scale_snap() const {
+ float snap_value;
+ if (Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ snap_value = snap_scale->get_text().to_double() / 2.0;
+ } else {
+ snap_value = snap_scale->get_text().to_double();
+ }
+
+ return snap_value;
+}
+
void SpatialEditorPlugin::_bind_methods() {
ClassDB::bind_method("snap_cursor_to_plane", &SpatialEditorPlugin::snap_cursor_to_plane);
@@ -5902,7 +5935,7 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *p_node) {
editor->get_viewport()->add_child(spatial_editor);
spatial_editor->hide();
- spatial_editor->connect("transform_key_request", editor, "_transform_keyed");
+ spatial_editor->connect("transform_key_request", editor->get_inspector_dock(), "_transform_keyed");
}
SpatialEditorPlugin::~SpatialEditorPlugin() {
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 65dd2a26fd..f3a1e657cc 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -677,9 +677,9 @@ public:
ToolMode get_tool_mode() const { return tool_mode; }
bool are_local_coords_enabled() const { return tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->is_pressed(); }
bool is_snap_enabled() const { return snap_enabled ^ snap_key_enabled; }
- float get_translate_snap() const { return snap_translate->get_text().to_double(); }
- float get_rotate_snap() const { return snap_rotate->get_text().to_double(); }
- float get_scale_snap() const { return snap_scale->get_text().to_double(); }
+ float get_translate_snap() const;
+ float get_rotate_snap() const;
+ float get_scale_snap() const;
Ref<ArrayMesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
Ref<ArrayMesh> get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; }
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index fe32c97a64..2886b3dc51 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -66,7 +66,6 @@ void TextEditor::_change_syntax_highlighter(int p_idx) {
el = el->next();
}
set_syntax_highlighter(highlighters[highlighter_menu->get_item_text(p_idx)]);
- EditorSettings::get_singleton()->set_project_metadata("text_editor", "syntax_highlighter", p_idx);
}
void TextEditor::_load_theme_settings() {
@@ -234,6 +233,14 @@ Variant TextEditor::get_edit_state() {
void TextEditor::set_edit_state(const Variant &p_state) {
code_editor->set_edit_state(p_state);
+
+ Dictionary state = p_state;
+ if (state.has("syntax_highlighter")) {
+ int idx = highlighter_menu->get_item_idx_from_text(state["syntax_highlighter"]);
+ if (idx >= 0) {
+ _change_syntax_highlighter(idx);
+ }
+ }
}
void TextEditor::trim_trailing_whitespace() {
@@ -299,7 +306,6 @@ void TextEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY:
_load_theme_settings();
- _change_syntax_highlighter(EditorSettings::get_singleton()->get_project_metadata("text_editor", "syntax_highlighter", 0));
break;
}
}
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index e9b9c03c1e..7c8e69ae70 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -36,7 +36,7 @@
void ThemeEditor::edit(const Ref<Theme> &p_theme) {
theme = p_theme;
- main_vb->set_theme(p_theme);
+ main_container->set_theme(p_theme);
}
void ThemeEditor::_propagate_redraw(Control *p_at) {
@@ -53,7 +53,7 @@ void ThemeEditor::_propagate_redraw(Control *p_at) {
void ThemeEditor::_refresh_interval() {
- _propagate_redraw(main_vb);
+ _propagate_redraw(main_container);
}
void ThemeEditor::_type_menu_cbk(int p_option) {
@@ -86,7 +86,7 @@ void ThemeEditor::_name_menu_about_to_show() {
}
name_menu->get_popup()->clear();
-
+ name_menu->get_popup()->set_size(Size2());
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
name_menu->get_popup()->add_item(E->get());
@@ -574,7 +574,6 @@ void ThemeEditor::_theme_menu_cbk(int p_option) {
}
}
- //types.sort();
types.sort_custom<StringName::AlphCompare>();
for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
@@ -610,30 +609,14 @@ ThemeEditor::ThemeEditor() {
time_left = 0;
- scroll = memnew(ScrollContainer);
- add_child(scroll);
- scroll->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 3);
- scroll->set_margin(MARGIN_TOP, 30 * EDSCALE);
- //scroll->set_enable_h_scroll(true);
- scroll->set_enable_v_scroll(true);
- scroll->set_enable_h_scroll(false);
-
- Panel *panel = memnew(Panel);
- scroll->add_child(panel);
- panel->set_custom_minimum_size(Size2(500, 800) * EDSCALE);
- panel->set_theme(Theme::get_default());
- panel->set_h_size_flags(SIZE_EXPAND_FILL);
+ HBoxContainer *top_menu = memnew(HBoxContainer);
+ add_child(top_menu);
- main_vb = memnew(VBoxContainer);
- panel->add_child(main_vb);
- main_vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 4 * EDSCALE);
-
- HBoxContainer *hb_menu = memnew(HBoxContainer);
- main_vb->add_child(hb_menu);
+ top_menu->add_child(memnew(Label(TTR("Preview:"))));
+ top_menu->add_spacer(false);
theme_menu = memnew(MenuButton);
- theme_menu->set_text(TTR("Edit theme..."));
- theme_menu->set_flat(false);
+ theme_menu->set_text(TTR("Edit Theme"));
theme_menu->set_tooltip(TTR("Theme editing menu."));
theme_menu->get_popup()->add_item(TTR("Add Item"), POPUP_ADD);
theme_menu->get_popup()->add_item(TTR("Add Class Items"), POPUP_CLASS_ADD);
@@ -643,51 +626,73 @@ ThemeEditor::ThemeEditor() {
theme_menu->get_popup()->add_item(TTR("Create Empty Template"), POPUP_CREATE_EMPTY);
theme_menu->get_popup()->add_item(TTR("Create Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY);
theme_menu->get_popup()->add_item(TTR("Create From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME);
- add_child(theme_menu);
- theme_menu->set_position(Vector2(3, 3) * EDSCALE);
+ top_menu->add_child(theme_menu);
theme_menu->get_popup()->connect("id_pressed", this, "_theme_menu_cbk");
+ scroll = memnew(ScrollContainer);
+ add_child(scroll);
+ scroll->set_enable_v_scroll(true);
+ scroll->set_enable_h_scroll(false);
+ scroll->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ main_container = memnew(MarginContainer);
+ scroll->add_child(main_container);
+ main_container->set_clip_contents(true);
+ main_container->set_custom_minimum_size(Size2(700, 0) * EDSCALE);
+ main_container->set_v_size_flags(SIZE_EXPAND_FILL);
+ main_container->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ //// Preview Controls ////
+
+ Panel *panel = memnew(Panel);
+ main_container->add_child(panel);
+ panel->set_theme(Theme::get_default());
+
+ MarginContainer *mc = memnew(MarginContainer);
+ main_container->add_child(mc);
+ mc->set_theme(Theme::get_default());
+ mc->add_constant_override("margin_right", 4 * EDSCALE);
+ mc->add_constant_override("margin_top", 4 * EDSCALE);
+ mc->add_constant_override("margin_left", 4 * EDSCALE);
+ mc->add_constant_override("margin_bottom", 4 * EDSCALE);
+
HBoxContainer *main_hb = memnew(HBoxContainer);
- main_vb->add_child(main_hb);
+ mc->add_child(main_hb);
VBoxContainer *first_vb = memnew(VBoxContainer);
- first_vb->set_h_size_flags(SIZE_EXPAND_FILL);
main_hb->add_child(first_vb);
-
- //main_panel->add_child(panel);
- //panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
- //panel->set_margin( MARGIN_TOP,20 );
+ first_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ first_vb->add_constant_override("separation", 10 * EDSCALE);
first_vb->add_child(memnew(Label("Label")));
first_vb->add_child(memnew(Button("Button")));
+ Button *bt = memnew(Button);
+ bt->set_text(TTR("Toggle Button"));
+ bt->set_toggle_mode(true);
+ bt->set_pressed(true);
+ first_vb->add_child(bt);
+ bt = memnew(Button);
+ bt->set_text(TTR("Disabled Button"));
+ bt->set_disabled(true);
+ first_vb->add_child(bt);
ToolButton *tb = memnew(ToolButton);
tb->set_text("ToolButton");
first_vb->add_child(tb);
+
CheckButton *cb = memnew(CheckButton);
cb->set_text("CheckButton");
first_vb->add_child(cb);
+ cb = memnew(CheckButton);
CheckBox *cbx = memnew(CheckBox);
cbx->set_text("CheckBox");
first_vb->add_child(cbx);
- VBoxContainer *bg = memnew(VBoxContainer);
- bg->set_v_size_flags(SIZE_EXPAND_FILL);
- VBoxContainer *gbvb = memnew(VBoxContainer);
- gbvb->set_v_size_flags(SIZE_EXPAND_FILL);
- CheckBox *rbx1 = memnew(CheckBox);
- rbx1->set_text(TTR("CheckBox Radio1"));
- rbx1->set_pressed(true);
- gbvb->add_child(rbx1);
- CheckBox *rbx2 = memnew(CheckBox);
- rbx2->set_text(TTR("CheckBox Radio2"));
- gbvb->add_child(rbx2);
- bg->add_child(gbvb);
- first_vb->add_child(bg);
-
MenuButton *test_menu_button = memnew(MenuButton);
test_menu_button->set_text("MenuButton");
test_menu_button->get_popup()->add_item(TTR("Item"));
+ test_menu_button->get_popup()->add_item(TTR("Disabled Item"));
+ test_menu_button->get_popup()->set_item_disabled(1, true);
test_menu_button->get_popup()->add_separator();
test_menu_button->get_popup()->add_check_item(TTR("Check Item"));
test_menu_button->get_popup()->add_check_item(TTR("Checked Item"));
@@ -696,6 +701,14 @@ ThemeEditor::ThemeEditor() {
test_menu_button->get_popup()->add_radio_check_item(TTR("Radio Item"));
test_menu_button->get_popup()->add_radio_check_item(TTR("Checked Radio Item"));
test_menu_button->get_popup()->set_item_checked(6, true);
+ test_menu_button->get_popup()->add_separator(TTR("Named Sep."));
+
+ PopupMenu *test_submenu = memnew(PopupMenu);
+ test_menu_button->get_popup()->add_child(test_submenu);
+ test_submenu->set_name("submenu");
+ test_menu_button->get_popup()->add_submenu_item(TTR("Submenu"), "submenu");
+ test_submenu->add_item(TTR("Item 1"));
+ test_submenu->add_item(TTR("Item 2"));
first_vb->add_child(test_menu_button);
OptionButton *test_option_button = memnew(OptionButton);
@@ -705,21 +718,7 @@ ThemeEditor::ThemeEditor() {
test_option_button->add_item(TTR("Many"));
test_option_button->add_item(TTR("Options"));
first_vb->add_child(test_option_button);
-
- ColorPickerButton *cpb = memnew(ColorPickerButton);
- first_vb->add_child(cpb);
-
- first_vb->add_child(memnew(HSeparator));
- first_vb->add_child(memnew(HSlider));
- first_vb->add_child(memnew(HScrollBar));
- first_vb->add_child(memnew(SpinBox));
- ProgressBar *pb = memnew(ProgressBar);
- pb->set_value(50);
- first_vb->add_child(pb);
- Panel *pn = memnew(Panel);
- pn->set_custom_minimum_size(Size2(40, 40) * EDSCALE);
- first_vb->add_child(pn);
- first_vb->add_constant_override("separation", 10 * EDSCALE);
+ first_vb->add_child(memnew(ColorPickerButton));
VBoxContainer *second_vb = memnew(VBoxContainer);
second_vb->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -728,50 +727,48 @@ ThemeEditor::ThemeEditor() {
LineEdit *le = memnew(LineEdit);
le->set_text("LineEdit");
second_vb->add_child(le);
+ le = memnew(LineEdit);
+ le->set_text(TTR("Disabled LineEdit"));
+ le->set_editable(false);
+ second_vb->add_child(le);
TextEdit *te = memnew(TextEdit);
te->set_text("TextEdit");
- //te->set_v_size_flags(SIZE_EXPAND_FILL);
- te->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
+ te->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
second_vb->add_child(te);
+ second_vb->add_child(memnew(SpinBox));
- Tree *test_tree = memnew(Tree);
- second_vb->add_child(test_tree);
- test_tree->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
-
- TreeItem *item = test_tree->create_item();
- item->set_editable(0, true);
- item->set_text(0, "Tree");
- item = test_tree->create_item(test_tree->get_root());
- item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- item->set_editable(0, true);
- item->set_text(0, "Check");
- item = test_tree->create_item(test_tree->get_root());
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0, true);
- item->set_range_config(0, 0, 20, 0.1);
- item->set_range(0, 2);
- item = test_tree->create_item(test_tree->get_root());
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0, true);
- item->set_text(0, TTR("Has,Many,Options"));
- item->set_range(0, 2);
+ HBoxContainer *vhb = memnew(HBoxContainer);
+ second_vb->add_child(vhb);
+ vhb->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
+ vhb->add_child(memnew(VSlider));
+ VScrollBar *vsb = memnew(VScrollBar);
+ vsb->set_page(25);
+ vhb->add_child(vsb);
+ vhb->add_child(memnew(VSeparator));
+ VBoxContainer *hvb = memnew(VBoxContainer);
+ vhb->add_child(hvb);
+ hvb->set_alignment(ALIGN_CENTER);
+ hvb->set_h_size_flags(SIZE_EXPAND_FILL);
+ hvb->add_child(memnew(HSlider));
+ HScrollBar *hsb = memnew(HScrollBar);
+ hsb->set_page(25);
+ hvb->add_child(hsb);
+ HSlider *hs = memnew(HSlider);
+ hs->set_editable(false);
+ hvb->add_child(hs);
+ hvb->add_child(memnew(HSeparator));
+ ProgressBar *pb = memnew(ProgressBar);
+ pb->set_value(50);
+ hvb->add_child(pb);
VBoxContainer *third_vb = memnew(VBoxContainer);
third_vb->set_h_size_flags(SIZE_EXPAND_FILL);
- third_vb->add_constant_override("separation", 10);
-
+ third_vb->add_constant_override("separation", 10 * EDSCALE);
main_hb->add_child(third_vb);
- HBoxContainer *vhb = memnew(HBoxContainer);
- vhb->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
- vhb->add_child(memnew(VSeparator));
- vhb->add_child(memnew(VSlider));
- vhb->add_child(memnew(VScrollBar));
- third_vb->add_child(vhb);
-
TabContainer *tc = memnew(TabContainer);
third_vb->add_child(tc);
- tc->set_custom_minimum_size(Size2(0, 160) * EDSCALE);
+ tc->set_custom_minimum_size(Size2(0, 135) * EDSCALE);
Control *tcc = memnew(Control);
tcc->set_name(TTR("Tab 1"));
tc->add_child(tcc);
@@ -781,9 +778,41 @@ ThemeEditor::ThemeEditor() {
tcc = memnew(Control);
tcc->set_name(TTR("Tab 3"));
tc->add_child(tcc);
+ tc->set_tab_disabled(2, true);
+
+ Tree *test_tree = memnew(Tree);
+ third_vb->add_child(test_tree);
+ test_tree->set_custom_minimum_size(Size2(0, 175) * EDSCALE);
+ test_tree->add_constant_override("draw_relationship_lines", 1);
+
+ TreeItem *item = test_tree->create_item();
+ item->set_text(0, "Tree");
+ item = test_tree->create_item(test_tree->get_root());
+ item->set_text(0, "Item");
+ item = test_tree->create_item(test_tree->get_root());
+ item->set_editable(0, true);
+ item->set_text(0, TTR("Editable Item"));
+ TreeItem *sub_tree = test_tree->create_item(test_tree->get_root());
+ sub_tree->set_text(0, TTR("Subtree"));
+ item = test_tree->create_item(sub_tree);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
+ item->set_editable(0, true);
+ item->set_text(0, "Check Item");
+ item = test_tree->create_item(sub_tree);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
+ item->set_editable(0, true);
+ item->set_range_config(0, 0, 20, 0.1);
+ item->set_range(0, 2);
+ item = test_tree->create_item(sub_tree);
+ item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
+ item->set_editable(0, true);
+ item->set_text(0, TTR("Has,Many,Options"));
+ item->set_range(0, 2);
main_hb->add_constant_override("separation", 20 * EDSCALE);
+ ////////
+
add_del_dialog = memnew(ConfirmationDialog);
add_del_dialog->hide();
add_child(add_del_dialog);
@@ -844,9 +873,6 @@ ThemeEditor::ThemeEditor() {
file_dialog->add_filter("*.theme ; Theme File");
add_child(file_dialog);
file_dialog->connect("file_selected", this, "_save_template_cbk");
-
- //MenuButton *name_menu;
- //LineEdit *name_edit;
}
void ThemeEditorPlugin::edit(Object *p_node) {
@@ -886,7 +912,6 @@ ThemeEditorPlugin::ThemeEditorPlugin(EditorNode *p_node) {
theme_editor = memnew(ThemeEditor);
theme_editor->set_custom_minimum_size(Size2(0, 200));
- //p_node->get_viewport()->add_child(theme_editor);
button = editor->add_bottom_panel_item(TTR("Theme"), theme_editor);
button->hide();
}
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 352988d69e..cc236907a9 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -33,6 +33,7 @@
#include "scene/gui/check_box.h"
#include "scene/gui/file_dialog.h"
+#include "scene/gui/margin_container.h"
#include "scene/gui/option_button.h"
#include "scene/gui/scroll_container.h"
#include "scene/gui/texture_rect.h"
@@ -40,12 +41,12 @@
#include "editor/editor_node.h"
-class ThemeEditor : public Control {
+class ThemeEditor : public VBoxContainer {
- GDCLASS(ThemeEditor, Control);
+ GDCLASS(ThemeEditor, VBoxContainer);
ScrollContainer *scroll;
- VBoxContainer *main_vb;
+ MarginContainer *main_container;
Ref<Theme> theme;
EditorFileDialog *file_dialog;
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 33e4bb2336..abb52f8359 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -66,6 +66,11 @@ void TileMapEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
+ paint_button->set_icon(get_icon("Edit", "EditorIcons"));
+ bucket_fill_button->set_icon(get_icon("Bucket", "EditorIcons"));
+ picker_button->set_icon(get_icon("ColorPick", "EditorIcons"));
+ select_button->set_icon(get_icon("ActionCopy", "EditorIcons"));
+
rotate_left_button->set_icon(get_icon("Rotate270", "EditorIcons"));
rotate_right_button->set_icon(get_icon("Rotate90", "EditorIcons"));
flip_horizontal_button->set_icon(get_icon("MirrorX", "EditorIcons"));
@@ -76,9 +81,6 @@ void TileMapEditor::_notification(int p_what) {
search_box->set_clear_button_enabled(true);
PopupMenu *p = options->get_popup();
- p->set_item_icon(p->get_item_index(OPTION_PAINTING), get_icon("Edit", "EditorIcons"));
- p->set_item_icon(p->get_item_index(OPTION_PICK_TILE), get_icon("ColorPick", "EditorIcons"));
- p->set_item_icon(p->get_item_index(OPTION_SELECT), get_icon("ActionCopy", "EditorIcons"));
p->set_item_icon(p->get_item_index(OPTION_CUT), get_icon("ActionCut", "EditorIcons"));
p->set_item_icon(p->get_item_index(OPTION_COPY), get_icon("Duplicate", "EditorIcons"));
p->set_item_icon(p->get_item_index(OPTION_ERASE_SELECTION), get_icon("Remove", "EditorIcons"));
@@ -87,37 +89,51 @@ void TileMapEditor::_notification(int p_what) {
}
}
-void TileMapEditor::_menu_option(int p_option) {
+void TileMapEditor::_update_button_tool() {
- switch (p_option) {
-
- case OPTION_PAINTING: {
- // NOTE: We do not set tool = TOOL_PAINTING as this begins painting
- // immediately without pressing the left mouse button first
- tool = TOOL_NONE;
-
- CanvasItemEditor::get_singleton()->update_viewport();
+ ToolButton *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button };
+ // Unpress all buttons
+ for (int i = 0; i < 4; i++) {
+ tb[i]->set_pressed(false);
+ }
+ // Press the good button
+ switch (tool) {
+ case TOOL_NONE:
+ case TOOL_PAINTING: {
+ paint_button->set_pressed(true);
} break;
- case OPTION_BUCKET: {
-
- tool = TOOL_BUCKET;
-
- CanvasItemEditor::get_singleton()->update_viewport();
+ case TOOL_BUCKET: {
+ bucket_fill_button->set_pressed(true);
} break;
- case OPTION_PICK_TILE: {
+ case TOOL_PICKING: {
+ picker_button->set_pressed(true);
+ } break;
+ case TOOL_SELECTING: {
+ select_button->set_pressed(true);
+ } break;
+ default:
+ break;
+ }
+}
- tool = TOOL_PICKING;
+void TileMapEditor::_button_tool_select(int p_tool) {
+ tool = (Tool)p_tool;
+ _update_button_tool();
+ switch (tool) {
+ case TOOL_SELECTING: {
- CanvasItemEditor::get_singleton()->update_viewport();
+ selection_active = false;
} break;
- case OPTION_SELECT: {
+ default:
+ break;
+ }
+ CanvasItemEditor::get_singleton()->update_viewport();
+}
- tool = TOOL_SELECTING;
- selection_active = false;
+void TileMapEditor::_menu_option(int p_option) {
- CanvasItemEditor::get_singleton()->update_viewport();
- } break;
+ switch (p_option) {
case OPTION_COPY: {
_update_copydata();
@@ -168,6 +184,7 @@ void TileMapEditor::_menu_option(int p_option) {
}
} break;
}
+ _update_button_tool();
}
void TileMapEditor::_palette_selected(int index) {
@@ -944,6 +961,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
selection_active = false;
rectangle_begin = over_tile;
+ _update_button_tool();
return true;
}
#ifdef APPLE_STYLE_KEYS
@@ -953,11 +971,13 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
#endif
tool = TOOL_PICKING;
_pick_tile(over_tile);
+ _update_button_tool();
return true;
}
tool = TOOL_PAINTING;
+ _update_button_tool();
}
if (tool == TOOL_PAINTING) {
@@ -979,6 +999,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
rectangle_begin = over_tile;
}
+ _update_button_tool();
return true;
} else {
@@ -1075,6 +1096,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
}
tool = TOOL_NONE;
+ _update_button_tool();
return true;
}
@@ -1090,6 +1112,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
@@ -1100,6 +1123,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
@@ -1130,6 +1154,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
_set_cell(local, invalid_cell);
}
+ _update_button_tool();
return true;
}
@@ -1144,6 +1169,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
tool = TOOL_NONE;
+ _update_button_tool();
return true;
} else if (tool == TOOL_BUCKET) {
@@ -1329,6 +1355,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
@@ -1343,17 +1370,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
tool = TOOL_NONE;
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) {
tool = TOOL_BUCKET;
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
_menu_option(OPTION_ERASE_SELECTION);
+ _update_button_tool();
return true;
}
if (ED_IS_SHORTCUT("tile_map_editor/select", p_event)) {
@@ -1362,6 +1392,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
if (ED_IS_SHORTCUT("tile_map_editor/copy_selection", p_event)) {
@@ -1372,6 +1403,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
}
@@ -1388,6 +1420,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
tool = TOOL_PASTING;
CanvasItemEditor::get_singleton()->update_viewport();
+ _update_button_tool();
return true;
}
}
@@ -1700,6 +1733,7 @@ void TileMapEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_text_entered"), &TileMapEditor::_text_entered);
ClassDB::bind_method(D_METHOD("_text_changed"), &TileMapEditor::_text_changed);
ClassDB::bind_method(D_METHOD("_sbox_input"), &TileMapEditor::_sbox_input);
+ ClassDB::bind_method(D_METHOD("_button_tool_select"), &TileMapEditor::_button_tool_select);
ClassDB::bind_method(D_METHOD("_menu_option"), &TileMapEditor::_menu_option);
ClassDB::bind_method(D_METHOD("_canvas_mouse_enter"), &TileMapEditor::_canvas_mouse_enter);
ClassDB::bind_method(D_METHOD("_canvas_mouse_exit"), &TileMapEditor::_canvas_mouse_exit);
@@ -1880,37 +1914,65 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
// Add menu items
toolbar = memnew(HBoxContainer);
- toolbar->set_h_size_flags(SIZE_EXPAND_FILL);
- toolbar->set_alignment(BoxContainer::ALIGN_END);
toolbar->hide();
CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar);
+ // Separator
+ toolbar->add_child(memnew(VSeparator));
+
+ // Tools
+ paint_button = memnew(ToolButton);
+ paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P));
+ paint_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_NONE));
+ paint_button->set_toggle_mode(true);
+ toolbar->add_child(paint_button);
+
+ bucket_fill_button = memnew(ToolButton);
+ bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_G));
+ bucket_fill_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_BUCKET));
+ bucket_fill_button->set_toggle_mode(true);
+ toolbar->add_child(bucket_fill_button);
+
+ picker_button = memnew(ToolButton);
+ picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_CONTROL));
+ picker_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PICKING));
+ picker_button->set_toggle_mode(true);
+ toolbar->add_child(picker_button);
+
+ select_button = memnew(ToolButton);
+ select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_MASK_CMD + KEY_B));
+ select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECTING));
+ select_button->set_toggle_mode(true);
+ toolbar->add_child(select_button);
+
+ _update_button_tool();
+
+ // Container to the right of the toolbar
+ toolbar_right = memnew(HBoxContainer);
+ toolbar_right->hide();
+ toolbar_right->set_h_size_flags(SIZE_EXPAND_FILL);
+ toolbar_right->set_alignment(BoxContainer::ALIGN_END);
+ CanvasItemEditor::get_singleton()->add_control_to_menu_panel(toolbar_right);
+
// Tile position
tile_info = memnew(Label);
- toolbar->add_child(tile_info);
+ toolbar_right->add_child(tile_info);
+ // Menu
options = memnew(MenuButton);
options->set_text("TileMap");
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons"));
options->set_process_unhandled_key_input(false);
+ toolbar_right->add_child(options);
PopupMenu *p = options->get_popup();
-
- p->add_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P), OPTION_PAINTING);
- p->add_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_G), OPTION_BUCKET);
- p->add_separator();
- p->add_item(TTR("Pick Tile"), OPTION_PICK_TILE, KEY_CONTROL);
- p->add_separator();
- p->add_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_MASK_CMD + KEY_B), OPTION_SELECT);
p->add_shortcut(ED_SHORTCUT("tile_map_editor/cut_selection", TTR("Cut Selection"), KEY_MASK_CMD + KEY_X), OPTION_CUT);
p->add_shortcut(ED_SHORTCUT("tile_map_editor/copy_selection", TTR("Copy Selection"), KEY_MASK_CMD + KEY_C), OPTION_COPY);
p->add_shortcut(ED_GET_SHORTCUT("tile_map_editor/erase_selection"), OPTION_ERASE_SELECTION);
p->add_separator();
p->add_item(TTR("Fix Invalid Tiles"), OPTION_FIX_INVALID);
-
p->connect("id_pressed", this, "_menu_option");
- toolbar->add_child(options);
rotate_left_button = memnew(ToolButton);
rotate_left_button->set_tooltip(TTR("Rotate left"));
rotate_left_button->set_focus_mode(FOCUS_NONE);
@@ -1984,10 +2046,12 @@ void TileMapEditorPlugin::make_visible(bool p_visible) {
tile_map_editor->show();
tile_map_editor->get_toolbar()->show();
+ tile_map_editor->get_toolbar_right()->show();
} else {
tile_map_editor->hide();
tile_map_editor->get_toolbar()->hide();
+ tile_map_editor->get_toolbar_right()->hide();
tile_map_editor->edit(NULL);
}
}
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index b30426eabe..3bc10861f0 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -66,12 +66,8 @@ class TileMapEditor : public VBoxContainer {
enum Options {
- OPTION_BUCKET,
- OPTION_PICK_TILE,
- OPTION_SELECT,
OPTION_COPY,
OPTION_ERASE_SELECTION,
- OPTION_PAINTING,
OPTION_FIX_INVALID,
OPTION_CUT
};
@@ -90,10 +86,16 @@ class TileMapEditor : public VBoxContainer {
ItemList *manual_palette;
HBoxContainer *toolbar;
+ HBoxContainer *toolbar_right;
Label *tile_info;
MenuButton *options;
+ ToolButton *paint_button;
+ ToolButton *bucket_fill_button;
+ ToolButton *picker_button;
+ ToolButton *select_button;
+
ToolButton *flip_horizontal_button;
ToolButton *flip_vertical_button;
ToolButton *rotate_left_button;
@@ -184,6 +186,8 @@ class TileMapEditor : public VBoxContainer {
void _text_changed(const String &p_text);
void _sbox_input(const Ref<InputEvent> &p_ie);
void _update_palette();
+ void _update_button_tool();
+ void _button_tool_select(int p_tool);
void _menu_option(int p_option);
void _palette_selected(int index);
void _palette_multi_selected(int index, bool selected);
@@ -210,6 +214,7 @@ protected:
public:
HBoxContainer *get_toolbar() const { return toolbar; }
+ HBoxContainer *get_toolbar_right() const { return toolbar_right; }
bool forward_gui_input(const Ref<InputEvent> &p_event);
void forward_canvas_draw_over_viewport(Control *p_overlay);
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 8cf00cf67d..21470d81ed 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -1561,13 +1561,42 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
_set_edited_collision_shape(Ref<ConvexPolygonShape2D>());
current_shape.resize(0);
- current_shape.push_back(snap_point(shape_anchor));
- current_shape.push_back(snap_point(shape_anchor + Vector2(current_tile_region.size.x, 0)));
- current_shape.push_back(snap_point(shape_anchor + current_tile_region.size));
- current_shape.push_back(snap_point(shape_anchor + Vector2(0, current_tile_region.size.y)));
- close_shape(shape_anchor);
+ Vector2 pos = mb->get_position();
+ pos = snap_point(pos);
+ current_shape.push_back(pos);
+ current_shape.push_back(pos);
+ current_shape.push_back(pos);
+ current_shape.push_back(pos);
+ creating_shape = true;
workspace->update();
+ return;
} else if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
+ if (creating_shape) {
+ creating_shape = false;
+ _select_edited_shape_coord();
+ workspace->update();
+ }
+ } else if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
+ if (creating_shape) {
+ if ((current_shape[0] - current_shape[1]).length_squared() <= grab_threshold) {
+ current_shape.set(0, snap_point(shape_anchor));
+ current_shape.set(1, snap_point(shape_anchor + Vector2(current_tile_region.size.x, 0)));
+ current_shape.set(2, snap_point(shape_anchor + current_tile_region.size));
+ current_shape.set(3, snap_point(shape_anchor + Vector2(0, current_tile_region.size.y)));
+ }
+ close_shape(shape_anchor);
+ workspace->update();
+ return;
+ }
+ }
+ } else if (mm.is_valid()) {
+ if (creating_shape) {
+ Vector2 pos = mm->get_position();
+ pos = snap_point(pos);
+ Vector2 p = current_shape[2];
+ current_shape.set(3, snap_point(Vector2(pos.x, p.y)));
+ current_shape.set(0, snap_point(pos));
+ current_shape.set(1, snap_point(Vector2(p.x, pos.y)));
workspace->update();
}
}
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 0aba7f3d15..e91b83bcd8 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -172,6 +172,7 @@ void VisualShaderEditor::_update_options_menu() {
int item_count = 0;
int item_count2 = 0;
+ bool is_first_item = true;
for (int i = 0; i < add_options.size() + 1; i++) {
@@ -197,6 +198,7 @@ void VisualShaderEditor::_update_options_menu() {
prev_sub_category = "";
category = members->create_item(root);
category->set_text(0, add_options[i].category);
+ category->set_selectable(0, false);
if (!use_filter)
category->set_collapsed(true);
}
@@ -212,6 +214,7 @@ void VisualShaderEditor::_update_options_menu() {
item_count2 = 0;
sub_category = members->create_item(category);
sub_category->set_text(0, add_options[i].sub_category);
+ sub_category->set_selectable(0, false);
if (!use_filter)
sub_category->set_collapsed(true);
}
@@ -221,6 +224,10 @@ void VisualShaderEditor::_update_options_menu() {
++item_count2;
TreeItem *item = members->create_item(sub_category);
item->set_text(0, add_options[i].name);
+ if (is_first_item) {
+ item->select(0);
+ is_first_item = false;
+ }
switch (add_options[i].return_type) {
case VisualShaderNode::PORT_TYPE_SCALAR:
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons"));
@@ -344,7 +351,6 @@ void VisualShaderEditor::_update_graph() {
Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, nodes[n_i]);
GraphNode *node = memnew(GraphNode);
- graph->add_child(node);
/*if (!vsnode->is_connected("changed", this, "_node_changed")) {
vsnode->connect("changed", this, "_node_changed", varray(vsnode->get_instance_id()), CONNECT_DEFERRED);
@@ -367,6 +373,8 @@ void VisualShaderEditor::_update_graph() {
Ref<VisualShaderNodeUniform> uniform = vsnode;
if (uniform.is_valid()) {
+ graph->add_child(node);
+
LineEdit *uniform_name = memnew(LineEdit);
uniform_name->set_text(uniform->get_uniform_name());
node->add_child(uniform_name);
@@ -484,7 +492,7 @@ void VisualShaderEditor::_update_graph() {
}
}
- if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT) {
+ if (valid_right && edit_type->get_selected() == VisualShader::TYPE_FRAGMENT && port_right != VisualShaderNode::PORT_TYPE_TRANSFORM) {
TextureButton *preview = memnew(TextureButton);
preview->set_toggle_mode(true);
preview->set_normal_texture(get_icon("GuiVisibilityHidden", "EditorIcons"));
@@ -502,21 +510,9 @@ void VisualShaderEditor::_update_graph() {
node->add_child(hb);
node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], valid_right, port_right, type_color[port_right]);
-
- if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) {
- Ref<StyleBoxFlat> sb = node->get_stylebox("frame", "GraphNode");
- Color c = sb->get_border_color();
- 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);
- mono_color.a = 0.85;
- c = mono_color;
-
- node->add_color_override("title_color", c);
- c.a = 0.7;
- node->add_color_override("close_color", c);
- }
}
- if (vsnode->get_output_port_for_preview() >= 0) {
+ if (vsnode->get_output_port_for_preview() >= 0 && vsnode->get_output_port_type(vsnode->get_output_port_for_preview()) != VisualShaderNode::PORT_TYPE_TRANSFORM) {
VisualShaderNodePortPreview *port_preview = memnew(VisualShaderNodePortPreview);
port_preview->setup(visual_shader, type, nodes[n_i], vsnode->get_output_port_for_preview());
port_preview->set_h_size_flags(SIZE_SHRINK_CENTER);
@@ -530,6 +526,22 @@ void VisualShaderEditor::_update_graph() {
error_label->set_text(error);
node->add_child(error_label);
}
+
+ if (!uniform.is_valid()) {
+ graph->add_child(node);
+ }
+
+ if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) {
+ Ref<StyleBoxFlat> sb = node->get_stylebox("frame", "GraphNode");
+ Color c = sb->get_border_color();
+ 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);
+ mono_color.a = 0.85;
+ c = mono_color;
+
+ node->add_color_override("title_color", c);
+ c.a = 0.7;
+ node->add_color_override("close_color", c);
+ }
}
for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
@@ -750,7 +762,6 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in
int to = p_to.to_int();
if (!visual_shader->can_connect_nodes(type, from, p_from_index, to, p_to_index)) {
- EditorNode::get_singleton()->show_warning(TTR("Unable to connect, port may be in use or connection may be invalid."));
return;
}
@@ -833,40 +844,56 @@ void VisualShaderEditor::_node_selected(Object *p_node) {
//EditorNode::get_singleton()->push_item(vsnode.ptr(), "", true);
}
-void VisualShaderEditor::_member_gui_input(const Ref<InputEvent> p_event) {
+void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> p_event) {
+
Ref<InputEventMouseButton> mb = p_event;
- Ref<InputEventKey> key = p_event;
- if (mb.is_valid()) {
- if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && mb->is_doubleclick()) {
- _member_create();
- }
- } else if (key.is_valid()) {
- if (key->is_pressed() && key->get_scancode() == KEY_ENTER) {
- _member_create();
- }
- }
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT)
+ _show_members_dialog(true);
}
-void VisualShaderEditor::_input(const Ref<InputEvent> p_event) {
- if (graph->has_focus()) {
- Ref<InputEventMouseButton> mb = p_event;
+void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) {
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) {
- saved_node_pos_dirty = true;
- saved_node_pos = graph->get_local_mouse_position();
+ members_dialog->popup();
- Point2 gpos = Input::get_singleton()->get_mouse_position();
- members_dialog->popup();
- members_dialog->set_position(gpos);
- }
+ if (at_mouse_pos) {
+ saved_node_pos_dirty = true;
+ saved_node_pos = graph->get_local_mouse_position();
+
+ Point2 gpos = Input::get_singleton()->get_mouse_position();
+ members_dialog->popup();
+ members_dialog->set_position(gpos);
+ } else {
+ saved_node_pos_dirty = false;
+ members_dialog->set_position(graph->get_global_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
+ }
+
+ // keep dialog within window bounds
+ Size2 window_size = OS::get_singleton()->get_window_size();
+ Rect2 dialog_rect = members_dialog->get_global_rect();
+ if (dialog_rect.position.y + dialog_rect.size.y > window_size.y) {
+ int difference = dialog_rect.position.y + dialog_rect.size.y - window_size.y;
+ members_dialog->set_position(members_dialog->get_position() - Point2(0, difference));
}
+ if (dialog_rect.position.x + dialog_rect.size.x > window_size.x) {
+ int difference = dialog_rect.position.x + dialog_rect.size.x - window_size.x;
+ members_dialog->set_position(members_dialog->get_position() - Point2(difference, 0));
+ }
+
+ node_filter->call_deferred("grab_focus"); // still not visible
+ node_filter->select_all();
}
-void VisualShaderEditor::_show_members_dialog() {
- saved_node_pos_dirty = false;
- members_dialog->popup();
- members_dialog->set_position(graph->get_global_position() + Point2(5 * EDSCALE, 65 * EDSCALE));
+void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_ie) {
+ Ref<InputEventKey> ie = p_ie;
+ if (ie.is_valid() && (ie->get_scancode() == KEY_UP ||
+ ie->get_scancode() == KEY_DOWN ||
+ ie->get_scancode() == KEY_ENTER ||
+ ie->get_scancode() == KEY_KP_ENTER)) {
+
+ members->call("_gui_input", ie);
+ node_filter->accept_event();
+ }
}
void VisualShaderEditor::_notification(int p_what) {
@@ -1238,7 +1265,7 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_mode_selected", &VisualShaderEditor::_mode_selected);
ClassDB::bind_method("_input_select_item", &VisualShaderEditor::_input_select_item);
ClassDB::bind_method("_preview_select_port", &VisualShaderEditor::_preview_select_port);
- ClassDB::bind_method("_input", &VisualShaderEditor::_input);
+ ClassDB::bind_method("_graph_gui_input", &VisualShaderEditor::_graph_gui_input);
ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &VisualShaderEditor::get_drag_data_fw);
ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &VisualShaderEditor::can_drop_data_fw);
@@ -1247,7 +1274,7 @@ void VisualShaderEditor::_bind_methods() {
ClassDB::bind_method("_is_available", &VisualShaderEditor::_is_available);
ClassDB::bind_method("_tools_menu_option", &VisualShaderEditor::_tools_menu_option);
ClassDB::bind_method("_show_members_dialog", &VisualShaderEditor::_show_members_dialog);
- ClassDB::bind_method("_member_gui_input", &VisualShaderEditor::_member_gui_input);
+ ClassDB::bind_method("_sbox_input", &VisualShaderEditor::_sbox_input);
ClassDB::bind_method("_member_filter_changed", &VisualShaderEditor::_member_filter_changed);
ClassDB::bind_method("_member_selected", &VisualShaderEditor::_member_selected);
ClassDB::bind_method("_member_unselected", &VisualShaderEditor::_member_unselected);
@@ -1278,6 +1305,7 @@ VisualShaderEditor::VisualShaderEditor() {
graph->connect("scroll_offset_changed", this, "_scroll_changed");
graph->connect("duplicate_nodes_request", this, "_duplicate_nodes");
graph->connect("delete_nodes_request", this, "_on_nodes_delete");
+ graph->connect("gui_input", this, "_graph_gui_input");
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN);
@@ -1306,7 +1334,7 @@ VisualShaderEditor::VisualShaderEditor() {
graph->get_zoom_hbox()->add_child(add_node);
add_node->set_text(TTR("Add Node..."));
graph->get_zoom_hbox()->move_child(add_node, 0);
- add_node->connect("pressed", this, "_show_members_dialog");
+ add_node->connect("pressed", this, "_show_members_dialog", varray(false));
///////////////////////////////////////
// SHADER NODES TREE
@@ -1321,6 +1349,7 @@ VisualShaderEditor::VisualShaderEditor() {
node_filter = memnew(LineEdit);
filter_hb->add_child(node_filter);
node_filter->connect("text_changed", this, "_member_filter_changed");
+ node_filter->connect("gui_input", this, "_sbox_input");
node_filter->set_h_size_flags(SIZE_EXPAND_FILL);
node_filter->set_placeholder(TTR("Search"));
@@ -1340,9 +1369,9 @@ VisualShaderEditor::VisualShaderEditor() {
members->set_allow_reselect(true);
members->set_hide_folding(false);
members->set_custom_minimum_size(Size2(180 * EDSCALE, 200 * EDSCALE));
+ members->connect("item_activated", this, "_member_create");
members->connect("item_selected", this, "_member_selected");
members->connect("nothing_selected", this, "_member_unselected");
- members->connect("gui_input", this, "_member_gui_input");
Label *desc_label = memnew(Label);
members_vb->add_child(desc_label);
@@ -1827,9 +1856,9 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<VisualShaderNode
if (Object::cast_to<EditorPropertyResource>(prop)) {
Object::cast_to<EditorPropertyResource>(prop)->set_use_sub_inspector(false);
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
- } else if (Object::cast_to<EditorPropertyTransform>(prop)) {
+ } else if (Object::cast_to<EditorPropertyTransform>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
prop->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
- } else if (Object::cast_to<EditorPropertyFloat>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
+ } else if (Object::cast_to<EditorPropertyFloat>(prop)) {
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
} else if (Object::cast_to<EditorPropertyEnum>(prop)) {
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 4b0b48ad92..a00f020ebd 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -85,7 +85,7 @@ class VisualShaderEditor : public VBoxContainer {
RichTextLabel *node_desc;
void _tools_menu_option(int p_idx);
- void _show_members_dialog();
+ void _show_members_dialog(bool at_mouse_pos);
void _update_graph();
@@ -166,10 +166,10 @@ class VisualShaderEditor : public VBoxContainer {
void _input_select_item(Ref<VisualShaderNodeInput> input, String name);
void _preview_select_port(int p_node, int p_port);
- void _input(const Ref<InputEvent> p_event);
+ void _graph_gui_input(const Ref<InputEvent> p_event);
- void _member_gui_input(const Ref<InputEvent> p_event);
void _member_filter_changed(const String &p_text);
+ void _sbox_input(const Ref<InputEvent> &p_ie);
void _member_selected();
void _member_unselected();
void _member_create();
diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index 5fdc725f50..09203a70a0 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -161,6 +161,7 @@ void ProgressDialog::_popup() {
main->set_margin(MARGIN_TOP, style->get_margin(MARGIN_TOP));
main->set_margin(MARGIN_BOTTOM, -style->get_margin(MARGIN_BOTTOM));
+ raise();
popup_centered(ms);
}
@@ -219,6 +220,8 @@ bool ProgressDialog::task_step(const String &p_task, const String &p_state, int
last_progress_tick = OS::get_singleton()->get_ticks_usec();
if (cancel_hb->is_visible()) {
OS::get_singleton()->force_process_input();
+ } else {
+ OS::get_singleton()->process_and_drop_events();
}
Main::iteration(); // this will not work on a lot of platforms, so it's only meant for the editor
return cancelled;
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 82a6a07805..b9cf7ec10a 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -631,6 +631,7 @@ void ProjectExportDialog::_delete_preset_confirm() {
int idx = presets->get_current();
_edit_preset(-1);
+ export_button->set_disabled(true);
EditorExport::get_singleton()->remove_export_preset(idx);
_update_presets();
}
@@ -931,7 +932,7 @@ void ProjectExportDialog::_export_project() {
Ref<EditorExportPlatform> platform = current->get_platform();
ERR_FAIL_COND(platform.is_null());
- export_project->set_access(FileDialog::ACCESS_FILESYSTEM);
+ export_project->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
export_project->clear_filters();
List<String> extension_list = platform->get_binary_extensions(current);
@@ -955,7 +956,7 @@ void ProjectExportDialog::_export_project() {
export_project->get_line_edit()->connect("text_entered", export_project, "_file_entered");
}
- export_project->set_mode(FileDialog::MODE_SAVE_FILE);
+ export_project->set_mode(EditorFileDialog::MODE_SAVE_FILE);
export_project->popup_centered_ratio();
}
@@ -1184,9 +1185,9 @@ ProjectExportDialog::ProjectExportDialog() {
patches_hb->add_child(patch_export);
patches_hb->add_spacer();
- patch_dialog = memnew(FileDialog);
+ patch_dialog = memnew(EditorFileDialog);
patch_dialog->add_filter("*.pck ; Pack File");
- patch_dialog->set_mode(FileDialog::MODE_OPEN_FILE);
+ patch_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
patch_dialog->connect("file_selected", this, "_patch_selected");
add_child(patch_dialog);
@@ -1266,11 +1267,11 @@ ProjectExportDialog::ProjectExportDialog() {
export_all_button->connect("pressed", this, "_export_all_dialog");
export_all_button->set_disabled(true);
- export_pck_zip = memnew(FileDialog);
+ export_pck_zip = memnew(EditorFileDialog);
export_pck_zip->add_filter("*.zip ; ZIP File");
export_pck_zip->add_filter("*.pck ; Godot Game Pack");
- export_pck_zip->set_access(FileDialog::ACCESS_FILESYSTEM);
- export_pck_zip->set_mode(FileDialog::MODE_SAVE_FILE);
+ export_pck_zip->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ export_pck_zip->set_mode(EditorFileDialog::MODE_SAVE_FILE);
add_child(export_pck_zip);
export_pck_zip->connect("file_selected", this, "_export_pck_zip_selected");
@@ -1300,8 +1301,8 @@ ProjectExportDialog::ProjectExportDialog() {
export_templates_error->add_child(download_templates);
download_templates->connect("pressed", this, "_open_export_template_manager");
- export_project = memnew(FileDialog);
- export_project->set_access(FileDialog::ACCESS_FILESYSTEM);
+ export_project = memnew(EditorFileDialog);
+ export_project->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
add_child(export_project);
export_project->connect("file_selected", this, "_export_project_to_path");
export_project->get_line_edit()->connect("text_changed", this, "_validate_export_path");
diff --git a/editor/project_export.h b/editor/project_export.h
index f8b6484477..476a30c9c0 100644
--- a/editor/project_export.h
+++ b/editor/project_export.h
@@ -90,7 +90,7 @@ private:
Tree *patches;
Button *patch_export;
int patch_index;
- FileDialog *patch_dialog;
+ EditorFileDialog *patch_dialog;
ConfirmationDialog *patch_erase;
Button *export_button;
@@ -139,8 +139,8 @@ private:
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
- FileDialog *export_pck_zip;
- FileDialog *export_project;
+ EditorFileDialog *export_pck_zip;
+ EditorFileDialog *export_project;
CheckBox *export_debug;
CheckBox *export_pck_zip_debug;
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 8473230758..1dca542138 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -892,10 +892,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
List<Node *>::Element *e = selection.front();
if (e) {
Node *node = e->get();
- if (node) {
- if (node && node->get_scene_inherited_state().is_valid()) {
- scene_tree->emit_signal("open", node->get_scene_inherited_state()->get_path());
- }
+ if (node && node->get_scene_inherited_state().is_valid()) {
+ scene_tree->emit_signal("open", node->get_scene_inherited_state()->get_path());
}
}
} break;
@@ -1942,7 +1940,13 @@ void SceneTreeDock::set_selected(Node *p_node, bool p_emit_selected) {
void SceneTreeDock::import_subscene() {
- import_subscene_dialog->popup_centered_ratio();
+ Size2 popup_size = Size2(500, 800) * editor_get_scale();
+ Size2 window_size = get_viewport_rect().size;
+
+ popup_size.x = MIN(window_size.x * 0.8, popup_size.x);
+ popup_size.y = MIN(window_size.y * 0.8, popup_size.y);
+
+ import_subscene_dialog->popup_centered(popup_size);
}
void SceneTreeDock::_import_subscene() {
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 2e06a903aa..f540b386aa 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -324,7 +324,6 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref
ERR_FAIL_COND(!spatial_node);
- ERR_FAIL_COND(!spatial_node);
Instance ins;
Ref<ArrayMesh> mesh = memnew(ArrayMesh);
@@ -1310,6 +1309,28 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
Ref<Material> material = get_material("camera_material", p_gizmo);
Ref<Material> icon = get_material("camera_icon", p_gizmo);
+#define ADD_TRIANGLE(m_a, m_b, m_c) \
+ { \
+ lines.push_back(m_a); \
+ lines.push_back(m_b); \
+ lines.push_back(m_b); \
+ lines.push_back(m_c); \
+ lines.push_back(m_c); \
+ lines.push_back(m_a); \
+ }
+
+#define ADD_QUAD(m_a, m_b, m_c, m_d) \
+ { \
+ lines.push_back(m_a); \
+ lines.push_back(m_b); \
+ lines.push_back(m_b); \
+ lines.push_back(m_c); \
+ lines.push_back(m_c); \
+ lines.push_back(m_d); \
+ lines.push_back(m_d); \
+ lines.push_back(m_a); \
+ }
+
switch (camera->get_projection()) {
case Camera::PROJECTION_PERSPECTIVE: {
@@ -1322,16 +1343,6 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
nside.x = -nside.x;
Vector3 up = Vector3(0, side.x, 0);
-#define ADD_TRIANGLE(m_a, m_b, m_c) \
- { \
- lines.push_back(m_a); \
- lines.push_back(m_b); \
- lines.push_back(m_b); \
- lines.push_back(m_c); \
- lines.push_back(m_c); \
- lines.push_back(m_a); \
- }
-
ADD_TRIANGLE(Vector3(), side + up, side - up);
ADD_TRIANGLE(Vector3(), nside + up, nside - up);
ADD_TRIANGLE(Vector3(), side + up, nside + up);
@@ -1346,17 +1357,6 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
} break;
case Camera::PROJECTION_ORTHOGONAL: {
-#define ADD_QUAD(m_a, m_b, m_c, m_d) \
- { \
- lines.push_back(m_a); \
- lines.push_back(m_b); \
- lines.push_back(m_b); \
- lines.push_back(m_c); \
- lines.push_back(m_c); \
- lines.push_back(m_d); \
- lines.push_back(m_d); \
- lines.push_back(m_a); \
- }
float size = camera->get_size();
float hsize = size * 0.5;
@@ -1369,6 +1369,7 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
ADD_QUAD(-up - right + back, -up + right + back, up + right + back, up - right + back);
ADD_QUAD(up + right, up + right + back, up - right + back, up - right);
ADD_QUAD(-up + right, -up + right + back, -up - right + back, -up - right);
+
handles.push_back(right + back);
right.x *= 0.25;
@@ -1376,8 +1377,30 @@ void CameraSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
ADD_TRIANGLE(tup, right + up + back, -right + up + back);
} break;
+ case Camera::PROJECTION_FRUSTUM: {
+ float hsize = camera->get_size() / 2.0;
+
+ Vector3 side = Vector3(hsize, 0, -camera->get_znear()).normalized();
+ Vector3 nside = side;
+ nside.x = -nside.x;
+ Vector3 up = Vector3(0, side.x, 0);
+ Vector3 offset = Vector3(camera->get_frustum_offset().x, camera->get_frustum_offset().y, 0.0);
+
+ ADD_TRIANGLE(Vector3(), side + up + offset, side - up + offset);
+ ADD_TRIANGLE(Vector3(), nside + up + offset, nside - up + offset);
+ ADD_TRIANGLE(Vector3(), side + up + offset, nside + up + offset);
+ ADD_TRIANGLE(Vector3(), side - up + offset, nside - up + offset);
+
+ side.x *= 0.25;
+ nside.x *= 0.25;
+ Vector3 tup(0, up.y * 3 / 2, side.z);
+ ADD_TRIANGLE(tup + offset, side + up + offset, nside + up + offset);
+ }
}
+#undef ADD_TRIANGLE
+#undef ADD_QUAD
+
p_gizmo->add_lines(lines, material);
p_gizmo->add_unscaled_billboard(icon, 0.05);
p_gizmo->add_handles(handles, get_material("handles"));
diff --git a/main/performance.cpp b/main/performance.cpp
index 2f7ebf7656..71cd94aeab 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -32,6 +32,7 @@
#include "core/message_queue.h"
#include "core/os/os.h"
+#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
#include "servers/audio_server.h"
#include "servers/physics_2d_server.h"
@@ -55,6 +56,7 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(OBJECT_COUNT);
BIND_ENUM_CONSTANT(OBJECT_RESOURCE_COUNT);
BIND_ENUM_CONSTANT(OBJECT_NODE_COUNT);
+ BIND_ENUM_CONSTANT(OBJECT_ORPHAN_NODE_COUNT);
BIND_ENUM_CONSTANT(RENDER_OBJECTS_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_VERTICES_IN_FRAME);
BIND_ENUM_CONSTANT(RENDER_MATERIAL_CHANGES_IN_FRAME);
@@ -76,6 +78,14 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(MONITOR_MAX);
}
+float Performance::_get_node_count() const {
+ MainLoop *ml = OS::get_singleton()->get_main_loop();
+ SceneTree *sml = Object::cast_to<SceneTree>(ml);
+ if (!sml)
+ return 0;
+ return sml->get_node_count();
+}
+
String Performance::get_monitor_name(Monitor p_monitor) const {
ERR_FAIL_INDEX_V(p_monitor, MONITOR_MAX, String());
@@ -92,6 +102,7 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"object/objects",
"object/resources",
"object/nodes",
+ "object/orphan_nodes",
"raster/objects_drawn",
"raster/vertices_drawn",
"raster/mat_changes",
@@ -128,14 +139,8 @@ float Performance::get_monitor(Monitor p_monitor) const {
case MEMORY_MESSAGE_BUFFER_MAX: return MessageQueue::get_singleton()->get_max_buffer_usage();
case OBJECT_COUNT: return ObjectDB::get_object_count();
case OBJECT_RESOURCE_COUNT: return ResourceCache::get_cached_resource_count();
- case OBJECT_NODE_COUNT: {
-
- MainLoop *ml = OS::get_singleton()->get_main_loop();
- SceneTree *sml = Object::cast_to<SceneTree>(ml);
- if (!sml)
- return 0;
- return sml->get_node_count();
- };
+ case OBJECT_NODE_COUNT: return _get_node_count();
+ case OBJECT_ORPHAN_NODE_COUNT: return Node::orphan_node_count;
case RENDER_OBJECTS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_OBJECTS_IN_FRAME);
case RENDER_VERTICES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_VERTICES_IN_FRAME);
case RENDER_MATERIAL_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_MATERIAL_CHANGES_IN_FRAME);
@@ -183,6 +188,7 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_QUANTITY,
+ MONITOR_TYPE_QUANTITY,
MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY,
MONITOR_TYPE_MEMORY,
diff --git a/main/performance.h b/main/performance.h
index 850c4c2d52..912e005c53 100644
--- a/main/performance.h
+++ b/main/performance.h
@@ -43,6 +43,8 @@ class Performance : public Object {
static Performance *singleton;
static void _bind_methods();
+ float _get_node_count() const;
+
float _process_time;
float _physics_process_time;
@@ -60,6 +62,7 @@ public:
OBJECT_COUNT,
OBJECT_RESOURCE_COUNT,
OBJECT_NODE_COUNT,
+ OBJECT_ORPHAN_NODE_COUNT,
RENDER_OBJECTS_IN_FRAME,
RENDER_VERTICES_IN_FRAME,
RENDER_MATERIAL_CHANGES_IN_FRAME,
diff --git a/methods.py b/methods.py
index ec9ecdb17f..11efd68ce4 100644
--- a/methods.py
+++ b/methods.py
@@ -24,10 +24,16 @@ def disable_warnings(self):
# We have to remove existing warning level defines before appending /w,
# otherwise we get: "warning D9025 : overriding '/W3' with '/w'"
warn_flags = ['/Wall', '/W4', '/W3', '/W2', '/W1', '/WX']
- self['CCFLAGS'] = [x for x in self['CCFLAGS'] if not x in warn_flags]
self.Append(CCFLAGS=['/w'])
+ self.Append(CFLAGS=['/w'])
+ self.Append(CPPFLAGS=['/w'])
+ self['CCFLAGS'] = [x for x in self['CCFLAGS'] if not x in warn_flags]
+ self['CFLAGS'] = [x for x in self['CFLAGS'] if not x in warn_flags]
+ self['CXXFLAGS'] = [x for x in self['CXXFLAGS'] if not x in warn_flags]
else:
self.Append(CCFLAGS=['-w'])
+ self.Append(CFLAGS=['-w'])
+ self.Append(CXXFLAGS=['-w'])
def add_module_version_string(self,s):
@@ -211,70 +217,6 @@ def win32_spawn(sh, escape, cmd, args, spawnenv):
return exit_code
"""
-def android_add_flat_dir(self, dir):
- if (dir not in self.android_flat_dirs):
- self.android_flat_dirs.append(dir)
-
-def android_add_maven_repository(self, url):
- if (url not in self.android_maven_repos):
- self.android_maven_repos.append(url)
-
-def android_add_dependency(self, depline):
- if (depline not in self.android_dependencies):
- self.android_dependencies.append(depline)
-
-def android_add_java_dir(self, subpath):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
- if (base_path not in self.android_java_dirs):
- self.android_java_dirs.append(base_path)
-
-def android_add_res_dir(self, subpath):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
- if (base_path not in self.android_res_dirs):
- self.android_res_dirs.append(base_path)
-
-def android_add_asset_dir(self, subpath):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
- if (base_path not in self.android_asset_dirs):
- self.android_asset_dirs.append(base_path)
-
-def android_add_aidl_dir(self, subpath):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
- if (base_path not in self.android_aidl_dirs):
- self.android_aidl_dirs.append(base_path)
-
-def android_add_jni_dir(self, subpath):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
- if (base_path not in self.android_jni_dirs):
- self.android_jni_dirs.append(base_path)
-
-def android_add_gradle_plugin(self, plugin):
- if (plugin not in self.android_gradle_plugins):
- self.android_gradle_plugins.append(plugin)
-
-def android_add_gradle_classpath(self, classpath):
- if (classpath not in self.android_gradle_classpath):
- self.android_gradle_classpath.append(classpath)
-
-def android_add_default_config(self, config):
- if (config not in self.android_default_config):
- self.android_default_config.append(config)
-
-def android_add_to_manifest(self, file):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file
- with open(base_path, "r") as f:
- self.android_manifest_chunk += f.read()
-
-def android_add_to_permissions(self, file):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file
- with open(base_path, "r") as f:
- self.android_permission_chunk += f.read()
-
-def android_add_to_attributes(self, file):
- base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file
- with open(base_path, "r") as f:
- self.android_appattributes_chunk += f.read()
-
def disable_module(self):
self.disabled_modules.append(self.current_module)
diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp
index 0330ab4604..8d82fb2eeb 100644
--- a/modules/assimp/editor_scene_importer_assimp.cpp
+++ b/modules/assimp/editor_scene_importer_assimp.cpp
@@ -126,8 +126,8 @@ Node *EditorSceneImporterAssimp::import_scene(const String &p_path, uint32_t p_f
int32_t post_process_Steps = aiProcess_CalcTangentSpace |
//aiProcess_FlipUVs |
//aiProcess_FlipWindingOrder |
- aiProcess_DropNormals |
- aiProcess_GenSmoothNormals |
+ //aiProcess_DropNormals |
+ //aiProcess_GenSmoothNormals |
aiProcess_JoinIdenticalVertices |
aiProcess_ImproveCacheLocality |
aiProcess_LimitBoneWeights |
diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp
index a8172c7f52..509b30c7e6 100644
--- a/modules/bmp/image_loader_bmp.cpp
+++ b/modules/bmp/image_loader_bmp.cpp
@@ -46,11 +46,11 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
size_t height = (size_t)p_header.bmp_info_header.bmp_height;
size_t bits_per_pixel = (size_t)p_header.bmp_info_header.bmp_bit_count;
- if (p_header.bmp_info_header.bmp_compression != 0) {
+ if (p_header.bmp_info_header.bmp_compression != BI_RGB) {
err = FAILED;
}
- if (!(bits_per_pixel == 24 || bits_per_pixel == 32)) {
+ if (!(bits_per_pixel == 8 || bits_per_pixel == 24 || bits_per_pixel == 32)) {
err = FAILED;
}
@@ -67,11 +67,26 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
PoolVector<uint8_t>::Write image_data_w = image_data.write();
uint8_t *write_buffer = image_data_w.ptr();
+ const uint32_t color_index_max = p_header.bmp_info_header.bmp_colors_used - 1;
const uint8_t *line = p_buffer + (line_width * (height - 1));
for (unsigned int i = 0; i < height; i++) {
const uint8_t *line_ptr = line;
for (unsigned int j = 0; j < width; j++) {
switch (bits_per_pixel) {
+ case 8: {
+ uint8_t color_index = CLAMP(*line_ptr, 0, color_index_max);
+ uint32_t color = 0x000000;
+
+ if (p_color_buffer != NULL)
+ color = ((uint32_t *)p_color_buffer)[color_index];
+
+ write_buffer[index + 2] = color & 0xff;
+ write_buffer[index + 1] = (color >> 8) & 0xff;
+ write_buffer[index + 0] = (color >> 16) & 0xff;
+ write_buffer[index + 3] = 0xff;
+ index += 4;
+ line_ptr += 1;
+ } break;
case 24: {
uint32_t color = *((uint32_t *)line_ptr);
@@ -108,7 +123,12 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
bmp_header_s bmp_header;
Error err = ERR_INVALID_DATA;
- if (f->get_len() > sizeof(bmp_header)) {
+ static const size_t FILE_HEADER_SIZE = 14;
+ static const size_t INFO_HEADER_SIZE = 40;
+
+ // A valid bmp file should always at least have a
+ // file header and a minimal info header
+ if (f->get_len() > FILE_HEADER_SIZE + INFO_HEADER_SIZE) {
// File Header
bmp_header.bmp_file_header.bmp_signature = f->get_16();
if (bmp_header.bmp_file_header.bmp_signature == BITMAP_SIGNATURE) {
@@ -129,35 +149,27 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
bmp_header.bmp_info_header.bmp_colors_used = f->get_32();
bmp_header.bmp_info_header.bmp_important_colors = f->get_32();
- bmp_header.bmp_info_header.bmp_red_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_green_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_blue_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_alpha_mask = f->get_32();
- bmp_header.bmp_info_header.bmp_cs_type = f->get_32();
- for (int i = 0; i < 9; i++)
- bmp_header.bmp_info_header.bmp_endpoints[i] = f->get_32();
-
- bmp_header.bmp_info_header.bmp_gamma_red = f->get_32();
- bmp_header.bmp_info_header.bmp_gamma_green = f->get_32();
- bmp_header.bmp_info_header.bmp_gamma_blue = f->get_32();
+ // Compressed bitmaps not supported, stop parsing
+ if (bmp_header.bmp_info_header.bmp_compression != BI_RGB) {
+ ERR_EXPLAIN("Unsupported bmp file: " + f->get_path());
+ f->close();
+ ERR_FAIL_V(err)
+ }
- f->seek(sizeof(bmp_header.bmp_file_header) +
+ f->seek(FILE_HEADER_SIZE +
bmp_header.bmp_info_header.bmp_header_size);
- uint32_t color_table_size = 0;
- if (bmp_header.bmp_info_header.bmp_bit_count == 1)
- color_table_size = 2;
- else if (bmp_header.bmp_info_header.bmp_bit_count == 4)
- color_table_size = 16;
- else if (bmp_header.bmp_info_header.bmp_bit_count == 8)
- color_table_size = 256;
+ if (bmp_header.bmp_info_header.bmp_bit_count < 16 && bmp_header.bmp_info_header.bmp_colors_used == 0)
+ bmp_header.bmp_info_header.bmp_colors_used = 1 << bmp_header.bmp_info_header.bmp_bit_count;
+
+ // Color table is usually 4 bytes per color -> [B][G][R][0]
+ uint32_t color_table_size = bmp_header.bmp_info_header.bmp_colors_used * 4;
PoolVector<uint8_t> bmp_color_table;
if (color_table_size > 0) {
- err = bmp_color_table.resize(color_table_size * 4);
+ err = bmp_color_table.resize(color_table_size);
PoolVector<uint8_t>::Write bmp_color_table_w = bmp_color_table.write();
- f->get_buffer(bmp_color_table_w.ptr(),
- bmp_header.bmp_info_header.bmp_colors_used * 4);
+ f->get_buffer(bmp_color_table_w.ptr(), color_table_size);
}
f->seek(bmp_header.bmp_file_header.bmp_file_offset);
diff --git a/modules/bmp/image_loader_bmp.h b/modules/bmp/image_loader_bmp.h
index d6899061d0..b27a47d402 100644
--- a/modules/bmp/image_loader_bmp.h
+++ b/modules/bmp/image_loader_bmp.h
@@ -37,6 +37,19 @@ class ImageLoaderBMP : public ImageFormatLoader {
protected:
static const unsigned BITMAP_SIGNATURE = 0x4d42;
+ enum bmp_compression_s {
+ BI_RGB = 0x00,
+ BI_RLE8 = 0x01,
+ BI_RLE4 = 0x02,
+ BI_BITFIELDS = 0x03,
+ BI_JPEG = 0x04,
+ BI_PNG = 0x05,
+ BI_ALPHABITFIELDS = 0x06,
+ BI_CMYK = 0x0b,
+ BI_CMYKRLE8 = 0x0c,
+ BI_CMYKRLE4 = 0x0d
+ };
+
struct bmp_header_s {
struct bmp_file_header_s {
uint16_t bmp_signature;
@@ -57,15 +70,6 @@ protected:
uint32_t bmp_pixels_per_meter_y;
uint32_t bmp_colors_used;
uint32_t bmp_important_colors;
- uint32_t bmp_red_mask;
- uint32_t bmp_green_mask;
- uint32_t bmp_blue_mask;
- uint32_t bmp_alpha_mask;
- uint32_t bmp_cs_type;
- uint32_t bmp_endpoints[9];
- uint32_t bmp_gamma_red;
- uint32_t bmp_gamma_green;
- uint32_t bmp_gamma_blue;
} bmp_info_header;
};
diff --git a/modules/bullet/SCsub b/modules/bullet/SCsub
index 7e714ba43f..e7c2fff54c 100644
--- a/modules/bullet/SCsub
+++ b/modules/bullet/SCsub
@@ -188,7 +188,7 @@ if env['builtin_bullet']:
env_bullet.Append(CPPPATH=[thirdparty_dir])
# if env['target'] == "debug" or env['target'] == "release_debug":
- # env_bullet.Append(CCFLAGS=['-DBT_DEBUG'])
+ # env_bullet.Append(CPPFLAGS=['-DBT_DEBUG'])
env_thirdparty = env_bullet.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 22f2214898..e5f70a0b34 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -597,6 +597,8 @@ void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant
if (!can_sleep) {
// Can't sleep
btBody->forceActivationState(DISABLE_DEACTIVATION);
+ } else {
+ btBody->forceActivationState(ACTIVE_TAG);
}
break;
}
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 775ec67ba6..e70773d914 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -724,6 +724,7 @@ CSGBrush *CSGMesh::_build_brush() {
PoolVector<bool> smooth;
PoolVector<Ref<Material> > materials;
PoolVector<Vector2> uvs;
+ Ref<Material> material = get_material();
for (int i = 0; i < mesh->get_surface_count(); i++) {
@@ -760,7 +761,12 @@ CSGBrush *CSGMesh::_build_brush() {
uvr_used = true;
}
- Ref<Material> mat = mesh->surface_get_material(i);
+ Ref<Material> mat;
+ if (material.is_valid()) {
+ mat = material;
+ } else {
+ mat = mesh->surface_get_material(i);
+ }
PoolVector<int> aindices = arrays[Mesh::ARRAY_INDEX];
if (aindices.size()) {
@@ -866,6 +872,18 @@ void CSGMesh::_mesh_changed() {
update_gizmo();
}
+void CSGMesh::set_material(const Ref<Material> &p_material) {
+ if (material == p_material)
+ return;
+ material = p_material;
+ _make_dirty();
+}
+
+Ref<Material> CSGMesh::get_material() const {
+
+ return material;
+}
+
void CSGMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_mesh", "mesh"), &CSGMesh::set_mesh);
@@ -873,7 +891,11 @@ void CSGMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("_mesh_changed"), &CSGMesh::_mesh_changed);
+ ClassDB::bind_method(D_METHOD("set_material", "material"), &CSGMesh::set_material);
+ ClassDB::bind_method(D_METHOD("get_material"), &CSGMesh::get_material);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "SpatialMaterial,ShaderMaterial"), "set_material", "get_material");
}
void CSGMesh::set_mesh(const Ref<Mesh> &p_mesh) {
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index 1622fb3a15..a5b2238e6b 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -38,8 +38,8 @@
#include "scene/resources/concave_polygon_shape.h"
#include "thirdparty/misc/mikktspace.h"
-class CSGShape : public VisualInstance {
- GDCLASS(CSGShape, VisualInstance);
+class CSGShape : public GeometryInstance {
+ GDCLASS(CSGShape, GeometryInstance);
public:
enum Operation {
@@ -187,6 +187,7 @@ class CSGMesh : public CSGPrimitive {
virtual CSGBrush *_build_brush();
Ref<Mesh> mesh;
+ Ref<Material> material;
void _mesh_changed();
@@ -196,6 +197,9 @@ protected:
public:
void set_mesh(const Ref<Mesh> &p_mesh);
Ref<Mesh> get_mesh();
+
+ void set_material(const Ref<Material> &p_material);
+ Ref<Material> get_material() const;
};
class CSGSphere : public CSGPrimitive {
diff --git a/modules/csg/doc_classes/CSGCylinder.xml b/modules/csg/doc_classes/CSGCylinder.xml
index 9adcbc4502..24c3f8ba2e 100644
--- a/modules/csg/doc_classes/CSGCylinder.xml
+++ b/modules/csg/doc_classes/CSGCylinder.xml
@@ -12,7 +12,7 @@
</methods>
<members>
<member name="cone" type="bool" setter="set_cone" getter="is_cone">
- If true a cone is created, the [member radius] will only apply to one side.
+ If [code]true[/code] a cone is created, the [member radius] will only apply to one side.
</member>
<member name="height" type="float" setter="set_height" getter="get_height">
The height of the cylinder.
@@ -27,7 +27,7 @@
The number of sides of the cylinder, the higher this number the more detail there will be in the cylinder.
</member>
<member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces">
- If true the normals of the cylinder are set to give a smooth effect making the cylinder seem rounded. When false the cylinder will have a flat shaded look.
+ If [code]true[/code] the normals of the cylinder are set to give a smooth effect making the cylinder seem rounded. If [code]false[/code] the cylinder will have a flat shaded look.
</member>
</members>
<constants>
diff --git a/modules/csg/doc_classes/CSGMesh.xml b/modules/csg/doc_classes/CSGMesh.xml
index c1f04d724a..afe0bc262d 100644
--- a/modules/csg/doc_classes/CSGMesh.xml
+++ b/modules/csg/doc_classes/CSGMesh.xml
@@ -11,6 +11,8 @@
<methods>
</methods>
<members>
+ <member name="material" type="Material" setter="set_material" getter="get_material">
+ </member>
<member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
The mesh resource to use as a CSG shape.
</member>
diff --git a/modules/csg/doc_classes/CSGPolygon.xml b/modules/csg/doc_classes/CSGPolygon.xml
index 931c7cba51..2c5d298222 100644
--- a/modules/csg/doc_classes/CSGPolygon.xml
+++ b/modules/csg/doc_classes/CSGPolygon.xml
@@ -21,16 +21,16 @@
Extrusion mode.
</member>
<member name="path_continuous_u" type="bool" setter="set_path_continuous_u" getter="is_path_continuous_u">
- If true the u component of our uv will continuously increase in unison with the distance traveled along our path when [member mode] is [constant MODE_PATH].
+ If [code]true[/code] the u component of our uv will continuously increase in unison with the distance traveled along our path when [member mode] is [constant MODE_PATH].
</member>
<member name="path_interval" type="float" setter="set_path_interval" getter="get_path_interval">
Interval at which a new extrusion slice is added along the path when [member mode] is [constant MODE_PATH].
</member>
<member name="path_joined" type="bool" setter="set_path_joined" getter="is_path_joined">
- If true the start and end of our path are joined together ensuring there is no seam when [member mode] is [constant MODE_PATH].
+ If [code]true[/code] the start and end of our path are joined together ensuring there is no seam when [member mode] is [constant MODE_PATH].
</member>
<member name="path_local" type="bool" setter="set_path_local" getter="is_path_local">
- If false we extrude centered on our path, if true we extrude in relation to the position of our CSGPolygon when [member mode] is [constant MODE_PATH].
+ If [code]false[/code] we extrude centered on our path, if [code]true[/code] we extrude in relation to the position of our CSGPolygon when [member mode] is [constant MODE_PATH].
</member>
<member name="path_node" type="NodePath" setter="set_path_node" getter="get_path_node">
The [Shape] object containing the path along which we extrude when [member mode] is [constant MODE_PATH].
diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml
index 152a8cd3bc..7fa7c78534 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.2">
+<class name="CSGShape" inherits="GeometryInstance" category="Core" version="3.2">
<brief_description>
The CSG base class.
</brief_description>
@@ -37,7 +37,7 @@
<return type="bool">
</return>
<description>
- Returns true if this is a root shape and is thus the object that is rendered.
+ Returns [code]true[/code] if this is a root shape and is thus the object that is rendered.
</description>
</method>
<method name="set_collision_layer_bit">
diff --git a/modules/csg/doc_classes/CSGSphere.xml b/modules/csg/doc_classes/CSGSphere.xml
index 5fe55996e5..2a12cf84db 100644
--- a/modules/csg/doc_classes/CSGSphere.xml
+++ b/modules/csg/doc_classes/CSGSphere.xml
@@ -24,7 +24,7 @@
Number of horizontal slices for the sphere.
</member>
<member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces">
- If true the normals of the sphere are set to give a smooth effect making the sphere seem rounded. When false the sphere will have a flat shaded look.
+ If [code]true[/code] the normals of the sphere are set to give a smooth effect making the sphere seem rounded. If [code]false[/code] the sphere will have a flat shaded look.
</member>
</members>
<constants>
diff --git a/modules/csg/doc_classes/CSGTorus.xml b/modules/csg/doc_classes/CSGTorus.xml
index e438b9e405..0d4437d87f 100644
--- a/modules/csg/doc_classes/CSGTorus.xml
+++ b/modules/csg/doc_classes/CSGTorus.xml
@@ -27,7 +27,7 @@
The number of slices the torus is constructed of.
</member>
<member name="smooth_faces" type="bool" setter="set_smooth_faces" getter="get_smooth_faces">
- If true the normals of the torus are set to give a smooth effect making the torus seem rounded. When false the torus will have a flat shaded look.
+ If [code]true[/code] the normals of the torus are set to give a smooth effect making the torus seem rounded. If [code]false[/code] the torus will have a flat shaded look.
</member>
</members>
<constants>
diff --git a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
index cecf08e9a5..894c17c684 100644
--- a/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
+++ b/modules/enet/doc_classes/NetworkedMultiplayerENet.xml
@@ -60,7 +60,7 @@
<argument index="1" name="now" type="bool" default="false">
</argument>
<description>
- Disconnect the given peer. If "now" is set to true, the connection will be closed immediately without flushing queued messages.
+ Disconnect the given peer. If "now" is set to [code]true[/code], the connection will be closed immediately without flushing queued messages.
</description>
</method>
<method name="get_last_packet_channel" qualifiers="const">
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index 193f1bb48d..492b365128 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -346,11 +346,10 @@ void NetworkedMultiplayerENet::poll() {
uint32_t *id = (uint32_t *)event.peer->data;
- ERR_CONTINUE(event.packet->dataLength < 12)
+ ERR_CONTINUE(event.packet->dataLength < 8)
uint32_t source = decode_uint32(&event.packet->data[0]);
int target = decode_uint32(&event.packet->data[4]);
- uint32_t flags = decode_uint32(&event.packet->data[8]);
packet.from = source;
packet.channel = event.channelID;
@@ -371,7 +370,7 @@ void NetworkedMultiplayerENet::poll() {
if (uint32_t(E->key()) == source) // Do not resend to self
continue;
- ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, flags);
+ ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags);
enet_peer_send(E->get(), event.channelID, packet2);
}
@@ -385,7 +384,7 @@ void NetworkedMultiplayerENet::poll() {
if (uint32_t(E->key()) == source || E->key() == -target) // Do not resend to self, also do not send to excluded
continue;
- ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, flags);
+ ENetPacket *packet2 = enet_packet_create(packet.packet->data, packet.packet->dataLength, packet.packet->flags);
enet_peer_send(E->get(), event.channelID, packet2);
}
@@ -503,8 +502,8 @@ Error NetworkedMultiplayerENet::get_packet(const uint8_t **r_buffer, int &r_buff
current_packet = incoming_packets.front()->get();
incoming_packets.pop_front();
- *r_buffer = (const uint8_t *)(&current_packet.packet->data[12]);
- r_buffer_size = current_packet.packet->dataLength - 12;
+ *r_buffer = (const uint8_t *)(&current_packet.packet->data[8]);
+ r_buffer_size = current_packet.packet->dataLength - 8;
return OK;
}
@@ -549,11 +548,10 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer
}
}
- ENetPacket *packet = enet_packet_create(NULL, p_buffer_size + 12, packet_flags);
+ ENetPacket *packet = enet_packet_create(NULL, p_buffer_size + 8, packet_flags);
encode_uint32(unique_id, &packet->data[0]); // Source ID
encode_uint32(target_peer, &packet->data[4]); // Dest ID
- encode_uint32(packet_flags, &packet->data[8]); // Dest ID
- copymem(&packet->data[12], p_buffer, p_buffer_size);
+ copymem(&packet->data[8], p_buffer, p_buffer_size);
if (server) {
diff --git a/modules/etc/SCsub b/modules/etc/SCsub
index 6e963ef766..eb2738053b 100644
--- a/modules/etc/SCsub
+++ b/modules/etc/SCsub
@@ -31,7 +31,7 @@ env_etc.Append(CPPPATH=[thirdparty_dir])
# upstream uses c++11
if not env.msvc:
- env_etc.Append(CCFLAGS="-std=c++11")
+ env_etc.Append(CXXFLAGS="-std=c++11")
env_thirdparty = env_etc.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index c2d165f367..f2cd9f9a60 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -72,9 +72,9 @@ if env['builtin_freetype']:
# Also needed in main env for scene/
env.Append(CPPPATH=[thirdparty_dir + "/include"])
- env_freetype.Append(CCFLAGS=['-DFT2_BUILD_LIBRARY', '-DFT_CONFIG_OPTION_USE_PNG'])
+ env_freetype.Append(CPPFLAGS=['-DFT2_BUILD_LIBRARY', '-DFT_CONFIG_OPTION_USE_PNG'])
if (env['target'] != 'release'):
- env_freetype.Append(CCFLAGS=['-DZLIB_DEBUG'])
+ env_freetype.Append(CPPFLAGS=['-DZLIB_DEBUG'])
# Also requires libpng headers
if env['builtin_libpng']:
@@ -100,4 +100,4 @@ if env['builtin_freetype']:
# Godot source files
env_freetype.add_source_files(env.modules_sources, "*.cpp")
# Used in scene/, needs to be in main env
-env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
+env.Append(CPPFLAGS=['-DFREETYPE_ENABLED'])
diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
index 8fcebe7855..9bb1186269 100644
--- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp
+++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp
@@ -61,8 +61,8 @@ int64_t GDAPI godot_videodecoder_file_seek(void *ptr, int64_t pos, int whence) {
// file
FileAccess *file = reinterpret_cast<FileAccess *>(ptr);
- size_t len = file->get_len();
if (file) {
+ size_t len = file->get_len();
switch (whence) {
case SEEK_SET: {
// Just for explicitness
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index df8fc2267d..ab34184bfb 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -3008,8 +3008,8 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
}
}
}
+ base_type = base_type.class_type->base_type;
}
- base_type = base_type.class_type->base_type;
} break;
case GDScriptParser::DataType::SCRIPT:
case GDScriptParser::DataType::GDSCRIPT: {
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 36503af4d7..b8048fb5dd 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -896,7 +896,7 @@ void GDScriptTokenizerText::_advance() {
}
hexa_found = true;
} else if (!hexa_found && GETCHAR(i) == 'e') {
- if (hexa_found || exponent_found) {
+ if (exponent_found) {
_make_error("Invalid numeric constant at 'e'");
return;
}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index fe7ced060d..259c0ffece 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -38,7 +38,6 @@
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/os/os.h"
-#include "core/string_builder.h"
#include "core/ucaps.h"
#include "../glue/cs_compressed.gen.h"
@@ -757,47 +756,47 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
}
}
-void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
+void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
// Constants (in partial GD class)
- p_output.push_back("\n#pragma warning disable CS1591 // Disable warning: "
- "'Missing XML comment for publicly visible type or member'\n");
+ p_output.append("\n#pragma warning disable CS1591 // Disable warning: "
+ "'Missing XML comment for publicly visible type or member'\n");
- p_output.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
- p_output.push_back(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{");
+ p_output.append("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ p_output.append(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{");
for (const List<ConstantInterface>::Element *E = global_constants.front(); E; E = E->next()) {
const ConstantInterface &iconstant = E->get();
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), NULL);
- Vector<String> summary_lines = xml_summary.split("\n");
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
if (summary_lines.size()) {
- p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ p_output.append(MEMBER_BEGIN "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
- p_output.push_back(INDENT2 "/// ");
- p_output.push_back(summary_lines[i]);
- p_output.push_back("\n");
+ p_output.append(INDENT2 "/// ");
+ p_output.append(summary_lines[i]);
+ p_output.append("\n");
}
- p_output.push_back(INDENT2 "/// </summary>");
+ p_output.append(INDENT2 "/// </summary>");
}
}
- p_output.push_back(MEMBER_BEGIN "public const int ");
- p_output.push_back(iconstant.proxy_name);
- p_output.push_back(" = ");
- p_output.push_back(itos(iconstant.value));
- p_output.push_back(";");
+ p_output.append(MEMBER_BEGIN "public const int ");
+ p_output.append(iconstant.proxy_name);
+ p_output.append(" = ");
+ p_output.append(itos(iconstant.value));
+ p_output.append(";");
}
if (!global_constants.empty())
- p_output.push_back("\n");
+ p_output.append("\n");
- p_output.push_back(INDENT1 CLOSE_BLOCK); // end of GD class
+ p_output.append(INDENT1 CLOSE_BLOCK); // end of GD class
// Enums
@@ -821,51 +820,51 @@ void BindingsGenerator::_generate_global_constants(List<String> &p_output) {
WARN_PRINTS("Declaring global enum `" + enum_proxy_name + "` inside static class `" + enum_class_name + "`");
}
- p_output.push_back("\n" INDENT1 "public static partial class ");
- p_output.push_back(enum_class_name);
- p_output.push_back("\n" INDENT1 OPEN_BLOCK);
+ p_output.append("\n" INDENT1 "public static partial class ");
+ p_output.append(enum_class_name);
+ p_output.append("\n" INDENT1 OPEN_BLOCK);
}
- p_output.push_back("\n" INDENT1 "public enum ");
- p_output.push_back(enum_proxy_name);
- p_output.push_back("\n" INDENT1 OPEN_BLOCK);
+ p_output.append("\n" INDENT1 "public enum ");
+ p_output.append(enum_proxy_name);
+ p_output.append("\n" INDENT1 OPEN_BLOCK);
for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
const ConstantInterface &iconstant = F->get();
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), NULL);
- Vector<String> summary_lines = xml_summary.split("\n");
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
if (summary_lines.size()) {
- p_output.push_back(INDENT2 "/// <summary>\n");
+ p_output.append(INDENT2 "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
- p_output.push_back(INDENT2 "/// ");
- p_output.push_back(summary_lines[i]);
- p_output.push_back("\n");
+ p_output.append(INDENT2 "/// ");
+ p_output.append(summary_lines[i]);
+ p_output.append("\n");
}
- p_output.push_back(INDENT2 "/// </summary>\n");
+ p_output.append(INDENT2 "/// </summary>\n");
}
}
- p_output.push_back(INDENT2);
- p_output.push_back(iconstant.proxy_name);
- p_output.push_back(" = ");
- p_output.push_back(itos(iconstant.value));
- p_output.push_back(F != ienum.constants.back() ? ",\n" : "\n");
+ p_output.append(INDENT2);
+ p_output.append(iconstant.proxy_name);
+ p_output.append(" = ");
+ p_output.append(itos(iconstant.value));
+ p_output.append(F != ienum.constants.back() ? ",\n" : "\n");
}
- p_output.push_back(INDENT1 CLOSE_BLOCK);
+ p_output.append(INDENT1 CLOSE_BLOCK);
if (enum_in_static_class)
- p_output.push_back(INDENT1 CLOSE_BLOCK);
+ p_output.append(INDENT1 CLOSE_BLOCK);
}
- p_output.push_back(CLOSE_BLOCK); // end of namespace
+ p_output.append(CLOSE_BLOCK); // end of namespace
- p_output.push_back("\n#pragma warning restore CS1591\n");
+ p_output.append("\n#pragma warning restore CS1591\n");
}
Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir, DotNetSolution &r_solution, bool p_verbose_output) {
@@ -893,7 +892,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir,
// Generate source file for global scope constants and enums
{
- List<String> constants_source;
+ StringBuilder constants_source;
_generate_global_constants(constants_source);
String output_file = path_join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs");
Error save_err = _save_file(output_file, constants_source);
@@ -951,28 +950,28 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir,
compile_items.push_back(output_file);
}
- List<String> cs_icalls_content;
-
- cs_icalls_content.push_back("using System;\n"
- "using System.Runtime.CompilerServices;\n"
- "\n");
- cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
- cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK);
-
- cs_icalls_content.push_back(MEMBER_BEGIN "internal static ulong godot_api_hash = ");
- cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n");
- cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint bindings_version = ");
- cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n");
- cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint cs_glue_version = ");
- cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n");
-
-#define ADD_INTERNAL_CALL(m_icall) \
- if (!m_icall.editor_only) { \
- cs_icalls_content.push_back(MEMBER_BEGIN "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
- cs_icalls_content.push_back(INDENT2 "internal extern static "); \
- cs_icalls_content.push_back(m_icall.im_type_out + " "); \
- cs_icalls_content.push_back(m_icall.name + "("); \
- cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
+ StringBuilder cs_icalls_content;
+
+ cs_icalls_content.append("using System;\n"
+ "using System.Runtime.CompilerServices;\n"
+ "\n");
+ cs_icalls_content.append("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ cs_icalls_content.append(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK);
+
+ cs_icalls_content.append(MEMBER_BEGIN "internal static ulong godot_api_hash = ");
+ cs_icalls_content.append(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n");
+ cs_icalls_content.append(MEMBER_BEGIN "internal static uint bindings_version = ");
+ cs_icalls_content.append(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n");
+ cs_icalls_content.append(MEMBER_BEGIN "internal static uint cs_glue_version = ");
+ cs_icalls_content.append(String::num_uint64(CS_GLUE_VERSION) + ";\n");
+
+#define ADD_INTERNAL_CALL(m_icall) \
+ if (!m_icall.editor_only) { \
+ cs_icalls_content.append(MEMBER_BEGIN "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
+ cs_icalls_content.append(INDENT2 "internal extern static "); \
+ cs_icalls_content.append(m_icall.im_type_out + " "); \
+ cs_icalls_content.append(m_icall.name + "("); \
+ cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next())
@@ -982,7 +981,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_solution_dir,
#undef ADD_INTERNAL_CALL
- cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
+ cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs");
@@ -1049,29 +1048,29 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir
compile_items.push_back(output_file);
}
- List<String> cs_icalls_content;
-
- cs_icalls_content.push_back("using System;\n"
- "using System.Runtime.CompilerServices;\n"
- "\n");
- cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
- cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK);
-
- cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = ");
- cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + ";\n");
- cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = ");
- cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n");
- cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = ");
- cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n");
- cs_icalls_content.push_back("\n");
-
-#define ADD_INTERNAL_CALL(m_icall) \
- if (m_icall.editor_only) { \
- cs_icalls_content.push_back(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
- cs_icalls_content.push_back(INDENT2 "internal extern static "); \
- cs_icalls_content.push_back(m_icall.im_type_out + " "); \
- cs_icalls_content.push_back(m_icall.name + "("); \
- cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
+ StringBuilder cs_icalls_content;
+
+ cs_icalls_content.append("using System;\n"
+ "using System.Runtime.CompilerServices;\n"
+ "\n");
+ cs_icalls_content.append("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ cs_icalls_content.append(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK);
+
+ cs_icalls_content.append(INDENT2 "internal static ulong godot_api_hash = ");
+ cs_icalls_content.append(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + ";\n");
+ cs_icalls_content.append(INDENT2 "internal static uint bindings_version = ");
+ cs_icalls_content.append(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n");
+ cs_icalls_content.append(INDENT2 "internal static uint cs_glue_version = ");
+ cs_icalls_content.append(String::num_uint64(CS_GLUE_VERSION) + ";\n");
+ cs_icalls_content.append("\n");
+
+#define ADD_INTERNAL_CALL(m_icall) \
+ if (m_icall.editor_only) { \
+ cs_icalls_content.append(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
+ cs_icalls_content.append(INDENT2 "internal extern static "); \
+ cs_icalls_content.append(m_icall.im_type_out + " "); \
+ cs_icalls_content.append(m_icall.name + "("); \
+ cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
@@ -1081,7 +1080,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_solution_dir
#undef ADD_INTERNAL_CALL
- cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
+ cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs");
@@ -1174,60 +1173,60 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
- List<String> output;
+ StringBuilder output;
- output.push_back("using System;\n"); // IntPtr
- output.push_back("using System.Diagnostics;\n"); // DebuggerBrowsable
+ output.append("using System;\n"); // IntPtr
+ output.append("using System.Diagnostics;\n"); // DebuggerBrowsable
- output.push_back("\n"
- "#pragma warning disable CS1591 // Disable warning: "
- "'Missing XML comment for publicly visible type or member'\n"
- "#pragma warning disable CS1573 // Disable warning: "
- "'Parameter has no matching param tag in the XML comment'\n");
+ output.append("\n"
+ "#pragma warning disable CS1591 // Disable warning: "
+ "'Missing XML comment for publicly visible type or member'\n"
+ "#pragma warning disable CS1573 // Disable warning: "
+ "'Parameter has no matching param tag in the XML comment'\n");
- output.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ output.append("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
const DocData::ClassDoc *class_doc = itype.class_doc;
if (class_doc && class_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(class_doc->description), &itype);
- Vector<String> summary_lines = xml_summary.split("\n");
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
if (summary_lines.size()) {
- output.push_back(INDENT1 "/// <summary>\n");
+ output.append(INDENT1 "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
- output.push_back(INDENT1 "/// ");
- output.push_back(summary_lines[i]);
- output.push_back("\n");
+ output.append(INDENT1 "/// ");
+ output.append(summary_lines[i]);
+ output.append("\n");
}
- output.push_back(INDENT1 "/// </summary>\n");
+ output.append(INDENT1 "/// </summary>\n");
}
}
- output.push_back(INDENT1 "public ");
+ output.append(INDENT1 "public ");
if (itype.is_singleton) {
- output.push_back("static partial class ");
+ output.append("static partial class ");
} else {
- output.push_back(itype.is_instantiable ? "partial class " : "abstract partial class ");
+ output.append(itype.is_instantiable ? "partial class " : "abstract partial class ");
}
- output.push_back(itype.proxy_name);
+ output.append(itype.proxy_name);
if (itype.is_singleton) {
- output.push_back("\n");
+ output.append("\n");
} else if (is_derived_type) {
if (obj_types.has(itype.base_name)) {
- output.push_back(" : ");
- output.push_back(obj_types[itype.base_name].proxy_name);
- output.push_back("\n");
+ output.append(" : ");
+ output.append(obj_types[itype.base_name].proxy_name);
+ output.append("\n");
} else {
ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name);
return ERR_INVALID_DATA;
}
}
- output.push_back(INDENT1 "{");
+ output.append(INDENT1 "{");
if (class_doc) {
@@ -1238,30 +1237,30 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
- Vector<String> summary_lines = xml_summary.split("\n");
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
if (summary_lines.size()) {
- output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ output.append(MEMBER_BEGIN "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
- output.push_back(INDENT2 "/// ");
- output.push_back(summary_lines[i]);
- output.push_back("\n");
+ output.append(INDENT2 "/// ");
+ output.append(summary_lines[i]);
+ output.append("\n");
}
- output.push_back(INDENT2 "/// </summary>");
+ output.append(INDENT2 "/// </summary>");
}
}
- output.push_back(MEMBER_BEGIN "public const int ");
- output.push_back(iconstant.proxy_name);
- output.push_back(" = ");
- output.push_back(itos(iconstant.value));
- output.push_back(";");
+ output.append(MEMBER_BEGIN "public const int ");
+ output.append(iconstant.proxy_name);
+ output.append(" = ");
+ output.append(itos(iconstant.value));
+ output.append(";");
}
if (itype.constants.size())
- output.push_back("\n");
+ output.append("\n");
// Add enums
@@ -1270,38 +1269,38 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
ERR_FAIL_COND_V(ienum.constants.empty(), ERR_BUG);
- output.push_back(MEMBER_BEGIN "public enum ");
- output.push_back(ienum.cname.operator String());
- output.push_back(MEMBER_BEGIN OPEN_BLOCK);
+ output.append(MEMBER_BEGIN "public enum ");
+ output.append(ienum.cname.operator String());
+ output.append(MEMBER_BEGIN OPEN_BLOCK);
for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
const ConstantInterface &iconstant = F->get();
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
- Vector<String> summary_lines = xml_summary.split("\n");
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
if (summary_lines.size()) {
- output.push_back(INDENT3 "/// <summary>\n");
+ output.append(INDENT3 "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
- output.push_back(INDENT3 "/// ");
- output.push_back(summary_lines[i]);
- output.push_back("\n");
+ output.append(INDENT3 "/// ");
+ output.append(summary_lines[i]);
+ output.append("\n");
}
- output.push_back(INDENT3 "/// </summary>\n");
+ output.append(INDENT3 "/// </summary>\n");
}
}
- output.push_back(INDENT3);
- output.push_back(iconstant.proxy_name);
- output.push_back(" = ");
- output.push_back(itos(iconstant.value));
- output.push_back(F != ienum.constants.back() ? ",\n" : "\n");
+ output.append(INDENT3);
+ output.append(iconstant.proxy_name);
+ output.append(" = ");
+ output.append(itos(iconstant.value));
+ output.append(F != ienum.constants.back() ? ",\n" : "\n");
}
- output.push_back(INDENT2 CLOSE_BLOCK);
+ output.append(INDENT2 CLOSE_BLOCK);
}
// Add properties
@@ -1322,53 +1321,53 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
if (itype.is_singleton) {
// Add the type name and the singleton pointer as static fields
- output.push_back(MEMBER_BEGIN "private static Godot.Object singleton;\n");
- output.push_back(MEMBER_BEGIN "public static Godot.Object Singleton\n" INDENT2 "{\n" INDENT3
- "get\n" INDENT3 "{\n" INDENT4 "if (singleton == null)\n" INDENT5
- "singleton = Engine.GetSingleton(" BINDINGS_NATIVE_NAME_FIELD ");\n" INDENT4
- "return singleton;\n" INDENT3 "}\n" INDENT2 "}\n");
-
- output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
- output.push_back(itype.name);
- output.push_back("\";\n");
-
- output.push_back(INDENT2 "internal static IntPtr " BINDINGS_PTR_FIELD " = ");
- output.push_back(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS);
- output.push_back("." ICALL_PREFIX);
- output.push_back(itype.name);
- output.push_back(SINGLETON_ICALL_SUFFIX "();\n");
+ output.append(MEMBER_BEGIN "private static Godot.Object singleton;\n");
+ output.append(MEMBER_BEGIN "public static Godot.Object Singleton\n" INDENT2 "{\n" INDENT3
+ "get\n" INDENT3 "{\n" INDENT4 "if (singleton == null)\n" INDENT5
+ "singleton = Engine.GetSingleton(" BINDINGS_NATIVE_NAME_FIELD ");\n" INDENT4
+ "return singleton;\n" INDENT3 "}\n" INDENT2 "}\n");
+
+ output.append(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
+ output.append(itype.name);
+ output.append("\";\n");
+
+ output.append(INDENT2 "internal static IntPtr " BINDINGS_PTR_FIELD " = ");
+ output.append(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS);
+ output.append("." ICALL_PREFIX);
+ output.append(itype.name);
+ output.append(SINGLETON_ICALL_SUFFIX "();\n");
} else if (is_derived_type) {
// Add member fields
- output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
- output.push_back(itype.name);
- output.push_back("\";\n");
+ output.append(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
+ output.append(itype.name);
+ output.append("\";\n");
// Add default constructor
if (itype.is_instantiable) {
- output.push_back(MEMBER_BEGIN "public ");
- output.push_back(itype.proxy_name);
- output.push_back("() : this(");
- output.push_back(itype.memory_own ? "true" : "false");
+ output.append(MEMBER_BEGIN "public ");
+ output.append(itype.proxy_name);
+ output.append("() : this(");
+ output.append(itype.memory_own ? "true" : "false");
// The default constructor may also be called by the engine when instancing existing native objects
// The engine will initialize the pointer field of the managed side before calling the constructor
// This is why we only allocate a new native object from the constructor if the pointer field is not set
- output.push_back(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = ");
- output.push_back(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS);
- output.push_back("." + ctor_method);
- output.push_back("(this);\n" CLOSE_BLOCK_L2);
+ output.append(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = ");
+ output.append(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS);
+ output.append("." + ctor_method);
+ output.append("(this);\n" CLOSE_BLOCK_L2);
} else {
// Hide the constructor
- output.push_back(MEMBER_BEGIN "internal ");
- output.push_back(itype.proxy_name);
- output.push_back("() {}\n");
+ output.append(MEMBER_BEGIN "internal ");
+ output.append(itype.proxy_name);
+ output.append("() {}\n");
}
// Add.. em.. trick constructor. Sort of.
- output.push_back(MEMBER_BEGIN "internal ");
- output.push_back(itype.proxy_name);
- output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
+ output.append(MEMBER_BEGIN "internal ");
+ output.append(itype.proxy_name);
+ output.append("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
}
int method_bind_count = 0;
@@ -1395,17 +1394,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
custom_icalls.push_back(ctor_icall);
}
- output.push_back(INDENT1 CLOSE_BLOCK /* class */
+ output.append(INDENT1 CLOSE_BLOCK /* class */
CLOSE_BLOCK /* namespace */);
- output.push_back("\n"
- "#pragma warning restore CS1591\n"
- "#pragma warning restore CS1573\n");
+ output.append("\n"
+ "#pragma warning restore CS1591\n"
+ "#pragma warning restore CS1573\n");
return _save_file(p_output_file, output);
}
-Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const PropertyInterface &p_iprop, List<String> &p_output) {
+Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output) {
const MethodInterface *setter = p_itype.find_method_by_name(p_iprop.setter);
@@ -1452,72 +1451,72 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte
if (p_iprop.prop_doc && p_iprop.prop_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(p_iprop.prop_doc->description), &p_itype);
- Vector<String> summary_lines = xml_summary.split("\n");
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
if (summary_lines.size()) {
- p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ p_output.append(MEMBER_BEGIN "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
- p_output.push_back(INDENT2 "/// ");
- p_output.push_back(summary_lines[i]);
- p_output.push_back("\n");
+ p_output.append(INDENT2 "/// ");
+ p_output.append(summary_lines[i]);
+ p_output.append("\n");
}
- p_output.push_back(INDENT2 "/// </summary>");
+ p_output.append(INDENT2 "/// </summary>");
}
}
- p_output.push_back(MEMBER_BEGIN "public ");
+ p_output.append(MEMBER_BEGIN "public ");
if (p_itype.is_singleton)
- p_output.push_back("static ");
+ p_output.append("static ");
- p_output.push_back(prop_itype->cs_type);
- p_output.push_back(" ");
- p_output.push_back(p_iprop.proxy_name);
- p_output.push_back("\n" INDENT2 OPEN_BLOCK);
+ p_output.append(prop_itype->cs_type);
+ p_output.append(" ");
+ p_output.append(p_iprop.proxy_name);
+ p_output.append("\n" INDENT2 OPEN_BLOCK);
if (getter) {
- p_output.push_back(INDENT3 "get\n" OPEN_BLOCK_L3);
- p_output.push_back("return ");
- p_output.push_back(getter->proxy_name + "(");
+ p_output.append(INDENT3 "get\n" OPEN_BLOCK_L3);
+ p_output.append("return ");
+ p_output.append(getter->proxy_name + "(");
if (p_iprop.index != -1) {
const ArgumentInterface &idx_arg = getter->arguments.front()->get();
if (idx_arg.type.cname != name_cache.type_int) {
// Assume the index parameter is an enum
const TypeInterface *idx_arg_type = _get_type_or_null(idx_arg.type);
CRASH_COND(idx_arg_type == NULL);
- p_output.push_back("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index));
+ p_output.append("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index));
} else {
- p_output.push_back(itos(p_iprop.index));
+ p_output.append(itos(p_iprop.index));
}
}
- p_output.push_back(");\n" CLOSE_BLOCK_L3);
+ p_output.append(");\n" CLOSE_BLOCK_L3);
}
if (setter) {
- p_output.push_back(INDENT3 "set\n" OPEN_BLOCK_L3);
- p_output.push_back(setter->proxy_name + "(");
+ p_output.append(INDENT3 "set\n" OPEN_BLOCK_L3);
+ p_output.append(setter->proxy_name + "(");
if (p_iprop.index != -1) {
const ArgumentInterface &idx_arg = setter->arguments.front()->get();
if (idx_arg.type.cname != name_cache.type_int) {
// Assume the index parameter is an enum
const TypeInterface *idx_arg_type = _get_type_or_null(idx_arg.type);
CRASH_COND(idx_arg_type == NULL);
- p_output.push_back("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index) + ", ");
+ p_output.append("(" + idx_arg_type->proxy_name + ")" + itos(p_iprop.index) + ", ");
} else {
- p_output.push_back(itos(p_iprop.index) + ", ");
+ p_output.append(itos(p_iprop.index) + ", ");
}
}
- p_output.push_back("value);\n" CLOSE_BLOCK_L3);
+ p_output.append("value);\n" CLOSE_BLOCK_L3);
}
- p_output.push_back(CLOSE_BLOCK_L2);
+ p_output.append(CLOSE_BLOCK_L2);
return OK;
}
-Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output) {
+Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output) {
const TypeInterface *return_type = _get_type_or_placeholder(p_imethod.return_type);
@@ -1529,7 +1528,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String icall_params = method_bind_field + ", ";
icall_params += sformat(p_itype.cs_in, "this");
- List<String> default_args_doc;
+ StringBuilder default_args_doc;
// Retrieve information from the arguments
for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
@@ -1598,7 +1597,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Apparently the name attribute must not include the @
String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name;
- default_args_doc.push_back(INDENT2 "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>\n");
+ default_args_doc.append(INDENT2 "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>\n");
} else {
icall_params += arg_type->cs_in.empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
}
@@ -1607,61 +1606,58 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method
{
if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
- p_output.push_back(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static IntPtr ");
- p_output.push_back(method_bind_field + " = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
- p_output.push_back(p_imethod.name);
- p_output.push_back("\");\n");
+ p_output.append(MEMBER_BEGIN "[DebuggerBrowsable(DebuggerBrowsableState.Never)]" MEMBER_BEGIN "private static IntPtr ");
+ p_output.append(method_bind_field + " = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
+ p_output.append(p_imethod.name);
+ p_output.append("\");\n");
}
if (p_imethod.method_doc && p_imethod.method_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(p_imethod.method_doc->description), &p_itype);
- Vector<String> summary_lines = xml_summary.split("\n");
+ Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
- if (summary_lines.size() || default_args_doc.size()) {
- p_output.push_back(MEMBER_BEGIN "/// <summary>\n");
+ if (summary_lines.size() || default_args_doc.get_string_length()) {
+ p_output.append(MEMBER_BEGIN "/// <summary>\n");
for (int i = 0; i < summary_lines.size(); i++) {
- p_output.push_back(INDENT2 "/// ");
- p_output.push_back(summary_lines[i]);
- p_output.push_back("\n");
+ p_output.append(INDENT2 "/// ");
+ p_output.append(summary_lines[i]);
+ p_output.append("\n");
}
- for (List<String>::Element *E = default_args_doc.front(); E; E = E->next()) {
- p_output.push_back(E->get());
- }
-
- p_output.push_back(INDENT2 "/// </summary>");
+ p_output.append(default_args_doc.as_string());
+ p_output.append(INDENT2 "/// </summary>");
}
}
if (!p_imethod.is_internal) {
- p_output.push_back(MEMBER_BEGIN "[GodotMethod(\"");
- p_output.push_back(p_imethod.name);
- p_output.push_back("\")]");
+ p_output.append(MEMBER_BEGIN "[GodotMethod(\"");
+ p_output.append(p_imethod.name);
+ p_output.append("\")]");
}
- p_output.push_back(MEMBER_BEGIN);
- p_output.push_back(p_imethod.is_internal ? "internal " : "public ");
+ p_output.append(MEMBER_BEGIN);
+ p_output.append(p_imethod.is_internal ? "internal " : "public ");
if (p_itype.is_singleton) {
- p_output.push_back("static ");
+ p_output.append("static ");
} else if (p_imethod.is_virtual) {
- p_output.push_back("virtual ");
+ p_output.append("virtual ");
}
- p_output.push_back(return_type->cs_type + " ");
- p_output.push_back(p_imethod.proxy_name + "(");
- p_output.push_back(arguments_sig + ")\n" OPEN_BLOCK_L2);
+ p_output.append(return_type->cs_type + " ");
+ p_output.append(p_imethod.proxy_name + "(");
+ p_output.append(arguments_sig + ")\n" OPEN_BLOCK_L2);
if (p_imethod.is_virtual) {
// Godot virtual method must be overridden, therefore we return a default value by default.
if (return_type->cname == name_cache.type_void) {
- p_output.push_back("return;\n" CLOSE_BLOCK_L2);
+ p_output.append("return;\n" CLOSE_BLOCK_L2);
} else {
- p_output.push_back("return default(");
- p_output.push_back(return_type->cs_type);
- p_output.push_back(");\n" CLOSE_BLOCK_L2);
+ p_output.append("return default(");
+ p_output.append(return_type->cs_type);
+ p_output.append(");\n" CLOSE_BLOCK_L2);
}
return OK; // Won't increment method bind count
@@ -1670,16 +1666,16 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
if (p_imethod.requires_object_call) {
// Fallback to Godot's object.Call(string, params)
- p_output.push_back(CS_METHOD_CALL "(\"");
- p_output.push_back(p_imethod.name);
- p_output.push_back("\"");
+ p_output.append(CS_METHOD_CALL "(\"");
+ p_output.append(p_imethod.name);
+ p_output.append("\"");
for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
- p_output.push_back(", ");
- p_output.push_back(F->get().name);
+ p_output.append(", ");
+ p_output.append(F->get().name);
}
- p_output.push_back(");\n" CLOSE_BLOCK_L2);
+ p_output.append(");\n" CLOSE_BLOCK_L2);
return OK; // Won't increment method bind count
}
@@ -1693,21 +1689,22 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
im_call += "." + im_icall->name + "(" + icall_params + ")";
if (p_imethod.arguments.size())
- p_output.push_back(cs_in_statements);
+ p_output.append(cs_in_statements);
if (return_type->cname == name_cache.type_void) {
- p_output.push_back(im_call + ";\n");
+ p_output.append(im_call + ";\n");
} else if (return_type->cs_out.empty()) {
- p_output.push_back("return " + im_call + ";\n");
+ p_output.append("return " + im_call + ";\n");
} else {
- p_output.push_back(sformat(return_type->cs_out, im_call, return_type->cs_type, return_type->im_type_out));
- p_output.push_back("\n");
+ p_output.append(sformat(return_type->cs_out, im_call, return_type->cs_type, return_type->im_type_out));
+ p_output.append("\n");
}
- p_output.push_back(CLOSE_BLOCK_L2);
+ p_output.append(CLOSE_BLOCK_L2);
}
p_method_bind_count++;
+
return OK;
}
@@ -1719,11 +1716,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
ERR_EXPLAIN("The output directory does not exist.");
ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
- List<String> output;
+ StringBuilder output;
- output.push_back("/* THIS FILE IS GENERATED DO NOT EDIT */\n");
- output.push_back("#include \"" GLUE_HEADER_FILE "\"\n");
- output.push_back("\n#ifdef MONO_GLUE_ENABLED\n");
+ output.append("/* THIS FILE IS GENERATED DO NOT EDIT */\n");
+ output.append("#include \"" GLUE_HEADER_FILE "\"\n");
+ output.append("\n#ifdef MONO_GLUE_ENABLED\n");
generated_icall_funcs.clear();
@@ -1763,11 +1760,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (!find_icall_by_name(singleton_icall.name, custom_icalls))
custom_icalls.push_back(singleton_icall);
- output.push_back("Object* ");
- output.push_back(singleton_icall_name);
- output.push_back("() " OPEN_BLOCK "\treturn Engine::get_singleton()->get_singleton_object(\"");
- output.push_back(itype.proxy_name);
- output.push_back("\");\n" CLOSE_BLOCK "\n");
+ output.append("Object* ");
+ output.append(singleton_icall_name);
+ output.append("() " OPEN_BLOCK "\treturn Engine::get_singleton()->get_singleton_object(\"");
+ output.append(itype.proxy_name);
+ output.append("\");\n" CLOSE_BLOCK "\n");
}
if (is_derived_type && itype.is_instantiable) {
@@ -1776,43 +1773,43 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (!find_icall_by_name(ctor_icall.name, custom_icalls))
custom_icalls.push_back(ctor_icall);
- output.push_back("Object* ");
- output.push_back(ctor_method);
- output.push_back("(MonoObject* obj) " OPEN_BLOCK
- "\t" C_MACRO_OBJECT_CONSTRUCT "(instance, \"");
- output.push_back(itype.name);
- output.push_back("\");\n"
- "\t" C_METHOD_TIE_MANAGED_TO_UNMANAGED "(obj, instance);\n"
- "\treturn instance;\n" CLOSE_BLOCK "\n");
+ output.append("Object* ");
+ output.append(ctor_method);
+ output.append("(MonoObject* obj) " OPEN_BLOCK
+ "\t" C_MACRO_OBJECT_CONSTRUCT "(instance, \"");
+ output.append(itype.name);
+ output.append("\");\n"
+ "\t" C_METHOD_TIE_MANAGED_TO_UNMANAGED "(obj, instance);\n"
+ "\treturn instance;\n" CLOSE_BLOCK "\n");
}
}
- output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK "\n");
+ output.append("namespace GodotSharpBindings\n" OPEN_BLOCK "\n");
- output.push_back("uint64_t get_core_api_hash() { return ");
- output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "U; }\n");
+ output.append("uint64_t get_core_api_hash() { return ");
+ output.append(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "U; }\n");
- output.push_back("#ifdef TOOLS_ENABLED\n"
- "uint64_t get_editor_api_hash() { return ");
- output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + "U; }\n");
- output.push_back("#endif // TOOLS_ENABLED\n");
+ output.append("#ifdef TOOLS_ENABLED\n"
+ "uint64_t get_editor_api_hash() { return ");
+ output.append(String::num_uint64(GDMono::get_singleton()->get_api_editor_hash()) + "U; }\n");
+ output.append("#endif // TOOLS_ENABLED\n");
- output.push_back("uint32_t get_bindings_version() { return ");
- output.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n");
+ output.append("uint32_t get_bindings_version() { return ");
+ output.append(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n");
- output.push_back("\nvoid register_generated_icalls() " OPEN_BLOCK);
- output.push_back("\tgodot_register_glue_header_icalls();\n");
+ output.append("\nvoid register_generated_icalls() " OPEN_BLOCK);
+ output.append("\tgodot_register_glue_header_icalls();\n");
-#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
- { \
- output.push_back("\tmono_add_internal_call("); \
- output.push_back("\"" BINDINGS_NAMESPACE "."); \
- output.push_back(m_icall.editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); \
- output.push_back("::"); \
- output.push_back(m_icall.name); \
- output.push_back("\", (void*)"); \
- output.push_back(m_icall.name); \
- output.push_back(");\n"); \
+#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
+ { \
+ output.append("\tmono_add_internal_call("); \
+ output.append("\"" BINDINGS_NAMESPACE "."); \
+ output.append(m_icall.editor_only ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS); \
+ output.append("::"); \
+ output.append(m_icall.name); \
+ output.append("\", (void*)"); \
+ output.append(m_icall.name); \
+ output.append(");\n"); \
}
bool tools_sequence = false;
@@ -1821,11 +1818,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (tools_sequence) {
if (!E->get().editor_only) {
tools_sequence = false;
- output.push_back("#endif\n");
+ output.append("#endif\n");
}
} else {
if (E->get().editor_only) {
- output.push_back("#ifdef TOOLS_ENABLED\n");
+ output.append("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
@@ -1835,23 +1832,23 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (tools_sequence) {
tools_sequence = false;
- output.push_back("#endif\n");
+ output.append("#endif\n");
}
- output.push_back("#ifdef TOOLS_ENABLED\n");
+ output.append("#ifdef TOOLS_ENABLED\n");
for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
ADD_INTERNAL_CALL_REGISTRATION(E->get());
- output.push_back("#endif // TOOLS_ENABLED\n");
+ output.append("#endif // TOOLS_ENABLED\n");
for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
if (tools_sequence) {
if (!E->get().editor_only) {
tools_sequence = false;
- output.push_back("#endif\n");
+ output.append("#endif\n");
}
} else {
if (E->get().editor_only) {
- output.push_back("#ifdef TOOLS_ENABLED\n");
+ output.append("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
@@ -1861,14 +1858,14 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
if (tools_sequence) {
tools_sequence = false;
- output.push_back("#endif\n");
+ output.append("#endif\n");
}
#undef ADD_INTERNAL_CALL_REGISTRATION
- output.push_back(CLOSE_BLOCK "\n} // namespace GodotSharpBindings\n");
+ output.append(CLOSE_BLOCK "\n} // namespace GodotSharpBindings\n");
- output.push_back("\n#endif // MONO_GLUE_ENABLED\n");
+ output.append("\n#endif // MONO_GLUE_ENABLED\n");
Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output);
if (save_err != OK)
@@ -1883,23 +1880,20 @@ uint32_t BindingsGenerator::get_version() {
return BINDINGS_GENERATOR_VERSION;
}
-Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_content) {
+Error BindingsGenerator::_save_file(const String &p_path, const StringBuilder &p_content) {
FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE);
ERR_EXPLAIN("Cannot open file: " + p_path);
ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
- for (const List<String>::Element *E = p_content.front(); E; E = E->next()) {
- file->store_string(E->get());
- }
-
+ file->store_string(p_content.as_string());
file->close();
return OK;
}
-Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, List<String> &p_output) {
+Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, StringBuilder &p_output) {
if (p_imethod.is_virtual)
return OK; // Ignore
@@ -1955,15 +1949,15 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
generated_icall_funcs.push_back(im_icall);
if (im_icall->editor_only)
- p_output.push_back("#ifdef TOOLS_ENABLED\n");
+ p_output.append("#ifdef TOOLS_ENABLED\n");
// Generate icall function
- p_output.push_back(ret_void ? "void " : return_type->c_type_out + " ");
- p_output.push_back(icall_method);
- p_output.push_back("(");
- p_output.push_back(c_func_sig);
- p_output.push_back(") " OPEN_BLOCK);
+ p_output.append(ret_void ? "void " : return_type->c_type_out + " ");
+ p_output.append(icall_method);
+ p_output.append("(");
+ p_output.append(c_func_sig);
+ p_output.append(") " OPEN_BLOCK);
String fail_ret = ret_void ? "" : ", " + (return_type->c_type_out.ends_with("*") ? "NULL" : return_type->c_type_out + "()");
@@ -1977,7 +1971,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
// the Variant alive until the method returns. Otherwise, if the returned Variant holds a RefPtr,
// it could be deleted too early. This is the case with GDScript.new() which returns OBJECT.
// Alternatively, we could just return Variant, but that would result in a worse API.
- p_output.push_back("\tVariant " C_LOCAL_VARARG_RET ";\n");
+ p_output.append("\tVariant " C_LOCAL_VARARG_RET ";\n");
}
if (return_type->is_object_type) {
@@ -1987,83 +1981,82 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
ptrcall_return_type = return_type->c_type;
}
- p_output.push_back("\t" + ptrcall_return_type);
- p_output.push_back(" " C_LOCAL_RET);
- p_output.push_back(initialization + ";\n");
- p_output.push_back("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE);
- p_output.push_back(fail_ret);
- p_output.push_back(");\n");
+ p_output.append("\t" + ptrcall_return_type);
+ p_output.append(" " C_LOCAL_RET);
+ p_output.append(initialization + ";\n");
+ p_output.append("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE);
+ p_output.append(fail_ret);
+ p_output.append(");\n");
} else {
- p_output.push_back("\tERR_FAIL_NULL(" CS_PARAM_INSTANCE ");\n");
+ p_output.append("\tERR_FAIL_NULL(" CS_PARAM_INSTANCE ");\n");
}
if (p_imethod.arguments.size()) {
if (p_imethod.is_vararg) {
- String err_fail_macro = ret_void ? "ERR_FAIL_COND" : "ERR_FAIL_COND_V";
String vararg_arg = "arg" + argc_str;
String real_argc_str = itos(p_imethod.arguments.size() - 1); // Arguments count without vararg
- p_output.push_back("\tint vararg_length = mono_array_length(");
- p_output.push_back(vararg_arg);
- p_output.push_back(");\n\tint total_length = ");
- p_output.push_back(real_argc_str);
- p_output.push_back(" + vararg_length;\n"
- "\tArgumentsVector<Variant> varargs(vararg_length);\n"
- "\tArgumentsVector<const Variant *> " C_LOCAL_PTRCALL_ARGS "(total_length);\n");
- p_output.push_back(c_in_statements);
- p_output.push_back("\tfor (int i = 0; i < vararg_length; i++) " OPEN_BLOCK
- "\t\tMonoObject* elem = mono_array_get(");
- p_output.push_back(vararg_arg);
- p_output.push_back(", MonoObject*, i);\n"
- "\t\tvarargs.set(i, GDMonoMarshal::mono_object_to_variant(elem));\n"
- "\t\t" C_LOCAL_PTRCALL_ARGS ".set(");
- p_output.push_back(real_argc_str);
- p_output.push_back(" + i, &varargs.get(i));\n\t" CLOSE_BLOCK);
+ p_output.append("\tint vararg_length = mono_array_length(");
+ p_output.append(vararg_arg);
+ p_output.append(");\n\tint total_length = ");
+ p_output.append(real_argc_str);
+ p_output.append(" + vararg_length;\n"
+ "\tArgumentsVector<Variant> varargs(vararg_length);\n"
+ "\tArgumentsVector<const Variant *> " C_LOCAL_PTRCALL_ARGS "(total_length);\n");
+ p_output.append(c_in_statements);
+ p_output.append("\tfor (int i = 0; i < vararg_length; i++) " OPEN_BLOCK
+ "\t\tMonoObject* elem = mono_array_get(");
+ p_output.append(vararg_arg);
+ p_output.append(", MonoObject*, i);\n"
+ "\t\tvarargs.set(i, GDMonoMarshal::mono_object_to_variant(elem));\n"
+ "\t\t" C_LOCAL_PTRCALL_ARGS ".set(");
+ p_output.append(real_argc_str);
+ p_output.append(" + i, &varargs.get(i));\n\t" CLOSE_BLOCK);
} else {
- p_output.push_back(c_in_statements);
- p_output.push_back("\tconst void* " C_LOCAL_PTRCALL_ARGS "[");
- p_output.push_back(argc_str + "] = { ");
- p_output.push_back(c_args_var_content + " };\n");
+ p_output.append(c_in_statements);
+ p_output.append("\tconst void* " C_LOCAL_PTRCALL_ARGS "[");
+ p_output.append(argc_str + "] = { ");
+ p_output.append(c_args_var_content + " };\n");
}
}
if (p_imethod.is_vararg) {
- p_output.push_back("\tVariant::CallError vcall_error;\n\t");
+ p_output.append("\tVariant::CallError vcall_error;\n\t");
if (!ret_void) {
// See the comment on the C_LOCAL_VARARG_RET declaration
if (return_type->cname != name_cache.type_Variant) {
- p_output.push_back(C_LOCAL_VARARG_RET " = ");
+ p_output.append(C_LOCAL_VARARG_RET " = ");
} else {
- p_output.push_back(C_LOCAL_RET " = ");
+ p_output.append(C_LOCAL_RET " = ");
}
}
- p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
- p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
- p_output.push_back(", total_length, vcall_error);\n");
+ p_output.append(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
+ p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
+ p_output.append(", total_length, vcall_error);\n");
// See the comment on the C_LOCAL_VARARG_RET declaration
if (return_type->cname != name_cache.type_Variant) {
- p_output.push_back("\t" C_LOCAL_RET " = " C_LOCAL_VARARG_RET ";\n");
+ p_output.append("\t" C_LOCAL_RET " = " C_LOCAL_VARARG_RET ";\n");
}
} else {
- p_output.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
- p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, ");
- p_output.push_back(!ret_void ? "&" C_LOCAL_RET ");\n" : "NULL);\n");
+ p_output.append("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
+ p_output.append(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, ");
+ p_output.append(!ret_void ? "&" C_LOCAL_RET ");\n" : "NULL);\n");
}
if (!ret_void) {
if (return_type->c_out.empty())
- p_output.push_back("\treturn " C_LOCAL_RET ";\n");
+ p_output.append("\treturn " C_LOCAL_RET ";\n");
else
- p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, C_LOCAL_RET, return_type->name));
+ p_output.append(sformat(return_type->c_out, return_type->c_type_out, C_LOCAL_RET, return_type->name));
}
- p_output.push_back(CLOSE_BLOCK "\n");
+ p_output.append(CLOSE_BLOCK "\n");
if (im_icall->editor_only)
- p_output.push_back("#endif // TOOLS_ENABLED\n");
+ p_output.append("#endif // TOOLS_ENABLED\n");
}
return OK;
@@ -2362,8 +2355,8 @@ void BindingsGenerator::_populate_object_type_interfaces() {
// Populate enums and constants
- List<String> constant_list;
- ClassDB::get_integer_constant_list(type_cname, &constant_list, true);
+ List<String> constants;
+ ClassDB::get_integer_constant_list(type_cname, &constants, true);
const HashMap<StringName, List<StringName> > &enum_map = class_info->enum_map;
const StringName *k = NULL;
@@ -2378,13 +2371,13 @@ void BindingsGenerator::_populate_object_type_interfaces() {
enum_proxy_cname = StringName(enum_proxy_name);
}
EnumInterface ienum(enum_proxy_cname);
- const List<StringName> &constants = enum_map.get(*k);
- for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) {
+ const List<StringName> &enum_constants = enum_map.get(*k);
+ for (const List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
const StringName &constant_cname = E->get();
String constant_name = constant_cname.operator String();
int *value = class_info->constant_map.getptr(constant_cname);
ERR_FAIL_NULL(value);
- constant_list.erase(constant_name);
+ constants.erase(constant_name);
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
@@ -2416,7 +2409,7 @@ void BindingsGenerator::_populate_object_type_interfaces() {
enum_types.insert(enum_itype.cname, enum_itype);
}
- for (const List<String>::Element *E = constant_list.front(); E; E = E->next()) {
+ for (const List<String>::Element *E = constants.front(); E; E = E->next()) {
const String &constant_name = E->get();
int *value = class_info->constant_map.getptr(StringName(E->get()));
ERR_FAIL_NULL(value);
@@ -2898,9 +2891,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
const List<String>::Element *elem = p_cmdline_args.front();
while (elem && options_left) {
-
if (elem->get() == mono_glue_option) {
-
const List<String>::Element *path_elem = elem->next();
if (path_elem) {
@@ -2912,9 +2903,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
}
--options_left;
-
} else if (elem->get() == cs_api_option) {
-
const List<String>::Element *path_elem = elem->next();
if (path_elem) {
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 42071f9c0d..a073c09910 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -32,6 +32,7 @@
#define BINDINGS_GENERATOR_H
#include "core/class_db.h"
+#include "core/string_builder.h"
#include "dotnet_solution.h"
#include "editor/doc/doc_data.h"
#include "editor/editor_help.h"
@@ -568,14 +569,14 @@ class BindingsGenerator {
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
- Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, List<String> &p_output);
- Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, List<String> &p_output);
+ Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output);
+ Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
- void _generate_global_constants(List<String> &p_output);
+ void _generate_global_constants(StringBuilder &p_output);
- Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, List<String> &p_output);
+ Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, StringBuilder &p_output);
- Error _save_file(const String &p_path, const List<String> &p_content);
+ Error _save_file(const String &p_path, const StringBuilder &p_content);
BindingsGenerator() {}
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
index 3191cdbd53..087a7a2e5c 100644
--- a/modules/mono/mono_gd/gd_mono_log.cpp
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -172,7 +172,7 @@ void GDMonoLog::initialize() {
OS::Time time_now = OS::get_singleton()->get_time();
int pid = OS::get_singleton()->get_process_id();
- String log_file_name = format("%d-%02d-%02d %02d:%02d:%02d (%d).txt",
+ String log_file_name = format("%d_%02d_%02d %02d.%02d.%02d (%d).txt",
date_now.year, date_now.month, date_now.day,
time_now.hour, time_now.min, time_now.sec, pid);
diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml
index 4caf6db1bb..c789724fc4 100644
--- a/modules/opensimplex/doc_classes/NoiseTexture.xml
+++ b/modules/opensimplex/doc_classes/NoiseTexture.xml
@@ -13,7 +13,7 @@
</methods>
<members>
<member name="as_normalmap" type="bool" setter="set_as_normalmap" getter="is_normalmap">
- If true, the resulting texture contains a normal map created from the original noise interpreted as a bump map.
+ If [code]true[/code], the resulting texture contains a normal map created from the original noise interpreted as a bump map.
</member>
<member name="bump_strength" type="float" setter="set_bump_strength" getter="get_bump_strength">
</member>
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index b72144c679..a1325734e2 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -139,7 +139,7 @@ if env['builtin_opus']:
opus_sources_silk = []
if env["platform"] in ["android", "iphone", "javascript"]:
- env_opus.Append(CFLAGS=["-DFIXED_POINT"])
+ env_opus.Append(CPPFLAGS=["-DFIXED_POINT"])
opus_sources_silk = [
"silk/fixed/LTP_analysis_filter_FIX.c",
"silk/fixed/LTP_scale_ctrl_FIX.c",
@@ -208,7 +208,7 @@ if env['builtin_opus']:
if env['builtin_libogg']:
env_opus.Append(CPPPATH=["#thirdparty/libogg"])
- env_opus.Append(CFLAGS=["-DHAVE_CONFIG_H"])
+ env_opus.Append(CPPFLAGS=["-DHAVE_CONFIG_H"])
thirdparty_include_paths = [
"",
@@ -222,14 +222,14 @@ if env['builtin_opus']:
if env["platform"] == "android":
if ("android_arch" in env and env["android_arch"] in ["armv6", "armv7"]):
- env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM_OPT"])
elif ("android_arch" in env and env["android_arch"] == "arm64v8"):
- env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM64_OPT"])
elif env["platform"] == "iphone":
if ("arch" in env and env["arch"] == "arm"):
- env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM_OPT"])
elif ("arch" in env and env["arch"] == "arm64"):
- env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+ env_opus.Append(CPPFLAGS=["-DOPUS_ARM64_OPT"])
env_thirdparty = env_opus.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/recast/navigation_mesh_editor_plugin.cpp b/modules/recast/navigation_mesh_editor_plugin.cpp
index a068f3b0f9..62108620bd 100644
--- a/modules/recast/navigation_mesh_editor_plugin.cpp
+++ b/modules/recast/navigation_mesh_editor_plugin.cpp
@@ -67,9 +67,7 @@ void NavigationMeshEditor::_bake_pressed() {
NavigationMeshGenerator::clear(node->get_navigation_mesh());
NavigationMeshGenerator::bake(node->get_navigation_mesh(), node);
- if (node) {
- node->update_gizmo();
- }
+ node->update_gizmo();
}
void NavigationMeshEditor::_clear_pressed() {
diff --git a/modules/svg/SCsub b/modules/svg/SCsub
index 22f0b1e3eb..66d9b3bf75 100644
--- a/modules/svg/SCsub
+++ b/modules/svg/SCsub
@@ -16,7 +16,7 @@ env_svg.Append(CPPPATH=[thirdparty_dir])
# FIXME: Needed in editor/editor_themes.cpp for now, but ideally there
# shouldn't be a dependency on modules/ and its own 3rd party deps.
env.Append(CPPPATH=[thirdparty_dir])
-env.Append(CCFLAGS=["-DSVG_ENABLED"])
+env.Append(CPPFLAGS=["-DSVG_ENABLED"])
env_thirdparty = env_svg.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/theora/SCsub b/modules/theora/SCsub
index 98c4274a7e..f98db2359c 100644
--- a/modules/theora/SCsub
+++ b/modules/theora/SCsub
@@ -66,7 +66,7 @@ if env['builtin_libtheora']:
thirdparty_sources += thirdparty_sources_x86_vc
if (env["x86_libtheora_opt_gcc"] or env["x86_libtheora_opt_vc"]):
- env_theora.Append(CCFLAGS=["-DOC_X86_ASM"])
+ env_theora.Append(CPPFLAGS=["-DOC_X86_ASM"])
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
diff --git a/modules/vhacd/SCsub b/modules/vhacd/SCsub
index 11cd5f4743..fdd3ddc1e6 100644
--- a/modules/vhacd/SCsub
+++ b/modules/vhacd/SCsub
@@ -29,7 +29,7 @@ env_vhacd.Append(CPPFLAGS=["-DGODOT_ENET"])
# upstream uses c++11
if not env.msvc:
- env_vhacd.Append(CCFLAGS="-std=c++11")
+ env_vhacd.Append(CXXFLAGS="-std=c++11")
env_thirdparty = env_vhacd.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
index 2ad399c951..1ab9f807fb 100644
--- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
@@ -143,7 +143,7 @@
</constant>
<constant name="STEP_PUSH_STACK_BIT" value="16777216">
Hint used by [method _step] to tell that control should return to it when there is no other node left to execute.
- This is used by [VisualScriptCondition] to redirect the sequence to the "Done" port after the true/false branch has finished execution.
+ This is used by [VisualScriptCondition] to redirect the sequence to the "Done" port after the [code]true[/code]/[code]false[/code] branch has finished execution.
</constant>
<constant name="STEP_GO_BACK_BIT" value="33554432">
Hint used by [method _step] to tell that control should return back, either hitting a previous STEP_PUSH_STACK_BIT or exiting the function.
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 6e7e566206..efd471eed1 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -37,6 +37,7 @@
#include "core/variant.h"
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
+#include "scene/main/viewport.h"
#include "visual_script_expression.h"
#include "visual_script_flow_control.h"
#include "visual_script_func_nodes.h"
@@ -1330,6 +1331,7 @@ void VisualScriptEditor::_input(const Ref<InputEvent> &p_event) {
}
void VisualScriptEditor::_generic_search() {
+ port_action_pos = graph->get_viewport()->get_mouse_position() - graph->get_global_position();
new_connect_node_select->select_from_visual_script(String(""), false);
}
diff --git a/modules/webm/SCsub b/modules/webm/SCsub
index cb35b926ab..dcc9a45044 100644
--- a/modules/webm/SCsub
+++ b/modules/webm/SCsub
@@ -19,7 +19,7 @@ env_webm.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "libwebm/"])
# upstream uses c++11
if (not env_webm.msvc):
- env_webm.Append(CCFLAGS="-std=c++11")
+ env_webm.Append(CXXFLAGS="-std=c++11")
# also requires libogg, libvorbis and libopus
if env['builtin_libogg']:
diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub
index 2639d20620..5bf4ea3464 100644
--- a/modules/webm/libvpx/SCsub
+++ b/modules/webm/libvpx/SCsub
@@ -323,7 +323,7 @@ if webm_cpu_x86:
elif cpu_bits == '64':
env_libvpx["ASCPU"] = 'X86_64'
- env_libvpx.Append(CCFLAGS=['-DWEBM_X86ASM'])
+ env_libvpx.Append(CPPFLAGS=['-DWEBM_X86ASM'])
webm_simd_optimizations = True
@@ -337,7 +337,7 @@ if webm_cpu_arm:
env_libvpx["ASFLAGS"] = ''
env_libvpx["ASCOM"] = '$AS $ASFLAGS -o $TARGET $SOURCES'
- env_libvpx.Append(CCFLAGS=['-DWEBM_ARMASM'])
+ env_libvpx.Append(CPPFLAGS=['-DWEBM_ARMASM'])
webm_simd_optimizations = True
diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub
index 0345e533bc..12b4969cf7 100644
--- a/modules/websocket/SCsub
+++ b/modules/websocket/SCsub
@@ -88,7 +88,7 @@ if env['builtin_libwebsockets'] and not env["platform"] == "javascript": # alrea
env_lws.Append(CPPPATH=[helper_dir])
if env["platform"] == "uwp":
- env_lws.Append(CCFLAGS=["/DLWS_MINGW_SUPPORT"])
+ env_lws.Append(CPPFLAGS=["/DLWS_MINGW_SUPPORT"])
env_thirdparty = env_lws.Clone()
env_thirdparty.disable_warnings()
diff --git a/modules/xatlas_unwrap/SCsub b/modules/xatlas_unwrap/SCsub
index ad364d5aaf..b8adfcb7df 100644
--- a/modules/xatlas_unwrap/SCsub
+++ b/modules/xatlas_unwrap/SCsub
@@ -24,18 +24,18 @@ if env['builtin_xatlas']:
if env["platform"] == 'x11':
# if not specifically one of the *BSD, then use LINUX as default
if platform.system() == "FreeBSD":
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_FREEBSD", "-DPOSH_COMPILER_GCC"])
+ env_xatlas_unwrap.Append(CPPFLAGS=["-DNV_OS_FREEBSD", "-DPOSH_COMPILER_GCC"])
elif platform.system() == "OpenBSD":
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_OPENBSD", "-DPOSH_COMPILER_GCC"])
+ env_xatlas_unwrap.Append(CPPFLAGS=["-DNV_OS_OPENBSD", "-DPOSH_COMPILER_GCC"])
else:
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_LINUX", "-DPOSH_COMPILER_GCC"])
+ env_xatlas_unwrap.Append(CPPFLAGS=["-DNV_OS_LINUX", "-DPOSH_COMPILER_GCC"])
elif env["platform"] == 'osx':
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_DARWIN", "-DPOSH_COMPILER_GCC"])
+ env_xatlas_unwrap.Append(CPPFLAGS=["-DNV_OS_DARWIN", "-DPOSH_COMPILER_GCC"])
elif env["platform"] == 'windows':
if env.msvc:
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_WIN32", "-DNV_CC_MSVC", "-DPOSH_COMPILER_MSVC" ])
+ env_xatlas_unwrap.Append(CPPFLAGS=["-DNV_OS_WIN32", "-DNV_CC_MSVC", "-DPOSH_COMPILER_MSVC" ])
else:
- env_xatlas_unwrap.Append(CCFLAGS=["-DNV_OS_MINGW", "-DNV_CC_GNUC", "-DPOSH_COMPILER_GCC", "-U__STRICT_ANSI__"])
+ env_xatlas_unwrap.Append(CPPFLAGS=["-DNV_OS_MINGW", "-DNV_CC_GNUC", "-DPOSH_COMPILER_GCC", "-U__STRICT_ANSI__"])
env.Append(LIBS=["dbghelp"])
env_thirdparty = env_xatlas_unwrap.Clone()
diff --git a/platform/android/SCsub b/platform/android/SCsub
index d494372bcd..22ed476c6f 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -34,114 +34,6 @@ env_thirdparty = env_android.Clone()
env_thirdparty.disable_warnings()
android_objects.append(env_thirdparty.SharedObject('#thirdparty/misc/ifaddrs-android.cc'))
-abspath = env.Dir(".").abspath
-
-with open_utf8(abspath + "/build.gradle.template", "r") as gradle_basein:
- gradle_text = gradle_basein.read()
-
-gradle_maven_flat_text = ""
-if len(env.android_flat_dirs) > 0:
- gradle_maven_flat_text += "flatDir {\n"
- gradle_maven_flat_text += "\tdirs "
- for x in env.android_flat_dirs:
- gradle_maven_flat_text += "'" + x + "',"
-
- gradle_maven_flat_text = gradle_maven_flat_text[:-1]
- gradle_maven_flat_text += "\n\t}\n"
-
-gradle_maven_repos_text = ""
-gradle_maven_repos_text += gradle_maven_flat_text
-
-if len(env.android_maven_repos) > 0:
- gradle_maven_repos_text += ""
- for x in env.android_maven_repos:
- gradle_maven_repos_text += "\tmaven {\n"
- gradle_maven_repos_text += "\t" + x + "\n"
- gradle_maven_repos_text += "\t}\n"
-
-gradle_maven_dependencies_text = ""
-
-for x in env.android_dependencies:
- gradle_maven_dependencies_text += x + "\n\t"
-
-gradle_java_dirs_text = ""
-
-for x in env.android_java_dirs:
- gradle_java_dirs_text += ",'" + x.replace("\\", "/") + "'"
-
-gradle_plugins = ""
-for x in env.android_gradle_plugins:
- gradle_plugins += "apply plugin: \"" + x + "\"\n"
-
-gradle_classpath = ""
-for x in env.android_gradle_classpath:
- gradle_classpath += "\t\tclasspath \"" + x + "\"\n"
-
-gradle_res_dirs_text = ""
-
-for x in env.android_res_dirs:
- gradle_res_dirs_text += ",'" + x.replace("\\", "/") + "'"
-
-gradle_aidl_dirs_text = ""
-
-for x in env.android_aidl_dirs:
- gradle_aidl_dirs_text += ",'" + x.replace("\\", "/") + "'"
-
-gradle_jni_dirs_text = ""
-
-for x in env.android_jni_dirs:
- gradle_jni_dirs_text += ",'" + x.replace("\\", "/") + "'"
-
-gradle_asset_dirs_text = ""
-
-for x in env.android_asset_dirs:
- gradle_asset_dirs_text += ",'" + x.replace("\\", "/") + "'"
-
-gradle_default_config_text = ""
-
-minSdk = 18
-targetSdk = 28
-
-for x in env.android_default_config:
- if x.startswith("minSdkVersion") and int(x.split(" ")[-1]) < minSdk:
- x = "minSdkVersion " + str(minSdk)
- if x.startswith("targetSdkVersion") and int(x.split(" ")[-1]) > targetSdk:
- x = "targetSdkVersion " + str(targetSdk)
-
- gradle_default_config_text += x + "\n\t\t"
-
-if "minSdkVersion" not in gradle_default_config_text:
- gradle_default_config_text += ("minSdkVersion " + str(minSdk) + "\n\t\t")
-
-if "targetSdkVersion" not in gradle_default_config_text:
- gradle_default_config_text += ("targetSdkVersion " + str(targetSdk) + "\n\t\t")
-
-gradle_text = gradle_text.replace("$$GRADLE_REPOSITORY_URLS$$", gradle_maven_repos_text)
-gradle_text = gradle_text.replace("$$GRADLE_DEPENDENCIES$$", gradle_maven_dependencies_text)
-gradle_text = gradle_text.replace("$$GRADLE_JAVA_DIRS$$", gradle_java_dirs_text)
-gradle_text = gradle_text.replace("$$GRADLE_RES_DIRS$$", gradle_res_dirs_text)
-gradle_text = gradle_text.replace("$$GRADLE_ASSET_DIRS$$", gradle_asset_dirs_text)
-gradle_text = gradle_text.replace("$$GRADLE_AIDL_DIRS$$", gradle_aidl_dirs_text)
-gradle_text = gradle_text.replace("$$GRADLE_JNI_DIRS$$", gradle_jni_dirs_text)
-gradle_text = gradle_text.replace("$$GRADLE_DEFAULT_CONFIG$$", gradle_default_config_text)
-gradle_text = gradle_text.replace("$$GRADLE_PLUGINS$$", gradle_plugins)
-gradle_text = gradle_text.replace("$$GRADLE_CLASSPATH$$", gradle_classpath)
-
-with open_utf8(abspath + "/java/build.gradle", "w") as gradle_baseout:
- gradle_baseout.write(gradle_text)
-
-
-with open_utf8(abspath + "/AndroidManifest.xml.template", "r") as pp_basein:
- manifest = pp_basein.read()
-
-manifest = manifest.replace("$$ADD_APPLICATION_CHUNKS$$", env.android_manifest_chunk)
-manifest = manifest.replace("$$ADD_PERMISSION_CHUNKS$$", env.android_permission_chunk)
-manifest = manifest.replace("$$ADD_APPATTRIBUTE_CHUNKS$$", env.android_appattributes_chunk)
-
-with open_utf8(abspath + "/java/AndroidManifest.xml", "w") as pp_baseout:
- pp_baseout.write(manifest)
-
-
lib = env_android.add_shared_library("#bin/libgodot", [android_objects], SHLIBSUFFIX=env["SHLIBSUFFIX"])
lib_arch_dir = ''
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 5623274050..6c67067db7 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -150,19 +150,21 @@ def configure(env):
if (env["target"].startswith("release")):
if (env["optimize"] == "speed"): #optimize for speed (default)
env.Append(LINKFLAGS=['-O2'])
- env.Append(CPPFLAGS=['-O2', '-DNDEBUG', '-fomit-frame-pointer'])
+ env.Append(CCFLAGS=['-O2', '-fomit-frame-pointer'])
+ env.Append(CPPFLAGS=['-DNDEBUG'])
else: #optimize for size
- env.Append(CPPFLAGS=['-Os', '-DNDEBUG'])
+ env.Append(CCFLAGS=['-Os'])
+ env.Append(CPPFLAGS=['-DNDEBUG'])
env.Append(LINKFLAGS=['-Os'])
if (can_vectorize):
- env.Append(CPPFLAGS=['-ftree-vectorize'])
+ env.Append(CCFLAGS=['-ftree-vectorize'])
if (env["target"] == "release_debug"):
env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
elif (env["target"] == "debug"):
env.Append(LINKFLAGS=['-O0'])
- env.Append(CPPFLAGS=['-O0', '-D_DEBUG', '-UNDEBUG', '-DDEBUG_ENABLED',
- '-DDEBUG_MEMORY_ENABLED', '-g', '-fno-limit-debug-info'])
+ env.Append(CCFLAGS=['-O0', '-g', '-fno-limit-debug-info'])
+ env.Append(CPPFLAGS=['-D_DEBUG', '-UNDEBUG', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
## Compiler configuration
@@ -216,15 +218,16 @@ def configure(env):
if env['android_stl']:
env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/include"])
env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++abi/include"])
- env.Append(CXXFLAGS=['-frtti',"-std=gnu++14"])
+ env.Append(CXXFLAGS=['-frtti', "-std=gnu++14"])
else:
- env.Append(CXXFLAGS=['-fno-rtti', '-fno-exceptions', '-DNO_SAFE_CAST'])
+ env.Append(CXXFLAGS=['-fno-rtti', '-fno-exceptions'])
+ env.Append(CPPFLAGS=['-DNO_SAFE_CAST'])
ndk_version = get_ndk_version(env["ANDROID_NDK_ROOT"])
if ndk_version != None and LooseVersion(ndk_version) >= LooseVersion("15.0.4075724"):
print("Using NDK unified headers")
sysroot = env["ANDROID_NDK_ROOT"] + "/sysroot"
- env.Append(CPPFLAGS=["--sysroot="+sysroot])
+ env.Append(CPPFLAGS=["--sysroot=" + sysroot])
env.Append(CPPFLAGS=["-isystem", sysroot + "/usr/include/" + abi_subpath])
env.Append(CPPFLAGS=["-isystem", env["ANDROID_NDK_ROOT"] + "/sources/android/support/include"])
# For unified headers this define has to be set manually
@@ -233,48 +236,51 @@ def configure(env):
print("Using NDK deprecated headers")
env.Append(CPPFLAGS=["-isystem", lib_sysroot + "/usr/include"])
- env.Append(CPPFLAGS='-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing'.split())
+ env.Append(CCFLAGS='-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden -fno-strict-aliasing'.split())
env.Append(CPPFLAGS='-DNO_STATVFS -DGLES_ENABLED'.split())
env['neon_enabled'] = False
if env['android_arch'] == 'x86':
target_opts = ['-target', 'i686-none-linux-android']
# The NDK adds this if targeting API < 21, so we can drop it when Godot targets it at least
- env.Append(CPPFLAGS=['-mstackrealign'])
+ env.Append(CCFLAGS=['-mstackrealign'])
elif env['android_arch'] == 'x86_64':
target_opts = ['-target', 'x86_64-none-linux-android']
elif env["android_arch"] == "armv6":
target_opts = ['-target', 'armv6-none-linux-androideabi']
- env.Append(CPPFLAGS='-D__ARM_ARCH_6__ -march=armv6 -mfpu=vfp -mfloat-abi=softfp'.split())
+ env.Append(CCFLAGS='-march=armv6 -mfpu=vfp -mfloat-abi=softfp'.split())
+ env.Append(CPPFLAGS=['-D__ARM_ARCH_6__'])
elif env["android_arch"] == "armv7":
target_opts = ['-target', 'armv7-none-linux-androideabi']
- env.Append(CPPFLAGS='-D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -march=armv7-a -mfloat-abi=softfp'.split())
+ env.Append(CCFLAGS='-march=armv7-a -mfloat-abi=softfp'.split())
+ env.Append(CPPFLAGS='-D__ARM_ARCH_7__ -D__ARM_ARCH_7A__'.split())
if env['android_neon']:
env['neon_enabled'] = True
- env.Append(CPPFLAGS=['-mfpu=neon', '-D__ARM_NEON__'])
+ env.Append(CCFLAGS=['-mfpu=neon'])
+ env.Append(CPPFLAGS=['-D__ARM_NEON__'])
else:
- env.Append(CPPFLAGS=['-mfpu=vfpv3-d16'])
+ env.Append(CCFLAGS=['-mfpu=vfpv3-d16'])
elif env["android_arch"] == "arm64v8":
target_opts = ['-target', 'aarch64-none-linux-android']
+ env.Append(CCFLAGS=['-mfix-cortex-a53-835769'])
env.Append(CPPFLAGS=['-D__ARM_ARCH_8A__'])
- env.Append(CPPFLAGS=['-mfix-cortex-a53-835769'])
- env.Append(CPPFLAGS=target_opts)
- env.Append(CPPFLAGS=common_opts)
+ env.Append(CCFLAGS=target_opts)
+ env.Append(CCFLAGS=common_opts)
## Link flags
if ndk_version != None and LooseVersion(ndk_version) >= LooseVersion("15.0.4075724"):
if LooseVersion(ndk_version) >= LooseVersion("17.1.4828580"):
- env.Append(LINKFLAGS=['-Wl,--exclude-libs,libgcc.a','-Wl,--exclude-libs,libatomic.a','-nostdlib++'])
+ env.Append(LINKFLAGS=['-Wl,--exclude-libs,libgcc.a', '-Wl,--exclude-libs,libatomic.a', '-nostdlib++'])
else:
- env.Append(LINKFLAGS=[env["ANDROID_NDK_ROOT"] +"/sources/cxx-stl/llvm-libc++/libs/"+arch_subpath+"/libandroid_support.a"])
+ env.Append(LINKFLAGS=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/libs/" + arch_subpath + "/libandroid_support.a"])
env.Append(LINKFLAGS=['-shared', '--sysroot=' + lib_sysroot, '-Wl,--warn-shared-textrel'])
- env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/libs/"+arch_subpath+"/"])
- env.Append(LINKFLAGS=[env["ANDROID_NDK_ROOT"] +"/sources/cxx-stl/llvm-libc++/libs/"+arch_subpath+"/libc++_shared.so"])
+ env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/llvm-libc++/libs/" + arch_subpath + "/"])
+ env.Append(LINKFLAGS=[env["ANDROID_NDK_ROOT"] +"/sources/cxx-stl/llvm-libc++/libs/" + arch_subpath + "/libc++_shared.so"])
else:
env.Append(LINKFLAGS=['-shared', '--sysroot=' + lib_sysroot, '-Wl,--warn-shared-textrel'])
if mt_link:
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index e489bce3f8..f70cee2964 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -417,6 +417,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
name = "noname";
pname = pname.replace("$genname", name);
+
return pname;
}
@@ -1143,11 +1144,12 @@ public:
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "one_click_deploy/clear_previous_install"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_package/use_custom_build"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.$genname"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "screen/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait"), 0));
@@ -1388,21 +1390,25 @@ public:
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
- r_missing_templates = find_export_template("android_debug.apk") == String() || find_export_template("android_release.apk") == String();
- if (p_preset->get("custom_package/debug") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/debug"))) {
- r_missing_templates = false;
- } else {
- err += TTR("Custom debug template not found.") + "\n";
+ if (!bool(p_preset->get("custom_package/use_custom_build"))) {
+
+ r_missing_templates = find_export_template("android_debug.apk") == String() || find_export_template("android_release.apk") == String();
+
+ if (p_preset->get("custom_package/debug") != "") {
+ if (FileAccess::exists(p_preset->get("custom_package/debug"))) {
+ r_missing_templates = false;
+ } else {
+ err += TTR("Custom debug template not found.") + "\n";
+ }
}
- }
- if (p_preset->get("custom_package/release") != "") {
- if (FileAccess::exists(p_preset->get("custom_package/release"))) {
- r_missing_templates = false;
- } else {
- err += TTR("Custom release template not found.") + "\n";
+ if (p_preset->get("custom_package/release") != "") {
+ if (FileAccess::exists(p_preset->get("custom_package/release"))) {
+ r_missing_templates = false;
+ } else {
+ err += TTR("Custom release template not found.") + "\n";
+ }
}
}
@@ -1435,6 +1441,30 @@ public:
}
}
+ if (bool(p_preset->get("custom_package/use_custom_build"))) {
+ String sdk_path = EditorSettings::get_singleton()->get("export/android/custom_build_sdk_path");
+ if (sdk_path == "") {
+ err += TTR("Custom build requires a valid Android SDK path in Editor Settings.") + "\n";
+ valid = false;
+ } else {
+ Error errn;
+ DirAccess *da = DirAccess::open(sdk_path.plus_file("tools"), &errn);
+ if (errn != OK) {
+ err += TTR("Invalid Android SDK path for custom build in Editor Settings.") + "\n";
+ valid = false;
+ }
+ if (da) {
+ memdelete(da);
+ }
+ }
+
+ if (!FileAccess::exists("res://android/build/build.gradle")) {
+
+ err += TTR("Android project is not installed for compiling. Install from Editor menu.") + "\n";
+ valid = false;
+ }
+ }
+
bool apk_expansion = p_preset->get("apk_expansion/enable");
if (apk_expansion) {
@@ -1473,6 +1503,260 @@ public:
return list;
}
+ void _update_custom_build_project() {
+
+ DirAccessRef da = DirAccess::open("res://android");
+
+ ERR_FAIL_COND(!da);
+ Map<String, List<String> > directory_paths;
+ Map<String, List<String> > manifest_sections;
+ Map<String, List<String> > gradle_sections;
+ da->list_dir_begin();
+ String d = da->get_next();
+ while (d != String()) {
+
+ if (!d.begins_with(".") && d != "build" && da->current_is_dir()) { //a dir and not the build dir
+ //add directories found
+ DirAccessRef ds = DirAccess::open(String("res://android").plus_file(d));
+ if (ds) {
+ ds->list_dir_begin();
+ String sd = ds->get_next();
+ while (sd != String()) {
+
+ if (!sd.begins_with(".") && ds->current_is_dir()) {
+ String key = sd.to_upper();
+ if (!directory_paths.has(key)) {
+ directory_paths[key] = List<String>();
+ }
+ String path = ProjectSettings::get_singleton()->get_resource_path().plus_file("android").plus_file(d).plus_file(sd);
+ directory_paths[key].push_back(path);
+ print_line("Add: " + sd + ":" + path);
+ }
+
+ sd = ds->get_next();
+ }
+ ds->list_dir_end();
+ }
+ //parse manifest
+ {
+ FileAccessRef f = FileAccess::open(String("res://android").plus_file(d).plus_file("AndroidManifest.conf"), FileAccess::READ);
+ if (f) {
+
+ String section;
+ while (!f->eof_reached()) {
+ String l = f->get_line();
+ String k = l.strip_edges();
+ if (k.begins_with("[")) {
+ section = k.substr(1, k.length() - 2).strip_edges().to_upper();
+ print_line("Section: " + section);
+ } else if (k != String()) {
+ if (!manifest_sections.has(section)) {
+ manifest_sections[section] = List<String>();
+ }
+ manifest_sections[section].push_back(l);
+ }
+ }
+
+ f->close();
+ }
+ }
+ //parse gradle
+ {
+ FileAccessRef f = FileAccess::open(String("res://android").plus_file(d).plus_file("gradle.conf"), FileAccess::READ);
+ if (f) {
+
+ String section;
+ while (!f->eof_reached()) {
+ String l = f->get_line().strip_edges();
+ String k = l.strip_edges();
+ if (k.begins_with("[")) {
+ section = k.substr(1, k.length() - 2).strip_edges().to_upper();
+ print_line("Section: " + section);
+ } else if (k != String()) {
+ if (!gradle_sections.has(section)) {
+ gradle_sections[section] = List<String>();
+ }
+ gradle_sections[section].push_back(l);
+ }
+ }
+ }
+ }
+ }
+ d = da->get_next();
+ }
+ da->list_dir_end();
+
+ { //fix gradle build
+
+ String new_file;
+ {
+ FileAccessRef f = FileAccess::open("res://android/build/build.gradle", FileAccess::READ);
+ if (f) {
+
+ while (!f->eof_reached()) {
+ String l = f->get_line();
+
+ if (l.begins_with("//CHUNK_")) {
+ String text = l.replace_first("//CHUNK_", "");
+ int begin_pos = text.find("_BEGIN");
+ if (begin_pos != -1) {
+ text = text.substr(0, begin_pos);
+ text = text.to_upper(); //just in case
+
+ String end_marker = "//CHUNK_" + text + "_END";
+ size_t pos = f->get_position();
+ bool found = false;
+ while (!f->eof_reached()) {
+ l = f->get_line();
+ if (l.begins_with(end_marker)) {
+ found = true;
+ break;
+ }
+ }
+
+ new_file += "//CHUNK_" + text + "_BEGIN\n";
+
+ if (!found) {
+ ERR_PRINTS("No end marker found in build.gradle for chunk: " + text);
+ f->seek(pos);
+ } else {
+
+ //add chunk lines
+ if (gradle_sections.has(text)) {
+ for (List<String>::Element *E = gradle_sections[text].front(); E; E = E->next()) {
+ new_file += E->get() + "\n";
+ }
+ }
+ new_file += end_marker + "\n";
+ }
+ } else {
+ new_file += l + "\n"; //pass line by
+ }
+ } else if (l.begins_with("//DIR_")) {
+ String text = l.replace_first("//DIR_", "");
+ int begin_pos = text.find("_BEGIN");
+ if (begin_pos != -1) {
+ text = text.substr(0, begin_pos);
+ text = text.to_upper(); //just in case
+
+ String end_marker = "//DIR_" + text + "_END";
+ size_t pos = f->get_position();
+ bool found = false;
+ while (!f->eof_reached()) {
+ l = f->get_line();
+ if (l.begins_with(end_marker)) {
+ found = true;
+ break;
+ }
+ }
+
+ new_file += "//DIR_" + text + "_BEGIN\n";
+
+ if (!found) {
+ ERR_PRINTS("No end marker found in build.gradle for dir: " + text);
+ f->seek(pos);
+ } else {
+ //add chunk lines
+ if (directory_paths.has(text)) {
+ for (List<String>::Element *E = directory_paths[text].front(); E; E = E->next()) {
+ new_file += ",'" + E->get().replace("'", "\'") + "'";
+ new_file += "\n";
+ }
+ }
+ new_file += end_marker + "\n";
+ }
+ } else {
+ new_file += l + "\n"; //pass line by
+ }
+
+ } else {
+ new_file += l + "\n";
+ }
+ }
+ }
+ }
+
+ FileAccessRef f = FileAccess::open("res://android/build/build.gradle", FileAccess::WRITE);
+ f->store_string(new_file);
+ f->close();
+ }
+
+ { //fix manifest
+
+ String new_file;
+ {
+ FileAccessRef f = FileAccess::open("res://android/build/AndroidManifest.xml", FileAccess::READ);
+ if (f) {
+
+ while (!f->eof_reached()) {
+ String l = f->get_line();
+
+ if (l.begins_with("<!--CHUNK_")) {
+ String text = l.replace_first("<!--CHUNK_", "");
+ int begin_pos = text.find("_BEGIN-->");
+ if (begin_pos != -1) {
+ text = text.substr(0, begin_pos);
+ text = text.to_upper(); //just in case
+
+ String end_marker = "<!--CHUNK_" + text + "_END-->";
+ size_t pos = f->get_position();
+ bool found = false;
+ while (!f->eof_reached()) {
+ l = f->get_line();
+ if (l.begins_with(end_marker)) {
+ found = true;
+ break;
+ }
+ }
+
+ new_file += "<!--CHUNK_" + text + "_BEGIN-->\n";
+
+ if (!found) {
+ ERR_PRINTS("No end marker found in AndroidManifest.conf for chunk: " + text);
+ f->seek(pos);
+ } else {
+ //add chunk lines
+ if (manifest_sections.has(text)) {
+ for (List<String>::Element *E = manifest_sections[text].front(); E; E = E->next()) {
+ new_file += E->get() + "\n";
+ }
+ }
+ new_file += end_marker + "\n";
+ }
+ } else {
+ new_file += l + "\n"; //pass line by
+ }
+
+ } else if (l.strip_edges().begins_with("<application")) {
+ String last_tag = "android:icon=\"@drawable/icon\"";
+ int last_tag_pos = l.find(last_tag);
+ if (last_tag_pos == -1) {
+ WARN_PRINTS("No adding of application tags because could not find last tag for <application: " + last_tag);
+ new_file += l + "\n";
+ } else {
+ String base = l.substr(0, last_tag_pos + last_tag.length());
+ if (manifest_sections.has("application_tags")) {
+ for (List<String>::Element *E = manifest_sections["application_tags"].front(); E; E = E->next()) {
+ String to_add = E->get().strip_edges();
+ base += " " + to_add + " ";
+ }
+ }
+ base += ">\n";
+ new_file += base;
+ }
+ } else {
+ new_file += l + "\n";
+ }
+ }
+ }
+ }
+
+ FileAccessRef f = FileAccess::open("res://android/build/AndroidManifest.xml", FileAccess::WRITE);
+ f->store_string(new_file);
+ f->close();
+ }
+ }
+
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
@@ -1481,21 +1765,86 @@ public:
EditorProgress ep("export", "Exporting for Android", 105);
- if (p_debug)
- src_apk = p_preset->get("custom_package/debug");
- else
- src_apk = p_preset->get("custom_package/release");
+ if (bool(p_preset->get("custom_package/use_custom_build"))) { //custom build
+ //re-generate build.gradle and AndroidManifest.xml
- src_apk = src_apk.strip_edges();
- if (src_apk == "") {
+ { //test that installed build version is alright
+ FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ);
+ if (!f) {
+ EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
+ return ERR_UNCONFIGURED;
+ }
+ String version = f->get_line().strip_edges();
+ if (version != VERSION_FULL_CONFIG) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG));
+ return ERR_UNCONFIGURED;
+ }
+ }
+ //build project if custom build is enabled
+ String sdk_path = EDITOR_GET("export/android/custom_build_sdk_path");
+
+ ERR_FAIL_COND_V(sdk_path == "", ERR_UNCONFIGURED);
+
+ _update_custom_build_project();
+
+ OS::get_singleton()->set_environment("ANDROID_HOME", sdk_path); //set and overwrite if required
+
+ String build_command;
+#ifdef WINDOWS_ENABLED
+ build_command = "gradlew.bat";
+#else
+ build_command = "gradlew";
+#endif
+
+ String build_path = ProjectSettings::get_singleton()->get_resource_path().plus_file("android/build");
+
+ build_command = build_path.plus_file(build_command);
+
+ List<String> cmdline;
+ cmdline.push_back("build");
+ cmdline.push_back("-p");
+ cmdline.push_back(build_path);
+ /*{ used for debug
+ int ec;
+ String pipe;
+ OS::get_singleton()->execute(build_command, cmdline, true, NULL, NULL, &ec);
+ print_line("exit code: " + itos(ec));
+ }
+ */
+ int result = EditorNode::get_singleton()->execute_and_show_output(TTR("Building Android Project (gradle)"), build_command, cmdline);
+ if (result != 0) {
+ EditorNode::get_singleton()->show_warning(TTR("Building of Android project failed, check output for the error.\nAlternatively visit docs.godotengine.org for Android build documentation."));
+ return ERR_CANT_CREATE;
+ }
if (p_debug) {
- src_apk = find_export_template("android_debug.apk");
+ src_apk = build_path.plus_file("build/outputs/apk/debug/build-debug-unsigned.apk");
} else {
- src_apk = find_export_template("android_release.apk");
+ src_apk = build_path.plus_file("build/outputs/apk/release/build-release-unsigned.apk");
}
+
+ if (!FileAccess::exists(src_apk)) {
+ EditorNode::get_singleton()->show_warning(TTR("No build apk generated at: ") + "\n" + src_apk);
+ return ERR_CANT_CREATE;
+ }
+
+ } else {
+
+ if (p_debug)
+ src_apk = p_preset->get("custom_package/debug");
+ else
+ src_apk = p_preset->get("custom_package/release");
+
+ src_apk = src_apk.strip_edges();
if (src_apk == "") {
- EditorNode::add_io_error("Package not found: " + src_apk);
- return ERR_FILE_NOT_FOUND;
+ if (p_debug) {
+ src_apk = find_export_template("android_debug.apk");
+ } else {
+ src_apk = find_export_template("android_release.apk");
+ }
+ if (src_apk == "") {
+ EditorNode::add_io_error("Package not found: " + src_apk);
+ return ERR_FILE_NOT_FOUND;
+ }
}
}
@@ -1923,10 +2272,6 @@ public:
zipClose(final_apk, NULL);
unzClose(tmp_unaligned);
- if (err) {
- return err;
- }
-
return OK;
}
@@ -1979,6 +2324,8 @@ void register_android_exporter() {
EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey");
EDITOR_DEF("export/android/debug_keystore_pass", "android");
EDITOR_DEF("export/android/force_system_user", false);
+ EDITOR_DEF("export/android/custom_build_sdk_path", "");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/custom_build_sdk_path", PROPERTY_HINT_GLOBAL_DIR, "*.keystore"));
EDITOR_DEF("export/android/timestamping_authority_url", "");
EDITOR_DEF("export/android/shutdown_adb_on_exit", true);
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index f8d46ea5d2..b8e78627ec 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -70,6 +70,8 @@ public:
virtual bool file_exists(const String &p_path); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
//static void make_default();
diff --git a/platform/android/file_access_jandroid.h b/platform/android/file_access_jandroid.h
index 4f02fea81d..9429100d65 100644
--- a/platform/android/file_access_jandroid.h
+++ b/platform/android/file_access_jandroid.h
@@ -74,6 +74,8 @@ public:
static void setup(jobject p_io);
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
+ virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
FileAccessJAndroid();
~FileAccessJAndroid();
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/java/AndroidManifest.xml
index daaf847f11..613d24fbd2 100644
--- a/platform/android/AndroidManifest.xml.template
+++ b/platform/android/java/AndroidManifest.xml
@@ -11,11 +11,20 @@
android:largeScreens="true"
android:xlargeScreens="true"/>
+<!--glEsVersion is modified by the exporter, changing this value here has no effect-->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
+<!--Adding custom text to manifest is fine, but do it outside the custom user and application BEGIN/ENDregions, as that gets rewritten-->
-$$ADD_PERMISSION_CHUNKS$$
+<!--Custom permissions XML added by add-ons. It's recommended to add them from the export preset, though-->
+<!--CHUNK_USER_PERMISSIONS_BEGIN-->
+<!--CHUNK_USER_PERMISSIONS_END-->
+
+<!--Anything in this line after the icon will be erased when doing custom build. If you want to add tags manually, do before it.-->
+ <application android:label="@string/godot_project_name_string" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@drawable/icon">
+
+<!--The following values are replaced when Godot exports, modifying them here has no effect. Do theses changes in the-->
+<!--export preset. Adding new ones is fine.-->
- <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" $$ADD_APPATTRIBUTE_CHUNKS$$ >
<activity android:name="org.godotengine.godot.Godot"
android:label="@string/godot_project_name_string"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
@@ -32,13 +41,15 @@ $$ADD_PERMISSION_CHUNKS$$
</activity>
<service android:name="org.godotengine.godot.GodotDownloaderService" />
-$$ADD_APPLICATION_CHUNKS$$
+<!--Custom application XML added by add-ons-->
+<!--CHUNK_APPLICATION_BEGIN-->
+<!--CHUNK_APPLICATION_END-->
</application>
<instrumentation android:icon="@drawable/icon"
android:label="@string/godot_project_name_string"
android:name="org.godotengine.godot.GodotInstrumentation"
- android:targetPackage="com.godot.game" />
+ android:targetPackage="org.godotengine.game" />
</manifest>
diff --git a/platform/android/build.gradle.template b/platform/android/java/build.gradle
index 2fea250061..c468277daa 100644
--- a/platform/android/build.gradle.template
+++ b/platform/android/java/build.gradle
@@ -1,12 +1,17 @@
+//Gradle project for Godot Engine Android port.
+//Do not modify code between the BEGIN/END sections, as it's autogenerated by add-ons
+
buildscript {
repositories {
google()
jcenter()
- $$GRADLE_REPOSITORY_URLS$$
+//CHUNK_BUILDSCRIPT_REPOSITORIES_BEGIN
+//CHUNK_BUILDSCRIPT_REPOSITORIES_END
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
- $$GRADLE_CLASSPATH$$
+//CHUNK_BUILDSCRIPT_DEPENDENCIES_BEGIN
+//CHUNK_BUILDSCRIPT_DEPENDENCIES_END
}
}
@@ -17,13 +22,16 @@ allprojects {
mavenCentral()
google()
jcenter()
- $$GRADLE_REPOSITORY_URLS$$
+//CHUNK_ALLPROJECTS_REPOSITORIES_BEGIN
+//CHUNK_ALLPROJECTS_REPOSITORIES_END
+
}
}
dependencies {
implementation "com.android.support:support-core-utils:28.0.0"
- $$GRADLE_DEPENDENCIES$$
+//CHUNK_DEPENDENCIES_BEGIN
+//CHUNK_DEPENDENCIES_END
}
android {
@@ -42,7 +50,10 @@ android {
exclude 'META-INF/NOTICE'
}
defaultConfig {
- $$GRADLE_DEFAULT_CONFIG$$
+ minSdkVersion 18
+ targetSdkVersion 28
+//CHUNK_ANDROID_DEFAULTCONFIG_BEGIN
+//CHUNK_ANDROID_DEFAULTCONFIG_END
}
// Both signing and zip-aligning will be done at export time
buildTypes.all { buildType ->
@@ -53,36 +64,50 @@ android {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src'
- $$GRADLE_JAVA_DIRS$$
+//DIR_SRC_BEGIN
+//DIR_SRC_END
]
res.srcDirs = [
'res'
- $$GRADLE_RES_DIRS$$
+//DIR_RES_BEGIN
+//DIR_RES_END
]
aidl.srcDirs = [
'aidl'
- $$GRADLE_AIDL_DIRS$$
+//DIR_AIDL_BEGIN
+//DIR_AIDL_END
]
assets.srcDirs = [
'assets'
- $$GRADLE_ASSET_DIRS$$
+//DIR_ASSETS_BEGIN
+//DIR_ASSETS_END
+
]
}
debug.jniLibs.srcDirs = [
'libs/debug'
- $$GRADLE_JNI_DIRS$$
+//DIR_JNI_DEBUG_BEGIN
+//DIR_JNI_DEBUG_END
]
release.jniLibs.srcDirs = [
'libs/release'
- $$GRADLE_JNI_DIRS$$
+//DIR_JNI_RELEASE_BEGIN
+//DIR_JNI_RELEASE_END
]
}
+// No longer used, as it's not useful for build source template
+// applicationVariants.all { variant ->
+// variant.outputs.all { output ->
+// output.outputFileName = "../../../../../../../bin/android_${variant.name}.apk"
+// }
+// }
- applicationVariants.all { variant ->
- variant.outputs.all { output ->
- output.outputFileName = "../../../../../../../bin/android_${variant.name}.apk"
- }
- }
}
-$$GRADLE_PLUGINS$$
+//CHUNK_GLOBAL_BEGIN
+//CHUNK_GLOBAL_END
+
+
+
+
+
diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py
index ae8cc58a4a..874b1ab1fb 100644
--- a/platform/haiku/detect.py
+++ b/platform/haiku/detect.py
@@ -150,6 +150,6 @@ def configure(env):
env.Append(CPPPATH=['#platform/haiku'])
env.Append(CPPFLAGS=['-DUNIX_ENABLED', '-DOPENGL_ENABLED', '-DGLES_ENABLED'])
env.Append(CPPFLAGS=['-DMEDIA_KIT_ENABLED'])
- # env.Append(CCFLAGS=['-DFREETYPE_ENABLED'])
+ # env.Append(CPPFLAGS=['-DFREETYPE_ENABLED'])
env.Append(CPPFLAGS=['-DPTHREAD_NO_RENAME']) # TODO: enable when we have pthread_setname_np
env.Append(LIBS=['be', 'game', 'media', 'network', 'bnetapi', 'z', 'GL'])
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 853f24379e..d56e28a4af 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -45,20 +45,21 @@ def configure(env):
if (env["target"].startswith("release")):
env.Append(CPPFLAGS=['-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1'])
if (env["optimize"] == "speed"): #optimize for speed (default)
- env.Append(CPPFLAGS=['-O2', '-ftree-vectorize', '-fomit-frame-pointer'])
+ env.Append(CCFLAGS=['-O2', '-ftree-vectorize', '-fomit-frame-pointer'])
env.Append(LINKFLAGS=['-O2'])
else: #optimize for size
- env.Append(CPPFLAGS=['-Os', '-ftree-vectorize'])
+ env.Append(CCFLAGS=['-Os', '-ftree-vectorize'])
env.Append(LINKFLAGS=['-Os'])
if env["target"] == "release_debug":
env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
elif (env["target"] == "debug"):
- env.Append(CPPFLAGS=['-D_DEBUG', '-DDEBUG=1', '-gdwarf-2', '-O0', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Append(CCFLAGS=['-gdwarf-2', '-O0'])
+ env.Append(CPPFLAGS=['-D_DEBUG', '-DDEBUG=1', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
if (env["use_lto"]):
- env.Append(CPPFLAGS=['-flto'])
+ env.Append(CCFLAGS=['-flto'])
env.Append(LINKFLAGS=['-flto'])
## Architecture
@@ -104,7 +105,7 @@ def configure(env):
detect_darwin_sdk_path('iphonesimulator', env)
env['ENV']['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
arch_flag = "i386" if env["arch"] == "x86" else env["arch"]
- env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=10.0 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\"').split())
+ env.Append(CCFLAGS=('-arch ' + arch_flag + ' -fobjc-abi-version=2 -fobjc-legacy-dispatch -fmessage-length=0 -fpascal-strings -fblocks -fasm-blocks -isysroot $IPHONESDK -mios-simulator-version-min=10.0').split())
elif (env["arch"] == "arm"):
detect_darwin_sdk_path('iphone', env)
env.Append(CCFLAGS='-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -fpascal-strings -fblocks -isysroot $IPHONESDK -fvisibility=hidden -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=10.0 -MMD -MT dependencies'.split())
@@ -115,9 +116,9 @@ def configure(env):
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
if env['ios_exceptions']:
- env.Append(CPPFLAGS=['-fexceptions'])
+ env.Append(CCFLAGS=['-fexceptions'])
else:
- env.Append(CPPFLAGS=['-fno-exceptions'])
+ env.Append(CCFLAGS=['-fno-exceptions'])
## Link flags
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 36a753e683..8024897195 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -53,16 +53,18 @@ def configure(env):
elif (env["target"] == "release_debug"):
if (env["optimize"] == "speed"): #optimize for speed (default)
- env.Prepend(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-O2'])
else: #optimize for size
- env.Prepend(CCFLAGS=['-Os', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-Os'])
+ env.Prepend(CPPFLAGS=['-DDEBUG_ENABLED'])
if (env["debug_symbols"] == "yes"):
env.Prepend(CCFLAGS=['-g1'])
if (env["debug_symbols"] == "full"):
env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "debug"):
- env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Prepend(CCFLAGS=['-g3'])
+ env.Prepend(CPPFLAGS=['-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
## Architecture
@@ -88,10 +90,10 @@ def configure(env):
env['AR'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-ar"
env['RANLIB'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-ranlib"
env['AS'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-as"
- env.Append(CCFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
+ env.Append(CPPFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
detect_darwin_sdk_path('osx', env)
- env.Append(CPPFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
+ env.Append(CCFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
env.Append(LINKFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
else: # osxcross build
@@ -110,7 +112,7 @@ def configure(env):
env['AR'] = basecmd + "ar"
env['RANLIB'] = basecmd + "ranlib"
env['AS'] = basecmd + "as"
- env.Append(CCFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
+ env.Append(CPPFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
if (env["CXX"] == "clang++"):
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
@@ -129,5 +131,5 @@ def configure(env):
env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreMIDI', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback', '-framework', 'CoreVideo'])
env.Append(LIBS=['pthread'])
- env.Append(CPPFLAGS=['-mmacosx-version-min=10.9'])
+ env.Append(CCFLAGS=['-mmacosx-version-min=10.9'])
env.Append(LINKFLAGS=['-mmacosx-version-min=10.9'])
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 5e94bc457b..1a63d6ff75 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -568,7 +568,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
f->close();
if (is_execute) {
// Chmod with 0755 if the file is executable
- f->_chmod(file, 0755);
+ FileAccess::set_unix_permissions(file, 0755);
}
memdelete(f);
} else {
diff --git a/platform/server/detect.py b/platform/server/detect.py
index f13ee72fd2..5306a2bf69 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -63,9 +63,10 @@ def configure(env):
elif (env["target"] == "release_debug"):
if (env["optimize"] == "speed"): #optimize for speed (default)
- env.Prepend(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-O2'])
else: #optimize for size
- env.Prepend(CCFLAGS=['-Os', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-Os'])
+ env.Prepend(CPPFLAGS=['-DDEBUG_ENABLED'])
if (env["debug_symbols"] == "yes"):
env.Prepend(CCFLAGS=['-g1'])
@@ -73,7 +74,8 @@ def configure(env):
env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "debug"):
- env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Prepend(CCFLAGS=['-g3'])
+ env.Prepend(CPPFLAGS=['-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
env.Append(LINKFLAGS=['-rdynamic'])
## Architecture
diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py
index f8f1b066f6..17f8242466 100644
--- a/platform/uwp/detect.py
+++ b/platform/uwp/detect.py
@@ -53,18 +53,20 @@ def configure(env):
## Build type
if (env["target"] == "release"):
- env.Append(CPPFLAGS=['/O2', '/GL'])
- env.Append(CPPFLAGS=['/MD'])
+ env.Append(CCFLAGS=['/O2', '/GL'])
+ env.Append(CCFLAGS=['/MD'])
env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS', '/LTCG'])
elif (env["target"] == "release_debug"):
- env.Append(CCFLAGS=['/O2', '/Zi', '/DDEBUG_ENABLED'])
- env.Append(CPPFLAGS=['/MD'])
+ env.Append(CCFLAGS=['/O2', '/Zi'])
+ env.Append(CCFLAGS=['/MD'])
+ env.Append(CPPFLAGS=['/DDEBUG_ENABLED'])
env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
elif (env["target"] == "debug"):
- env.Append(CCFLAGS=['/Zi', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED'])
- env.Append(CPPFLAGS=['/MDd'])
+ env.Append(CCFLAGS=['/Zi'])
+ env.Append(CCFLAGS=['/MDd'])
+ env.Append(CPPFLAGS=['/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED'])
env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
env.Append(LINKFLAGS=['/DEBUG'])
@@ -136,18 +138,19 @@ def configure(env):
## Compile flags
env.Append(CPPPATH=['#platform/uwp', '#drivers/windows'])
- env.Append(CCFLAGS=['/DUWP_ENABLED', '/DWINDOWS_ENABLED', '/DTYPED_METHOD_BIND'])
- env.Append(CCFLAGS=['/DGLES_ENABLED', '/DGL_GLEXT_PROTOTYPES', '/DEGL_EGLEXT_PROTOTYPES', '/DANGLE_ENABLED'])
+ env.Append(CPPFLAGS=['/DUWP_ENABLED', '/DWINDOWS_ENABLED', '/DTYPED_METHOD_BIND'])
+ env.Append(CPPFLAGS=['/DGLES_ENABLED', '/DGL_GLEXT_PROTOTYPES', '/DEGL_EGLEXT_PROTOTYPES', '/DANGLE_ENABLED'])
winver = "0x0602" # Windows 8 is the minimum target for UWP build
- env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
+ env.Append(CPPFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
- env.Append(CPPFLAGS=['/D', '__WRL_NO_DEFAULT_LIB__', '/D', 'WIN32', '/DPNG_ABORT=abort'])
+ env.Append(CPPFLAGS=['/D__WRL_NO_DEFAULT_LIB__', '/DWIN32', '/DPNG_ABORT=abort'])
env.Append(CPPFLAGS=['/AI', vc_base_path + 'lib/store/references'])
env.Append(CPPFLAGS=['/AI', vc_base_path + 'lib/x86/store/references'])
- env.Append(CCFLAGS='/FS /MP /GS /wd"4453" /wd"28204" /wd"4291" /Zc:wchar_t /Gm- /fp:precise /D "_UNICODE" /D "UNICODE" /D "WINAPI_FAMILY=WINAPI_FAMILY_APP" /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo'.split())
- env.Append(CXXFLAGS='/ZW /FS'.split())
+ env.Append(CCFLAGS='/FS /MP /GS /wd"4453" /wd"28204" /wd"4291" /Zc:wchar_t /Gm- /fp:precise /errorReport:prompt /WX- /Zc:forScope /Gd /EHsc /nologo'.split())
+ env.Append(CPPFLAGS=['/D_UNICODE', '/DUNICODE', '/D "WINAPI_FAMILY=WINAPI_FAMILY_APP"'])
+ env.Append(CXXFLAGS=['/ZW'])
env.Append(CCFLAGS=['/AI', vc_base_path + '\\vcpackages', '/AI', os.environ['WINDOWSSDKDIR'] + '\\References\\CommonConfiguration\\Neutral'])
## Link flags
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 2f7334657f..5c38eebf04 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -273,7 +273,8 @@ def configure_mingw(env):
env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "release_debug"):
- env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ env.Append(CCFLAGS=['-O2'])
+ env.Append(CPPFLAGS=['-DDEBUG_ENABLED'])
if (env["debug_symbols"] == "yes"):
env.Prepend(CCFLAGS=['-g1'])
if (env["debug_symbols"] == "full"):
@@ -284,7 +285,8 @@ def configure_mingw(env):
env.Prepend(CCFLAGS=['-Os'])
elif (env["target"] == "debug"):
- env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Append(CCFLAGS=['-g3'])
+ env.Append(CPPFLAGS=['-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
## Compiler configuration
@@ -325,12 +327,13 @@ def configure_mingw(env):
## Compile flags
- env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows'])
- env.Append(CCFLAGS=['-DOPENGL_ENABLED'])
- env.Append(CCFLAGS=['-DWASAPI_ENABLED'])
- env.Append(CCFLAGS=['-DWINMIDI_ENABLED'])
- env.Append(CCFLAGS=['-DWINVER=%s' % env['target_win_version'], '-D_WIN32_WINNT=%s' % env['target_win_version']])
- env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt','avrt'])
+ env.Append(CCFLAGS=['-mwindows'])
+ env.Append(CPPFLAGS=['-DWINDOWS_ENABLED'])
+ env.Append(CPPFLAGS=['-DOPENGL_ENABLED'])
+ env.Append(CPPFLAGS=['-DWASAPI_ENABLED'])
+ env.Append(CPPFLAGS=['-DWINMIDI_ENABLED'])
+ env.Append(CPPFLAGS=['-DWINVER=%s' % env['target_win_version'], '-D_WIN32_WINNT=%s' % env['target_win_version']])
+ env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid', 'ksuser', 'imm32', 'bcrypt', 'avrt', 'uuid'])
env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 1a5050a15a..193a3fa2c6 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -53,6 +53,7 @@
#include <avrt.h>
#include <direct.h>
+#include <knownfolders.h>
#include <process.h>
#include <regstr.h>
#include <shlobj.h>
@@ -2460,7 +2461,7 @@ void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent,
DeleteDC(hMainDC);
}
-Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
+Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
if (p_blocking && r_pipe) {
@@ -2479,7 +2480,13 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
char buf[65535];
while (fgets(buf, 65535, f)) {
+ if (p_pipe_mutex) {
+ p_pipe_mutex->lock();
+ }
(*r_pipe) += buf;
+ if (p_pipe_mutex) {
+ p_pipe_mutex->unlock();
+ }
}
int rv = _pclose(f);
@@ -2870,39 +2877,41 @@ String OS_Windows::get_godot_dir_name() const {
String OS_Windows::get_system_dir(SystemDir p_dir) const {
- int id;
+ KNOWNFOLDERID id;
switch (p_dir) {
case SYSTEM_DIR_DESKTOP: {
- id = CSIDL_DESKTOPDIRECTORY;
+ id = FOLDERID_Desktop;
} break;
case SYSTEM_DIR_DCIM: {
- id = CSIDL_MYPICTURES;
+ id = FOLDERID_Pictures;
} break;
case SYSTEM_DIR_DOCUMENTS: {
- id = CSIDL_PERSONAL;
+ id = FOLDERID_Documents;
} break;
case SYSTEM_DIR_DOWNLOADS: {
- id = 0x000C;
+ id = FOLDERID_Downloads;
} break;
case SYSTEM_DIR_MOVIES: {
- id = CSIDL_MYVIDEO;
+ id = FOLDERID_Videos;
} break;
case SYSTEM_DIR_MUSIC: {
- id = CSIDL_MYMUSIC;
+ id = FOLDERID_Music;
} break;
case SYSTEM_DIR_PICTURES: {
- id = CSIDL_MYPICTURES;
+ id = FOLDERID_Pictures;
} break;
case SYSTEM_DIR_RINGTONES: {
- id = CSIDL_MYMUSIC;
+ id = FOLDERID_Music;
} break;
}
- WCHAR szPath[MAX_PATH];
- HRESULT res = SHGetFolderPathW(NULL, id, NULL, 0, szPath);
+ PWSTR szPath;
+ HRESULT res = SHGetKnownFolderPath(id, 0, NULL, &szPath);
ERR_FAIL_COND_V(res != S_OK, String());
- return String(szPath);
+ String path = String(szPath);
+ CoTaskMemFree(szPath);
+ return path;
}
String OS_Windows::get_user_data_dir() const {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index c15e1cabc3..0e0b9bf3f6 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -261,7 +261,7 @@ public:
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false);
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id = NULL, String *r_pipe = NULL, int *r_exitcode = NULL, bool read_stderr = false, Mutex *p_pipe_mutex = NULL);
virtual Error kill(const ProcessID &p_pid);
virtual int get_process_id() const;
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 5f7b825f5e..1905b035e6 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -58,11 +58,12 @@ def get_opts():
return [
BoolVariable('use_llvm', 'Use the LLVM compiler', False),
+ BoolVariable('use_lld', 'Use the LLD linker', False),
BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically for better portability', False),
BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False),
BoolVariable('use_asan', 'Use LLVM/GCC compiler address sanitizer (ASAN))', False),
BoolVariable('use_lsan', 'Use LLVM/GCC compiler leak sanitizer (LSAN))', False),
- BoolVariable('pulseaudio', 'Detect & use pulseaudio', True),
+ BoolVariable('pulseaudio', 'Detect and use PulseAudio', True),
BoolVariable('udev', 'Use udev for gamepad connection callbacks', False),
EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')),
BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False),
@@ -97,9 +98,10 @@ def configure(env):
elif (env["target"] == "release_debug"):
if (env["optimize"] == "speed"): #optimize for speed (default)
- env.Prepend(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-O2'])
else: #optimize for size
- env.Prepend(CCFLAGS=['-Os', '-DDEBUG_ENABLED'])
+ env.Prepend(CCFLAGS=['-Os'])
+ env.Prepend(CPPFLAGS=['-DDEBUG_ENABLED'])
if (env["debug_symbols"] == "yes"):
env.Prepend(CCFLAGS=['-g1'])
@@ -107,7 +109,8 @@ def configure(env):
env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "debug"):
- env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Prepend(CCFLAGS=['-g3'])
+ env.Prepend(CPPFLAGS=['-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
env.Append(LINKFLAGS=['-rdynamic'])
## Architecture
@@ -130,6 +133,12 @@ def configure(env):
env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND'])
env.extra_suffix = ".llvm" + env.extra_suffix
+ if env['use_lld']:
+ if env['use_llvm']:
+ env.Append(LINKFLAGS=['-fuse-ld=lld'])
+ else:
+ print("Using LLD with GCC is not supported yet, try compiling with 'use_llvm=yes'.")
+ sys.exit(255)
if env['use_ubsan'] or env['use_asan'] or env['use_lsan']:
env.extra_suffix += "s"
@@ -148,6 +157,7 @@ def configure(env):
if env['use_lto']:
env.Append(CCFLAGS=['-flto'])
+
if not env['use_llvm'] and env.GetOption("num_jobs") > 1:
env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))])
else:
@@ -307,10 +317,10 @@ def configure(env):
## Cross-compilation
if (is64 and env["bits"] == "32"):
- env.Append(CPPFLAGS=['-m32'])
+ env.Append(CCFLAGS=['-m32'])
env.Append(LINKFLAGS=['-m32', '-L/usr/lib/i386-linux-gnu'])
elif (not is64 and env["bits"] == "64"):
- env.Append(CPPFLAGS=['-m64'])
+ env.Append(CCFLAGS=['-m64'])
env.Append(LINKFLAGS=['-m64', '-L/usr/lib/i686-linux-gnu'])
# Link those statically for portability
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index c96047dfbd..f6161a9485 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -1165,7 +1165,7 @@ int OS_X11::get_screen_dpi(int p_screen) const {
int height_mm = DisplayHeightMM(x11_display, p_screen);
double xdpi = (width_mm ? sc.width / (double)width_mm * 25.4 : 0);
double ydpi = (height_mm ? sc.height / (double)height_mm * 25.4 : 0);
- if (xdpi || xdpi)
+ if (xdpi || ydpi)
return (xdpi + ydpi) / (xdpi && ydpi ? 2 : 1);
//could not get dpi
@@ -3036,34 +3036,40 @@ bool OS_X11::is_vsync_enabled() const {
*/
void OS_X11::set_context(int p_context) {
- char *config_name = NULL;
XClassHint *classHint = XAllocClassHint();
if (classHint) {
- char *wm_class = (char *)"Godot";
- if (p_context == CONTEXT_EDITOR)
- classHint->res_name = (char *)"Godot_Editor";
- if (p_context == CONTEXT_PROJECTMAN)
- classHint->res_name = (char *)"Godot_ProjectList";
+ CharString name_str;
+ switch (p_context) {
+ case CONTEXT_EDITOR:
+ name_str = "Godot_Editor";
+ break;
+ case CONTEXT_PROJECTMAN:
+ name_str = "Godot_ProjectList";
+ break;
+ case CONTEXT_ENGINE:
+ name_str = "Godot_Engine";
+ break;
+ }
+ CharString class_str;
if (p_context == CONTEXT_ENGINE) {
- classHint->res_name = (char *)"Godot_Engine";
- String config_name_tmp = GLOBAL_GET("application/config/name");
- if (config_name_tmp.length() > 0) {
- config_name = strdup(config_name_tmp.utf8().get_data());
+ String config_name = GLOBAL_GET("application/config/name");
+ if (config_name.length() == 0) {
+ class_str = "Godot_Engine";
} else {
- config_name = strdup("Godot Engine");
+ class_str = config_name.utf8();
}
-
- wm_class = config_name;
+ } else {
+ class_str = "Godot";
}
- classHint->res_class = wm_class;
+ classHint->res_class = class_str.ptrw();
+ classHint->res_name = name_str.ptrw();
XSetClassHint(x11_display, x11_window, classHint);
XFree(classHint);
- free(config_name);
}
}
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 932db8f001..25ad6bd5c9 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -645,6 +645,9 @@ void AnimatedSprite::_reset_timeout() {
void AnimatedSprite::set_animation(const StringName &p_animation) {
+ ERR_EXPLAIN(vformat("There is no animation with name '%s'.", p_animation));
+ ERR_FAIL_COND(frames->get_animation_names().find(p_animation) == -1);
+
if (animation == p_animation)
return;
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index d1fce74085..6b12db9e44 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -438,7 +438,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_energy", "get_energy");
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Add,Sub,Mix,Mask"), "set_mode", "get_mode");
ADD_GROUP("Range", "range_");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "range_height", PROPERTY_HINT_RANGE, "-100,100,0.1"), "set_height", "get_height");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "range_height", PROPERTY_HINT_RANGE, "-2048,2048,0.1,or_lesser,or_greater"), "set_height", "get_height");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_min", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_min", "get_z_range_min");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_max", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_max", "get_z_range_max");
ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_min", PROPERTY_HINT_RANGE, "-512,512,1"), "set_layer_range_min", "get_layer_range_min");
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 690f1d4b4a..578c9aa5f9 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1275,9 +1275,6 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
if (collided) {
found_collision = true;
- }
-
- if (collided) {
colliders.push_back(collision);
motion = collision.remainder;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index 4d5ffc31b3..8bc48914d5 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -224,6 +224,7 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
case ATTENUATION_LOGARITHMIC: {
att = -20 * Math::log(p_distance / unit_size + CMP_EPSILON);
} break;
+ case ATTENUATION_DISABLED: break;
default: {
ERR_PRINT("Unknown attenuation type");
break;
@@ -831,7 +832,7 @@ float AudioStreamPlayer3D::get_attenuation_filter_db() const {
}
void AudioStreamPlayer3D::set_attenuation_model(AttenuationModel p_model) {
- ERR_FAIL_INDEX(p_model, 3);
+ ERR_FAIL_INDEX((int)p_model, 4);
attenuation_model = p_model;
}
@@ -962,7 +963,7 @@ void AudioStreamPlayer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer3D::_bus_layout_changed);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Log"), "set_attenuation_model", "get_attenuation_model");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "attenuation_model", PROPERTY_HINT_ENUM, "Inverse,InverseSquare,Log,Disabled"), "set_attenuation_model", "get_attenuation_model");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_db", PROPERTY_HINT_RANGE, "-80,80"), "set_unit_db", "get_unit_db");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_size", PROPERTY_HINT_RANGE, "0.1,100,0.1"), "set_unit_size", "get_unit_size");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_db", PROPERTY_HINT_RANGE, "-24,6"), "set_max_db", "get_max_db");
@@ -987,6 +988,7 @@ void AudioStreamPlayer3D::_bind_methods() {
BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_DISTANCE);
BIND_ENUM_CONSTANT(ATTENUATION_INVERSE_SQUARE_DISTANCE);
BIND_ENUM_CONSTANT(ATTENUATION_LOGARITHMIC);
+ BIND_ENUM_CONSTANT(ATTENUATION_DISABLED);
BIND_ENUM_CONSTANT(OUT_OF_RANGE_MIX);
BIND_ENUM_CONSTANT(OUT_OF_RANGE_PAUSE);
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index 1175547028..ad83c47afc 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -46,6 +46,7 @@ public:
ATTENUATION_INVERSE_DISTANCE,
ATTENUATION_INVERSE_SQUARE_DISTANCE,
ATTENUATION_LOGARITHMIC,
+ ATTENUATION_DISABLED,
};
enum OutOfRangeMode {
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 368cebeeab..54d7681a3a 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -55,16 +55,23 @@ void Camera::_update_camera_mode() {
case PROJECTION_ORTHOGONAL: {
set_orthogonal(size, near, far);
} break;
+ case PROJECTION_FRUSTUM: {
+ set_frustum(size, frustum_offset, near, far);
+ } break;
}
}
void Camera::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "fov") {
- if (mode == PROJECTION_ORTHOGONAL) {
+ if (mode != PROJECTION_PERSPECTIVE) {
p_property.usage = PROPERTY_USAGE_NOEDITOR;
}
} else if (p_property.name == "size") {
- if (mode == PROJECTION_PERSPECTIVE) {
+ if (mode != PROJECTION_ORTHOGONAL && mode != PROJECTION_FRUSTUM) {
+ p_property.usage = PROPERTY_USAGE_NOEDITOR;
+ }
+ } else if (p_property.name == "frustum_offset") {
+ if (mode != PROJECTION_FRUSTUM) {
p_property.usage = PROPERTY_USAGE_NOEDITOR;
}
}
@@ -177,8 +184,24 @@ void Camera::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
update_gizmo();
}
+void Camera::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
+ if (!force_change && size == p_size && frustum_offset == p_offset && p_z_near == near && p_z_far == far && mode == PROJECTION_FRUSTUM)
+ return;
+
+ size = p_size;
+ frustum_offset = p_offset;
+
+ near = p_z_near;
+ far = p_z_far;
+ mode = PROJECTION_FRUSTUM;
+ force_change = false;
+
+ VisualServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far);
+ update_gizmo();
+}
+
void Camera::set_projection(Camera::Projection p_mode) {
- if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL) {
+ if (p_mode == PROJECTION_PERSPECTIVE || p_mode == PROJECTION_ORTHOGONAL || p_mode == PROJECTION_FRUSTUM) {
mode = p_mode;
_update_camera_mode();
_change_notify();
@@ -470,16 +493,19 @@ void Camera::_bind_methods() {
ClassDB::bind_method(D_METHOD("project_position", "screen_point"), &Camera::project_position);
ClassDB::bind_method(D_METHOD("set_perspective", "fov", "z_near", "z_far"), &Camera::set_perspective);
ClassDB::bind_method(D_METHOD("set_orthogonal", "size", "z_near", "z_far"), &Camera::set_orthogonal);
+ ClassDB::bind_method(D_METHOD("set_frustum", "size", "offset", "z_near", "z_far"), &Camera::set_frustum);
ClassDB::bind_method(D_METHOD("make_current"), &Camera::make_current);
ClassDB::bind_method(D_METHOD("clear_current", "enable_next"), &Camera::clear_current, DEFVAL(true));
ClassDB::bind_method(D_METHOD("set_current"), &Camera::set_current);
ClassDB::bind_method(D_METHOD("is_current"), &Camera::is_current);
ClassDB::bind_method(D_METHOD("get_camera_transform"), &Camera::get_camera_transform);
ClassDB::bind_method(D_METHOD("get_fov"), &Camera::get_fov);
+ ClassDB::bind_method(D_METHOD("get_frustum_offset"), &Camera::get_frustum_offset);
ClassDB::bind_method(D_METHOD("get_size"), &Camera::get_size);
ClassDB::bind_method(D_METHOD("get_zfar"), &Camera::get_zfar);
ClassDB::bind_method(D_METHOD("get_znear"), &Camera::get_znear);
ClassDB::bind_method(D_METHOD("set_fov"), &Camera::set_fov);
+ ClassDB::bind_method(D_METHOD("set_frustum_offset"), &Camera::set_frustum_offset);
ClassDB::bind_method(D_METHOD("set_size"), &Camera::set_size);
ClassDB::bind_method(D_METHOD("set_zfar"), &Camera::set_zfar);
ClassDB::bind_method(D_METHOD("set_znear"), &Camera::set_znear);
@@ -510,15 +536,17 @@ void Camera::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset");
ADD_PROPERTY(PropertyInfo(Variant::INT, "doppler_tracking", PROPERTY_HINT_ENUM, "Disabled,Idle,Physics"), "set_doppler_tracking", "get_doppler_tracking");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal"), "set_projection", "get_projection");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "fov", PROPERTY_HINT_RANGE, "1,179,0.1"), "set_fov", "get_fov");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "near", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01,or_greater"), "set_znear", "get_znear");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "far", PROPERTY_HINT_EXP_RANGE, "0.1,8192,0.1,or_greater"), "set_zfar", "get_zfar");
BIND_ENUM_CONSTANT(PROJECTION_PERSPECTIVE);
BIND_ENUM_CONSTANT(PROJECTION_ORTHOGONAL);
+ BIND_ENUM_CONSTANT(PROJECTION_FRUSTUM);
BIND_ENUM_CONSTANT(KEEP_WIDTH);
BIND_ENUM_CONSTANT(KEEP_HEIGHT);
@@ -543,6 +571,10 @@ float Camera::get_znear() const {
return near;
}
+Vector2 Camera::get_frustum_offset() const {
+ return frustum_offset;
+}
+
float Camera::get_zfar() const {
return far;
@@ -570,6 +602,11 @@ void Camera::set_znear(float p_znear) {
_update_camera_mode();
}
+void Camera::set_frustum_offset(Vector2 p_offset) {
+ frustum_offset = p_offset;
+ _update_camera_mode();
+}
+
void Camera::set_zfar(float p_zfar) {
far = p_zfar;
_update_camera_mode();
@@ -648,6 +685,7 @@ Camera::Camera() {
camera = VisualServer::get_singleton()->camera_create();
size = 1;
fov = 0;
+ frustum_offset = Vector2();
near = 0;
far = 0;
current = false;
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index a531324a85..fe8cb84f0d 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -46,7 +46,8 @@ public:
enum Projection {
PROJECTION_PERSPECTIVE,
- PROJECTION_ORTHOGONAL
+ PROJECTION_ORTHOGONAL,
+ PROJECTION_FRUSTUM
};
enum KeepAspect {
@@ -68,6 +69,7 @@ private:
float fov;
float size;
+ Vector2 frustum_offset;
float near, far;
float v_offset;
float h_offset;
@@ -110,6 +112,7 @@ public:
void set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
void set_orthogonal(float p_size, float p_z_near, float p_z_far);
+ void set_frustum(float p_size, Vector2 p_offset, float p_near, float p_far);
void set_projection(Camera::Projection p_mode);
void make_current();
@@ -123,12 +126,15 @@ public:
float get_size() const;
float get_zfar() const;
float get_znear() const;
+ Vector2 get_frustum_offset() const;
+
Projection get_projection() const;
void set_fov(float p_fov);
void set_size(float p_size);
void set_zfar(float p_zfar);
void set_znear(float p_znear);
+ void set_frustum_offset(Vector2 p_offset);
virtual Transform get_camera_transform() const;
diff --git a/scene/3d/collision_shape.cpp b/scene/3d/collision_shape.cpp
index ac33e2b714..6bb2b547c7 100644
--- a/scene/3d/collision_shape.cpp
+++ b/scene/3d/collision_shape.cpp
@@ -91,7 +91,7 @@ void CollisionShape::_notification(int p_what) {
_update_in_shape_owner();
}
if (get_tree()->is_debugging_collisions_hint()) {
- _create_debug_shape();
+ _update_debug_shape();
}
} break;
case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
@@ -142,17 +142,24 @@ void CollisionShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_convex_from_brothers"), &CollisionShape::make_convex_from_brothers);
ClassDB::set_method_flags("CollisionShape", "make_convex_from_brothers", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("_shape_changed"), &CollisionShape::_shape_changed);
+ ClassDB::bind_method(D_METHOD("_update_debug_shape"), &CollisionShape::_update_debug_shape);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape"), "set_shape", "get_shape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled");
}
void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
- if (!shape.is_null())
+ if (!shape.is_null()) {
shape->unregister_owner(this);
+ shape->disconnect("changed", this, "_shape_changed");
+ }
shape = p_shape;
- if (!shape.is_null())
+ if (!shape.is_null()) {
shape->register_owner(this);
+ shape->connect("changed", this, "_shape_changed");
+ }
update_gizmo();
if (parent) {
parent->shape_owner_clear_shapes(owner_id);
@@ -161,6 +168,8 @@ void CollisionShape::set_shape(const Ref<Shape> &p_shape) {
}
}
+ if (is_inside_tree())
+ _shape_changed();
update_configuration_warning();
}
@@ -199,7 +208,8 @@ CollisionShape::~CollisionShape() {
//VisualServer::get_singleton()->free(indicator);
}
-void CollisionShape::_create_debug_shape() {
+void CollisionShape::_update_debug_shape() {
+ debug_shape_dirty = false;
if (debug_shape) {
debug_shape->queue_delete();
@@ -207,15 +217,19 @@ void CollisionShape::_create_debug_shape() {
}
Ref<Shape> s = get_shape();
-
if (s.is_null())
return;
Ref<Mesh> mesh = s->get_debug_mesh();
-
MeshInstance *mi = memnew(MeshInstance);
mi->set_mesh(mesh);
-
add_child(mi);
debug_shape = mi;
}
+
+void CollisionShape::_shape_changed() {
+ if (get_tree()->is_debugging_collisions_hint() && !debug_shape_dirty) {
+ debug_shape_dirty = true;
+ call_deferred("_update_debug_shape");
+ }
+}
diff --git a/scene/3d/collision_shape.h b/scene/3d/collision_shape.h
index 0c8e383a7f..98427b8590 100644
--- a/scene/3d/collision_shape.h
+++ b/scene/3d/collision_shape.h
@@ -45,12 +45,14 @@ class CollisionShape : public Spatial {
CollisionObject *parent;
Node *debug_shape;
+ bool debug_shape_dirty;
void resource_changed(RES res);
bool disabled;
protected:
- void _create_debug_shape();
+ void _update_debug_shape();
+ void _shape_changed();
void _update_in_shape_owner(bool p_xform_only = false);
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index 469a1e87db..d4e242dcb7 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -1394,6 +1394,7 @@ CPUParticles::CPUParticles() {
redraw = false;
multimesh = VisualServer::get_singleton()->multimesh_create();
+ VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, 0);
set_base(multimesh);
set_emitting(true);
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 05214ed669..e2dc89aa6e 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -1203,9 +1203,6 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
if (collided) {
found_collision = true;
- }
-
- if (collided) {
colliders.push_back(collision);
motion = collision.remainder;
diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index c7f7b14a8f..fde135c972 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -716,7 +716,7 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
real_t rollingFriction = 0.f;
if (wheelInfo.m_raycastInfo.m_isInContact) {
- if (engine_force != 0.f) {
+ if (engine_force != 0.f && wheelInfo.engine_traction != false) {
rollingFriction = -engine_force * s->get_step();
} else {
real_t defaultRollingFrictionImpulse = 0.f;
diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp
index 1bbf1b7bc7..1aded826c0 100644
--- a/scene/3d/visual_instance.cpp
+++ b/scene/3d/visual_instance.cpp
@@ -123,6 +123,8 @@ void VisualInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("_get_visual_instance_rid"), &VisualInstance::_get_visual_instance_rid);
ClassDB::bind_method(D_METHOD("set_base", "base"), &VisualInstance::set_base);
+ ClassDB::bind_method(D_METHOD("get_base"), &VisualInstance::get_base);
+ ClassDB::bind_method(D_METHOD("get_instance"), &VisualInstance::get_instance);
ClassDB::bind_method(D_METHOD("set_layer_mask", "mask"), &VisualInstance::set_layer_mask);
ClassDB::bind_method(D_METHOD("get_layer_mask"), &VisualInstance::get_layer_mask);
ClassDB::bind_method(D_METHOD("set_layer_mask_bit", "layer", "enabled"), &VisualInstance::set_layer_mask_bit);
@@ -136,6 +138,12 @@ void VisualInstance::_bind_methods() {
void VisualInstance::set_base(const RID &p_base) {
VisualServer::get_singleton()->instance_set_base(instance, p_base);
+ base = p_base;
+}
+
+RID VisualInstance::get_base() const {
+
+ return base;
}
VisualInstance::VisualInstance() {
diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h
index 3b6fccf65f..f5b7479bb1 100644
--- a/scene/3d/visual_instance.h
+++ b/scene/3d/visual_instance.h
@@ -43,6 +43,7 @@ class VisualInstance : public Spatial {
GDCLASS(VisualInstance, Spatial);
OBJ_CATEGORY("3D Visual Nodes");
+ RID base;
RID instance;
uint32_t layers;
@@ -69,6 +70,7 @@ public:
virtual AABB get_transformed_aabb() const; // helper
void set_base(const RID &p_base);
+ RID get_base() const;
void set_layer_mask(uint32_t p_mask);
uint32_t get_layer_mask() const;
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 13b8ebe12d..d1d3582c9d 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -891,7 +891,7 @@ void AnimationTree::_process_graph(float p_delta) {
t->loc = Vector3();
t->rot = Quat();
t->rot_blend_accum = 0;
- t->scale = Vector3();
+ t->scale = Vector3(1, 1, 1);
}
float prev_time = time - delta;
@@ -952,11 +952,9 @@ void AnimationTree::_process_graph(float p_delta) {
t->loc = loc;
t->rot = rot;
t->rot_blend_accum = 0;
- t->scale = Vector3();
+ t->scale = scale;
}
- scale -= Vector3(1.0, 1.0, 1.0); //helps make it work properly with Add nodes
-
if (err != OK)
continue;
@@ -1241,8 +1239,6 @@ void AnimationTree::_process_graph(float p_delta) {
Transform xform;
xform.origin = t->loc;
- t->scale += Vector3(1.0, 1.0, 1.0); //helps make it work properly with Add nodes and root motion
-
xform.basis.set_quat_scale(t->rot, t->scale);
if (t->root_motion) {
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 806c8afa5b..d68cdd5f8d 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -59,7 +59,7 @@ void BaseButton::_gui_input(Ref<InputEvent> p_event) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
- if (status.disabled || ((1 << (b->get_button_index() - 1)) & button_mask) == 0)
+ if (((1 << (b->get_button_index() - 1)) & button_mask) == 0)
return;
if (status.pressing_button)
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 0c5dc39273..1e8d73b6a4 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -722,6 +722,8 @@ void LineEdit::_notification(int p_what) {
} else {
x_ofs = MAX(style->get_margin(MARGIN_LEFT), x_ofs - r_icon->get_width() - style->get_margin(MARGIN_RIGHT));
}
+
+ ofs_max -= r_icon->get_width();
}
int caret_height = font->get_height() > y_area ? y_area : font->get_height();
@@ -918,6 +920,10 @@ void LineEdit::undo() {
TextOperation op = undo_stack_pos->get();
text = op.text;
set_cursor_position(op.cursor_pos);
+
+ if (expand_to_text_length)
+ minimum_size_changed();
+
_emit_text_change();
}
@@ -932,6 +938,10 @@ void LineEdit::redo() {
TextOperation op = undo_stack_pos->get();
text = op.text;
set_cursor_position(op.cursor_pos);
+
+ if (expand_to_text_length)
+ minimum_size_changed();
+
_emit_text_change();
}
@@ -1159,8 +1169,10 @@ void LineEdit::set_cursor_position(int p_pos) {
} else if (cursor_pos > window_pos) {
/* Adjust window if cursor goes too much to the right */
int window_width = get_size().width - style->get_minimum_size().width;
- if (right_icon.is_valid()) {
- window_width -= right_icon->get_width();
+ bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled;
+ if (right_icon.is_valid() || display_clear_icon) {
+ Ref<Texture> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon;
+ window_width -= r_icon->get_width();
}
if (window_width < 0)
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 94c73b2e42..23c61f37d6 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -239,7 +239,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
for (int i = search_from; i >= 0; i--) {
- if (i < 0 || i >= items.size())
+ if (i >= items.size())
continue;
if (!items[i].separator && !items[i].disabled) {
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 3fbf809012..d6b5c0b82d 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -901,13 +901,21 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
Control::CursorShape RichTextLabel::get_cursor_shape(const Point2 &p_pos) const {
- if (selection.click)
+ if (!underline_meta || selection.click)
return CURSOR_ARROW;
if (main->first_invalid_line < main->lines.size())
return CURSOR_ARROW; //invalid
- return get_default_cursor_shape();
+ int line = 0;
+ Item *item = NULL;
+
+ ((RichTextLabel *)(this))->_find_click(main, p_pos, &item, &line);
+
+ if (item && ((RichTextLabel *)(this))->_find_meta(item, NULL))
+ return CURSOR_POINTING_HAND;
+
+ return CURSOR_ARROW;
}
void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
@@ -1997,7 +2005,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
Item *it = main;
int charidx = 0;
- if (p_from_selection && selection.active && selection.enabled) {
+ if (p_from_selection && selection.active) {
it = selection.to;
charidx = selection.to_char + 1;
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 39a0b0aaf2..1f498ea16e 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -350,6 +350,10 @@ void TextEdit::_update_scrollbars() {
total_width += cache.breakpoint_gutter_width;
}
+ if (draw_info_gutter) {
+ total_width += cache.info_gutter_width;
+ }
+
if (draw_fold_gutter) {
total_width += cache.fold_gutter_width;
}
@@ -608,6 +612,13 @@ void TextEdit::_notification(int p_what) {
cache.breakpoint_gutter_width = 0;
}
+ if (draw_info_gutter) {
+ info_gutter_width = (get_row_height());
+ cache.info_gutter_width = info_gutter_width;
+ } else {
+ cache.info_gutter_width = 0;
+ }
+
if (draw_fold_gutter) {
fold_gutter_width = (get_row_height() * 55) / 100;
cache.fold_gutter_width = fold_gutter_width;
@@ -637,7 +648,7 @@ void TextEdit::_notification(int p_what) {
RID ci = get_canvas_item();
VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true);
- int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width;
+ int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width;
int xmargin_end = size.width - cache.style_normal->get_margin(MARGIN_RIGHT);
//let's do it easy for now:
cache.style_normal->draw(ci, Rect2(Point2(), size));
@@ -952,10 +963,35 @@ void TextEdit::_notification(int p_what) {
}
}
+ // draw info icons
+ if (draw_info_gutter && text.has_info_icon(line)) {
+ int vertical_gap = (get_row_height() * 40) / 100;
+ int horizontal_gap = (cache.info_gutter_width * 30) / 100;
+ int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width;
+
+ Ref<Texture> info_icon = text.get_info_icon(line);
+ // ensure the icon fits the gutter size
+ Size2i icon_size = info_icon->get_size();
+ if (icon_size.width > cache.info_gutter_width - horizontal_gap) {
+ icon_size.width = cache.info_gutter_width - horizontal_gap;
+ }
+ if (icon_size.height > get_row_height() - horizontal_gap) {
+ icon_size.height = get_row_height() - horizontal_gap;
+ }
+
+ Size2i icon_pos;
+ int xofs = horizontal_gap - (info_icon->get_width() / 4);
+ int yofs = vertical_gap - (info_icon->get_height() / 4);
+ icon_pos.x = gutter_left + xofs + ofs_x;
+ icon_pos.y = ofs_y + yofs;
+
+ draw_texture_rect(info_icon, Rect2(icon_pos, icon_size));
+ }
+
// draw fold markers
if (draw_fold_gutter) {
int horizontal_gap = (cache.fold_gutter_width * 30) / 100;
- int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + cache.line_number_w;
+ int gutter_left = cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + cache.line_number_w + cache.info_gutter_width;
if (is_folded(line)) {
int xofs = horizontal_gap - (cache.can_fold_icon->get_width()) / 2;
int yofs = (get_row_height() - cache.folded_icon->get_height()) / 2;
@@ -975,7 +1011,7 @@ void TextEdit::_notification(int p_what) {
fc = line_num_padding + fc;
}
- cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + ofs_x, yofs + cache.font->get_ascent()), fc, text.is_safe(line) ? cache.safe_line_number_color : cache.line_number_color);
+ cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + cache.info_gutter_width + ofs_x, yofs + cache.font->get_ascent()), fc, text.is_safe(line) ? cache.safe_line_number_color : cache.line_number_color);
}
}
@@ -1566,6 +1602,10 @@ void TextEdit::backspace_at_cursor() {
set_line_as_breakpoint(prev_line, true);
}
+ if (text.has_info_icon(cursor.line)) {
+ set_line_info_icon(prev_line, text.get_info_icon(cursor.line), text.get_info(cursor.line));
+ }
+
if (auto_brace_completion_enabled &&
cursor.column > 0 &&
_is_pair_left_symbol(text[cursor.line][cursor.column - 1])) {
@@ -1718,7 +1758,7 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co
col = text[row].size();
} else {
- int colx = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width);
+ int colx = p_mouse.x - (cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width);
colx += cursor.x_ofs;
col = get_char_pos_for_line(colx, row, wrap_index);
if (is_wrap_enabled() && wrap_index < times_line_wraps(row)) {
@@ -1816,18 +1856,28 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// toggle breakpoint on gutter click
if (draw_breakpoint_gutter) {
int gutter = cache.style_normal->get_margin(MARGIN_LEFT);
- if (mb->get_position().x > gutter && mb->get_position().x <= gutter + cache.breakpoint_gutter_width + 3) {
+ if (mb->get_position().x > gutter - 6 && mb->get_position().x <= gutter + cache.breakpoint_gutter_width - 3) {
set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row));
emit_signal("breakpoint_toggled", row);
return;
}
}
+ // emit info clicked
+ if (draw_info_gutter && text.has_info_icon(row)) {
+ int left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
+ int gutter_left = left_margin + cache.breakpoint_gutter_width;
+ if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.info_gutter_width - 3) {
+ emit_signal("info_clicked", row, text.get_info(row));
+ return;
+ }
+ }
+
// toggle fold on gutter click if can
if (draw_fold_gutter) {
int left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
- int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w;
+ int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w + cache.info_gutter_width;
if (mb->get_position().x > gutter_left - 6 && mb->get_position().x <= gutter_left + cache.fold_gutter_width - 3) {
if (is_folded(row)) {
unfold_line(row);
@@ -1841,7 +1891,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// unfold on folded icon click
if (is_folded(row)) {
int line_width = text.get_line_width(row);
- line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width - cursor.x_ofs;
+ line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.info_gutter_width + cache.fold_gutter_width - cursor.x_ofs;
if (mb->get_position().x > line_width - 3 && mb->get_position().x <= line_width + cache.folded_eol_icon->get_width() + 3) {
unfold_line(row);
return;
@@ -3374,8 +3424,11 @@ void TextEdit::_base_insert_text(int p_line, int p_char, const String &p_text, i
if (shift_first_line) {
text.set_breakpoint(p_line + 1, text.is_breakpoint(p_line));
text.set_hidden(p_line + 1, text.is_hidden(p_line));
+ text.set_info_icon(p_line + 1, text.get_info_icon(p_line), text.get_info(p_line));
+
text.set_breakpoint(p_line, false);
text.set_hidden(p_line, false);
+ text.set_info_icon(p_line, NULL, "");
}
text.set_line_wrap_amount(p_line, -1);
@@ -3628,7 +3681,7 @@ int TextEdit::get_total_visible_rows() const {
void TextEdit::_update_wrap_at() {
- wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - wrap_right_offset;
+ wrap_at = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width - wrap_right_offset;
update_cursor_wrap_offset();
text.clear_wrap_cache();
@@ -3662,7 +3715,7 @@ void TextEdit::adjust_viewport_to_cursor() {
set_line_as_last_visible(cur_line, cur_wrap);
}
- int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width;
+ int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width;
if (v_scroll->is_visible_in_tree())
visible_width -= v_scroll->get_combined_minimum_size().width;
visible_width -= 20; // give it a little more space
@@ -3693,7 +3746,7 @@ void TextEdit::center_viewport_to_cursor() {
unfold_line(cursor.line);
set_line_as_center_visible(cursor.line, get_cursor_wrap_index());
- int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width;
+ int visible_width = get_size().width - cache.style_normal->get_minimum_size().width - cache.line_number_w - cache.breakpoint_gutter_width - cache.fold_gutter_width - cache.info_gutter_width;
if (v_scroll->is_visible_in_tree())
visible_width -= v_scroll->get_combined_minimum_size().width;
visible_width -= 20; // give it a little more space
@@ -4132,7 +4185,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
if (highlighted_word != String())
return CURSOR_POINTING_HAND;
- int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width;
+ int gutter = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width;
if ((completion_active && completion_rect.has_point(p_pos))) {
return CURSOR_ARROW;
}
@@ -4143,18 +4196,27 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
int left_margin = cache.style_normal->get_margin(MARGIN_LEFT);
// breakpoint icon
- if (draw_breakpoint_gutter && p_pos.x > left_margin && p_pos.x <= left_margin + cache.breakpoint_gutter_width + 3) {
+ if (draw_breakpoint_gutter && p_pos.x > left_margin - 6 && p_pos.x <= left_margin + cache.breakpoint_gutter_width - 3) {
return CURSOR_POINTING_HAND;
}
+ // info icons
+ int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.info_gutter_width;
+ if (draw_info_gutter && p_pos.x > left_margin + cache.breakpoint_gutter_width - 6 && p_pos.x <= gutter_left - 3) {
+ if (text.has_info_icon(row)) {
+ return CURSOR_POINTING_HAND;
+ }
+ return CURSOR_ARROW;
+ }
+
// fold icon
- int gutter_left = left_margin + cache.breakpoint_gutter_width + cache.line_number_w;
- if (draw_fold_gutter && p_pos.x > gutter_left - 6 && p_pos.x <= gutter_left + cache.fold_gutter_width - 3) {
+ if (draw_fold_gutter && p_pos.x > gutter_left + cache.line_number_w - 6 && p_pos.x <= gutter_left + cache.line_number_w + cache.fold_gutter_width - 3) {
if (is_folded(row) || can_fold(row))
return CURSOR_POINTING_HAND;
else
return CURSOR_ARROW;
}
+
return CURSOR_ARROW;
} else {
int row, col;
@@ -4162,7 +4224,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
// eol fold icon
if (is_folded(row)) {
int line_width = text.get_line_width(row);
- line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width - cursor.x_ofs;
+ line_width += cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width - cursor.x_ofs;
if (p_pos.x > line_width - 3 && p_pos.x <= line_width + cache.folded_eol_icon->get_width() + 3) {
return CURSOR_POINTING_HAND;
}
@@ -4973,6 +5035,19 @@ void TextEdit::remove_breakpoints() {
}
}
+void TextEdit::set_line_info_icon(int p_line, Ref<Texture> p_icon, String p_info) {
+ ERR_FAIL_INDEX(p_line, text.size());
+ text.set_info_icon(p_line, p_icon, p_info);
+ update();
+}
+
+void TextEdit::clear_info_icons() {
+ for (int i = 0; i < text.size(); i++) {
+ text.set_info_icon(i, NULL, "");
+ }
+ update();
+}
+
void TextEdit::set_line_as_hidden(int p_line, bool p_hidden) {
ERR_FAIL_INDEX(p_line, text.size());
@@ -5189,6 +5264,17 @@ bool TextEdit::is_folded(int p_line) const {
return false;
}
+Vector<int> TextEdit::get_folded_lines() const {
+ Vector<int> folded_lines;
+
+ for (int i = 0; i < text.size(); i++) {
+ if (is_folded(i)) {
+ folded_lines.push_back(i);
+ }
+ }
+ return folded_lines;
+}
+
void TextEdit::fold_line(int p_line) {
ERR_FAIL_INDEX(p_line, text.size());
@@ -5999,6 +6085,24 @@ int TextEdit::get_fold_gutter_width() const {
return cache.fold_gutter_width;
}
+void TextEdit::set_draw_info_gutter(bool p_draw) {
+ draw_info_gutter = p_draw;
+ update();
+}
+
+bool TextEdit::is_drawing_info_gutter() const {
+ return draw_info_gutter;
+}
+
+void TextEdit::set_info_gutter_width(int p_gutter_width) {
+ info_gutter_width = p_gutter_width;
+ update();
+}
+
+int TextEdit::get_info_gutter_width() const {
+ return info_gutter_width;
+}
+
void TextEdit::set_hiding_enabled(int p_enabled) {
if (!p_enabled)
unhide_all_lines();
@@ -6224,6 +6328,7 @@ void TextEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("request_completion"));
ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "row")));
ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column")));
+ ADD_SIGNAL(MethodInfo("info_clicked", PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::STRING, "info")));
BIND_ENUM_CONSTANT(MENU_CUT);
BIND_ENUM_CONSTANT(MENU_COPY);
@@ -6259,6 +6364,8 @@ TextEdit::TextEdit() {
breakpoint_gutter_width = 0;
cache.fold_gutter_width = 0;
fold_gutter_width = 0;
+ info_gutter_width = 0;
+ cache.info_gutter_width = 0;
set_default_cursor_shape(CURSOR_IBEAM);
indent_size = 4;
@@ -6331,6 +6438,7 @@ TextEdit::TextEdit() {
line_length_guideline_col = 80;
draw_breakpoint_gutter = false;
draw_fold_gutter = false;
+ draw_info_gutter = false;
hiding_enabled = false;
next_operation_is_complex = false;
scroll_past_end_of_file_enabled = false;
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 96b409c6d4..e854032159 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -79,6 +79,8 @@ public:
bool safe : 1;
int wrap_amount_cache : 24;
Map<int, ColorRegionInfo> region_info;
+ Ref<Texture> info_icon;
+ String info;
String data;
};
@@ -109,6 +111,13 @@ public:
bool is_hidden(int p_line) const { return text[p_line].hidden; }
void set_safe(int p_line, bool p_safe) { text.write[p_line].safe = p_safe; }
bool is_safe(int p_line) const { return text[p_line].safe; }
+ void set_info_icon(int p_line, Ref<Texture> p_icon, String p_info) {
+ text.write[p_line].info_icon = p_icon;
+ text.write[p_line].info = p_info;
+ }
+ bool has_info_icon(int p_line) const { return text[p_line].info_icon.is_valid(); }
+ const Ref<Texture> &get_info_icon(int p_line) const { return text[p_line].info_icon; }
+ const String &get_info(int p_line) const { return text[p_line].info; }
void insert(int p_at, const String &p_text);
void remove(int p_at);
int size() const { return text.size(); }
@@ -193,6 +202,7 @@ private:
int line_number_w;
int breakpoint_gutter_width;
int fold_gutter_width;
+ int info_gutter_width;
} cache;
Map<int, int> color_region_cache;
@@ -291,6 +301,8 @@ private:
bool draw_fold_gutter;
int fold_gutter_width;
bool hiding_enabled;
+ bool draw_info_gutter;
+ int info_gutter_width;
bool highlight_all_occurrences;
bool scroll_past_end_of_file_enabled;
@@ -480,6 +492,9 @@ public:
Array get_breakpoints_array() const;
void remove_breakpoints();
+ void set_line_info_icon(int p_line, Ref<Texture> p_icon, String p_info = "");
+ void clear_info_icons();
+
void set_line_as_hidden(int p_line, bool p_hidden);
bool is_line_hidden(int p_line) const;
void fold_all_lines();
@@ -490,6 +505,7 @@ public:
bool can_fold(int p_line) const;
bool is_folded(int p_line) const;
+ Vector<int> get_folded_lines() const;
void fold_line(int p_line);
void unfold_line(int p_line);
void toggle_fold_line(int p_line);
@@ -650,6 +666,12 @@ public:
void set_fold_gutter_width(int p_gutter_width);
int get_fold_gutter_width() const;
+ void set_draw_info_gutter(bool p_draw);
+ bool is_drawing_info_gutter() const;
+
+ void set_info_gutter_width(int p_gutter_width);
+ int get_info_gutter_width() const;
+
void set_hiding_enabled(int p_enabled);
int is_hiding_enabled() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 7e59606d2b..f22fe5b6a5 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -3938,7 +3938,6 @@ Tree::Tree() {
cache.click_item = NULL;
cache.click_column = 0;
cache.hover_cell = -1;
- cache.hover_index = -1;
last_keypress = 0;
focus_in_id = 0;
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 8b68b3215c..e65314644e 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -286,7 +286,7 @@ bool HTTPRequest::_update_connection() {
call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, PoolByteArray());
return true;
}
- if (got_response && body_len < 0) {
+ if (body_len < 0) {
// Chunked transfer is done
call_deferred("_request_done", RESULT_SUCCESS, response_code, response_headers, body);
return true;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index cbe700c826..0465ffe442 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -41,6 +41,8 @@
VARIANT_ENUM_CAST(Node::PauseMode);
+int Node::orphan_node_count = 0;
+
void Node::_notification(int p_notification) {
switch (p_notification) {
@@ -84,11 +86,14 @@ void Node::_notification(int p_notification) {
add_to_group("_vp_unhandled_key_input" + itos(get_viewport()->get_instance_id()));
get_tree()->node_count++;
+ orphan_node_count--;
} break;
case NOTIFICATION_EXIT_TREE: {
get_tree()->node_count--;
+ orphan_node_count++;
+
if (data.input)
remove_from_group("_vp_input" + itos(get_viewport()->get_instance_id()));
if (data.unhandled_input)
@@ -2938,6 +2943,8 @@ Node::Node() {
data.use_placeholder = false;
data.display_folded = false;
data.ready_first = true;
+
+ orphan_node_count++;
}
Node::~Node() {
@@ -2948,6 +2955,8 @@ Node::~Node() {
ERR_FAIL_COND(data.parent);
ERR_FAIL_COND(data.children.size());
+
+ orphan_node_count--;
}
////////////////////////////////
diff --git a/scene/main/node.h b/scene/main/node.h
index b490db37c5..9b9ca06455 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -75,6 +75,8 @@ public:
bool operator()(const Node *p_a, const Node *p_b) const { return p_b->data.process_priority == p_a->data.process_priority ? p_b->is_greater_than(p_a) : p_b->data.process_priority > p_a->data.process_priority; }
};
+ static int orphan_node_count;
+
private:
struct GroupData {
diff --git a/scene/resources/box_shape.cpp b/scene/resources/box_shape.cpp
index d93754076c..d819e9f776 100644
--- a/scene/resources/box_shape.cpp
+++ b/scene/resources/box_shape.cpp
@@ -51,6 +51,7 @@ Vector<Vector3> BoxShape::_gen_debug_mesh_lines() {
void BoxShape::_update_shape() {
PhysicsServer::get_singleton()->shape_set_data(get_shape(), extents);
+ Shape::_update_shape();
}
void BoxShape::set_extents(const Vector3 &p_extents) {
diff --git a/scene/resources/capsule_shape.cpp b/scene/resources/capsule_shape.cpp
index 3f7bf1e0ec..669b261bfe 100644
--- a/scene/resources/capsule_shape.cpp
+++ b/scene/resources/capsule_shape.cpp
@@ -75,6 +75,7 @@ void CapsuleShape::_update_shape() {
d["radius"] = radius;
d["height"] = height;
PhysicsServer::get_singleton()->shape_set_data(get_shape(), d);
+ Shape::_update_shape();
}
void CapsuleShape::set_radius(float p_radius) {
diff --git a/scene/resources/concave_polygon_shape.cpp b/scene/resources/concave_polygon_shape.cpp
index b192d088d8..b4cc38c8c0 100644
--- a/scene/resources/concave_polygon_shape.cpp
+++ b/scene/resources/concave_polygon_shape.cpp
@@ -65,6 +65,7 @@ Vector<Vector3> ConcavePolygonShape::_gen_debug_mesh_lines() {
}
void ConcavePolygonShape::_update_shape() {
+ Shape::_update_shape();
}
void ConcavePolygonShape::set_faces(const PoolVector<Vector3> &p_faces) {
diff --git a/scene/resources/convex_polygon_shape.cpp b/scene/resources/convex_polygon_shape.cpp
index 5845e4be50..499688a185 100644
--- a/scene/resources/convex_polygon_shape.cpp
+++ b/scene/resources/convex_polygon_shape.cpp
@@ -58,7 +58,7 @@ Vector<Vector3> ConvexPolygonShape::_gen_debug_mesh_lines() {
void ConvexPolygonShape::_update_shape() {
PhysicsServer::get_singleton()->shape_set_data(get_shape(), points);
- emit_changed();
+ Shape::_update_shape();
}
void ConvexPolygonShape::set_points(const PoolVector<Vector3> &p_points) {
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 464ca60d31..ece8ad4bb0 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -268,7 +268,7 @@ void Curve::update_auto_tangents(int i) {
}
if (i + 1 < _points.size()) {
- if (p.right_mode == TANGENT_LINEAR && i + 1 < _points.size()) {
+ if (p.right_mode == TANGENT_LINEAR) {
Vector2 v = (_points[i + 1].pos - p.pos).normalized();
p.right_tangent = v.y / v.x;
}
diff --git a/scene/resources/cylinder_shape.cpp b/scene/resources/cylinder_shape.cpp
index 4fd829b349..f60f7ab376 100644
--- a/scene/resources/cylinder_shape.cpp
+++ b/scene/resources/cylinder_shape.cpp
@@ -68,6 +68,7 @@ void CylinderShape::_update_shape() {
d["radius"] = radius;
d["height"] = height;
PhysicsServer::get_singleton()->shape_set_data(get_shape(), d);
+ Shape::_update_shape();
}
void CylinderShape::set_radius(float p_radius) {
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index c7a815d8a4..f425972183 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -795,7 +795,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_font("bold_italics_font", "RichTextLabel", default_font);
theme->set_font("mono_font", "RichTextLabel", default_font);
- theme->set_color("default_color", "RichTextLabel", control_font_color);
+ theme->set_color("default_color", "RichTextLabel", Color(1, 1, 1));
theme->set_color("font_color_selected", "RichTextLabel", font_color_selection);
theme->set_color("selection_color", "RichTextLabel", Color(0.1, 0.1, 1, 0.8));
diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp
index 1b406551ab..be0b9f9ac3 100644
--- a/scene/resources/multimesh.cpp
+++ b/scene/resources/multimesh.cpp
@@ -162,6 +162,16 @@ int MultiMesh::get_instance_count() const {
return instance_count;
}
+void MultiMesh::set_visible_instance_count(int p_count) {
+ ERR_FAIL_COND(p_count < -1);
+ VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, p_count);
+ visible_instance_count = p_count;
+}
+int MultiMesh::get_visible_instance_count() const {
+
+ return visible_instance_count;
+}
+
void MultiMesh::set_instance_transform(int p_instance, const Transform &p_transform) {
VisualServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform);
@@ -255,6 +265,8 @@ void MultiMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_instance_count", "count"), &MultiMesh::set_instance_count);
ClassDB::bind_method(D_METHOD("get_instance_count"), &MultiMesh::get_instance_count);
+ ClassDB::bind_method(D_METHOD("set_visible_instance_count", "count"), &MultiMesh::set_visible_instance_count);
+ ClassDB::bind_method(D_METHOD("get_visible_instance_count"), &MultiMesh::get_visible_instance_count);
ClassDB::bind_method(D_METHOD("set_instance_transform", "instance", "transform"), &MultiMesh::set_instance_transform);
ClassDB::bind_method(D_METHOD("set_instance_transform_2d", "instance", "transform"), &MultiMesh::set_instance_transform_2d);
ClassDB::bind_method(D_METHOD("get_instance_transform", "instance"), &MultiMesh::get_instance_transform);
@@ -276,6 +288,7 @@ void MultiMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "transform_format", PROPERTY_HINT_ENUM, "2D,3D"), "set_transform_format", "get_transform_format");
ADD_PROPERTY(PropertyInfo(Variant::INT, "custom_data_format", PROPERTY_HINT_ENUM, "None,Byte,Float"), "set_custom_data_format", "get_custom_data_format");
ADD_PROPERTY(PropertyInfo(Variant::INT, "instance_count", PROPERTY_HINT_RANGE, "0,16384,1,or_greater"), "set_instance_count", "get_instance_count");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_instance_count", PROPERTY_HINT_RANGE, "-1,16384,1,or_greater"), "set_visible_instance_count", "get_visible_instance_count");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "transform_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_transform_array", "_get_transform_array");
ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "color_array", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_color_array", "_get_color_array");
@@ -299,6 +312,7 @@ MultiMesh::MultiMesh() {
color_format = COLOR_NONE;
custom_data_format = CUSTOM_DATA_NONE;
transform_format = TRANSFORM_2D;
+ visible_instance_count = -1;
instance_count = 0;
}
diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h
index ac2c69e022..24b4beaa89 100644
--- a/scene/resources/multimesh.h
+++ b/scene/resources/multimesh.h
@@ -64,6 +64,7 @@ private:
ColorFormat color_format;
CustomDataFormat custom_data_format;
int instance_count;
+ int visible_instance_count;
protected:
static void _bind_methods();
@@ -93,6 +94,9 @@ public:
void set_instance_count(int p_count);
int get_instance_count() const;
+ void set_visible_instance_count(int p_count);
+ int get_visible_instance_count() const;
+
void set_instance_transform(int p_instance, const Transform &p_transform);
void set_instance_transform_2d(int p_instance, const Transform2D &p_transform);
Transform get_instance_transform(int p_instance) const;
diff --git a/scene/resources/plane_shape.cpp b/scene/resources/plane_shape.cpp
index 419ff8f972..08f6ccd764 100644
--- a/scene/resources/plane_shape.cpp
+++ b/scene/resources/plane_shape.cpp
@@ -64,6 +64,7 @@ Vector<Vector3> PlaneShape::_gen_debug_mesh_lines() {
void PlaneShape::_update_shape() {
PhysicsServer::get_singleton()->shape_set_data(get_shape(), plane);
+ Shape::_update_shape();
}
void PlaneShape::set_plane(Plane p_plane) {
diff --git a/scene/resources/ray_shape.cpp b/scene/resources/ray_shape.cpp
index b7925d8a58..0acfffdc06 100644
--- a/scene/resources/ray_shape.cpp
+++ b/scene/resources/ray_shape.cpp
@@ -47,7 +47,7 @@ void RayShape::_update_shape() {
d["length"] = length;
d["slips_on_slope"] = slips_on_slope;
PhysicsServer::get_singleton()->shape_set_data(get_shape(), d);
- emit_changed();
+ Shape::_update_shape();
}
void RayShape::set_length(float p_length) {
diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp
index 825b7f4c8b..6ba46f066c 100644
--- a/scene/resources/shape.cpp
+++ b/scene/resources/shape.cpp
@@ -96,6 +96,11 @@ Ref<ArrayMesh> Shape::get_debug_mesh() {
return debug_mesh_cache;
}
+void Shape::_update_shape() {
+ emit_changed();
+ debug_mesh_cache.unref();
+}
+
void Shape::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Shape::set_margin);
diff --git a/scene/resources/shape.h b/scene/resources/shape.h
index de99a967a8..ba763eaab1 100644
--- a/scene/resources/shape.h
+++ b/scene/resources/shape.h
@@ -51,6 +51,8 @@ protected:
Shape(RID p_shape);
virtual Vector<Vector3> _gen_debug_mesh_lines() = 0; // { return Vector<Vector3>(); }
+ virtual void _update_shape();
+
public:
virtual RID get_rid() const { return shape; }
diff --git a/scene/resources/sphere_shape.cpp b/scene/resources/sphere_shape.cpp
index 492cf3959d..af89413ced 100644
--- a/scene/resources/sphere_shape.cpp
+++ b/scene/resources/sphere_shape.cpp
@@ -58,6 +58,7 @@ Vector<Vector3> SphereShape::_gen_debug_mesh_lines() {
void SphereShape::_update_shape() {
PhysicsServer::get_singleton()->shape_set_data(get_shape(), radius);
+ Shape::_update_shape();
}
void SphereShape::set_radius(float p_radius) {
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 4229147ba2..b8f21948c3 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -240,6 +240,9 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
if (!g->nodes.has(p_from_node))
return false;
+ if (p_from_node == p_to_node)
+ return false;
+
if (p_from_port < 0 || p_from_port >= g->nodes[p_from_node].node->get_output_port_count())
return false;
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 88f3ed8d15..ad5bcde382 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -201,10 +201,8 @@ void AudioRBResampler::clear() {
return;
//should be stopped at this point but just in case
- if (rb) {
- memdelete_arr(rb);
- memdelete_arr(read_buf);
- }
+ memdelete_arr(rb);
+ memdelete_arr(read_buf);
rb = NULL;
offset = 0;
rb_read_pos = 0;
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index 2dd71f9452..96d5c9df89 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -66,7 +66,7 @@ void AudioEffectRecordInstance::_io_thread_process() {
while (is_recording) {
//Check: The current recording has been requested to stop
- if (is_recording && !base->recording_active) {
+ if (!base->recording_active) {
is_recording = false;
}
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 4ab92715f4..e52cc376c0 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -351,10 +351,8 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_sh
CollisionSolverSW::CallbackResult cbkres = NULL;
PhysicsServerSW::CollCbkData *cbkptr = NULL;
- if (p_result_max > 0) {
- cbkptr = &cbk;
- cbkres = PhysicsServerSW::_shape_col_cbk;
- }
+ cbkptr = &cbk;
+ cbkres = PhysicsServerSW::_shape_col_cbk;
for (int i = 0; i < amount; i++) {
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 56b87f620c..66d2dcd417 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -586,7 +586,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2 &p_point) const {
in = true;
}
- return (in && !out) || (!in && out);
+ return in != out;
}
bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const {
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 831764b40c..f5acadd71c 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -333,10 +333,8 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &
CollisionSolver2DSW::CallbackResult cbkres = NULL;
Physics2DServerSW::CollCbkData *cbkptr = NULL;
- if (p_result_max > 0) {
- cbkptr = &cbk;
- cbkres = Physics2DServerSW::_shape_col_cbk;
- }
+ cbkptr = &cbk;
+ cbkres = Physics2DServerSW::_shape_col_cbk;
for (int i = 0; i < amount; i++) {
@@ -353,7 +351,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D &
cbk.valid_depth = 0;
if (CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
- collided = p_result_max == 0 || cbk.amount > 0;
+ collided = cbk.amount > 0;
}
}
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index 791d59038a..d5e154a7fc 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -33,11 +33,9 @@
#include "visual_server_raster.h"
#include "visual_server_viewport.h"
-void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) {
+static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1;
- static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1;
- RasterizerCanvas::Item *z_list[z_range];
- RasterizerCanvas::Item *z_last_list[z_range];
+void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) {
memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *));
@@ -1456,5 +1454,15 @@ bool VisualServerCanvas::free(RID p_rid) {
}
VisualServerCanvas::VisualServerCanvas() {
+
+ z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *));
+ z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *));
+
disable_scale = false;
}
+
+VisualServerCanvas::~VisualServerCanvas() {
+
+ memfree(z_list);
+ memfree(z_last_list);
+}
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
index 7691d68639..4e99bb3676 100644
--- a/servers/visual/visual_server_canvas.h
+++ b/servers/visual/visual_server_canvas.h
@@ -160,6 +160,9 @@ private:
void _render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights);
+ RasterizerCanvas::Item **z_list;
+ RasterizerCanvas::Item **z_last_list;
+
public:
void render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect);
@@ -254,6 +257,7 @@ public:
bool free(RID p_rid);
VisualServerCanvas();
+ ~VisualServerCanvas();
};
#endif // VISUALSERVERCANVAS_H
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 9c7f474f44..efe2a99d2e 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -430,6 +430,7 @@ public:
BIND0R(RID, camera_create)
BIND4(camera_set_perspective, RID, float, float, float)
BIND4(camera_set_orthogonal, RID, float, float, float)
+ BIND5(camera_set_frustum, RID, float, Vector2, float, float)
BIND2(camera_set_transform, RID, const Transform &)
BIND2(camera_set_cull_mask, RID, uint32_t)
BIND2(camera_set_environment, RID, RID)
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index a5858ab661..c1dc94daa2 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -61,6 +61,16 @@ void VisualServerScene::camera_set_orthogonal(RID p_camera, float p_size, float
camera->zfar = p_z_far;
}
+void VisualServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
+ Camera *camera = camera_owner.get(p_camera);
+ ERR_FAIL_COND(!camera);
+ camera->type = Camera::FRUSTUM;
+ camera->size = p_size;
+ camera->offset = p_offset;
+ camera->znear = p_z_near;
+ camera->zfar = p_z_far;
+}
+
void VisualServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) {
Camera *camera = camera_owner.get(p_camera);
@@ -1730,6 +1740,17 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view
ortho = false;
} break;
+ case Camera::FRUSTUM: {
+
+ camera_matrix.set_frustum(
+ camera->size,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->offset,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect);
+ ortho = false;
+ } break;
}
_prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->visible_layers, p_scenario, p_shadow_atlas, RID());
@@ -1871,7 +1892,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
//failure
} else if (ins->base_type == VS::INSTANCE_LIGHT && ins->visible) {
- if (ins->visible && light_cull_count < MAX_LIGHTS_CULLED) {
+ if (light_cull_count < MAX_LIGHTS_CULLED) {
InstanceLightData *light = static_cast<InstanceLightData *>(ins->base_data);
@@ -1888,7 +1909,7 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca
}
} else if (ins->base_type == VS::INSTANCE_REFLECTION_PROBE && ins->visible) {
- if (ins->visible && reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
+ if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(ins->base_data);
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
index 7583acd88f..2c2ba7e15f 100644
--- a/servers/visual/visual_server_scene.h
+++ b/servers/visual/visual_server_scene.h
@@ -77,12 +77,14 @@ public:
enum Type {
PERSPECTIVE,
- ORTHOGONAL
+ ORTHOGONAL,
+ FRUSTUM
};
Type type;
float fov;
float znear, zfar;
float size;
+ Vector2 offset;
uint32_t visible_layers;
bool vaspect;
RID env;
@@ -97,6 +99,7 @@ public:
znear = 0.05;
zfar = 100;
size = 1.0;
+ offset = Vector2();
vaspect = false;
}
};
@@ -106,6 +109,7 @@ public:
virtual RID camera_create();
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
+ virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
virtual void camera_set_transform(RID p_camera, const Transform &p_transform);
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
virtual void camera_set_environment(RID p_camera, RID p_env);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 9f23ad644e..3e451511cd 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -360,6 +360,7 @@ public:
FUNCRID(camera)
FUNC4(camera_set_perspective, RID, float, float, float)
FUNC4(camera_set_orthogonal, RID, float, float, float)
+ FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
FUNC2(camera_set_transform, RID, const Transform &)
FUNC2(camera_set_cull_mask, RID, uint32_t)
FUNC2(camera_set_environment, RID, RID)
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 19c6106502..041fb2b84f 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -1863,6 +1863,7 @@ void VisualServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("camera_create"), &VisualServer::camera_create);
ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &VisualServer::camera_set_perspective);
ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &VisualServer::camera_set_orthogonal);
+ ClassDB::bind_method(D_METHOD("camera_set_frustum", "camera", "size", "offset", "z_near", "z_far"), &VisualServer::camera_set_frustum);
ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &VisualServer::camera_set_transform);
ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &VisualServer::camera_set_cull_mask);
ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &VisualServer::camera_set_environment);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index c98c5b39a9..7693faf42b 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -584,6 +584,7 @@ public:
virtual RID camera_create() = 0;
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0;
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0;
+ virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0;
virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 815c533645..c98f593920 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -4,7 +4,7 @@
## assimp
- Upstream: http://github.com/assimp/assimp
-- Version: git (d2b45377e4b09a1f43be95e45553afcc06b03f4b)
+- Version: git (d3d98a7ec0c8d38e1952b46dfe53f7e9233dc92d)
- License: BSD-3-Clause
diff --git a/thirdparty/assimp/code/FBXConverter.cpp b/thirdparty/assimp/code/FBXConverter.cpp
index 000c4ed53b..09ae06a64f 100644
--- a/thirdparty/assimp/code/FBXConverter.cpp
+++ b/thirdparty/assimp/code/FBXConverter.cpp
@@ -78,6 +78,16 @@ namespace Assimp {
FBXConverter::FBXConverter(aiScene* out, const Document& doc)
: defaultMaterialIndex()
+ , lights()
+ , cameras()
+ , textures()
+ , materials_converted()
+ , textures_converted()
+ , meshes_converted()
+ , node_anim_chain_bits()
+ , mNodeNameInstances()
+ , mNodeNames()
+ , anim_fps()
, out(out)
, doc(doc) {
// animations need to be converted first since this will
@@ -410,19 +420,24 @@ namespace Assimp {
void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName)
{
- int i = 0;
uniqueName = name;
- while (mNodeNames.find(uniqueName) != mNodeNames.end())
+ int i = 0;
+ auto it = mNodeNameInstances.find(name); // duplicate node name instance count
+ if (it != mNodeNameInstances.end())
{
- ++i;
- std::stringstream ext;
- ext << name << std::setfill('0') << std::setw(3) << i;
- uniqueName = ext.str();
+ i = it->second;
+ while (mNodeNames.find(uniqueName) != mNodeNames.end())
+ {
+ i++;
+ std::stringstream ext;
+ ext << name << std::setfill('0') << std::setw(3) << i;
+ uniqueName = ext.str();
+ }
}
+ mNodeNameInstances[name] = i;
mNodeNames.insert(uniqueName);
}
-
const char* FBXConverter::NameTransformationComp(TransformationComp comp) {
switch (comp) {
case TransformationComp_Translation:
@@ -2041,6 +2056,12 @@ namespace Assimp {
CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
}
+ // try to get the transparency factor
+ const float TransparencyFactor = PropertyGet<float>(props, "TransparencyFactor", ok);
+ if (ok) {
+ out_mat->AddProperty(&TransparencyFactor, 1, AI_MATKEY_TRANSPARENCYFACTOR);
+ }
+
// use of TransparencyFactor is inconsistent.
// Maya always stores it as 1.0,
// so we can't use it to set AI_MATKEY_OPACITY.
diff --git a/thirdparty/assimp/code/FBXConverter.h b/thirdparty/assimp/code/FBXConverter.h
index 398baa445f..50637468b9 100644
--- a/thirdparty/assimp/code/FBXConverter.h
+++ b/thirdparty/assimp/code/FBXConverter.h
@@ -58,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/texture.h>
#include <assimp/camera.h>
#include <assimp/StringComparison.h>
+#include <unordered_map>
+#include <unordered_set>
struct aiScene;
struct aiNode;
@@ -74,8 +76,6 @@ namespace FBX {
class Document;
-using NodeNameCache = std::set<std::string>;
-
/**
* Convert a FBX #Document to #aiScene
* @param out Empty scene to be populated
@@ -419,7 +419,6 @@ private:
void TransferDataToScene();
private:
-
// 0: not assigned yet, others: index is value - 1
unsigned int defaultMaterialIndex;
@@ -429,22 +428,27 @@ private:
std::vector<aiLight*> lights;
std::vector<aiCamera*> cameras;
std::vector<aiTexture*> textures;
-
- typedef std::map<const Material*, unsigned int> MaterialMap;
+ using MaterialMap = std::map<const Material*, unsigned int>;
MaterialMap materials_converted;
- typedef std::map<const Video*, unsigned int> VideoMap;
+ using VideoMap = std::map<const Video*, unsigned int>;
VideoMap textures_converted;
- typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap;
+ using MeshMap = std::map<const Geometry*, std::vector<unsigned int> >;
MeshMap meshes_converted;
// fixed node name -> which trafo chain components have animations?
- typedef std::map<std::string, unsigned int> NodeAnimBitMap;
+ using NodeAnimBitMap = std::map<std::string, unsigned int> ;
NodeAnimBitMap node_anim_chain_bits;
+ // number of nodes with the same name
+ using NodeAnimNameMap = std::unordered_map<std::string, unsigned int>;
+ NodeAnimNameMap mNodeNameInstances;
+
+ using NodeNameCache = std::unordered_set<std::string>;
NodeNameCache mNodeNames;
+
double anim_fps;
aiScene* const out;
diff --git a/thirdparty/assimp/code/FBXMaterial.cpp b/thirdparty/assimp/code/FBXMaterial.cpp
index 08347740fa..f16f134404 100644
--- a/thirdparty/assimp/code/FBXMaterial.cpp
+++ b/thirdparty/assimp/code/FBXMaterial.cpp
@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ByteSwapper.h>
#include <algorithm> // std::transform
+#include "FBXUtil.h"
namespace Assimp {
namespace FBX {
@@ -206,6 +207,20 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc);
+ // 3DS Max and FBX SDK use "Scaling" and "Translation" instead of "ModelUVScaling" and "ModelUVTranslation". Use these properties if available.
+ bool ok;
+ const aiVector3D& scaling = PropertyGet<aiVector3D>(*props, "Scaling", ok);
+ if (ok) {
+ uvScaling.x = scaling.x;
+ uvScaling.y = scaling.y;
+ }
+
+ const aiVector3D& trans = PropertyGet<aiVector3D>(*props, "Translation", ok);
+ if (ok) {
+ uvTrans.x = trans.x;
+ uvTrans.y = trans.y;
+ }
+
// resolve video links
if(doc.Settings().readTextures) {
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
@@ -307,7 +322,22 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
const Token& token = GetRequiredToken(*Content, 0);
const char* data = token.begin();
if (!token.IsBinary()) {
- DOMWarning("video content is not binary data, ignoring", &element);
+ if (*data != '"') {
+ DOMError("embedded content is not surrounded by quotation marks", &element);
+ }
+ else {
+ const char* encodedData = data + 1;
+ size_t encodedDataLen = static_cast<size_t>(token.end() - token.begin());
+ // search for last quotation mark
+ while (encodedDataLen > 1 && encodedData[encodedDataLen] != '"')
+ encodedDataLen--;
+ if (encodedDataLen % 4 != 0) {
+ DOMError("embedded content is invalid, needs to be in base64", &element);
+ }
+ else {
+ contentLength = Util::DecodeBase64(encodedData, encodedDataLen, content);
+ }
+ }
}
else if (static_cast<size_t>(token.end() - data) < 5) {
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
diff --git a/thirdparty/assimp/code/FBXUtil.cpp b/thirdparty/assimp/code/FBXUtil.cpp
index c184c4a00b..fb483161b2 100644
--- a/thirdparty/assimp/code/FBXUtil.cpp
+++ b/thirdparty/assimp/code/FBXUtil.cpp
@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/TinyFormatter.h>
#include <string>
+#include <cstring>
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
@@ -113,6 +114,49 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
text) );
}
+static const uint8_t base64DecodeTable[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0,
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
+ 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
+};
+
+uint8_t DecodeBase64(char ch)
+{
+ return base64DecodeTable[size_t(ch)];
+}
+
+size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
+{
+ if (inLength < 4) {
+ out = 0;
+ return 0;
+ }
+
+ const size_t outLength = (inLength * 3) / 4;
+ out = new uint8_t[outLength];
+ memset(out, 0, outLength);
+
+ size_t i = 0;
+ size_t j = 0;
+ for (i = 0; i < inLength - 4; i += 4)
+ {
+ uint8_t b0 = Util::DecodeBase64(in[i]);
+ uint8_t b1 = Util::DecodeBase64(in[i + 1]);
+ uint8_t b2 = Util::DecodeBase64(in[i + 2]);
+ uint8_t b3 = Util::DecodeBase64(in[i + 3]);
+
+ out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
+ out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
+ out[j++] = (uint8_t)((b2 << 6) | b3);
+ }
+ return outLength;
+}
+
} // !Util
} // !FBX
} // !Assimp
diff --git a/thirdparty/assimp/code/FBXUtil.h b/thirdparty/assimp/code/FBXUtil.h
index 1a37d346b4..6890e015ba 100644
--- a/thirdparty/assimp/code/FBXUtil.h
+++ b/thirdparty/assimp/code/FBXUtil.h
@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXCompileConfig.h"
#include "FBXTokenizer.h"
+#include <stdint.h>
namespace Assimp {
namespace FBX {
@@ -98,6 +99,20 @@ std::string AddLineAndColumn(const std::string& prefix, const std::string& text,
* @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
+/** Decode a single Base64-encoded character.
+*
+* @param ch Character to decode (from base64 to binary).
+* @return decoded byte value*/
+uint8_t DecodeBase64(char ch);
+
+/** Decode a Base64-encoded string
+*
+* @param in Characters to decode.
+* @param inLength Number of characters to decode.
+* @param out Reference to pointer where we will store the decoded data.
+* @return size of the decoded data (number of bytes)*/
+size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
+
}
}
}
diff --git a/thirdparty/assimp/code/Version.cpp b/thirdparty/assimp/code/Version.cpp
index cc94340ac8..0381037ff1 100644
--- a/thirdparty/assimp/code/Version.cpp
+++ b/thirdparty/assimp/code/Version.cpp
@@ -134,7 +134,7 @@ ASSIMP_API aiScene::aiScene()
, mCameras(nullptr)
, mMetaData(nullptr)
, mPrivate(new Assimp::ScenePrivateData()) {
- // empty
+ // empty
}
// ------------------------------------------------------------------------------------------------
diff --git a/thirdparty/assimp/include/assimp/material.h b/thirdparty/assimp/include/assimp/material.h
index b882bbc72c..4b5a1293dd 100644
--- a/thirdparty/assimp/include/assimp/material.h
+++ b/thirdparty/assimp/include/assimp/material.h
@@ -900,6 +900,7 @@ extern "C" {
#define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe",0,0
#define AI_MATKEY_BLEND_FUNC "$mat.blend",0,0
#define AI_MATKEY_OPACITY "$mat.opacity",0,0
+#define AI_MATKEY_TRANSPARENCYFACTOR "$mat.transparencyfactor",0,0
#define AI_MATKEY_BUMPSCALING "$mat.bumpscaling",0,0
#define AI_MATKEY_SHININESS "$mat.shininess",0,0
#define AI_MATKEY_REFLECTIVITY "$mat.reflectivity",0,0