summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/linux_builds.yml4
-rw-r--r--core/config/project_settings.cpp12
-rw-r--r--core/core_bind.cpp34
-rw-r--r--core/core_constants.cpp1
-rw-r--r--core/extension/gdnative_interface.h2
-rw-r--r--core/extension/native_extension.cpp1
-rw-r--r--core/io/dir_access.cpp14
-rw-r--r--core/io/dir_access.h2
-rw-r--r--core/io/logger.cpp10
-rw-r--r--core/io/resource.cpp20
-rw-r--r--core/io/resource_format_binary.cpp22
-rw-r--r--core/object/class_db.cpp13
-rw-r--r--core/object/class_db.h17
-rw-r--r--core/object/make_virtuals.py5
-rw-r--r--core/object/object.h10
-rw-r--r--core/os/os.cpp8
-rw-r--r--core/os/time.cpp20
-rw-r--r--core/os/time.h5
-rw-r--r--core/register_core_types.cpp32
-rw-r--r--doc/classes/@GlobalScope.xml5
-rw-r--r--doc/classes/AudioEffect.xml7
-rw-r--r--doc/classes/AudioEffectInstance.xml15
-rw-r--r--doc/classes/AudioStreamPlaybackResampled.xml19
-rw-r--r--doc/classes/CompressedTexture2D.xml6
-rw-r--r--doc/classes/Curve2D.xml2
-rw-r--r--doc/classes/Curve3D.xml2
-rw-r--r--doc/classes/EditorFileDialog.xml6
-rw-r--r--doc/classes/FileDialog.xml6
-rw-r--r--doc/classes/FontData.xml7
-rw-r--r--doc/classes/ItemList.xml1
-rw-r--r--doc/classes/Material.xml22
-rw-r--r--doc/classes/Mesh.xml83
-rw-r--r--doc/classes/PopupMenu.xml1
-rw-r--r--doc/classes/PrimitiveMesh.xml5
-rw-r--r--doc/classes/ProceduralSkyMaterial.xml6
-rw-r--r--doc/classes/ProjectSettings.xml3
-rw-r--r--doc/classes/Range.xml6
-rw-r--r--doc/classes/Resource.xml5
-rw-r--r--doc/classes/ResourceFormatLoader.xml2
-rw-r--r--doc/classes/StyleBox.xml31
-rw-r--r--doc/classes/TextServer.xml31
-rw-r--r--doc/classes/TextServerExtension.xml31
-rw-r--r--doc/classes/Texture2D.xml52
-rw-r--r--doc/classes/Texture3D.xml30
-rw-r--r--doc/classes/TextureLayered.xml36
-rw-r--r--doc/classes/Time.xml7
-rw-r--r--doc/classes/VisualInstance3D.xml5
-rw-r--r--doc/classes/XRPositionalTracker.xml9
-rw-r--r--editor/action_map_editor.cpp2
-rw-r--r--editor/action_map_editor.h2
-rw-r--r--editor/animation_track_editor.cpp32
-rw-r--r--editor/animation_track_editor.h28
-rw-r--r--editor/animation_track_editor_plugins.cpp18
-rw-r--r--editor/animation_track_editor_plugins.h9
-rw-r--r--editor/code_editor.cpp6
-rw-r--r--editor/code_editor.h8
-rw-r--r--editor/create_dialog.cpp4
-rw-r--r--editor/dependency_editor.cpp3
-rw-r--r--editor/editor_asset_installer.cpp6
-rw-r--r--editor/editor_asset_installer.h2
-rw-r--r--editor/editor_audio_buses.cpp7
-rw-r--r--editor/editor_audio_buses.h6
-rw-r--r--editor/editor_autoload_settings.cpp63
-rw-r--r--editor/editor_autoload_settings.h22
-rw-r--r--editor/editor_data.cpp3
-rw-r--r--editor/editor_data.h6
-rw-r--r--editor/editor_dir_dialog.cpp4
-rw-r--r--editor/editor_dir_dialog.h4
-rw-r--r--editor/editor_export.cpp11
-rw-r--r--editor/editor_export.h4
-rw-r--r--editor/editor_feature_profile.cpp6
-rw-r--r--editor/editor_feature_profile.h2
-rw-r--r--editor/editor_file_dialog.cpp36
-rw-r--r--editor/editor_file_dialog.h8
-rw-r--r--editor/editor_file_system.cpp14
-rw-r--r--editor/editor_file_system.h20
-rw-r--r--editor/editor_fonts.cpp4
-rw-r--r--editor/editor_help.cpp2
-rw-r--r--editor/editor_help.h4
-rw-r--r--editor/editor_help_search.cpp2
-rw-r--r--editor/editor_help_search.h2
-rw-r--r--editor/editor_inspector.cpp45
-rw-r--r--editor/editor_inspector.h56
-rw-r--r--editor/editor_node.cpp44
-rw-r--r--editor/editor_node.h33
-rw-r--r--editor/editor_plugin_settings.cpp2
-rw-r--r--editor/editor_plugin_settings.h2
-rw-r--r--editor/editor_properties.cpp32
-rw-r--r--editor/editor_properties.h44
-rw-r--r--editor/editor_properties_array_dict.cpp236
-rw-r--r--editor/editor_properties_array_dict.h42
-rw-r--r--editor/editor_property_name_processor.cpp121
-rw-r--r--editor/editor_property_name_processor.h58
-rw-r--r--editor/editor_run_native.cpp3
-rw-r--r--editor/editor_run_native.h2
-rw-r--r--editor/editor_sectioned_inspector.cpp4
-rw-r--r--editor/editor_settings.cpp12
-rw-r--r--editor/editor_settings.h4
-rw-r--r--editor/editor_settings_dialog.cpp6
-rw-r--r--editor/editor_settings_dialog.h2
-rw-r--r--editor/editor_spin_slider.cpp11
-rw-r--r--editor/editor_spin_slider.h22
-rw-r--r--editor/editor_themes.cpp7
-rw-r--r--editor/editor_vcs_interface.cpp1
-rw-r--r--editor/editor_vcs_interface.h2
-rw-r--r--editor/export_template_manager.cpp3
-rw-r--r--editor/filesystem_dock.cpp54
-rw-r--r--editor/filesystem_dock.h10
-rw-r--r--editor/find_in_files.cpp2
-rw-r--r--editor/find_in_files.h2
-rw-r--r--editor/icons/CompressedTexture2D.svg (renamed from editor/icons/StreamTexture.svg)0
-rw-r--r--editor/import/dynamic_font_import_settings.cpp14
-rw-r--r--editor/import/resource_importer_dynamic_font.cpp6
-rw-r--r--editor/import/resource_importer_layered_texture.cpp16
-rw-r--r--editor/import/resource_importer_layered_texture.h2
-rw-r--r--editor/import/resource_importer_texture.cpp14
-rw-r--r--editor/import/resource_importer_texture.h4
-rw-r--r--editor/import_dock.cpp6
-rw-r--r--editor/localization_editor.cpp1
-rw-r--r--editor/localization_editor.h2
-rw-r--r--editor/plugin_config_dialog.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp9
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp45
-rw-r--r--editor/plugins/animation_state_machine_editor.h2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/debugger_editor_plugin.cpp18
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.cpp8
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp10
-rw-r--r--editor/plugins/multimesh_editor_plugin.cpp6
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp5
-rw-r--r--editor/plugins/script_editor_plugin.cpp4
-rw-r--r--editor/plugins/script_text_editor.cpp4
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_editor.cpp2
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp2
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp2
-rw-r--r--editor/project_export.cpp7
-rw-r--r--editor/project_export.h6
-rw-r--r--editor/project_manager.cpp32
-rw-r--r--editor/property_editor.cpp5
-rw-r--r--editor/property_editor.h4
-rw-r--r--editor/property_selector.cpp1
-rw-r--r--editor/property_selector.h2
-rw-r--r--editor/quick_open.cpp2
-rw-r--r--editor/quick_open.h2
-rw-r--r--editor/scene_tree_dock.cpp7
-rw-r--r--editor/scene_tree_dock.h8
-rw-r--r--editor/scene_tree_editor.cpp10
-rw-r--r--editor/scene_tree_editor.h18
-rw-r--r--editor/script_create_dialog.cpp54
-rw-r--r--editor/script_create_dialog.h28
-rwxr-xr-xeditor/translations/extract.py172
-rw-r--r--main/main.cpp12
-rw-r--r--misc/dist/osx_template.app/Contents/Info.plist2
-rw-r--r--misc/dist/osx_tools.app/Contents/Info.plist2
-rw-r--r--modules/csg/csg_shape.cpp30
-rw-r--r--modules/csg/csg_shape.h1
-rw-r--r--modules/csg/register_types.cpp4
-rw-r--r--modules/enet/register_types.cpp2
-rw-r--r--modules/minimp3/audio_stream_mp3.cpp2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs5
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs5
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp3
-rw-r--r--modules/openxr/doc_classes/OpenXRInterface.xml27
-rw-r--r--modules/openxr/openxr_api.cpp456
-rw-r--r--modules/openxr/openxr_api.h83
-rw-r--r--modules/openxr/openxr_interface.cpp224
-rw-r--r--modules/openxr/openxr_interface.h48
-rw-r--r--modules/openxr/openxr_util.cpp14
-rw-r--r--modules/openxr/openxr_util.h1
-rw-r--r--modules/openxr/register_types.cpp13
-rw-r--r--modules/text_server_adv/text_server_adv.cpp103
-rw-r--r--modules/text_server_adv/text_server_adv.h12
-rw-r--r--modules/text_server_fb/text_server_fb.cpp81
-rw-r--r--modules/text_server_fb/text_server_fb.h10
-rw-r--r--modules/visual_script/editor/visual_script_editor.cpp2
-rw-r--r--modules/visual_script/editor/visual_script_editor.h2
-rw-r--r--modules/visual_script/register_types.cpp4
-rw-r--r--modules/visual_script/visual_script_expression.cpp2
-rw-r--r--modules/visual_script/visual_script_flow_control.cpp28
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp49
-rw-r--r--modules/visual_script/visual_script_nodes.cpp52
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp27
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp2
-rw-r--r--modules/webrtc/register_types.cpp2
-rw-r--r--modules/websocket/register_types.cpp2
-rw-r--r--modules/webxr/register_types.cpp2
-rw-r--r--platform/android/export/export_plugin.cpp6
-rw-r--r--platform/android/export/gradle_export_util.cpp9
-rw-r--r--platform/iphone/export/export_plugin.cpp181
-rw-r--r--platform/iphone/os_iphone.mm4
-rw-r--r--platform/javascript/api/api.cpp4
-rw-r--r--platform/javascript/api/javascript_tools_editor_plugin.cpp2
-rw-r--r--platform/javascript/export/export_plugin.cpp22
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp42
-rw-r--r--platform/osx/export/codesign.cpp4
-rw-r--r--platform/osx/export/export_plugin.cpp118
-rw-r--r--scene/3d/cpu_particles_3d.cpp4
-rw-r--r--scene/3d/cpu_particles_3d.h1
-rw-r--r--scene/3d/decal.cpp4
-rw-r--r--scene/3d/decal.h1
-rw-r--r--scene/3d/fog_volume.h1
-rw-r--r--scene/3d/gpu_particles_3d.cpp4
-rw-r--r--scene/3d/gpu_particles_3d.h1
-rw-r--r--scene/3d/gpu_particles_collision_3d.h4
-rw-r--r--scene/3d/light_3d.cpp4
-rw-r--r--scene/3d/light_3d.h1
-rw-r--r--scene/3d/lightmap_gi.cpp4
-rw-r--r--scene/3d/lightmap_gi.h1
-rw-r--r--scene/3d/mesh_instance_3d.cpp12
-rw-r--r--scene/3d/mesh_instance_3d.h1
-rw-r--r--scene/3d/multimesh_instance_3d.cpp4
-rw-r--r--scene/3d/multimesh_instance_3d.h2
-rw-r--r--scene/3d/occluder_instance_3d.cpp4
-rw-r--r--scene/3d/occluder_instance_3d.h1
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/3d/reflection_probe.h1
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/3d/sprite_3d.h2
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.cpp4
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.h2
-rw-r--r--scene/3d/visual_instance_3d.cpp9
-rw-r--r--scene/3d/visual_instance_3d.h4
-rw-r--r--scene/3d/voxel_gi.cpp4
-rw-r--r--scene/3d/voxel_gi.h1
-rw-r--r--scene/animation/root_motion_view.cpp4
-rw-r--r--scene/animation/root_motion_view.h1
-rw-r--r--scene/gui/file_dialog.cpp8
-rw-r--r--scene/gui/file_dialog.h1
-rw-r--r--scene/gui/graph_edit.cpp2
-rw-r--r--scene/gui/item_list.cpp48
-rw-r--r--scene/gui/popup_menu.cpp60
-rw-r--r--scene/gui/range.cpp5
-rw-r--r--scene/gui/range.h4
-rw-r--r--scene/gui/rich_text_label.cpp23
-rw-r--r--scene/gui/spin_box.cpp3
-rw-r--r--scene/gui/spin_box.h2
-rw-r--r--scene/gui/text_edit.cpp6
-rw-r--r--scene/register_scene_types.cpp94
-rw-r--r--scene/resources/default_theme/default_theme.cpp37
-rw-r--r--scene/resources/default_theme/default_theme.h2
-rw-r--r--scene/resources/font.cpp42
-rw-r--r--scene/resources/font.h8
-rw-r--r--scene/resources/material.cpp36
-rw-r--r--scene/resources/material.h13
-rw-r--r--scene/resources/mesh.cpp131
-rw-r--r--scene/resources/mesh.h63
-rw-r--r--scene/resources/primitive_meshes.cpp12
-rw-r--r--scene/resources/primitive_meshes.h3
-rw-r--r--scene/resources/resource_format_text.cpp3
-rw-r--r--scene/resources/sky_material.cpp33
-rw-r--r--scene/resources/sky_material.h8
-rw-r--r--scene/resources/style_box.cpp33
-rw-r--r--scene/resources/style_box.h10
-rw-r--r--scene/resources/texture.cpp252
-rw-r--r--scene/resources/texture.h62
-rw-r--r--servers/audio/audio_effect.cpp31
-rw-r--r--servers/audio/audio_effect.h18
-rw-r--r--servers/audio/audio_stream.cpp32
-rw-r--r--servers/audio/audio_stream.h11
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp2
-rw-r--r--servers/register_server_types.cpp32
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/shaders/sky.glsl9
-rw-r--r--servers/text/text_server_extension.cpp30
-rw-r--r--servers/text/text_server_extension.h10
-rw-r--r--servers/text_server.cpp6
-rw-r--r--servers/text_server.h6
-rw-r--r--servers/xr/xr_positional_tracker.cpp17
-rw-r--r--servers/xr/xr_positional_tracker.h5
-rw-r--r--tests/core/math/test_vector2.h3
-rw-r--r--tests/core/math/test_vector3.h3
-rw-r--r--tests/core/test_time.h3
276 files changed, 3829 insertions, 1632 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index bb3416743b..d75680b4b5 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -36,7 +36,9 @@ jobs:
tests: true
sconsflags: float=64 use_asan=yes use_ubsan=yes
proj-test: true
- godot-cpp-test: true
+ # Can be turned off for PRs that intentionally break compat with godot-cpp,
+ # until both the upstream PR and the matching godot-cpp changes are merged.
+ godot-cpp-test: false
bin: "./bin/godot.linuxbsd.double.tools.64.san"
build-mono: false
# Skip 2GiB artifact speeding up action.
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 83f58311f1..93c1abe7b5 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -145,7 +145,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
return p_path.simplify_path();
}
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String path = p_path.replace("\\", "/").simplify_path();
@@ -153,8 +153,6 @@ String ProjectSettings::localize_path(const String &p_path) const {
String cwd = dir->get_current_dir();
cwd = cwd.replace("\\", "/");
- memdelete(dir);
-
// Ensure that we end with a '/'.
// This is important to ensure that we do not wrongly localize the resource path
// in an absolute path that just happens to contain this string but points to a
@@ -173,8 +171,6 @@ String ProjectSettings::localize_path(const String &p_path) const {
return cwd.replace_first(res_path, "res://");
} else {
- memdelete(dir);
-
int sep = path.rfind("/");
if (sep == -1) {
return "res://" + path;
@@ -541,7 +537,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// Nothing was found, try to find a project file in provided path (`p_path`)
// or, if requested (`p_upwards`) in parent directories.
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
ERR_FAIL_COND_V_MSG(!d, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
d->change_dir(p_path);
@@ -573,8 +569,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
}
}
- memdelete(d);
-
if (!found) {
return err;
}
@@ -1199,6 +1193,8 @@ ProjectSettings::ProjectSettings() {
singleton = this;
GLOBAL_DEF_BASIC("application/config/name", "");
+ GLOBAL_DEF_BASIC("application/config/name_localized", Dictionary());
+ custom_prop_info["application/config/name_localized"] = PropertyInfo(Variant::DICTIONARY, "application/config/name_localized", PROPERTY_HINT_LOCALIZABLE_STRING);
GLOBAL_DEF_BASIC("application/config/description", "");
custom_prop_info["application/config/description"] = PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT);
GLOBAL_DEF_BASIC("application/run/main_scene", "");
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 590d1c12c6..2d0eaadbdf 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1569,10 +1569,8 @@ String Directory::get_current_dir() {
Error Directory::make_dir(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_dir);
- Error err = d->make_dir(p_dir);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_dir);
+ return da->make_dir(p_dir);
}
return d->make_dir(p_dir);
}
@@ -1580,10 +1578,8 @@ Error Directory::make_dir(String p_dir) {
Error Directory::make_dir_recursive(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_dir);
- Error err = d->make_dir_recursive(p_dir);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_dir);
+ return da->make_dir_recursive(p_dir);
}
return d->make_dir_recursive(p_dir);
}
@@ -1593,19 +1589,14 @@ bool Directory::file_exists(String p_file) {
if (!p_file.is_relative_path()) {
return FileAccess::exists(p_file);
}
-
return d->file_exists(p_file);
}
bool Directory::dir_exists(String p_dir) {
ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_dir);
- bool exists = d->dir_exists(p_dir);
- memdelete(d);
- return exists;
+ return DirAccess::exists(p_dir);
}
-
return d->dir_exists(p_dir);
}
@@ -1624,11 +1615,9 @@ Error Directory::rename(String p_from, String p_to) {
ERR_FAIL_COND_V_MSG(p_from.is_empty() || p_from == "." || p_from == "..", ERR_INVALID_PARAMETER, "Invalid path to rename.");
if (!p_from.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_from);
- ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
- Error err = d->rename(p_from, p_to);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_from);
+ ERR_FAIL_COND_V_MSG(!da->file_exists(p_from) && !da->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
+ return da->rename(p_from, p_to);
}
ERR_FAIL_COND_V_MSG(!d->file_exists(p_from) && !d->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
@@ -1638,10 +1627,8 @@ Error Directory::rename(String p_from, String p_to) {
Error Directory::remove(String p_name) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_name.is_relative_path()) {
- DirAccess *d = DirAccess::create_for_path(p_name);
- Error err = d->remove(p_name);
- memdelete(d);
- return err;
+ DirAccessRef da = DirAccess::create_for_path(p_name);
+ return da->remove(p_name);
}
return d->remove(p_name);
@@ -1664,7 +1651,6 @@ void Directory::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_dir_recursive", "path"), &Directory::make_dir_recursive);
ClassDB::bind_method(D_METHOD("file_exists", "path"), &Directory::file_exists);
ClassDB::bind_method(D_METHOD("dir_exists", "path"), &Directory::dir_exists);
- //ClassDB::bind_method(D_METHOD("get_modified_time","file"),&Directory::get_modified_time);
ClassDB::bind_method(D_METHOD("get_space_left"), &Directory::get_space_left);
ClassDB::bind_method(D_METHOD("copy", "from", "to"), &Directory::copy);
ClassDB::bind_method(D_METHOD("rename", "from", "to"), &Directory::rename);
diff --git a/core/core_constants.cpp b/core/core_constants.cpp
index 89926ee81b..98b720ab65 100644
--- a/core/core_constants.cpp
+++ b/core/core_constants.cpp
@@ -591,6 +591,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID);
+ BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE);
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 62934d1d73..76e87eaf23 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -194,6 +194,7 @@ typedef void *GDExtensionClassInstancePtr;
typedef GDNativeBool (*GDNativeExtensionClassSet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, const GDNativeVariantPtr p_value);
typedef GDNativeBool (*GDNativeExtensionClassGet)(GDExtensionClassInstancePtr p_instance, const GDNativeStringNamePtr p_name, GDNativeVariantPtr r_ret);
+typedef uint64_t (*GDNativeExtensionClassGetRID)(GDExtensionClassInstancePtr p_instance);
typedef struct {
uint32_t type;
@@ -228,6 +229,7 @@ typedef struct {
GDNativeExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
GDNativeExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
GDNativeExtensionClassGetVirtual get_virtual_func;
+ GDNativeExtensionClassGetRID get_rid_func;
void *class_userdata;
} GDNativeExtensionClassCreationInfo;
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 325ccec6c4..1a39c937e8 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -158,6 +158,7 @@ void NativeExtension::_register_extension_class(const GDNativeExtensionClassLibr
extension->native_extension.create_instance = p_extension_funcs->create_instance_func;
extension->native_extension.free_instance = p_extension_funcs->free_instance_func;
extension->native_extension.get_virtual = p_extension_funcs->get_virtual_func;
+ extension->native_extension.get_rid = p_extension_funcs->get_rid_func;
ClassDB::register_extension_class(&extension->native_extension);
}
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index 86d8dea3d9..73efdeb38e 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -250,6 +250,14 @@ DirAccess *DirAccess::create(AccessType p_access) {
DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr;
if (da) {
da->_access_type = p_access;
+
+ // for ACCESS_RESOURCES and ACCESS_FILESYSTEM, current_dir already defaults to where game was started
+ // in case current directory is force changed elsewhere for ACCESS_RESOURCES
+ if (p_access == ACCESS_RESOURCES) {
+ da->change_dir("res://");
+ } else if (p_access == ACCESS_USERDATA) {
+ da->change_dir("user://");
+ }
}
return da;
@@ -414,8 +422,6 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_
}
bool DirAccess::exists(String p_dir) {
- DirAccess *da = DirAccess::create_for_path(p_dir);
- bool valid = da->change_dir(p_dir) == OK;
- memdelete(da);
- return valid;
+ DirAccessRef da = DirAccess::create_for_path(p_dir);
+ return da->change_dir(p_dir) == OK;
}
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index 8154f5366c..d63453e947 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -134,7 +134,7 @@ struct DirAccessRef {
operator bool() const { return f != nullptr; }
- DirAccess *f;
+ DirAccess *f = nullptr;
DirAccessRef(DirAccess *fa) { f = fa; }
~DirAccessRef() {
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index cb6369ae3d..2b6f230434 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -128,7 +128,7 @@ void RotatedFileLogger::clear_old_backups() {
String basename = base_path.get_file().get_basename();
String extension = base_path.get_extension();
- DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ DirAccessRef da = DirAccess::open(base_path.get_base_dir());
if (!da) {
return;
}
@@ -152,8 +152,6 @@ void RotatedFileLogger::clear_old_backups() {
da->remove(E->get());
}
}
-
- memdelete(da);
}
void RotatedFileLogger::rotate_file() {
@@ -167,18 +165,16 @@ void RotatedFileLogger::rotate_file() {
backup_name += "." + base_path.get_extension();
}
- DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ DirAccessRef da = DirAccess::open(base_path.get_base_dir());
if (da) {
da->copy(base_path, backup_name);
- memdelete(da);
}
clear_old_backups();
}
} else {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_USERDATA);
if (da) {
da->make_dir_recursive(base_path.get_base_dir());
- memdelete(da);
}
}
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index 66d5c54b53..f90a6e9304 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -290,6 +290,21 @@ void Resource::_take_over_path(const String &p_path) {
}
RID Resource::get_rid() const {
+ if (get_script_instance()) {
+ Callable::CallError ce;
+ RID ret = get_script_instance()->callp(SNAME("_get_rid"), nullptr, 0, ce);
+ if (ce.error == Callable::CallError::CALL_OK && ret.is_valid()) {
+ return ret;
+ }
+ }
+ if (_get_extension() && _get_extension()->get_rid) {
+ RID ret;
+ ret.from_uint64(_get_extension()->get_rid(_get_extension_instance()));
+ if (ret.is_valid()) {
+ return ret;
+ }
+ }
+
return RID();
}
@@ -428,6 +443,11 @@ void Resource::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resource_local_to_scene"), "set_local_to_scene", "is_local_to_scene");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_path", "get_path");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "resource_name"), "set_name", "get_name");
+
+ MethodInfo get_rid_bind("_get_rid");
+ get_rid_bind.return_val.type = Variant::RID;
+
+ ::ClassDB::add_virtual_method(get_class_static(), get_rid_bind, true, Vector<String>(), true);
}
Resource::Resource() :
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index ee59a916f1..b65993e3dd 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1032,7 +1032,6 @@ RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_origi
String path = !p_original_path.is_empty() ? p_original_path : p_path;
loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.open(f);
err = loader.load();
@@ -1086,17 +1085,14 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str
ResourceLoaderBinary loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.get_dependencies(f, p_dependencies, p_add_types);
}
Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
- //Error error=OK;
-
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
- FileAccess *fw = nullptr; //=FileAccess::open(p_path+".depren");
+ FileAccess *fw = nullptr;
String local_path = p_path.get_base_dir();
@@ -1158,10 +1154,12 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) {
memdelete(f);
memdelete(fw);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->remove(p_path + ".depren");
- memdelete(da);
- //use the old approach
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->remove(p_path + ".depren");
+ }
+
+ // Use the old approach.
WARN_PRINT("This file is old, so it can't refactor dependencies, opening and resaving '" + p_path + "'.");
@@ -1174,7 +1172,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
loader.remaps = p_map;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.open(f);
err = loader.load();
@@ -1304,10 +1301,9 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
return ERR_CANT_CREATE;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(p_path);
da->rename(p_path + ".depren", p_path);
- memdelete(da);
return OK;
}
@@ -1320,7 +1316,6 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
ResourceLoaderBinary loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
String r = loader.recognize(f);
return ClassDB::get_compatibility_remapped_class(r);
}
@@ -1339,7 +1334,6 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat
ResourceLoaderBinary loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( Globals::get_singleton()->localize_path(p_path) );
loader.open(f, true);
if (loader.error != OK) {
return ResourceUID::INVALID_ID; //could not read
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index 4a71597f84..08e12dfcaa 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -557,6 +557,19 @@ bool ClassDB::can_instantiate(const StringName &p_class) {
return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance));
}
+bool ClassDB::is_virtual(const StringName &p_class) {
+ OBJTYPE_RLOCK;
+
+ ClassInfo *ti = classes.getptr(p_class);
+ ERR_FAIL_COND_V_MSG(!ti, false, "Cannot get class '" + String(p_class) + "'.");
+#ifdef TOOLS_ENABLED
+ if (ti->api == API_EDITOR && !Engine::get_singleton()->is_editor_hint()) {
+ return false;
+ }
+#endif
+ return (!ti->disabled && ti->creation_func != nullptr && !(ti->native_extension && !ti->native_extension->create_instance) && ti->is_virtual);
+}
+
void ClassDB::_add_class2(const StringName &p_class, const StringName &p_inherits) {
OBJTYPE_WLOCK;
diff --git a/core/object/class_db.h b/core/object/class_db.h
index 5d258a29bf..580ae3582f 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -118,6 +118,7 @@ public:
StringName name;
bool disabled = false;
bool exposed = false;
+ bool is_virtual = false;
Object *(*creation_func)() = nullptr;
ClassInfo() {}
@@ -156,20 +157,21 @@ public:
}
template <class T>
- static void register_class() {
+ static void register_class(bool p_virtual = false) {
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
ERR_FAIL_COND(!t);
t->creation_func = &creator<T>;
t->exposed = true;
+ t->is_virtual = p_virtual;
t->class_ptr = T::get_class_ptr_static();
t->api = current_api;
T::register_custom_data_to_otdb();
}
template <class T>
- static void register_virtual_class() {
+ static void register_abstract_class() {
GLOBAL_LOCK_FUNCTION;
T::initialize_class();
ClassInfo *t = classes.getptr(T::get_class_static());
@@ -210,6 +212,7 @@ public:
static bool class_exists(const StringName &p_class);
static bool is_parent_class(const StringName &p_class, const StringName &p_inherits);
static bool can_instantiate(const StringName &p_class);
+ static bool is_virtual(const StringName &p_class);
static Object *instantiate(const StringName &p_class);
static void set_object_extension_instance(Object *p_object, const StringName &p_class, GDExtensionClassInstancePtr p_instance);
@@ -436,9 +439,13 @@ _FORCE_INLINE_ Vector<Error> errarray(P... p_args) {
if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
::ClassDB::register_class<m_class>(); \
}
-#define GDREGISTER_VIRTUAL_CLASS(m_class) \
- if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
- ::ClassDB::register_virtual_class<m_class>(); \
+#define GDREGISTER_VIRTUAL_CLASS(m_class) \
+ if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ ::ClassDB::register_class<m_class>(true); \
+ }
+#define GDREGISTER_ABSTRACT_CLASS(m_class) \
+ if (!GD_IS_DEFINED(ClassDB_Disable_##m_class)) { \
+ ::ClassDB::register_abstract_class<m_class>(); \
}
#include "core/disabled_classes.gen.h"
diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py
index 552f2fa2bf..2e909b8042 100644
--- a/core/object/make_virtuals.py
+++ b/core/object/make_virtuals.py
@@ -3,6 +3,7 @@ proto = """
StringName _gdvirtual_##m_name##_sn = #m_name;\\
mutable bool _gdvirtual_##m_name##_initialized = false;\\
mutable GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\
+template<bool required>\\
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
if (script_instance) {\\
@@ -25,6 +26,10 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
$CALLPTRRET\\
return true;\\
}\\
+ \\
+ if (required) {\\
+ WARN_PRINT_ONCE("Required virtual method: "+get_class()+"::" + #m_name + " must be overriden before calling.");\\
+ }\\
\\
return false;\\
}\\
diff --git a/core/object/object.h b/core/object/object.h
index 8a8b6b5487..6b4f1c81e6 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -88,6 +88,7 @@ enum PropertyHint {
PROPERTY_HINT_ARRAY_TYPE,
PROPERTY_HINT_INT_IS_POINTER,
PROPERTY_HINT_LOCALE_ID,
+ PROPERTY_HINT_LOCALIZABLE_STRING,
PROPERTY_HINT_MAX,
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
};
@@ -255,6 +256,7 @@ struct ObjectNativeExtension {
GDNativeExtensionClassToString to_string;
GDNativeExtensionClassReference reference;
GDNativeExtensionClassReference unreference;
+ GDNativeExtensionClassGetRID get_rid;
_FORCE_INLINE_ bool is_class(const String &p_class) const {
const ObjectNativeExtension *e = this;
@@ -273,8 +275,12 @@ struct ObjectNativeExtension {
GDNativeExtensionClassGetVirtual get_virtual;
};
-#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
-#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__)
+#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
+#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<false>(__VA_ARGS__)
+
+#define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call<true>(__VA_ARGS__)
+#define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<true>(__VA_ARGS__)
+
#ifdef DEBUG_METHODS_ENABLED
#define GDVIRTUAL_BIND(m_name, ...) ::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), true, sarray(__VA_ARGS__));
#else
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 9837b6e0aa..2e5db145a4 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -328,17 +328,13 @@ void OS::yield() {
void OS::ensure_user_data_dir() {
String dd = get_user_data_dir();
- DirAccess *da = DirAccess::open(dd);
- if (da) {
- memdelete(da);
+ if (DirAccess::exists(dd)) {
return;
}
- da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = da->make_dir_recursive(dd);
ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + ".");
-
- memdelete(da);
}
String OS::get_model_name() const {
diff --git a/core/os/time.cpp b/core/os/time.cpp
index 5eae94279a..e339805475 100644
--- a/core/os/time.cpp
+++ b/core/os/time.cpp
@@ -270,7 +270,7 @@ Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday
return dict;
}
-String Time::get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_space) const {
+String Time::get_datetime_string_from_dict(const Dictionary p_datetime, bool p_use_space) const {
ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), "", "Invalid datetime Dictionary: Dictionary is empty.");
EXTRACT_FROM_DICTIONARY
// vformat only supports up to 6 arguments, so we need to split this up into 2 parts.
@@ -283,7 +283,7 @@ String Time::get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_spa
return timestamp;
}
-int64_t Time::get_unix_time_from_datetime_dict(Dictionary p_datetime) const {
+int64_t Time::get_unix_time_from_datetime_dict(const Dictionary p_datetime) const {
ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty");
EXTRACT_FROM_DICTIONARY
VALIDATE_YMDHMS
@@ -298,6 +298,21 @@ int64_t Time::get_unix_time_from_datetime_string(String p_datetime) const {
return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second;
}
+String Time::get_offset_string_from_offset_minutes(int64_t p_offset_minutes) const {
+ String sign;
+ if (p_offset_minutes < 0) {
+ sign = "-";
+ p_offset_minutes = -p_offset_minutes;
+ } else {
+ sign = "+";
+ }
+ // These two lines can be optimized to one instruction on x86 and others.
+ // Note that % is acceptable here only because we ensure it's positive.
+ int64_t offset_hours = p_offset_minutes / 60;
+ int64_t offset_minutes = p_offset_minutes % 60;
+ return vformat("%s%02d:%02d", sign, offset_hours, offset_minutes);
+}
+
Dictionary Time::get_datetime_dict_from_system(bool p_utc) const {
OS::Date date = OS::get_singleton()->get_date(p_utc);
OS::Time time = OS::get_singleton()->get_time(p_utc);
@@ -389,6 +404,7 @@ void Time::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_datetime_string_from_dict", "datetime", "use_space"), &Time::get_datetime_string_from_dict);
ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_dict", "datetime"), &Time::get_unix_time_from_datetime_dict);
ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime_string", "datetime"), &Time::get_unix_time_from_datetime_string);
+ ClassDB::bind_method(D_METHOD("get_offset_string_from_offset_minutes", "offset_minutes"), &Time::get_offset_string_from_offset_minutes);
ClassDB::bind_method(D_METHOD("get_datetime_dict_from_system", "utc"), &Time::get_datetime_dict_from_system, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_date_dict_from_system", "utc"), &Time::get_date_dict_from_system, DEFVAL(false));
diff --git a/core/os/time.h b/core/os/time.h
index 3f00ba1478..0021c0ac6f 100644
--- a/core/os/time.h
+++ b/core/os/time.h
@@ -86,9 +86,10 @@ public:
String get_date_string_from_unix_time(int64_t p_unix_time_val) const;
String get_time_string_from_unix_time(int64_t p_unix_time_val) const;
Dictionary get_datetime_dict_from_string(String p_datetime, bool p_weekday = true) const;
- String get_datetime_string_from_dict(Dictionary p_datetime, bool p_use_space = false) const;
- int64_t get_unix_time_from_datetime_dict(Dictionary p_datetime) const;
+ String get_datetime_string_from_dict(const Dictionary p_datetime, bool p_use_space = false) const;
+ int64_t get_unix_time_from_datetime_dict(const Dictionary p_datetime) const;
int64_t get_unix_time_from_datetime_string(String p_datetime) const;
+ String get_offset_string_from_offset_minutes(int64_t p_offset_minutes) const;
// Methods that get information from OS.
Dictionary get_datetime_dict_from_system(bool p_utc = false) const;
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 63aa8050c4..2aa47c6c96 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -141,7 +141,7 @@ void register_core_types() {
GDREGISTER_CLASS(Object);
- GDREGISTER_VIRTUAL_CLASS(Script);
+ GDREGISTER_ABSTRACT_CLASS(Script);
GDREGISTER_CLASS(RefCounted);
GDREGISTER_CLASS(WeakRef);
@@ -149,12 +149,12 @@ void register_core_types() {
GDREGISTER_CLASS(Image);
GDREGISTER_CLASS(Shortcut);
- GDREGISTER_VIRTUAL_CLASS(InputEvent);
- GDREGISTER_VIRTUAL_CLASS(InputEventWithModifiers);
- GDREGISTER_VIRTUAL_CLASS(InputEventFromWindow);
+ GDREGISTER_ABSTRACT_CLASS(InputEvent);
+ GDREGISTER_ABSTRACT_CLASS(InputEventWithModifiers);
+ GDREGISTER_ABSTRACT_CLASS(InputEventFromWindow);
GDREGISTER_CLASS(InputEventKey);
GDREGISTER_CLASS(InputEventShortcut);
- GDREGISTER_VIRTUAL_CLASS(InputEventMouse);
+ GDREGISTER_ABSTRACT_CLASS(InputEventMouse);
GDREGISTER_CLASS(InputEventMouseButton);
GDREGISTER_CLASS(InputEventMouseMotion);
GDREGISTER_CLASS(InputEventJoypadButton);
@@ -162,21 +162,21 @@ void register_core_types() {
GDREGISTER_CLASS(InputEventScreenDrag);
GDREGISTER_CLASS(InputEventScreenTouch);
GDREGISTER_CLASS(InputEventAction);
- GDREGISTER_VIRTUAL_CLASS(InputEventGesture);
+ GDREGISTER_ABSTRACT_CLASS(InputEventGesture);
GDREGISTER_CLASS(InputEventMagnifyGesture);
GDREGISTER_CLASS(InputEventPanGesture);
GDREGISTER_CLASS(InputEventMIDI);
// Network
- GDREGISTER_VIRTUAL_CLASS(IP);
+ GDREGISTER_ABSTRACT_CLASS(IP);
- GDREGISTER_VIRTUAL_CLASS(StreamPeer);
+ GDREGISTER_ABSTRACT_CLASS(StreamPeer);
GDREGISTER_CLASS(StreamPeerExtension);
GDREGISTER_CLASS(StreamPeerBuffer);
GDREGISTER_CLASS(StreamPeerTCP);
GDREGISTER_CLASS(TCPServer);
- GDREGISTER_VIRTUAL_CLASS(PacketPeer);
+ GDREGISTER_ABSTRACT_CLASS(PacketPeer);
GDREGISTER_CLASS(PacketPeerExtension);
GDREGISTER_CLASS(PacketPeerStream);
GDREGISTER_CLASS(PacketPeerUDP);
@@ -200,7 +200,7 @@ void register_core_types() {
resource_format_loader_crypto.instantiate();
ResourceLoader::add_resource_format_loader(resource_format_loader_crypto);
- GDREGISTER_VIRTUAL_CLASS(MultiplayerPeer);
+ GDREGISTER_ABSTRACT_CLASS(MultiplayerPeer);
GDREGISTER_CLASS(MultiplayerPeerExtension);
GDREGISTER_CLASS(MultiplayerAPI);
GDREGISTER_CLASS(MainLoop);
@@ -226,19 +226,19 @@ void register_core_types() {
GDREGISTER_CLASS(PCKPacker);
GDREGISTER_CLASS(PackedDataContainer);
- GDREGISTER_VIRTUAL_CLASS(PackedDataContainerRef);
+ GDREGISTER_ABSTRACT_CLASS(PackedDataContainerRef);
GDREGISTER_CLASS(AStar);
GDREGISTER_CLASS(AStar2D);
GDREGISTER_CLASS(EncodedObjectAsID);
GDREGISTER_CLASS(RandomNumberGenerator);
- GDREGISTER_VIRTUAL_CLASS(ResourceImporter);
+ GDREGISTER_ABSTRACT_CLASS(ResourceImporter);
GDREGISTER_CLASS(NativeExtension);
- GDREGISTER_VIRTUAL_CLASS(NativeExtensionManager);
+ GDREGISTER_ABSTRACT_CLASS(NativeExtensionManager);
- GDREGISTER_VIRTUAL_CLASS(ResourceUID);
+ GDREGISTER_ABSTRACT_CLASS(ResourceUID);
GDREGISTER_CLASS(EngineProfiler);
@@ -276,7 +276,7 @@ void register_core_settings() {
void register_core_singletons() {
GDREGISTER_CLASS(ProjectSettings);
- GDREGISTER_VIRTUAL_CLASS(IP);
+ GDREGISTER_ABSTRACT_CLASS(IP);
GDREGISTER_CLASS(core_bind::Geometry2D);
GDREGISTER_CLASS(core_bind::Geometry3D);
GDREGISTER_CLASS(core_bind::ResourceLoader);
@@ -286,7 +286,7 @@ void register_core_singletons() {
GDREGISTER_CLASS(core_bind::special::ClassDB);
GDREGISTER_CLASS(core_bind::Marshalls);
GDREGISTER_CLASS(TranslationServer);
- GDREGISTER_VIRTUAL_CLASS(Input);
+ GDREGISTER_ABSTRACT_CLASS(Input);
GDREGISTER_CLASS(InputMap);
GDREGISTER_CLASS(Expression);
GDREGISTER_CLASS(core_bind::EngineDebugger);
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index 1228cd771c..f692a49ba1 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -2516,7 +2516,10 @@
<constant name="PROPERTY_HINT_LOCALE_ID" value="41" enum="PropertyHint">
Hints that a string property is a locale code. Editing it will show a locale dialog for picking language and country.
</constant>
- <constant name="PROPERTY_HINT_MAX" value="42" enum="PropertyHint">
+ <constant name="PROPERTY_HINT_LOCALIZABLE_STRING" value="42" enum="PropertyHint">
+ Hints that a dictionary property is string translation map. Dictionary keys are locale codes and, values are translated strings.
+ </constant>
+ <constant name="PROPERTY_HINT_MAX" value="43" enum="PropertyHint">
</constant>
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
</constant>
diff --git a/doc/classes/AudioEffect.xml b/doc/classes/AudioEffect.xml
index 424669eab9..5bfa5be0ca 100644
--- a/doc/classes/AudioEffect.xml
+++ b/doc/classes/AudioEffect.xml
@@ -9,4 +9,11 @@
<tutorials>
<link title="Audio Mic Record Demo">https://godotengine.org/asset-library/asset/527</link>
</tutorials>
+ <methods>
+ <method name="_instantiate" qualifiers="virtual">
+ <return type="AudioEffectInstance" />
+ <description>
+ </description>
+ </method>
+ </methods>
</class>
diff --git a/doc/classes/AudioEffectInstance.xml b/doc/classes/AudioEffectInstance.xml
index 369b4130d4..f50246d6ca 100644
--- a/doc/classes/AudioEffectInstance.xml
+++ b/doc/classes/AudioEffectInstance.xml
@@ -6,4 +6,19 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="_process" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="src_buffer" type="const void*" />
+ <argument index="1" name="dst_buffer" type="AudioFrame*" />
+ <argument index="2" name="frame_count" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_process_silence" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
+ </methods>
</class>
diff --git a/doc/classes/AudioStreamPlaybackResampled.xml b/doc/classes/AudioStreamPlaybackResampled.xml
index 228b8c19c0..eb41e4256e 100644
--- a/doc/classes/AudioStreamPlaybackResampled.xml
+++ b/doc/classes/AudioStreamPlaybackResampled.xml
@@ -6,4 +6,23 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="_get_stream_sampling_rate" qualifiers="virtual const">
+ <return type="float" />
+ <description>
+ </description>
+ </method>
+ <method name="_mix_resampled" qualifiers="virtual">
+ <return type="int" />
+ <argument index="0" name="dst_buffer" type="AudioFrame*" />
+ <argument index="1" name="frame_count" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="begin_resample">
+ <return type="void" />
+ <description>
+ </description>
+ </method>
+ </methods>
</class>
diff --git a/doc/classes/CompressedTexture2D.xml b/doc/classes/CompressedTexture2D.xml
index c99fcf2280..5f73b55f69 100644
--- a/doc/classes/CompressedTexture2D.xml
+++ b/doc/classes/CompressedTexture2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CompressedTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- A [code].stex[/code] texture.
+ A [code].ctex[/code] texture.
</brief_description>
<description>
- A texture that is loaded from a [code].stex[/code] file.
+ A texture that is loaded from a [code].ctex[/code] file.
</description>
<tutorials>
</tutorials>
@@ -19,7 +19,7 @@
</methods>
<members>
<member name="load_path" type="String" setter="load" getter="get_load_path" default="&quot;&quot;">
- The CompressedTexture's file path to a [code].stex[/code] file.
+ The CompressedTexture's file path to a [code].ctex[/code] file.
</member>
</members>
</class>
diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml
index f040d292e9..94e52912a1 100644
--- a/doc/classes/Curve2D.xml
+++ b/doc/classes/Curve2D.xml
@@ -17,7 +17,7 @@
<argument index="2" name="out" type="Vector2" default="Vector2(0, 0)" />
<argument index="3" name="at_position" type="int" default="-1" />
<description>
- Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code].
+ Adds a point to a curve at [code]position[/code] relative to the [Curve2D]'s position, with control points [code]in[/code] and [code]out[/code].
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position &lt;0[/code] or [code]at_position &gt;= [method get_point_count][/code]), the point will be appended at the end of the point list.
</description>
</method>
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 27856f2564..ed642e0ddc 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -17,7 +17,7 @@
<argument index="2" name="out" type="Vector3" default="Vector3(0, 0, 0)" />
<argument index="3" name="at_position" type="int" default="-1" />
<description>
- Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code].
+ Adds a point to a curve at [code]position[/code] relative to the [Curve3D]'s position, with control points [code]in[/code] and [code]out[/code].
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position &lt;0[/code] or [code]at_position &gt;= [method get_point_count][/code]), the point will be appended at the end of the point list.
</description>
</method>
diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml
index 0474cbd387..b1fd7b4e76 100644
--- a/doc/classes/EditorFileDialog.xml
+++ b/doc/classes/EditorFileDialog.xml
@@ -40,13 +40,13 @@
<member name="access" type="int" setter="set_access" getter="get_access" enum="EditorFileDialog.Access" default="0">
The location from which the user may select a file, including [code]res://[/code], [code]user://[/code], and the local file system.
</member>
- <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir" default="&quot;res://&quot;">
+ <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir">
The currently occupied directory.
</member>
- <member name="current_file" type="String" setter="set_current_file" getter="get_current_file" default="&quot;&quot;">
+ <member name="current_file" type="String" setter="set_current_file" getter="get_current_file">
The currently selected file.
</member>
- <member name="current_path" type="String" setter="set_current_path" getter="get_current_path" default="&quot;res://&quot;">
+ <member name="current_path" type="String" setter="set_current_path" getter="get_current_path">
The file system path in the address bar.
</member>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" />
diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml
index 05d90390f8..db536a738a 100644
--- a/doc/classes/FileDialog.xml
+++ b/doc/classes/FileDialog.xml
@@ -56,13 +56,13 @@
The file system access scope. See enum [code]Access[/code] constants.
[b]Warning:[/b] Currently, in sandboxed environments such as HTML5 builds or sandboxed macOS apps, FileDialog cannot access the host file system. See [url=https://github.com/godotengine/godot-proposals/issues/1123]godot-proposals#1123[/url].
</member>
- <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir" default="&quot;res://&quot;">
+ <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir">
The current working directory of the file dialog.
</member>
- <member name="current_file" type="String" setter="set_current_file" getter="get_current_file" default="&quot;&quot;">
+ <member name="current_file" type="String" setter="set_current_file" getter="get_current_file">
The currently selected file of the file dialog.
</member>
- <member name="current_path" type="String" setter="set_current_path" getter="get_current_path" default="&quot;res://&quot;">
+ <member name="current_path" type="String" setter="set_current_path" getter="get_current_path">
The currently selected file path of the file dialog.
</member>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" />
diff --git a/doc/classes/FontData.xml b/doc/classes/FontData.xml
index ccaefc60ee..9344a1fe80 100644
--- a/doc/classes/FontData.xml
+++ b/doc/classes/FontData.xml
@@ -567,6 +567,9 @@
<member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()">
Contents of the dynamic font source file.
</member>
+ <member name="embolden" type="float" setter="set_embolden" getter="get_embolden" default="0.0">
+ If is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </member>
<member name="fixed_size" type="int" setter="set_fixed_size" getter="get_fixed_size" default="0">
Font size, used only for the bitmap fonts.
</member>
@@ -603,5 +606,9 @@
<member name="subpixel_positioning" type="int" setter="set_subpixel_positioning" getter="get_subpixel_positioning" enum="TextServer.SubpixelPositioning" default="1">
Font glyph sub-pixel positioning mode. Subpixel positioning provides shaper text and better kerning for smaller font sizes, at the cost of memory usage and font rasterization speed. Use [constant TextServer.SUBPIXEL_POSITIONING_AUTO] to automatically enable it based on the font size.
</member>
+ <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
+ 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
+ For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
+ </member>
</members>
</class>
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index 48fa009300..06bd64577b 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -7,6 +7,7 @@
This control provides a selectable list of items that may be in a single (or multiple columns) with option of text, icons, or both text and icon. Tooltips are supported and may be different for every item in the list.
Selectable items in the list may be selected or deselected and multiple selection may be enabled. Selection with right mouse button may also be enabled to allow use of popup context menus. Items may also be "activated" by double-clicking them or by pressing [kbd]Enter[/kbd].
Item text only supports single-line strings, newline characters (e.g. [code]\n[/code]) in the string won't produce a newline. Text wrapping is enabled in [constant ICON_MODE_TOP] mode, but column's width is adjusted to fully fit its content by default. You need to set [member fixed_column_width] greater than zero to wrap the text.
+ All [code]set_*[/code] methods allow negative item index, which makes the item accessed from the last one.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Material.xml b/doc/classes/Material.xml
index 78dbf8729b..c5d567c1fe 100644
--- a/doc/classes/Material.xml
+++ b/doc/classes/Material.xml
@@ -11,6 +11,26 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
+ <method name="_can_do_next_pass" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="_can_use_render_priority" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_shader_mode" qualifiers="virtual const">
+ <return type="int" enum="Shader.Mode" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_shader_rid" qualifiers="virtual const">
+ <return type="RID" />
+ <description>
+ </description>
+ </method>
<method name="inspect_native_shader_code">
<return type="void" />
<description>
@@ -22,7 +42,7 @@
Sets the [Material] to be used for the next pass. This renders the object again using a different material.
[b]Note:[/b] This only applies to [StandardMaterial3D]s and [ShaderMaterial]s with type "Spatial".
</member>
- <member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority" default="0">
+ <member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority">
Sets the render priority for transparent objects in 3D scenes. Higher priority objects will be sorted in front of lower priority objects.
[b]Note:[/b] This only applies to [StandardMaterial3D]s and [ShaderMaterial]s with type "Spatial".
[b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority).
diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml
index c5bfdcecd2..e4116cddfe 100644
--- a/doc/classes/Mesh.xml
+++ b/doc/classes/Mesh.xml
@@ -13,6 +13,89 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
+ <method name="_get_aabb" qualifiers="virtual const">
+ <return type="AABB" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_blend_shape_count" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_blend_shape_name" qualifiers="virtual const">
+ <return type="StringName" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_surface_count" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_set_blend_shape_name" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="index" type="int" />
+ <argument index="1" name="name" type="StringName" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_array_index_len" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_array_len" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_arrays" qualifiers="virtual const">
+ <return type="Array" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_blend_shape_arrays" qualifiers="virtual const">
+ <return type="Array" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_format" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_lods" qualifiers="virtual const">
+ <return type="Dictionary" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_material" qualifiers="virtual const">
+ <return type="Material" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_get_primitive_type" qualifiers="virtual const">
+ <return type="int" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_surface_set_material" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="index" type="int" />
+ <argument index="1" name="material" type="Material" />
+ <description>
+ </description>
+ </method>
<method name="create_convex_shape" qualifiers="const">
<return type="Shape3D" />
<argument index="0" name="clean" type="bool" default="true" />
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index b64c392357..4bcfc3c726 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -7,6 +7,7 @@
[PopupMenu] is a modal window used to display a list of options. They are popular in toolbars or context menus.
The size of a [PopupMenu] can be limited by using [member Window.max_size]. If the height of the list of items is larger than the maximum height of the [PopupMenu], a [ScrollContainer] within the popup will allow the user to scroll the contents.
If no maximum size is set, or if it is set to 0, the [PopupMenu] height will be limited by its parent rect.
+ All [code]set_*[/code] methods allow negative item index, which makes the item accessed from the last one.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/PrimitiveMesh.xml b/doc/classes/PrimitiveMesh.xml
index d0136e389a..329d81342b 100644
--- a/doc/classes/PrimitiveMesh.xml
+++ b/doc/classes/PrimitiveMesh.xml
@@ -9,6 +9,11 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_create_mesh_array" qualifiers="virtual const">
+ <return type="Array" />
+ <description>
+ </description>
+ </method>
<method name="get_mesh_arrays" qualifiers="const">
<return type="Array" />
<description>
diff --git a/doc/classes/ProceduralSkyMaterial.xml b/doc/classes/ProceduralSkyMaterial.xml
index 2b15508119..bf33232406 100644
--- a/doc/classes/ProceduralSkyMaterial.xml
+++ b/doc/classes/ProceduralSkyMaterial.xml
@@ -23,6 +23,12 @@
<member name="ground_horizon_color" type="Color" setter="set_ground_horizon_color" getter="get_ground_horizon_color" default="Color(0.6463, 0.6558, 0.6708, 1)">
Color of the ground at the horizon. Blends with [member ground_bottom_color].
</member>
+ <member name="sky_cover" type="Texture2D" setter="set_sky_cover" getter="get_sky_cover">
+ The sky cover texture to use. This texture must use an equirectangular projection (similar to [PanoramaSkyMaterial]). The texture's colors will be [i]added[/i] to the existing sky color, and will be multiplied by [member sky_energy] and [member sky_cover_modulate]. This is mainly suited to displaying stars at night, but it can also be used to display clouds at day or night (with a non-physically-accurate look).
+ </member>
+ <member name="sky_cover_modulate" type="Color" setter="set_sky_cover_modulate" getter="get_sky_cover_modulate" default="Color(1, 1, 1, 1)">
+ The tint to apply to the [member sky_cover] texture. This can be used to change the sky cover's colors or opacity independently of the sky energy, which is useful for day/night or weather transitions. Only effective if a texture is defined in [member sky_cover].
+ </member>
<member name="sky_curve" type="float" setter="set_sky_curve" getter="get_sky_curve" default="0.15">
How quickly the [member sky_horizon_color] fades into the [member sky_top_color].
</member>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 701e947fd1..068b2c7757 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -226,6 +226,9 @@
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. The window title will be set to match the project name automatically on startup.
[b]Note:[/b] Changing this value will also change the user data folder's path if [member application/config/use_custom_user_dir] is [code]false[/code]. After renaming the project, you will no longer be able to access existing data in [code]user://[/code] unless you rename the old folder to match the new project name. See [url=$DOCS_URL/tutorials/io/data_paths.html]Data paths[/url] in the documentation for more information.
</member>
+ <member name="application/config/name_localized" type="Dictionary" setter="" getter="" default="{}">
+ Translations of the project's name. This setting is used by OS tools to translate application name on Android, iOS and macOS.
+ </member>
<member name="application/config/project_settings_override" type="String" setter="" getter="" default="&quot;&quot;">
Specifies a file to override project settings. For example: [code]user://custom_settings.cfg[/code]. See "Overriding" in the [ProjectSettings] class description at the top for more information.
[b]Note:[/b] Regardless of this setting's value, [code]res://override.cfg[/code] will still be read to override the project settings.
diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml
index 70a9912b76..c150198eb1 100644
--- a/doc/classes/Range.xml
+++ b/doc/classes/Range.xml
@@ -9,6 +9,12 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_value_changed" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="" type="float" />
+ <description>
+ </description>
+ </method>
<method name="share">
<return type="void" />
<argument index="0" name="with" type="Node" />
diff --git a/doc/classes/Resource.xml b/doc/classes/Resource.xml
index 0850d39015..b08b1540ab 100644
--- a/doc/classes/Resource.xml
+++ b/doc/classes/Resource.xml
@@ -12,6 +12,11 @@
<link title="When and how to avoid using nodes for everything">$DOCS_URL/tutorials/best_practices/node_alternatives.html</link>
</tutorials>
<methods>
+ <method name="_get_rid" qualifiers="virtual">
+ <return type="RID" />
+ <description>
+ </description>
+ </method>
<method name="duplicate" qualifiers="const">
<return type="Resource" />
<argument index="0" name="subresources" type="bool" default="false" />
diff --git a/doc/classes/ResourceFormatLoader.xml b/doc/classes/ResourceFormatLoader.xml
index 983a05800f..36b64f5a86 100644
--- a/doc/classes/ResourceFormatLoader.xml
+++ b/doc/classes/ResourceFormatLoader.xml
@@ -6,7 +6,7 @@
<description>
Godot loads resources in the editor or in exported games using ResourceFormatLoaders. They are queried automatically via the [ResourceLoader] singleton, or when a resource with internal dependencies is loaded. Each file type may load as a different resource type, so multiple ResourceFormatLoaders are registered in the engine.
Extending this class allows you to define your own loader. Be sure to respect the documented return types and values. You should give it a global class name with [code]class_name[/code] for it to be registered. Like built-in ResourceFormatLoaders, it will be called automatically when loading resources of its handled type(s). You may also implement a [ResourceFormatSaver].
- [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].stex[/code] ([CompressedTexture2D]) first, so they can be loaded with better efficiency on the graphics card.
+ [b]Note:[/b] You can also extend [EditorImportPlugin] if the resource type you need exists but Godot is unable to load its format. Choosing one way over another depends on if the format is suitable or not for the final exported game. For example, it's better to import [code].png[/code] textures as [code].ctex[/code] ([CompressedTexture2D]) first, so they can be loaded with better efficiency on the graphics card.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/StyleBox.xml b/doc/classes/StyleBox.xml
index f805692f4d..bc2333f26a 100644
--- a/doc/classes/StyleBox.xml
+++ b/doc/classes/StyleBox.xml
@@ -10,6 +10,37 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_draw" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="to_canvas_item" type="RID" />
+ <argument index="1" name="rect" type="Rect2" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_center_size" qualifiers="virtual const">
+ <return type="Vector2" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_draw_rect" qualifiers="virtual const">
+ <return type="Rect2" />
+ <argument index="0" name="rect" type="Rect2" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_style_margin" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="side" type="int" enum="Side" />
+ <description>
+ </description>
+ </method>
+ <method name="_test_mask" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="point" type="Vector2" />
+ <argument index="1" name="rect" type="Rect2" />
+ <description>
+ </description>
+ </method>
<method name="draw" qualifiers="const">
<return type="void" />
<argument index="0" name="canvas_item" type="RID" />
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index 3157eea436..020c30b9cd 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline).
</description>
</method>
+ <method name="font_get_embolden" qualifiers="const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns font embolden strength.
+ </description>
+ </method>
<method name="font_get_fixed_size" qualifiers="const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -368,6 +375,13 @@
Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="font_get_transform" qualifiers="const">
+ <return type="Transform2D" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns 2D transform applied to the font outlines.
+ </description>
+ </method>
<method name="font_get_underline_position" qualifiers="const">
<return type="float" />
<argument index="0" name="font_rid" type="RID" />
@@ -542,6 +556,14 @@
Sets the font descent (number of pixels below the baseline).
</description>
</method>
+ <method name="font_set_embolden">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="strength" type="float" />
+ <description>
+ Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </description>
+ </method>
<method name="font_set_fixed_size">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@@ -765,6 +787,15 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="font_set_transform">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="transform" type="Transform2D" />
+ <description>
+ Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
+ For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
+ </description>
+ </method>
<method name="font_set_underline_position">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index f730f28e79..5ffd80bf63 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -112,6 +112,13 @@
Returns the font descent (number of pixels below the baseline).
</description>
</method>
+ <method name="_font_get_embolden" qualifiers="virtual const">
+ <return type="float" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns font embolden strength.
+ </description>
+ </method>
<method name="_font_get_fixed_size" qualifiers="virtual const">
<return type="int" />
<argument index="0" name="font_rid" type="RID" />
@@ -368,6 +375,13 @@
Returns array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="_font_get_transform" qualifiers="virtual const">
+ <return type="Transform2D" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Retruns 2D transform applied to the font outlines.
+ </description>
+ </method>
<method name="_font_get_underline_position" qualifiers="virtual const">
<return type="float" />
<argument index="0" name="font_rid" type="RID" />
@@ -551,6 +565,14 @@
Sets bitmap font fixed size. If set to value greater than zero, same cache entry will be used for all font sizes.
</description>
</method>
+ <method name="_font_set_embolden" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="strength" type="float" />
+ <description>
+ Sets font embolden strength. If [code]strength[/code] is not equal to zero, emboldens the font outlines. Negative values reduce the outline thickness.
+ </description>
+ </method>
<method name="_font_set_fixed_size" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
@@ -773,6 +795,15 @@
Sets array containing the first free pixel in the each column of texture. Should be the same size as texture width or empty.
</description>
</method>
+ <method name="_font_set_transform" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="transform" type="Transform2D" />
+ <description>
+ Sets 2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
+ For example, to simulate italic typeface by slanting, apply the following transform [code]Transform2D(1.0, slant, 0.0, 1.0, 0.0, 0.0)[/code].
+ </description>
+ </method>
<method name="_font_set_underline_position" qualifiers="virtual">
<return type="void" />
<argument index="0" name="font_rid" type="RID" />
diff --git a/doc/classes/Texture2D.xml b/doc/classes/Texture2D.xml
index de9bbb4b3d..1bbebe085e 100644
--- a/doc/classes/Texture2D.xml
+++ b/doc/classes/Texture2D.xml
@@ -12,6 +12,58 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_draw" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="to_canvas_item" type="RID" />
+ <argument index="1" name="pos" type="Vector2" />
+ <argument index="2" name="modulate" type="Color" />
+ <argument index="3" name="transpose" type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="_draw_rect" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="to_canvas_item" type="RID" />
+ <argument index="1" name="rect" type="Rect2" />
+ <argument index="2" name="tile" type="bool" />
+ <argument index="3" name="modulate" type="Color" />
+ <argument index="4" name="transpose" type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="_draw_rect_region" qualifiers="virtual const">
+ <return type="void" />
+ <argument index="0" name="tp_canvas_item" type="RID" />
+ <argument index="1" name="rect" type="Rect2" />
+ <argument index="2" name="src_rect" type="Rect2" />
+ <argument index="3" name="modulate" type="Color" />
+ <argument index="4" name="transpose" type="bool" />
+ <argument index="5" name="clip_uv" type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_height" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_width" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_has_alpha" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
+ <method name="_is_pixel_opaque" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="x" type="int" />
+ <argument index="1" name="y" type="int" />
+ <description>
+ </description>
+ </method>
<method name="draw" qualifiers="const">
<return type="void" />
<argument index="0" name="canvas_item" type="RID" />
diff --git a/doc/classes/Texture3D.xml b/doc/classes/Texture3D.xml
index bdfa428328..4968f46fe8 100644
--- a/doc/classes/Texture3D.xml
+++ b/doc/classes/Texture3D.xml
@@ -7,6 +7,36 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_get_data" qualifiers="virtual const">
+ <return type="Image[]" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_depth" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_format" qualifiers="virtual const">
+ <return type="int" enum="Image.Format" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_height" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_width" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_has_mipmaps" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
<method name="get_data" qualifiers="const">
<return type="Image[]" />
<description>
diff --git a/doc/classes/TextureLayered.xml b/doc/classes/TextureLayered.xml
index 13679908d7..3445329f32 100644
--- a/doc/classes/TextureLayered.xml
+++ b/doc/classes/TextureLayered.xml
@@ -9,6 +9,42 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_get_format" qualifiers="virtual const">
+ <return type="int" enum="Image.Format" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_height" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_layer_data" qualifiers="virtual const">
+ <return type="Image" />
+ <argument index="0" name="layer_index" type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_layered_type" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_layers" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_get_width" qualifiers="virtual const">
+ <return type="int" />
+ <description>
+ </description>
+ </method>
+ <method name="_has_mipmaps" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
<method name="get_format" qualifiers="const">
<return type="int" enum="Image.Format" />
<description>
diff --git a/doc/classes/Time.xml b/doc/classes/Time.xml
index bb59881db9..dd83fa54ff 100644
--- a/doc/classes/Time.xml
+++ b/doc/classes/Time.xml
@@ -97,6 +97,13 @@
If [code]use_space[/code] is true, use a space instead of the letter T in the middle.
</description>
</method>
+ <method name="get_offset_string_from_offset_minutes" qualifiers="const">
+ <return type="String" />
+ <argument index="0" name="offset_minutes" type="int" />
+ <description>
+ Converts the given timezone offset in minutes to a timezone offset string. For example, -480 returns "-08:00", 345 returns "+05:45", and 0 returns "+00:00".
+ </description>
+ </method>
<method name="get_ticks_msec" qualifiers="const">
<return type="int" />
<description>
diff --git a/doc/classes/VisualInstance3D.xml b/doc/classes/VisualInstance3D.xml
index 1aae85c7e1..7efa1f4df8 100644
--- a/doc/classes/VisualInstance3D.xml
+++ b/doc/classes/VisualInstance3D.xml
@@ -9,6 +9,11 @@
<tutorials>
</tutorials>
<methods>
+ <method name="_get_aabb" qualifiers="virtual const">
+ <return type="AABB" />
+ <description>
+ </description>
+ </method>
<method name="get_aabb" qualifiers="const">
<return type="AABB" />
<description>
diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml
index da378759d8..d15558c9e8 100644
--- a/doc/classes/XRPositionalTracker.xml
+++ b/doc/classes/XRPositionalTracker.xml
@@ -72,6 +72,9 @@
- [code]left_hand[/code] identifies the controller held in the players left hand
- [code]right_hand[/code] identifies the controller held in the players right hand
</member>
+ <member name="profile" type="String" setter="set_tracker_profile" getter="get_tracker_profile" default="&quot;&quot;">
+ The profile associated with this tracker, interface dependent but will indicate the type of controller being tracked.
+ </member>
<member name="type" type="int" setter="set_tracker_type" getter="get_tracker_type" enum="XRServer.TrackerType" default="128">
The type of tracker.
</member>
@@ -109,6 +112,12 @@
Emitted when the state of a pose tracked by this tracker changes.
</description>
</signal>
+ <signal name="profile_changed">
+ <argument index="0" name="role" type="String" />
+ <description>
+ Emitted when the profile of our tracker changes.
+ </description>
+ </signal>
</signals>
<constants>
<constant name="TRACKER_HAND_UNKNOWN" value="0" enum="TrackerHand">
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 92d53cc005..aab9743c43 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -1122,8 +1122,6 @@ void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) {
}
ActionMapEditor::ActionMapEditor() {
- show_builtin_actions = false;
-
// Main Vbox Container
VBoxContainer *main_vbox = memnew(VBoxContainer);
main_vbox->set_anchors_and_offsets_preset(PRESET_WIDE);
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index de24d3ee1f..34c70c942e 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -164,7 +164,7 @@ private:
// Filtering and Adding actions
- bool show_builtin_actions;
+ bool show_builtin_actions = false;
CheckButton *show_builtin_actions_checkbutton;
LineEdit *action_list_search;
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 11995e8cb4..e61a1aae9c 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1814,13 +1814,6 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> mm = p_event;
if (mm.is_valid()) {
- if (hsize_rect.has_point(mm->get_position())) {
- // Change the cursor to indicate that the track name column's width can be adjusted
- set_default_cursor_shape(Control::CURSOR_HSIZE);
- } else {
- set_default_cursor_shape(Control::CURSOR_ARROW);
- }
-
if (dragging_hsize) {
int ofs = mm->get_position().x - dragging_hsize_from;
name_limit = dragging_hsize_at + ofs;
@@ -1836,6 +1829,15 @@ void AnimationTimelineEdit::gui_input(const Ref<InputEvent> &p_event) {
}
}
+Control::CursorShape AnimationTimelineEdit::get_cursor_shape(const Point2 &p_pos) const {
+ if (dragging_hsize || hsize_rect.has_point(p_pos)) {
+ // Indicate that the track name column's width can be adjusted
+ return Control::CURSOR_HSIZE;
+ } else {
+ return get_default_cursor_shape();
+ }
+}
+
void AnimationTimelineEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) {
// Timeline has no vertical scroll, so we change it to horizontal.
p_scroll_vec.x += p_scroll_vec.y;
@@ -1884,8 +1886,6 @@ void AnimationTimelineEdit::_bind_methods() {
}
AnimationTimelineEdit::AnimationTimelineEdit() {
- use_fps = false;
- editing = false;
name_limit = 150 * EDSCALE;
zoom = nullptr;
track_edit = nullptr;
@@ -1933,9 +1933,6 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
add_track->get_popup()->connect("index_pressed", callable_mp(this, &AnimationTimelineEdit::_track_added));
len_hb->hide();
- dragging_timeline = false;
- dragging_hsize = false;
-
panner.instantiate();
panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_scroll_callback), callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback));
@@ -3149,13 +3146,8 @@ AnimationTrackEdit::AnimationTrackEdit() {
path = nullptr;
path_popup = nullptr;
menu = nullptr;
- clicking_on_name = false;
dropping_at = 0;
- in_group = false;
-
- moving_selection_attempt = false;
- moving_selection = false;
select_single_attempt = -1;
play_position_pos = 0;
@@ -6314,8 +6306,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
add_child(method_selector);
method_selector->connect("selected", callable_mp(this, &AnimationTrackEditor::_add_method_key));
- insert_queue = false;
-
insert_confirm = memnew(ConfirmationDialog);
add_child(insert_confirm);
insert_confirm->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_confirm_insert_list));
@@ -6333,8 +6323,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
insert_confirm_reset->set_text(TTR("Create RESET Track(s)", ""));
insert_confirm_reset->set_pressed(EDITOR_GET("editors/animation/default_create_reset_tracks"));
ichb->add_child(insert_confirm_reset);
- keying = false;
- moving_selection = false;
key_edit = nullptr;
multi_key_edit = nullptr;
@@ -6344,7 +6332,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
box_selection->set_mouse_filter(MOUSE_FILTER_IGNORE);
box_selection->hide();
box_selection->connect("draw", callable_mp(this, &AnimationTrackEditor::_box_selection_draw));
- box_selecting = false;
// Default Plugins.
@@ -6441,7 +6428,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
track_copy_select->set_hide_root(true);
track_vbox->add_child(track_copy_select);
track_copy_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed), varray(EDIT_COPY_TRACKS_CONFIRM));
- animation_changing_awaiting_update = false;
}
AnimationTrackEditor::~AnimationTrackEditor() {
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 5f803ae796..1baebc469e 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -77,16 +77,16 @@ class AnimationTimelineEdit : public Range {
UndoRedo *undo_redo;
Rect2 hsize_rect;
- bool editing;
- bool use_fps;
+ bool editing = false;
+ bool use_fps = false;
Ref<ViewPanner> panner;
void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
void _pan_callback(Vector2 p_scroll_vec);
void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
- bool dragging_timeline;
- bool dragging_hsize;
+ bool dragging_timeline = false;
+ bool dragging_hsize = false;
float dragging_hsize_from;
float dragging_hsize_at;
@@ -121,6 +121,8 @@ public:
void set_hscroll(HScrollBar *p_hscroll);
+ virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;
+
AnimationTimelineEdit();
};
@@ -169,7 +171,7 @@ class AnimationTrackEdit : public Control {
PopupMenu *menu;
- bool clicking_on_name;
+ bool clicking_on_name = false;
void _zoom_changed();
@@ -186,12 +188,12 @@ class AnimationTrackEdit : public Control {
mutable int dropping_at;
float insert_at_pos;
- bool moving_selection_attempt;
+ bool moving_selection_attempt = false;
int select_single_attempt;
- bool moving_selection;
+ bool moving_selection = false;
float moving_selection_from_ofs;
- bool in_group;
+ bool in_group = false;
AnimationTrackEditor *editor;
protected:
@@ -310,7 +312,7 @@ class AnimationTrackEditor : public VBoxContainer {
Vector<AnimationTrackEdit *> track_edits;
Vector<AnimationTrackEditGroup *> groups;
- bool animation_changing_awaiting_update;
+ bool animation_changing_awaiting_update = false;
void _animation_update();
int _get_track_selected();
void _animation_changed();
@@ -340,7 +342,7 @@ class AnimationTrackEditor : public VBoxContainer {
int adding_track_type;
NodePath adding_track_path;
- bool keying;
+ bool keying = false;
struct InsertData {
Animation::TrackType type;
@@ -355,7 +357,7 @@ class AnimationTrackEditor : public VBoxContainer {
CheckBox *insert_confirm_bezier;
CheckBox *insert_confirm_reset;
ConfirmationDialog *insert_confirm;
- bool insert_queue;
+ bool insert_queue = false;
List<InsertData> insert_data;
void _query_insert(const InsertData &p_id);
@@ -410,7 +412,7 @@ class AnimationTrackEditor : public VBoxContainer {
void _key_selected(int p_key, bool p_single, int p_track);
void _key_deselected(int p_key, int p_track);
- bool moving_selection;
+ bool moving_selection = false;
float moving_selection_offset;
void _move_selection_begin();
void _move_selection(float p_offset);
@@ -425,7 +427,7 @@ class AnimationTrackEditor : public VBoxContainer {
Control *box_selection;
void _box_selection_draw();
- bool box_selecting;
+ bool box_selecting = false;
Vector2 box_selecting_from;
Rect2 box_select_rect;
void _scroll_input(const Ref<InputEvent> &p_event);
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index e87678a51b..2ad8b2d2a4 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -1080,12 +1080,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
len_resizing_index = i;
}
}
-
- if (use_hsize_cursor) {
- set_default_cursor_shape(CURSOR_HSIZE);
- } else {
- set_default_cursor_shape(CURSOR_ARROW);
- }
+ over_drag_position = use_hsize_cursor;
}
if (len_resizing && mm.is_valid()) {
@@ -1097,7 +1092,7 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseButton> mb = p_event;
- if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && get_default_cursor_shape() == CURSOR_HSIZE) {
+ if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && over_drag_position) {
len_resizing = true;
len_resizing_start = mb->is_shift_pressed();
len_resizing_from_px = mb->get_position().x;
@@ -1124,7 +1119,6 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
get_undo_redo()->commit_action();
}
- len_resizing = false;
len_resizing_index = -1;
update();
accept_event();
@@ -1134,6 +1128,14 @@ void AnimationTrackEditTypeAudio::gui_input(const Ref<InputEvent> &p_event) {
AnimationTrackEdit::gui_input(p_event);
}
+Control::CursorShape AnimationTrackEditTypeAudio::get_cursor_shape(const Point2 &p_pos) const {
+ if (over_drag_position || len_resizing) {
+ return Control::CURSOR_HSIZE;
+ } else {
+ return get_default_cursor_shape();
+ }
+}
+
////////////////////
/// SUB ANIMATION ///
diff --git a/editor/animation_track_editor_plugins.h b/editor/animation_track_editor_plugins.h
index 271c1a000b..adfe517356 100644
--- a/editor/animation_track_editor_plugins.h
+++ b/editor/animation_track_editor_plugins.h
@@ -81,7 +81,7 @@ class AnimationTrackEditSpriteFrame : public AnimationTrackEdit {
GDCLASS(AnimationTrackEditSpriteFrame, AnimationTrackEdit);
ObjectID id;
- bool is_coords;
+ bool is_coords = false;
public:
virtual int get_key_height() const override;
@@ -92,7 +92,7 @@ public:
void set_node(Object *p_object);
void set_as_coords();
- AnimationTrackEditSpriteFrame() { is_coords = false; }
+ AnimationTrackEditSpriteFrame() {}
};
class AnimationTrackEditSubAnim : public AnimationTrackEdit {
@@ -114,11 +114,12 @@ class AnimationTrackEditTypeAudio : public AnimationTrackEdit {
void _preview_changed(ObjectID p_which);
- bool len_resizing;
+ bool len_resizing = false;
bool len_resizing_start;
int len_resizing_index;
float len_resizing_from_px;
float len_resizing_rel;
+ bool over_drag_position = false;
protected:
static void _bind_methods();
@@ -134,6 +135,8 @@ public:
virtual bool is_key_selectable_by_distance() const override;
virtual void draw_key(int p_index, float p_pixels_sec, int p_x, bool p_selected, int p_clip_left, int p_clip_right) override;
+ virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;
+
AnimationTrackEditTypeAudio();
};
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 22d3155159..2896fda2d2 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -618,8 +618,6 @@ void FindReplaceBar::_bind_methods() {
FindReplaceBar::FindReplaceBar() {
results_count = -1;
- replace_all_mode = false;
- preserve_cursor = false;
vbc_lineedit = memnew(VBoxContainer);
add_child(vbc_lineedit);
@@ -1887,8 +1885,6 @@ CodeTextEditor::CodeTextEditor() {
error_button->set_default_cursor_shape(CURSOR_POINTING_HAND);
error_button->connect("pressed", callable_mp(this, &CodeTextEditor::_error_button_pressed));
error_button->set_tooltip(TTR("Errors"));
-
- is_errors_panel_opened = false;
set_error_count(0);
// Warnings
@@ -1899,8 +1895,6 @@ CodeTextEditor::CodeTextEditor() {
warning_button->set_default_cursor_shape(CURSOR_POINTING_HAND);
warning_button->connect("pressed", callable_mp(this, &CodeTextEditor::_warning_button_pressed));
warning_button->set_tooltip(TTR("Warnings"));
-
- is_warnings_panel_opened = false;
set_warning_count(0);
// Line and column
diff --git a/editor/code_editor.h b/editor/code_editor.h
index 24316bf8b0..d7025e7fd9 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -86,8 +86,8 @@ class FindReplaceBar : public HBoxContainer {
int result_col;
int results_count;
- bool replace_all_mode;
- bool preserve_cursor;
+ bool replace_all_mode = false;
+ bool preserve_cursor = false;
void _get_search_from(int &r_line, int &r_col);
void _update_results_count();
@@ -206,8 +206,8 @@ protected:
void _notification(int);
static void _bind_methods();
- bool is_warnings_panel_opened;
- bool is_errors_panel_opened;
+ bool is_warnings_panel_opened = false;
+ bool is_errors_panel_opened = false;
public:
void trim_trailing_whitespace();
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 7e59fc31c4..f9858aa514 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -130,8 +130,8 @@ bool CreateDialog::_should_hide_type(const String &p_type) const {
}
if (ClassDB::class_exists(p_type)) {
- if (!ClassDB::can_instantiate(p_type)) {
- return true; // Can't create abstract class.
+ if (!ClassDB::can_instantiate(p_type) || ClassDB::is_virtual(p_type)) {
+ return true; // Can't create abstract or virtual class.
}
if (!ClassDB::is_parent_class(p_type, base_type)) {
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 1802bdec93..95b3a02631 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -749,12 +749,11 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path
}
void OrphanResourcesDialog::_delete_confirm() {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (const String &E : paths) {
da->remove(E);
EditorFileSystem::get_singleton()->update_file(E);
}
- memdelete(da);
refresh();
}
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 3835399c99..f1674c47c5 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -277,10 +277,8 @@ void EditorAssetInstaller::ok_pressed() {
dirpath = dirpath.substr(0, dirpath.length() - 1);
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->make_dir(dirpath);
- memdelete(da);
-
} else {
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
@@ -358,7 +356,5 @@ EditorAssetInstaller::EditorAssetInstaller() {
get_ok_button()->set_text(TTR("Install"));
set_title(TTR("Asset Installer"));
- updating = false;
-
set_hide_on_ok(true);
}
diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h
index f5993f73e7..58c232f351 100644
--- a/editor/editor_asset_installer.h
+++ b/editor/editor_asset_installer.h
@@ -42,7 +42,7 @@ class EditorAssetInstaller : public ConfirmationDialog {
String asset_name;
AcceptDialog *error;
Map<String, TreeItem *> status_map;
- bool updating;
+ bool updating = false;
void _item_edited();
void _check_propagated_to_item(Object *p_obj, int column);
virtual void ok_pressed() override;
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index b64b48b4ee..4474d6893a 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -771,9 +771,7 @@ void EditorAudioBus::_bind_methods() {
EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
buses = p_buses;
- updating_bus = false;
is_master = p_is_master;
- hovering_drop = false;
set_tooltip(TTR("Drag & drop to rearrange."));
@@ -919,13 +917,13 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
ClassDB::get_inheriters_from_class("AudioEffect", &effects);
effects.sort_custom<StringName::AlphCompare>();
for (const StringName &E : effects) {
- if (!ClassDB::can_instantiate(E)) {
+ if (!ClassDB::can_instantiate(E) || ClassDB::is_virtual(E)) {
continue;
}
String name = E.operator String().replace("AudioEffect", "");
effect_options->add_item(name);
- effect_options->set_item_metadata(effect_options->get_item_count() - 1, E);
+ effect_options->set_item_metadata(-1, E);
}
bus_options = memnew(MenuButton);
@@ -992,7 +990,6 @@ void EditorAudioBusDrop::_bind_methods() {
}
EditorAudioBusDrop::EditorAudioBusDrop() {
- hovering_drop = false;
}
void EditorAudioBuses::_update_buses() {
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index a830a2719d..0020b61370 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -85,9 +85,9 @@ class EditorAudioBus : public PanelContainer {
Tree *effects;
- bool updating_bus;
+ bool updating_bus = false;
bool is_master;
- mutable bool hovering_drop;
+ mutable bool hovering_drop = false;
virtual void gui_input(const Ref<InputEvent> &p_event) override;
void _effects_gui_input(Ref<InputEvent> p_event);
@@ -140,7 +140,7 @@ class EditorAudioBusDrop : public Control {
virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const override;
virtual void drop_data(const Point2 &p_point, const Variant &p_data) override;
- mutable bool hovering_drop;
+ mutable bool hovering_drop = false;
protected:
static void _bind_methods();
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 829948d3cb..b37b06748d 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/filesystem_dock.h"
#include "project_settings_editor.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
@@ -63,6 +64,28 @@ void EditorAutoloadSettings::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
} break;
+
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ FileSystemDock *dock = FileSystemDock::get_singleton();
+
+ if (dock != nullptr) {
+ ScriptCreateDialog *dialog = dock->get_script_create_dialog();
+
+ if (dialog != nullptr) {
+ Callable script_created = callable_mp(this, &EditorAutoloadSettings::_script_created);
+
+ if (is_visible_in_tree()) {
+ if (!dialog->is_connected(SNAME("script_created"), script_created)) {
+ dialog->connect("script_created", script_created);
+ }
+ } else {
+ if (dialog->is_connected(SNAME("script_created"), script_created)) {
+ dialog->disconnect("script_created", script_created);
+ }
+ }
+ }
+ }
+ } break;
}
}
@@ -134,12 +157,22 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin
}
void EditorAutoloadSettings::_autoload_add() {
- if (autoload_add(autoload_add_name->get_text(), autoload_add_path->get_text())) {
- autoload_add_path->set_text("");
- }
+ if (autoload_add_path->get_text().is_empty()) {
+ ScriptCreateDialog *dialog = FileSystemDock::get_singleton()->get_script_create_dialog();
+ String fpath = path;
+ if (!fpath.ends_with("/")) {
+ fpath = fpath.get_base_dir();
+ }
+ dialog->config("Node", fpath.plus_file(vformat("%s.gd", autoload_add_name->get_text().camelcase_to_underscore())), false, false);
+ dialog->popup_centered();
+ } else {
+ if (autoload_add(autoload_add_name->get_text(), autoload_add_path->get_text())) {
+ autoload_add_path->set_text("");
+ }
- autoload_add_name->set_text("");
- add_autoload->set_disabled(true);
+ autoload_add_name->set_text("");
+ add_autoload->set_disabled(true);
+ }
}
void EditorAutoloadSettings::_autoload_selected() {
@@ -351,14 +384,13 @@ void EditorAutoloadSettings::_autoload_text_submitted(const String p_name) {
}
void EditorAutoloadSettings::_autoload_path_text_changed(const String p_path) {
- add_autoload->set_disabled(
- p_path.is_empty() || !_autoload_name_is_valid(autoload_add_name->get_text(), nullptr));
+ add_autoload->set_disabled(!_autoload_name_is_valid(autoload_add_name->get_text(), nullptr));
}
void EditorAutoloadSettings::_autoload_text_changed(const String p_name) {
String error_string;
bool is_name_valid = _autoload_name_is_valid(p_name, &error_string);
- add_autoload->set_disabled(autoload_add_path->get_text().is_empty() || !is_name_valid);
+ add_autoload->set_disabled(!is_name_valid);
error_message->set_text(error_string);
error_message->set_visible(!autoload_add_name->get_text().is_empty() && !is_name_valid);
}
@@ -540,6 +572,14 @@ void EditorAutoloadSettings::update_autoload() {
updating_autoload = false;
}
+void EditorAutoloadSettings::_script_created(Ref<Script> p_script) {
+ FileSystemDock::get_singleton()->get_script_create_dialog()->hide();
+ path = p_script->get_path().get_base_dir();
+ autoload_add_path->set_text(p_script->get_path());
+ autoload_add_name->set_text(p_script->get_path().get_file().get_basename().capitalize().replace(" ", ""));
+ _autoload_add();
+}
+
Variant EditorAutoloadSettings::get_drag_data_fw(const Point2 &p_point, Control *p_control) {
if (autoload_cache.size() <= 1) {
return false;
@@ -833,11 +873,6 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
}
}
- autoload_changed = "autoload_changed";
-
- updating_autoload = false;
- selected_autoload = "";
-
HBoxContainer *hbc = memnew(HBoxContainer);
add_child(hbc);
@@ -854,6 +889,8 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
autoload_add_path = memnew(LineEdit);
hbc->add_child(autoload_add_path);
autoload_add_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ autoload_add_path->set_clear_button_enabled(true);
+ autoload_add_path->set_placeholder(vformat(TTR(R"(Set path or press "%s" to create a script.)"), TTR("Add")));
autoload_add_path->connect("text_changed", callable_mp(this, &EditorAutoloadSettings::_autoload_path_text_changed));
browse_button = memnew(Button);
diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h
index 044eea4245..380cadbebb 100644
--- a/editor/editor_autoload_settings.h
+++ b/editor/editor_autoload_settings.h
@@ -47,7 +47,8 @@ class EditorAutoloadSettings : public VBoxContainer {
BUTTON_DELETE
};
- String autoload_changed;
+ String path = "res://";
+ String autoload_changed = "autoload_changed";
struct AutoloadInfo {
String name;
@@ -64,17 +65,16 @@ class EditorAutoloadSettings : public VBoxContainer {
List<AutoloadInfo> autoload_cache;
- bool updating_autoload;
- int number_of_autoloads;
+ bool updating_autoload = false;
String selected_autoload;
- Tree *tree;
- LineEdit *autoload_add_name;
- Button *add_autoload;
- LineEdit *autoload_add_path;
- Label *error_message;
- Button *browse_button;
- EditorFileDialog *file_dialog;
+ Tree *tree = nullptr;
+ LineEdit *autoload_add_name = nullptr;
+ Button *add_autoload = nullptr;
+ LineEdit *autoload_add_path = nullptr;
+ Label *error_message = nullptr;
+ Button *browse_button = nullptr;
+ EditorFileDialog *file_dialog = nullptr;
bool _autoload_name_is_valid(const String &p_name, String *r_error = nullptr);
@@ -90,6 +90,8 @@ class EditorAutoloadSettings : public VBoxContainer {
void _autoload_file_callback(const String &p_path);
Node *_create_autoload(const String &p_path);
+ void _script_created(Ref<Script> p_script);
+
Variant get_drag_data_fw(const Point2 &p_point, Control *p_control);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_control) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_control);
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 69c7e9d52c..c16451f3c6 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -1206,9 +1206,6 @@ void EditorSelection::clear() {
}
EditorSelection::EditorSelection() {
- emitted = false;
- changed = false;
- nl_changed = false;
}
EditorSelection::~EditorSelection() {
diff --git a/editor/editor_data.h b/editor/editor_data.h
index 0d1efc9b62..79f8227e5c 100644
--- a/editor/editor_data.h
+++ b/editor/editor_data.h
@@ -239,9 +239,9 @@ class EditorSelection : public Object {
private:
Map<Node *, Object *> selection;
- bool emitted;
- bool changed;
- bool nl_changed;
+ bool emitted = false;
+ bool changed = false;
+ bool nl_changed = false;
void _node_removed(Node *p_node);
diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp
index f181c04004..32ef87a4ab 100644
--- a/editor/editor_dir_dialog.cpp
+++ b/editor/editor_dir_dialog.cpp
@@ -175,8 +175,6 @@ void EditorDirDialog::_bind_methods() {
}
EditorDirDialog::EditorDirDialog() {
- updating = false;
-
set_title(TTR("Choose a Directory"));
set_hide_on_ok(false);
@@ -206,6 +204,4 @@ EditorDirDialog::EditorDirDialog() {
add_child(mkdirerr);
get_ok_button()->set_text(TTR("Choose"));
-
- must_reload = false;
}
diff --git a/editor/editor_dir_dialog.h b/editor/editor_dir_dialog.h
index 053c1f5503..e97b5ce8af 100644
--- a/editor/editor_dir_dialog.h
+++ b/editor/editor_dir_dialog.h
@@ -47,7 +47,7 @@ class EditorDirDialog : public ConfirmationDialog {
Set<String> opened_paths;
Tree *tree;
- bool updating;
+ bool updating = false;
void _item_collapsed(Object *p_item);
void _item_activated();
@@ -58,7 +58,7 @@ class EditorDirDialog : public ConfirmationDialog {
void ok_pressed() override;
- bool must_reload;
+ bool must_reload = false;
protected:
void _notification(int p_what);
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 1afd59e99c..c3c8f40164 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -678,7 +678,6 @@ void EditorExportPlugin::_bind_methods() {
}
EditorExportPlugin::EditorExportPlugin() {
- skipped = false;
}
EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_containers(const Ref<EditorExportPreset> &p_preset) {
@@ -1722,7 +1721,6 @@ EditorExport::EditorExport() {
save_timer->set_wait_time(0.8);
save_timer->set_one_shot(true);
save_timer->connect("timeout", callable_mp(this, &EditorExport::_save));
- block_save = false;
_export_presets_updated = "export_presets_updated";
@@ -1831,10 +1829,6 @@ List<String> EditorExportPlatformPC::get_binary_extensions(const Ref<EditorExpor
Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
ExportNotifier notifier(*this, p_preset, p_debug, p_path, p_flags);
- if (!DirAccess::exists(p_path.get_base_dir())) {
- return ERR_FILE_BAD_PATH;
- }
-
String custom_debug = p_preset->get("custom_template/debug");
String custom_release = p_preset->get("custom_template/release");
@@ -1863,9 +1857,9 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
return ERR_FILE_NOT_FOUND;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ da->make_dir_recursive(p_path.get_base_dir());
Error err = da->copy(template_path, p_path, get_chmod_flags());
- memdelete(da);
if (err == OK) {
String pck_path;
@@ -1901,7 +1895,6 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
err = sign_shared_object(p_preset, p_debug, p_path.get_base_dir().plus_file(so_files[i].path.get_file()));
}
}
- memdelete(da);
}
}
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 796fb12793..182312b18f 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -297,7 +297,7 @@ class EditorExportPlugin : public RefCounted {
bool remap = false;
};
Vector<ExtraFile> extra_files;
- bool skipped;
+ bool skipped = false;
Vector<String> ios_frameworks;
Vector<String> ios_embedded_frameworks;
@@ -379,7 +379,7 @@ class EditorExport : public Node {
StringName _export_presets_updated;
Timer *save_timer;
- bool block_save;
+ bool block_save = false;
static EditorExport *singleton;
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 008c42b3a7..3d5ca7de42 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -34,6 +34,7 @@
#include "core/io/json.h"
#include "editor/editor_file_dialog.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
@@ -617,7 +618,8 @@ void EditorFeatureProfileManager::_class_list_item_selected() {
property->set_editable(0, true);
property->set_selectable(0, true);
property->set_checked(0, !edited->is_class_property_disabled(class_name, name));
- property->set_text(0, name.capitalize());
+ property->set_text(0, EditorPropertyNameProcessor::get_singleton()->process_name(name));
+ property->set_tooltip(0, EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(name));
property->set_metadata(0, name);
String icon_type = Variant::get_type_name(E.type);
property->set_icon(0, EditorNode::get_singleton()->get_class_icon(icon_type));
@@ -1008,7 +1010,5 @@ EditorFeatureProfileManager::EditorFeatureProfileManager() {
update_timer->connect("timeout", callable_mp(this, &EditorFeatureProfileManager::_emit_current_profile_changed));
update_timer->set_one_shot(true);
- updating_features = false;
-
singleton = this;
}
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
index 7ea40502a6..881f14638f 100644
--- a/editor/editor_feature_profile.h
+++ b/editor/editor_feature_profile.h
@@ -155,7 +155,7 @@ class EditorFeatureProfileManager : public AcceptDialog {
void _import_profiles(const Vector<String> &p_paths);
void _export_profile(const String &p_path);
- bool updating_features;
+ bool updating_features = false;
void _class_list_item_selected();
void _class_list_item_edited();
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 0fef4597be..31f2f24066 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -214,7 +214,7 @@ void EditorFileDialog::update_dir() {
if (dir_access->get_current_dir().is_network_share_path()) {
_update_drives(false);
drives->add_item(RTR("Network"));
- drives->set_item_disabled(drives->get_item_count() - 1, true);
+ drives->set_item_disabled(-1, true);
drives->select(drives->get_item_count() - 1);
} else {
drives->select(dir_access->get_current_drive());
@@ -314,8 +314,8 @@ void EditorFileDialog::_post_popup() {
recentd.remove_at(i--);
} else {
recent->add_item(name, folder);
- recent->set_item_metadata(recent->get_item_count() - 1, recentd[i]);
- recent->set_item_icon_modulate(recent->get_item_count() - 1, folder_color);
+ recent->set_item_metadata(-1, recentd[i]);
+ recent->set_item_icon_modulate(-1, folder_color);
}
}
EditorSettings::get_singleton()->set_recent_dirs(recentd);
@@ -800,9 +800,9 @@ void EditorFileDialog::update_file_list() {
item_list->add_item(dir_name);
if (display_mode == DISPLAY_THUMBNAILS) {
- item_list->set_item_icon(item_list->get_item_count() - 1, folder_thumbnail);
+ item_list->set_item_icon(-1, folder_thumbnail);
} else {
- item_list->set_item_icon(item_list->get_item_count() - 1, folder);
+ item_list->set_item_icon(-1, folder);
}
Dictionary d;
@@ -810,8 +810,8 @@ void EditorFileDialog::update_file_list() {
d["path"] = cdir.plus_file(dir_name);
d["dir"] = true;
- item_list->set_item_metadata(item_list->get_item_count() - 1, d);
- item_list->set_item_icon_modulate(item_list->get_item_count() - 1, folder_color);
+ item_list->set_item_metadata(-1, d);
+ item_list->set_item_icon_modulate(-1, folder_color);
dirs.pop_front();
}
@@ -858,10 +858,10 @@ void EditorFileDialog::update_file_list() {
if (get_icon_func) {
Ref<Texture2D> icon = get_icon_func(cdir.plus_file(files.front()->get()));
if (display_mode == DISPLAY_THUMBNAILS) {
- item_list->set_item_icon(item_list->get_item_count() - 1, file_thumbnail);
- item_list->set_item_tag_icon(item_list->get_item_count() - 1, icon);
+ item_list->set_item_icon(-1, file_thumbnail);
+ item_list->set_item_tag_icon(-1, icon);
} else {
- item_list->set_item_icon(item_list->get_item_count() - 1, icon);
+ item_list->set_item_icon(-1, icon);
}
}
@@ -870,7 +870,7 @@ void EditorFileDialog::update_file_list() {
d["dir"] = false;
String fullpath = cdir.plus_file(files.front()->get());
d["path"] = fullpath;
- item_list->set_item_metadata(item_list->get_item_count() - 1, d);
+ item_list->set_item_metadata(-1, d);
if (display_mode == DISPLAY_THUMBNAILS && previews_enabled) {
EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath, this, "_thumbnail_result", fullpath);
@@ -1321,8 +1321,8 @@ void EditorFileDialog::_update_favorites() {
continue; // We don't handle favorite files here.
}
- favorites->set_item_metadata(favorites->get_item_count() - 1, favorited[i]);
- favorites->set_item_icon_modulate(favorites->get_item_count() - 1, folder_color);
+ favorites->set_item_metadata(-1, favorited[i]);
+ favorites->set_item_icon_modulate(-1, folder_color);
if (setthis) {
favorite->set_pressed(true);
@@ -1471,9 +1471,9 @@ void EditorFileDialog::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
ADD_PROPERTY(PropertyInfo(Variant::INT, "display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"), "set_display_mode", "get_display_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_file_mode", "get_file_mode");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR), "set_current_dir", "get_current_dir");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*"), "set_current_file", "get_current_file");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path"), "set_current_path", "get_current_path");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_path", "get_current_path");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_overwrite_warning"), "set_disable_overwrite_warning", "is_overwrite_warning_disabled");
@@ -1557,7 +1557,6 @@ EditorFileDialog::EditorFileDialog() {
show_hidden_files = default_show_hidden_files;
display_mode = default_display_mode;
local_history_pos = 0;
- disable_overwrite_warning = false;
VBoxContainer *vbc = memnew(VBoxContainer);
add_child(vbc);
@@ -1814,15 +1813,12 @@ EditorFileDialog::EditorFileDialog() {
set_hide_on_ok(false);
vbox = vbc;
- invalidated = true;
if (register_func) {
register_func(this);
}
- previews_enabled = true;
preview_wheel_timeout = 0;
preview_wheel_index = 0;
- preview_waiting = false;
}
EditorFileDialog::~EditorFileDialog() {
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 65a4c9e544..a747255ce8 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -135,8 +135,8 @@ private:
Vector<String> filters;
- bool previews_enabled;
- bool preview_waiting;
+ bool previews_enabled = true;
+ bool preview_waiting = false;
int preview_wheel_index;
float preview_wheel_timeout;
@@ -145,8 +145,8 @@ private:
bool show_hidden_files;
DisplayMode display_mode;
- bool disable_overwrite_warning;
- bool invalidated;
+ bool disable_overwrite_warning = false;
+ bool invalidated = true;
void update_dir();
void update_file_name();
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 0c46cebec0..98ba3ae3d8 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -194,7 +194,6 @@ void EditorFileSystemDirectory::_bind_methods() {
EditorFileSystemDirectory::EditorFileSystemDirectory() {
modified_time = 0;
parent = nullptr;
- verified = false;
}
EditorFileSystemDirectory::~EditorFileSystemDirectory() {
@@ -1094,12 +1093,11 @@ void EditorFileSystem::_delete_internal_files(String p_file) {
if (FileAccess::exists(p_file + ".import")) {
List<String> paths;
ResourceFormatImporter::get_singleton()->get_internal_resource_path_list(p_file, &paths);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (const String &E : paths) {
da->remove(E);
}
da->remove(p_file + ".import");
- memdelete(da);
}
}
@@ -2384,24 +2382,14 @@ EditorFileSystem::EditorFileSystem() {
filesystem = memnew(EditorFileSystemDirectory); //like, empty
filesystem->parent = nullptr;
- scanning = false;
- importing = false;
- use_threads = true;
new_filesystem = nullptr;
- abort_scan = false;
- scanning_changes = false;
- scanning_changes_done = false;
-
// This should probably also work on Unix and use the string it returns for FAT32 or exFAT
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT");
scan_total = 0;
update_script_classes_queued.clear();
- first_scan = true;
- scan_changes_pending = false;
- revalidate_import_files = false;
import_threads.init();
ResourceUID::get_singleton()->clear(); //will be updated on scan
ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path);
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index 0c1bfbca47..0ec0094030 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -47,7 +47,7 @@ class EditorFileSystemDirectory : public Object {
String name;
uint64_t modified_time;
- bool verified; //used for checking changes
+ bool verified = false; //used for checking changes
EditorFileSystemDirectory *parent;
Vector<EditorFileSystemDirectory *> subdirs;
@@ -132,20 +132,20 @@ class EditorFileSystem : public Node {
EditorFileSystemDirectory::FileInfo *new_file = nullptr;
};
- bool use_threads;
+ bool use_threads = true;
Thread thread;
static void _thread_func(void *_userdata);
EditorFileSystemDirectory *new_filesystem;
- bool abort_scan;
- bool scanning;
- bool importing;
- bool first_scan;
- bool scan_changes_pending;
+ bool abort_scan = false;
+ bool scanning = false;
+ bool importing = false;
+ bool first_scan = true;
+ bool scan_changes_pending = false;
float scan_total;
String filesystem_settings_version_for_import;
- bool revalidate_import_files;
+ bool revalidate_import_files = false;
void _scan_filesystem();
@@ -197,8 +197,8 @@ class EditorFileSystem : public Node {
void _scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress);
Thread thread_sources;
- bool scanning_changes;
- bool scanning_changes_done;
+ bool scanning_changes = false;
+ bool scanning_changes_done = false;
static void _thread_func_sources(void *_userdata);
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index d80ee1d569..853278c5fc 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -174,7 +174,7 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te
}
void editor_register_fonts(Ref<Theme> p_theme) {
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
/* Custom font */
@@ -236,8 +236,6 @@ void editor_register_fonts(Ref<Theme> p_theme) {
EditorSettings::get_singleton()->set_manually("interface/editor/code_font", "");
}
- memdelete(dir);
-
/* Noto Sans */
Ref<FontData> DefaultFont = load_cached_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning);
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 39c8509148..622547f0a8 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -1897,8 +1897,6 @@ EditorHelp::EditorHelp() {
class_desc->set_selection_enabled(true);
- scroll_locked = false;
- select_locked = false;
class_desc->hide();
}
diff --git a/editor/editor_help.h b/editor/editor_help.h
index 10281a764c..b40d1709b6 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -98,7 +98,7 @@ class EditorHelp : public VBoxContainer {
};
- bool select_locked;
+ bool select_locked = false;
String prev_search;
@@ -144,7 +144,7 @@ class EditorHelp : public VBoxContainer {
void _help_callback(const String &p_topic);
void _add_text(const String &p_bbcode);
- bool scroll_locked;
+ bool scroll_locked = false;
//void _button_pressed(int p_idx);
void _add_type(const String &p_type, const String &p_enum = String());
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index eab62349d1..8e03c55712 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -180,8 +180,6 @@ void EditorHelpSearch::popup_dialog(const String &p_term) {
}
EditorHelpSearch::EditorHelpSearch() {
- old_search = false;
-
set_hide_on_ok(false);
set_title(TTR("Search Help"));
diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h
index 7d918d0c68..bf69fe1693 100644
--- a/editor/editor_help_search.h
+++ b/editor/editor_help_search.h
@@ -60,7 +60,7 @@ class EditorHelpSearch : public ConfirmationDialog {
Button *hierarchy_button;
OptionButton *filter_combo;
Tree *results_tree;
- bool old_search;
+ bool old_search = false;
String old_term;
class Runner;
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 999f057db9..9efd942a51 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -36,6 +36,7 @@
#include "editor/doc_tools.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "multi_node_edit.h"
@@ -947,31 +948,13 @@ void EditorProperty::_bind_methods() {
}
EditorProperty::EditorProperty() {
- draw_top_bg = true;
object = nullptr;
split_ratio = 0.5;
- selectable = true;
text_size = 0;
- read_only = false;
- checkable = false;
- checked = false;
- draw_warning = false;
- keying = false;
- deletable = false;
- keying_hover = false;
- revert_hover = false;
- check_hover = false;
- can_revert = false;
- can_pin = false;
- pin_hidden = false;
- pinned = false;
- use_folding = false;
property_usage = 0;
- selected = false;
selected_focusable = -1;
label_reference = nullptr;
bottom_editor = nullptr;
- delete_hover = false;
menu = nullptr;
set_process_unhandled_key_input(true);
}
@@ -2681,10 +2664,10 @@ void EditorInspector::update_tree() {
if (dot != -1) {
String ov = property_label_string.substr(dot);
property_label_string = property_label_string.substr(0, dot);
- property_label_string = property_label_string.capitalize();
+ property_label_string = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
property_label_string += ov;
} else {
- property_label_string = property_label_string.capitalize();
+ property_label_string = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
}
}
@@ -2735,13 +2718,15 @@ void EditorInspector::update_tree() {
current_vbox->add_child(section);
sections.push_back(section);
+ String label = component;
if (capitalize_paths) {
- component = component.capitalize();
+ label = EditorPropertyNameProcessor::get_singleton()->process_name(label);
}
Color c = sscolor;
c.a /= level;
- section->setup(acc_path, component, object, c, use_folding, section_depth);
+ section->setup(acc_path, label, object, c, use_folding, section_depth);
+ section->set_tooltip(EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(component));
// Add editors at the start of a group.
for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
@@ -2773,7 +2758,7 @@ void EditorInspector::update_tree() {
editor_inspector_array = memnew(EditorInspectorArray);
String array_label = path.contains("/") ? path.substr(path.rfind("/") + 1) : path;
- array_label = property_label_string.capitalize();
+ array_label = EditorPropertyNameProcessor::get_singleton()->process_name(property_label_string);
int page = per_array_page.has(array_element_prefix) ? per_array_page[array_element_prefix] : 0;
editor_inspector_array->setup_with_move_element_function(object, array_label, array_element_prefix, page, c, use_folding);
editor_inspector_array->connect("page_change_request", callable_mp(this, &EditorInspector::_page_change_request), varray(array_element_prefix));
@@ -3674,25 +3659,11 @@ EditorInspector::EditorInspector() {
add_child(main_vbox);
set_horizontal_scroll_mode(SCROLL_MODE_DISABLED);
- wide_editors = false;
- show_categories = false;
- hide_script = true;
- use_doc_hints = false;
- capitalize_paths = true;
- use_filter = false;
- autoclear = false;
changing = 0;
- use_folding = false;
- update_all_pending = false;
- update_tree_pending = false;
- read_only = false;
search_box = nullptr;
- keying = false;
_prop_edited = "property_edited";
set_process(false);
property_focusable = -1;
- sub_inspector = false;
- deletable_properties = false;
property_clipboard = Variant();
get_v_scroll_bar()->connect("value_changed", callable_mp(this, &EditorInspector::_vscroll_changed));
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index b76d16e59c..3c482a07e7 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -72,12 +72,12 @@ private:
int property_usage;
- bool read_only;
- bool checkable;
- bool checked;
- bool draw_warning;
- bool keying;
- bool deletable;
+ bool read_only = false;
+ bool checkable = false;
+ bool checked = false;
+ bool draw_warning = false;
+ bool keying = false;
+ bool deletable = false;
Rect2 right_child_rect;
Rect2 bottom_child_rect;
@@ -91,19 +91,19 @@ private:
Rect2 delete_rect;
bool delete_hover = false;
- bool can_revert;
- bool can_pin;
- bool pin_hidden;
- bool pinned;
+ bool can_revert = false;
+ bool can_pin = false;
+ bool pin_hidden = false;
+ bool pinned = false;
- bool use_folding;
- bool draw_top_bg;
+ bool use_folding = false;
+ bool draw_top_bg = true;
void _update_popup();
void _focusable_focused(int p_index);
- bool selectable;
- bool selected;
+ bool selectable = true;
+ bool selected = false;
int selected_focusable;
float split_ratio;
@@ -443,23 +443,23 @@ class EditorInspector : public ScrollContainer {
//
LineEdit *search_box;
- bool show_categories;
- bool hide_script;
- bool use_doc_hints;
- bool capitalize_paths;
- bool use_filter;
- bool autoclear;
- bool use_folding;
+ bool show_categories = false;
+ bool hide_script = true;
+ bool use_doc_hints = false;
+ bool capitalize_paths = true;
+ bool use_filter = false;
+ bool autoclear = false;
+ bool use_folding = false;
int changing;
- bool update_all_pending;
- bool read_only;
- bool keying;
- bool sub_inspector;
- bool wide_editors;
- bool deletable_properties;
+ bool update_all_pending = false;
+ bool read_only = false;
+ bool keying = false;
+ bool sub_inspector = false;
+ bool wide_editors = false;
+ bool deletable_properties = false;
float refresh_countdown;
- bool update_tree_pending;
+ bool update_tree_pending = false;
StringName _prop_edited;
StringName property_selected;
int property_focusable;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 7a9511e8c6..de0465a160 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -90,6 +90,7 @@
#include "editor/editor_paths.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_resource_picker.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_run.h"
@@ -700,7 +701,7 @@ void EditorNode::_notification(int p_what) {
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
- scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
+ scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int());
bool theme_changed =
EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") ||
@@ -3858,18 +3859,18 @@ void EditorNode::register_editor_types() {
GDREGISTER_CLASS(EditorScript);
GDREGISTER_CLASS(EditorSelection);
GDREGISTER_CLASS(EditorFileDialog);
- GDREGISTER_VIRTUAL_CLASS(EditorSettings);
+ GDREGISTER_ABSTRACT_CLASS(EditorSettings);
GDREGISTER_CLASS(EditorNode3DGizmo);
GDREGISTER_CLASS(EditorNode3DGizmoPlugin);
- GDREGISTER_VIRTUAL_CLASS(EditorResourcePreview);
+ GDREGISTER_ABSTRACT_CLASS(EditorResourcePreview);
GDREGISTER_CLASS(EditorResourcePreviewGenerator);
- GDREGISTER_VIRTUAL_CLASS(EditorFileSystem);
+ GDREGISTER_ABSTRACT_CLASS(EditorFileSystem);
GDREGISTER_CLASS(EditorFileSystemDirectory);
GDREGISTER_CLASS(EditorVCSInterface);
- GDREGISTER_VIRTUAL_CLASS(ScriptEditor);
- GDREGISTER_VIRTUAL_CLASS(ScriptEditorBase);
+ GDREGISTER_ABSTRACT_CLASS(ScriptEditor);
+ GDREGISTER_ABSTRACT_CLASS(ScriptEditorBase);
GDREGISTER_CLASS(EditorSyntaxHighlighter);
- GDREGISTER_VIRTUAL_CLASS(EditorInterface);
+ GDREGISTER_ABSTRACT_CLASS(EditorInterface);
GDREGISTER_CLASS(EditorExportPlugin);
GDREGISTER_CLASS(EditorResourceConversionPlugin);
GDREGISTER_CLASS(EditorSceneFormatImporter);
@@ -3884,7 +3885,7 @@ void EditorNode::register_editor_types() {
GDREGISTER_CLASS(EditorResourcePicker);
GDREGISTER_CLASS(EditorScriptPicker);
- GDREGISTER_VIRTUAL_CLASS(FileSystemDock);
+ GDREGISTER_ABSTRACT_CLASS(FileSystemDock);
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
GDREGISTER_CLASS(EditorScenePostImport);
@@ -5803,6 +5804,9 @@ void EditorNode::notify_settings_changed() {
}
EditorNode::EditorNode() {
+ EditorPropertyNameProcessor *epnp = memnew(EditorPropertyNameProcessor);
+ add_child(epnp);
+
Input::get_singleton()->set_use_accumulated_input(true);
Resource::_get_local_scene_func = _resource_get_edited_scene;
@@ -5837,16 +5841,7 @@ EditorNode::EditorNode() {
}
singleton = this;
- exiting = false;
- dimmed = false;
last_checked_version = 0;
- changing_scene = false;
- _initializing_addons = false;
- docks_visible = true;
- restoring_scenes = false;
- cmdline_export_mode = false;
- scene_distraction = false;
- script_distraction = false;
TranslationServer::get_singleton()->set_enabled(false);
// load settings
@@ -6021,10 +6016,10 @@ EditorNode::EditorNode() {
ClassDB::set_class_enabled("RootMotionView", true);
// defs here, use EDITOR_GET in logic
- EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false);
EDITOR_DEF("interface/editor/save_on_focus_loss", false);
EDITOR_DEF("interface/editor/show_update_spinner", false);
EDITOR_DEF("interface/editor/update_continuously", false);
+ EDITOR_DEF("interface/editor/translate_properties", true);
EDITOR_DEF_RST("interface/scene_tabs/restore_scenes_on_load", true);
EDITOR_DEF_RST("interface/inspector/capitalize_properties", true);
EDITOR_DEF_RST("interface/inspector/default_float_step", 0.001);
@@ -6246,7 +6241,7 @@ EditorNode::EditorNode() {
scene_tabs->set_select_with_rmb(true);
scene_tabs->add_tab("unsaved");
scene_tabs->set_tab_alignment(TabBar::ALIGNMENT_LEFT);
- scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
+ scene_tabs->set_tab_close_display_policy((TabBar::CloseButtonDisplayPolicy)EDITOR_GET("interface/scene_tabs/display_close_button").operator int());
scene_tabs->set_max_tab_width(int(EDITOR_GET("interface/scene_tabs/maximum_width")) * EDSCALE);
scene_tabs->set_drag_to_rearrange_enabled(true);
scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed));
@@ -6511,7 +6506,7 @@ EditorNode::EditorNode() {
ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KeyModifierMask::CMD | Key::F12);
p->add_shortcut(ED_GET_SHORTCUT("editor/take_screenshot"), EDITOR_SCREENSHOT);
- p->set_item_tooltip(p->get_item_count() - 1, TTR("Screenshots are stored in the Editor Data/Settings Folder."));
+ p->set_item_tooltip(-1, TTR("Screenshots are stored in the Editor Data/Settings Folder."));
ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTR("Toggle Fullscreen"), KeyModifierMask::SHIFT | Key::F11);
ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::F);
@@ -7107,9 +7102,6 @@ EditorNode::EditorNode() {
current = nullptr;
saving_resource = Ref<Resource>();
- reference_resource_mem = true;
- save_external_resources_mem = true;
-
set_process(true);
open_imported = memnew(ConfirmationDialog);
@@ -7120,7 +7112,6 @@ EditorNode::EditorNode() {
gui_base->add_child(open_imported);
saved_version = 1;
- unsaved_cache = true;
_last_instantiated_scene = nullptr;
quick_open = memnew(EditorQuickOpen);
@@ -7134,10 +7125,7 @@ EditorNode::EditorNode() {
_update_recent_scenes();
editor_data.restore_editor_global_states();
- convert_old = false;
- opening_prev = false;
set_process_unhandled_input(true);
- _playing_edited = false;
load_errors = memnew(RichTextLabel);
load_error_dialog = memnew(AcceptDialog);
@@ -7178,8 +7166,6 @@ EditorNode::EditorNode() {
FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
- waiting_for_first_scan = true;
-
print_handler.printfunc = _print_handler;
print_handler.userdata = this;
add_print_handler(&print_handler);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index c05e6cd281..0b6dbaec49 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -263,8 +263,8 @@ private:
TextureRect *tab_preview;
int tab_closing;
- bool exiting;
- bool dimmed;
+ bool exiting = false;
+ bool dimmed = false;
int old_split_ofs;
VSplitContainer *top_split;
@@ -380,15 +380,15 @@ private:
Button *dock_tab_move_right;
int dock_popup_selected;
Timer *dock_drag_timer;
- bool docks_visible;
+ bool docks_visible = true;
HBoxContainer *tabbar_container;
Button *distraction_free;
Button *scene_tab_add;
Control *scene_tab_add_ph;
- bool scene_distraction;
- bool script_distraction;
+ bool scene_distraction = false;
+ bool script_distraction = false;
String _tmp_import_path;
@@ -397,18 +397,15 @@ private:
Object *current;
Ref<Resource> saving_resource;
- bool _playing_edited;
+ bool _playing_edited = false;
String run_custom_filename;
- bool reference_resource_mem;
- bool save_external_resources_mem;
+ bool reference_resource_mem = true;
uint64_t saved_version;
uint64_t last_checked_version;
- bool unsaved_cache;
+ bool unsaved_cache = true;
String open_navigate;
- bool changing_scene;
- bool waiting_for_first_scan;
-
- bool waiting_for_sources_changed;
+ bool changing_scene = false;
+ bool waiting_for_first_scan = true;
uint64_t update_spinner_step_msec;
uint64_t update_spinner_step_frame;
@@ -457,7 +454,7 @@ private:
String external_file;
List<String> previous_scenes;
- bool opening_prev;
+ bool opening_prev = false;
void _dialog_action(String p_file);
@@ -534,7 +531,7 @@ private:
void _exit_editor(int p_exit_code);
- bool convert_old;
+ bool convert_old = false;
virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
@@ -551,7 +548,7 @@ private:
Map<String, Ref<Texture2D>> icon_type_cache;
void _build_icon_type_cache();
- bool _initializing_addons;
+ bool _initializing_addons = false;
Map<String, EditorPlugin *> plugin_addons;
static Ref<Texture2D> _file_dialog_get_icon(const String &p_path);
@@ -587,7 +584,7 @@ private:
bool pack_only = false;
} export_defer;
- bool cmdline_export_mode;
+ bool cmdline_export_mode = false;
static EditorNode *singleton;
@@ -627,7 +624,7 @@ private:
void _update_dock_slots_visibility();
void _dock_tab_changed(int p_tab);
- bool restoring_scenes;
+ bool restoring_scenes = false;
void _save_open_scenes_to_config(Ref<ConfigFile> p_layout, const String &p_section);
void _load_open_scenes_from_config(Ref<ConfigFile> p_layout, const String &p_section);
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 401414ae50..b6f48c7536 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -240,6 +240,4 @@ EditorPluginSettings::EditorPluginSettings() {
mc->set_h_size_flags(SIZE_EXPAND_FILL);
add_child(mc);
-
- updating = false;
}
diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h
index 4648d105f7..c239b735de 100644
--- a/editor/editor_plugin_settings.h
+++ b/editor/editor_plugin_settings.h
@@ -48,7 +48,7 @@ class EditorPluginSettings : public VBoxContainer {
Button *create_plugin;
Button *update_list;
Tree *plugin_list;
- bool updating;
+ bool updating = false;
void _plugin_activity_changed();
void _create_clicked();
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 1a4d507eef..b495d29911 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -110,9 +110,6 @@ EditorPropertyText::EditorPropertyText() {
add_focusable(text);
text->connect("text_changed", callable_mp(this, &EditorPropertyText::_text_changed));
text->connect("text_submitted", callable_mp(this, &EditorPropertyText::_text_submitted));
-
- string_name = false;
- updating = false;
}
///////////////////// MULTILINE TEXT /////////////////////////
@@ -500,9 +497,6 @@ EditorPropertyPath::EditorPropertyPath() {
add_focusable(path);
dialog = nullptr;
path_edit->connect("pressed", callable_mp(this, &EditorPropertyPath::_path_pressed));
- folder = false;
- global = false;
- save_mode = false;
}
///////////////////// CLASS NAME /////////////////////////
@@ -1278,7 +1272,6 @@ EditorPropertyInteger::EditorPropertyInteger() {
add_child(spin);
add_focusable(spin);
spin->connect("value_changed", callable_mp(this, &EditorPropertyInteger::_value_changed));
- setting = false;
}
///////////////////// OBJECT ID /////////////////////////
@@ -1587,10 +1580,6 @@ EditorPropertyEasing::EditorPropertyEasing() {
spin->get_line_edit()->connect("focus_exited", callable_mp(this, &EditorPropertyEasing::_spin_focus_exited));
spin->hide();
add_child(spin);
-
- dragging = false;
- flip = false;
- full = false;
}
///////////////////// VECTOR2 /////////////////////////
@@ -1680,7 +1669,6 @@ EditorPropertyVector2::EditorPropertyVector2(bool p_force_wide) {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// RECT2 /////////////////////////
@@ -1784,7 +1772,6 @@ EditorPropertyRect2::EditorPropertyRect2(bool p_force_wide) {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// VECTOR3 /////////////////////////
@@ -1993,7 +1980,6 @@ EditorPropertyVector2i::EditorPropertyVector2i(bool p_force_wide) {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// RECT2i /////////////////////////
@@ -2097,7 +2083,6 @@ EditorPropertyRect2i::EditorPropertyRect2i(bool p_force_wide) {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// VECTOR3i /////////////////////////
@@ -2188,7 +2173,6 @@ EditorPropertyVector3i::EditorPropertyVector3i(bool p_force_wide) {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// PLANE /////////////////////////
@@ -2282,7 +2266,6 @@ EditorPropertyPlane::EditorPropertyPlane(bool p_force_wide) {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// QUATERNION /////////////////////////
@@ -2373,7 +2356,6 @@ EditorPropertyQuaternion::EditorPropertyQuaternion() {
if (!horizontal) {
set_label_reference(spin[0]); //show text and buttons around this
}
- setting = false;
}
///////////////////// AABB /////////////////////////
@@ -2457,7 +2439,6 @@ EditorPropertyAABB::EditorPropertyAABB() {
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyAABB::_value_changed), varray(desc[i]));
}
set_bottom_editor(g);
- setting = false;
}
///////////////////// TRANSFORM2D /////////////////////////
@@ -2547,7 +2528,6 @@ EditorPropertyTransform2D::EditorPropertyTransform2D(bool p_include_origin) {
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform2D::_value_changed), varray(desc[i]));
}
set_bottom_editor(g);
- setting = false;
}
///////////////////// BASIS /////////////////////////
@@ -2636,7 +2616,6 @@ EditorPropertyBasis::EditorPropertyBasis() {
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyBasis::_value_changed), varray(desc[i]));
}
set_bottom_editor(g);
- setting = false;
}
///////////////////// TRANSFORM /////////////////////////
@@ -2733,7 +2712,6 @@ EditorPropertyTransform3D::EditorPropertyTransform3D() {
spin[i]->connect("value_changed", callable_mp(this, &EditorPropertyTransform3D::_value_changed), varray(desc[i]));
}
set_bottom_editor(g);
- setting = false;
}
////////////// COLOR PICKER //////////////////////
@@ -2969,7 +2947,6 @@ EditorPropertyNodePath::EditorPropertyNodePath() {
clear->set_flat(true);
clear->connect("pressed", callable_mp(this, &EditorPropertyNodePath::_node_clear));
hbc->add_child(clear);
- use_path_from_scene_root = false;
scene_tree = nullptr; //do not allocate unnecessarily
}
@@ -3738,8 +3715,13 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
} break;
case Variant::DICTIONARY: {
- EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
- return editor;
+ if (p_hint == PROPERTY_HINT_LOCALIZABLE_STRING) {
+ EditorPropertyLocalizableString *editor = memnew(EditorPropertyLocalizableString);
+ return editor;
+ } else {
+ EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary);
+ return editor;
+ }
} break;
case Variant::ARRAY: {
EditorPropertyArray *editor = memnew(EditorPropertyArray);
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index 9a16a78ff8..c21e0e0b4d 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -54,8 +54,8 @@ class EditorPropertyText : public EditorProperty {
GDCLASS(EditorPropertyText, EditorProperty);
LineEdit *text;
- bool updating;
- bool string_name;
+ bool updating = false;
+ bool string_name = false;
void _text_changed(const String &p_string);
void _text_submitted(const String &p_string);
@@ -131,9 +131,9 @@ public:
class EditorPropertyPath : public EditorProperty {
GDCLASS(EditorPropertyPath, EditorProperty);
Vector<String> extensions;
- bool folder;
- bool global;
- bool save_mode;
+ bool folder = false;
+ bool global = false;
+ bool save_mode = false;
EditorFileDialog *dialog;
LineEdit *path;
Button *path_edit;
@@ -359,7 +359,7 @@ public:
class EditorPropertyInteger : public EditorProperty {
GDCLASS(EditorPropertyInteger, EditorProperty);
EditorSpinSlider *spin;
- bool setting;
+ bool setting = false;
void _value_changed(int64_t p_val);
protected:
@@ -410,11 +410,11 @@ class EditorPropertyEasing : public EditorProperty {
Control *easing_draw;
PopupMenu *preset;
EditorSpinSlider *spin;
- bool setting;
+ bool setting = false;
- bool dragging;
- bool full;
- bool flip;
+ bool dragging = false;
+ bool full = false;
+ bool flip = false;
enum {
EASING_ZERO,
@@ -450,7 +450,7 @@ public:
class EditorPropertyVector2 : public EditorProperty {
GDCLASS(EditorPropertyVector2, EditorProperty);
EditorSpinSlider *spin[2];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -467,7 +467,7 @@ public:
class EditorPropertyRect2 : public EditorProperty {
GDCLASS(EditorPropertyRect2, EditorProperty);
EditorSpinSlider *spin[4];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -504,7 +504,7 @@ public:
class EditorPropertyVector2i : public EditorProperty {
GDCLASS(EditorPropertyVector2i, EditorProperty);
EditorSpinSlider *spin[2];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -521,7 +521,7 @@ public:
class EditorPropertyRect2i : public EditorProperty {
GDCLASS(EditorPropertyRect2i, EditorProperty);
EditorSpinSlider *spin[4];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -538,7 +538,7 @@ public:
class EditorPropertyVector3i : public EditorProperty {
GDCLASS(EditorPropertyVector3i, EditorProperty);
EditorSpinSlider *spin[3];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -555,7 +555,7 @@ public:
class EditorPropertyPlane : public EditorProperty {
GDCLASS(EditorPropertyPlane, EditorProperty);
EditorSpinSlider *spin[4];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -572,7 +572,7 @@ public:
class EditorPropertyQuaternion : public EditorProperty {
GDCLASS(EditorPropertyQuaternion, EditorProperty);
EditorSpinSlider *spin[4];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -589,7 +589,7 @@ public:
class EditorPropertyAABB : public EditorProperty {
GDCLASS(EditorPropertyAABB, EditorProperty);
EditorSpinSlider *spin[6];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -606,7 +606,7 @@ public:
class EditorPropertyTransform2D : public EditorProperty {
GDCLASS(EditorPropertyTransform2D, EditorProperty);
EditorSpinSlider *spin[6];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -623,7 +623,7 @@ public:
class EditorPropertyBasis : public EditorProperty {
GDCLASS(EditorPropertyBasis, EditorProperty);
EditorSpinSlider *spin[9];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -640,7 +640,7 @@ public:
class EditorPropertyTransform3D : public EditorProperty {
GDCLASS(EditorPropertyTransform3D, EditorProperty);
EditorSpinSlider *spin[12];
- bool setting;
+ bool setting = false;
void _value_changed(double p_val, const String &p_name);
protected:
@@ -681,7 +681,7 @@ class EditorPropertyNodePath : public EditorProperty {
Button *clear;
SceneTreeDialog *scene_tree;
NodePath base_hint;
- bool use_path_from_scene_root;
+ bool use_path_from_scene_root = false;
Vector<StringName> valid_types;
void _node_selected(const NodePath &p_path);
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index d354be9af5..76d1ada820 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -714,7 +714,6 @@ EditorPropertyArray::EditorPropertyArray() {
size_slider = nullptr;
button_add_item = nullptr;
paginator = nullptr;
- updating = false;
change_type = memnew(PopupMenu);
add_child(change_type);
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyArray::_change_type_menu));
@@ -723,8 +722,6 @@ EditorPropertyArray::EditorPropertyArray() {
subtype = Variant::NIL;
subtype_hint = PROPERTY_HINT_NONE;
subtype_hint_string = "";
-
- dropping = false;
}
///////////////////// DICTIONARY ///////////////////////////
@@ -742,7 +739,7 @@ void EditorPropertyDictionary::_property_changed(const String &p_property, Varia
emit_changed(get_edited_property(), dict, "", true);
- dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
}
}
@@ -805,7 +802,7 @@ void EditorPropertyDictionary::_change_type_menu(int p_index) {
emit_changed(get_edited_property(), dict, "", false);
- dict = dict.duplicate(); // Duplicate, so undo/redo works better\.
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
object->set_dict(dict);
update_property();
}
@@ -814,7 +811,7 @@ void EditorPropertyDictionary::update_property() {
Variant updated_val = get_edited_object()->get(get_edited_property());
if (updated_val.get_type() == Variant::NIL) {
- edit->set_text("Dictionary (Nil)"); // This provides symmetry with the array property.
+ edit->set_text(TTR("Dictionary (Nil)")); // This provides symmetry with the array property.
edit->set_pressed(false);
if (vbox) {
set_bottom_editor(nullptr);
@@ -826,7 +823,7 @@ void EditorPropertyDictionary::update_property() {
Dictionary dict = updated_val;
- edit->set_text("Dictionary (size " + itos(dict.size()) + ")");
+ edit->set_text(vformat(TTR("Dictionary (size %d)"), dict.size()));
bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
if (edit->is_pressed() != unfolded) {
@@ -1144,6 +1141,7 @@ void EditorPropertyDictionary::update_property() {
if (vbox) {
set_bottom_editor(nullptr);
memdelete(vbox);
+ button_add_item = nullptr;
vbox = nullptr;
}
}
@@ -1210,9 +1208,231 @@ EditorPropertyDictionary::EditorPropertyDictionary() {
vbox = nullptr;
button_add_item = nullptr;
paginator = nullptr;
- updating = false;
change_type = memnew(PopupMenu);
add_child(change_type);
change_type->connect("id_pressed", callable_mp(this, &EditorPropertyDictionary::_change_type_menu));
changing_type_index = -1;
}
+
+///////////////////// LOCALIZABLE STRING ///////////////////////////
+
+void EditorPropertyLocalizableString::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) {
+ if (p_property.begins_with("indices")) {
+ int index = p_property.get_slice("/", 1).to_int();
+ Dictionary dict = object->get_dict();
+ Variant key = dict.get_key_at_index(index);
+ dict[key] = p_value;
+
+ emit_changed(get_edited_property(), dict, "", true);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ }
+}
+
+void EditorPropertyLocalizableString::_add_locale_popup() {
+ locale_select->popup_locale_dialog();
+}
+
+void EditorPropertyLocalizableString::_add_locale(const String &p_locale) {
+ Dictionary dict = object->get_dict();
+
+ object->set_new_item_key(p_locale);
+ object->set_new_item_value(String());
+ dict[object->get_new_item_key()] = object->get_new_item_value();
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyLocalizableString::_remove_item(Object *p_button, int p_index) {
+ Dictionary dict = object->get_dict();
+
+ Variant key = dict.get_key_at_index(p_index);
+ dict.erase(key);
+
+ emit_changed(get_edited_property(), dict, "", false);
+
+ dict = dict.duplicate(); // Duplicate, so undo/redo works better.
+ object->set_dict(dict);
+ update_property();
+}
+
+void EditorPropertyLocalizableString::update_property() {
+ Variant updated_val = get_edited_object()->get(get_edited_property());
+
+ if (updated_val.get_type() == Variant::NIL) {
+ edit->set_text(TTR("Localizable String (Nil)")); // This provides symmetry with the array property.
+ edit->set_pressed(false);
+ if (vbox) {
+ set_bottom_editor(nullptr);
+ memdelete(vbox);
+ vbox = nullptr;
+ }
+ return;
+ }
+
+ Dictionary dict = updated_val;
+
+ edit->set_text(vformat(TTR("Localizable String (size %d)"), dict.size()));
+
+ bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property());
+ if (edit->is_pressed() != unfolded) {
+ edit->set_pressed(unfolded);
+ }
+
+ if (unfolded) {
+ updating = true;
+
+ if (!vbox) {
+ vbox = memnew(VBoxContainer);
+ add_child(vbox);
+ set_bottom_editor(vbox);
+
+ property_vbox = memnew(VBoxContainer);
+ property_vbox->set_h_size_flags(SIZE_EXPAND_FILL);
+ vbox->add_child(property_vbox);
+
+ paginator = memnew(EditorPaginator);
+ paginator->connect("page_changed", callable_mp(this, &EditorPropertyLocalizableString::_page_changed));
+ vbox->add_child(paginator);
+ } else {
+ // Queue children for deletion, deleting immediately might cause errors.
+ for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) {
+ property_vbox->get_child(i)->queue_delete();
+ }
+ }
+
+ int size = dict.size();
+
+ int max_page = MAX(0, size - 1) / page_length;
+ page_index = MIN(page_index, max_page);
+
+ paginator->update(page_index, max_page);
+ paginator->set_visible(max_page > 0);
+
+ int offset = page_index * page_length;
+
+ int amount = MIN(size - offset, page_length);
+
+ dict = dict.duplicate();
+
+ object->set_dict(dict);
+
+ for (int i = 0; i < amount; i++) {
+ String prop_name;
+ Variant key;
+ Variant value;
+
+ prop_name = "indices/" + itos(i + offset);
+ key = dict.get_key_at_index(i + offset);
+ value = dict.get_value_at_index(i + offset);
+
+ EditorProperty *prop = memnew(EditorPropertyText);
+
+ prop->set_object_and_property(object.ptr(), prop_name);
+ int remove_index = 0;
+
+ String cs = key.get_construct_string();
+ prop->set_label(cs);
+ prop->set_tooltip(cs);
+ remove_index = i + offset;
+
+ prop->set_selectable(false);
+ prop->connect("property_changed", callable_mp(this, &EditorPropertyLocalizableString::_property_changed));
+ prop->connect("object_id_selected", callable_mp(this, &EditorPropertyLocalizableString::_object_id_selected));
+
+ HBoxContainer *hbox = memnew(HBoxContainer);
+ property_vbox->add_child(hbox);
+ hbox->add_child(prop);
+ prop->set_h_size_flags(SIZE_EXPAND_FILL);
+ Button *edit = memnew(Button);
+ edit->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ hbox->add_child(edit);
+ edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_remove_item), varray(edit, remove_index));
+
+ prop->update_property();
+ }
+
+ if (page_index == max_page) {
+ button_add_item = memnew(Button);
+ button_add_item->set_text(TTR("Add Translation"));
+ button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ button_add_item->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_add_locale_popup));
+ property_vbox->add_child(button_add_item);
+ }
+
+ updating = false;
+
+ } else {
+ if (vbox) {
+ set_bottom_editor(nullptr);
+ memdelete(vbox);
+ button_add_item = nullptr;
+ vbox = nullptr;
+ }
+ }
+}
+
+void EditorPropertyLocalizableString::_object_id_selected(const StringName &p_property, ObjectID p_id) {
+ emit_signal(SNAME("object_id_selected"), p_property, p_id);
+}
+
+void EditorPropertyLocalizableString::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_THEME_CHANGED:
+ case NOTIFICATION_ENTER_TREE: {
+ if (Object::cast_to<Button>(button_add_item)) {
+ button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ }
+ } break;
+ }
+}
+
+void EditorPropertyLocalizableString::_edit_pressed() {
+ Variant prop_val = get_edited_object()->get(get_edited_property());
+ if (prop_val.get_type() == Variant::NIL) {
+ Callable::CallError ce;
+ Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce);
+ get_edited_object()->set(get_edited_property(), prop_val);
+ }
+
+ get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed());
+ update_property();
+}
+
+void EditorPropertyLocalizableString::_page_changed(int p_page) {
+ if (updating) {
+ return;
+ }
+ page_index = p_page;
+ update_property();
+}
+
+void EditorPropertyLocalizableString::_bind_methods() {
+}
+
+EditorPropertyLocalizableString::EditorPropertyLocalizableString() {
+ object.instantiate();
+ page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page"));
+
+ edit = memnew(Button);
+ edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ edit->set_clip_text(true);
+ edit->connect("pressed", callable_mp(this, &EditorPropertyLocalizableString::_edit_pressed));
+ edit->set_toggle_mode(true);
+ add_child(edit);
+ add_focusable(edit);
+
+ vbox = nullptr;
+ button_add_item = nullptr;
+ paginator = nullptr;
+ updating = false;
+
+ locale_select = memnew(EditorLocaleDialog);
+ locale_select->connect("locale_selected", callable_mp(this, &EditorPropertyLocalizableString::_add_locale));
+ add_child(locale_select);
+}
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index 292de6d6db..3d9fe90b20 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -32,6 +32,7 @@
#define EDITOR_PROPERTIES_ARRAY_DICT_H
#include "editor/editor_inspector.h"
+#include "editor/editor_locale_dialog.h"
#include "editor/editor_spin_slider.h"
#include "editor/filesystem_dock.h"
#include "scene/gui/button.h"
@@ -80,8 +81,8 @@ class EditorPropertyArray : public EditorProperty {
GDCLASS(EditorPropertyArray, EditorProperty);
PopupMenu *change_type;
- bool updating;
- bool dropping;
+ bool updating = false;
+ bool dropping = false;
Ref<EditorPropertyArrayObject> object;
int page_length = 20;
@@ -138,7 +139,7 @@ class EditorPropertyDictionary : public EditorProperty {
GDCLASS(EditorPropertyDictionary, EditorProperty);
PopupMenu *change_type;
- bool updating;
+ bool updating = false;
Ref<EditorPropertyDictionaryObject> object;
int page_length = 20;
@@ -169,4 +170,39 @@ public:
EditorPropertyDictionary();
};
+class EditorPropertyLocalizableString : public EditorProperty {
+ GDCLASS(EditorPropertyLocalizableString, EditorProperty);
+
+ EditorLocaleDialog *locale_select;
+
+ bool updating;
+
+ Ref<EditorPropertyDictionaryObject> object;
+ int page_length = 20;
+ int page_index = 0;
+ Button *edit;
+ VBoxContainer *vbox;
+ VBoxContainer *property_vbox;
+ EditorSpinSlider *size_slider;
+ Button *button_add_item;
+ EditorPaginator *paginator;
+
+ void _page_changed(int p_page);
+ void _edit_pressed();
+ void _remove_item(Object *p_button, int p_index);
+ void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false);
+
+ void _add_locale_popup();
+ void _add_locale(const String &p_locale);
+ void _object_id_selected(const StringName &p_property, ObjectID p_id);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ virtual void update_property() override;
+ EditorPropertyLocalizableString();
+};
+
#endif // EDITOR_PROPERTIES_ARRAY_DICT_H
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
new file mode 100644
index 0000000000..38003ab2f4
--- /dev/null
+++ b/editor/editor_property_name_processor.cpp
@@ -0,0 +1,121 @@
+/*************************************************************************/
+/* editor_property_name_processor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor_property_name_processor.h"
+
+#include "editor_settings.h"
+
+EditorPropertyNameProcessor *EditorPropertyNameProcessor::singleton = nullptr;
+
+String EditorPropertyNameProcessor::_capitalize_name(const String &p_name) const {
+ String capitalized_string = p_name.capitalize();
+
+ // Fix the casing of a few strings commonly found in editor property/setting names.
+ for (Map<String, String>::Element *E = capitalize_string_remaps.front(); E; E = E->next()) {
+ capitalized_string = capitalized_string.replace(E->key(), E->value());
+ }
+
+ return capitalized_string;
+}
+
+String EditorPropertyNameProcessor::process_name(const String &p_name) const {
+ const String capitalized_string = _capitalize_name(p_name);
+ if (EDITOR_GET("interface/editor/translate_properties")) {
+ return TTRGET(capitalized_string);
+ }
+ return capitalized_string;
+}
+
+String EditorPropertyNameProcessor::make_tooltip_for_name(const String &p_name) const {
+ const String capitalized_string = _capitalize_name(p_name);
+ if (EDITOR_GET("interface/editor/translate_properties")) {
+ return capitalized_string;
+ }
+ return TTRGET(capitalized_string);
+}
+
+EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
+ ERR_FAIL_COND(singleton != nullptr);
+ singleton = this;
+
+ // The following initialization is parsed in `editor/translations/extract.py` with a regex.
+ // The map name and value definition format should be kept synced with the regex.
+ capitalize_string_remaps["2d"] = "2D";
+ capitalize_string_remaps["3d"] = "3D";
+ capitalize_string_remaps["Adb"] = "ADB";
+ capitalize_string_remaps["Bptc"] = "BPTC";
+ capitalize_string_remaps["Bvh"] = "BVH";
+ capitalize_string_remaps["Csg"] = "CSG";
+ capitalize_string_remaps["Cpu"] = "CPU";
+ capitalize_string_remaps["Db"] = "dB";
+ capitalize_string_remaps["Dof"] = "DoF";
+ capitalize_string_remaps["Dpi"] = "DPI";
+ capitalize_string_remaps["Etc"] = "ETC";
+ capitalize_string_remaps["Fbx"] = "FBX";
+ capitalize_string_remaps["Fps"] = "FPS";
+ capitalize_string_remaps["Fov"] = "FOV";
+ capitalize_string_remaps["Fs"] = "FS";
+ capitalize_string_remaps["Fxaa"] = "FXAA";
+ capitalize_string_remaps["Ggx"] = "GGX";
+ capitalize_string_remaps["Gdscript"] = "GDScript";
+ capitalize_string_remaps["Gles 2"] = "GLES2";
+ capitalize_string_remaps["Gles 3"] = "GLES3";
+ capitalize_string_remaps["Gi Probe"] = "GI Probe";
+ capitalize_string_remaps["Hdr"] = "HDR";
+ capitalize_string_remaps["Hidpi"] = "hiDPI";
+ capitalize_string_remaps["Ik"] = "IK";
+ capitalize_string_remaps["Ios"] = "iOS";
+ capitalize_string_remaps["Kb"] = "KB";
+ capitalize_string_remaps["Msaa"] = "MSAA";
+ capitalize_string_remaps["Macos"] = "macOS";
+ capitalize_string_remaps["Opentype"] = "OpenType";
+ capitalize_string_remaps["Png"] = "PNG";
+ capitalize_string_remaps["Pvs"] = "PVS";
+ capitalize_string_remaps["Pvrtc"] = "PVRTC";
+ capitalize_string_remaps["S 3 Tc"] = "S3TC";
+ capitalize_string_remaps["Sdfgi"] = "SDFGI";
+ capitalize_string_remaps["Srgb"] = "sRGB";
+ capitalize_string_remaps["Ssao"] = "SSAO";
+ capitalize_string_remaps["Ssl"] = "SSL";
+ capitalize_string_remaps["Ssh"] = "SSH";
+ capitalize_string_remaps["Sdk"] = "SDK";
+ capitalize_string_remaps["Tcp"] = "TCP";
+ capitalize_string_remaps["Uv 1"] = "UV1";
+ capitalize_string_remaps["Uv 2"] = "UV2";
+ capitalize_string_remaps["Vram"] = "VRAM";
+ capitalize_string_remaps["Vsync"] = "V-Sync";
+ capitalize_string_remaps["Vector 2"] = "Vector2";
+ capitalize_string_remaps["Webrtc"] = "WebRTC";
+ capitalize_string_remaps["Websocket"] = "WebSocket";
+}
+
+EditorPropertyNameProcessor::~EditorPropertyNameProcessor() {
+ singleton = nullptr;
+}
diff --git a/editor/editor_property_name_processor.h b/editor/editor_property_name_processor.h
new file mode 100644
index 0000000000..efd7abced3
--- /dev/null
+++ b/editor/editor_property_name_processor.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* editor_property_name_processor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef EDITOR_PROPERTY_NAME_PROCESSOR_H
+#define EDITOR_PROPERTY_NAME_PROCESSOR_H
+
+#include "scene/main/node.h"
+
+class EditorPropertyNameProcessor : public Node {
+ GDCLASS(EditorPropertyNameProcessor, Node);
+
+ static EditorPropertyNameProcessor *singleton;
+
+ Map<String, String> capitalize_string_remaps;
+
+ String _capitalize_name(const String &p_name) const;
+
+public:
+ static EditorPropertyNameProcessor *get_singleton() { return singleton; }
+
+ // Capitalize & localize property path segments.
+ String process_name(const String &p_name) const;
+
+ // Make tooltip string for names processed by process_name().
+ String make_tooltip_for_name(const String &p_name) const;
+
+ EditorPropertyNameProcessor();
+ ~EditorPropertyNameProcessor();
+};
+
+#endif // EDITOR_PROPERTY_NAME_PROCESSOR_H
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 85d304ec5d..5db7b8673f 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -83,7 +83,7 @@ void EditorRunNative::_notification(int p_what) {
mb->set_tooltip(eep->get_options_tooltip());
for (int i = 0; i < dc; i++) {
mb->get_popup()->add_icon_item(eep->get_option_icon(i), eep->get_option_label(i));
- mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() - 1, eep->get_option_tooltip(i));
+ mb->get_popup()->set_item_tooltip(-1, eep->get_option_tooltip(i));
}
}
}
@@ -168,7 +168,6 @@ bool EditorRunNative::is_deploy_debug_remote_enabled() const {
EditorRunNative::EditorRunNative() {
set_process(true);
- first = true;
resume_idx = 0;
resume_platform = 0;
}
diff --git a/editor/editor_run_native.h b/editor/editor_run_native.h
index 199d094e55..4cb5779350 100644
--- a/editor/editor_run_native.h
+++ b/editor/editor_run_native.h
@@ -38,7 +38,7 @@ class EditorRunNative : public HBoxContainer {
GDCLASS(EditorRunNative, HBoxContainer);
Map<int, MenuButton *> menus;
- bool first;
+ bool first = true;
int resume_idx;
int resume_platform;
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index 19374f826a..a44cf20771 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -30,6 +30,7 @@
#include "editor_sectioned_inspector.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
class SectionedInspectorFilter : public Object {
@@ -259,7 +260,8 @@ void SectionedInspector::update_category_list() {
if (!section_map.has(metasection)) {
TreeItem *ms = sections->create_item(parent);
section_map[metasection] = ms;
- ms->set_text(0, sectionarr[i].capitalize());
+ ms->set_text(0, EditorPropertyNameProcessor::get_singleton()->process_name(sectionarr[i]));
+ ms->set_tooltip(0, EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(sectionarr[i]));
ms->set_metadata(0, metasection);
ms->set_selectable(0, false);
}
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 45685b8fb2..2d80fe85f8 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -460,6 +460,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/theme/custom_theme", "", "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
// Scene tabs
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/scene_tabs/display_close_button", 1, "Never,If Tab Active,Always"); // TabBar::CloseButtonDisplayPolicy
_initial_set("interface/scene_tabs/show_thumbnail_on_hover", true);
EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "interface/scene_tabs/maximum_width", 350, "0,9999,1", PROPERTY_USAGE_DEFAULT)
_initial_set("interface/scene_tabs/show_script_button", false);
@@ -1222,7 +1223,7 @@ bool EditorSettings::is_dark_theme() {
void EditorSettings::list_text_editor_themes() {
String themes = "Default,Godot 2,Custom";
- DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
+ DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
if (d) {
List<String> custom_themes;
d->list_dir_begin();
@@ -1234,7 +1235,6 @@ void EditorSettings::list_text_editor_themes() {
file = d->get_next();
}
d->list_dir_end();
- memdelete(d);
custom_themes.sort();
for (const String &E : custom_themes) {
@@ -1289,10 +1289,9 @@ bool EditorSettings::import_text_editor_theme(String p_file) {
return false;
}
- DirAccess *d = DirAccess::open(get_text_editor_themes_dir());
+ DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
if (d) {
d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file()));
- memdelete(d);
return true;
}
}
@@ -1342,7 +1341,7 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c
if (!p_custom_path.is_empty()) {
template_dir = p_custom_path;
}
- DirAccess *d = DirAccess::open(template_dir);
+ DirAccessRef d = DirAccess::open(template_dir);
if (d) {
d->list_dir_begin();
String file = d->get_next();
@@ -1353,7 +1352,6 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c
file = d->get_next();
}
d->list_dir_end();
- memdelete(d);
}
return templates;
}
@@ -1663,8 +1661,6 @@ void EditorSettings::_bind_methods() {
EditorSettings::EditorSettings() {
last_order = 0;
- optimize_save = true;
- save_changed_setting = true;
_load_defaults();
}
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 65723a24f8..4f25259a01 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -92,8 +92,8 @@ private:
Vector<String> favorites;
Vector<String> recent_dirs;
- bool save_changed_setting;
- bool optimize_save; //do not save stuff that came from config but was not set from engine
+ bool save_changed_setting = true;
+ bool optimize_save = true; //do not save stuff that came from config but was not set from engine
bool _set(const StringName &p_name, const Variant &p_value);
bool _set_only(const StringName &p_name, const Variant &p_value);
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index c0113e281e..eb3cf08578 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -37,6 +37,7 @@
#include "editor/editor_file_system.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
+#include "editor/editor_property_name_processor.h"
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "scene/gui/margin_container.h"
@@ -430,8 +431,9 @@ void EditorSettingsDialog::_update_shortcuts() {
} else {
section = shortcuts->create_item(root);
- String item_name = section_name.capitalize();
+ String item_name = EditorPropertyNameProcessor::get_singleton()->process_name(section_name);
section->set_text(0, item_name);
+ section->set_tooltip(0, EditorPropertyNameProcessor::get_singleton()->make_tooltip_for_name(section_name));
section->set_selectable(0, false);
section->set_selectable(1, false);
section->set_custom_bg_color(0, shortcuts->get_theme_color(SNAME("prop_subsection"), SNAME("Editor")));
@@ -762,8 +764,6 @@ EditorSettingsDialog::EditorSettingsDialog() {
add_child(timer);
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &EditorSettingsDialog::_settings_changed));
get_ok_button()->set_text(TTR("Close"));
-
- updating = false;
}
EditorSettingsDialog::~EditorSettingsDialog() {
diff --git a/editor/editor_settings_dialog.h b/editor/editor_settings_dialog.h
index 4b90506b4b..e3139bb07a 100644
--- a/editor/editor_settings_dialog.h
+++ b/editor/editor_settings_dialog.h
@@ -43,7 +43,7 @@
class EditorSettingsDialog : public AcceptDialog {
GDCLASS(EditorSettingsDialog, AcceptDialog);
- bool updating;
+ bool updating = false;
TabContainer *tabs;
Control *tab_general;
diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp
index 509a316ef3..ef34f13d45 100644
--- a/editor/editor_spin_slider.cpp
+++ b/editor/editor_spin_slider.cpp
@@ -655,14 +655,10 @@ void EditorSpinSlider::_ensure_input_popup() {
}
EditorSpinSlider::EditorSpinSlider() {
- flat = false;
- grabbing_spinner_attempt = false;
- grabbing_spinner = false;
grabbing_spinner_dist_cache = 0;
pre_grab_value = 0;
set_focus_mode(FOCUS_ALL);
updown_offset = -1;
- hover_updown = false;
grabber = memnew(TextureRect);
add_child(grabber);
grabber->hide();
@@ -671,12 +667,5 @@ EditorSpinSlider::EditorSpinSlider() {
grabber->connect("mouse_entered", callable_mp(this, &EditorSpinSlider::_grabber_mouse_entered));
grabber->connect("mouse_exited", callable_mp(this, &EditorSpinSlider::_grabber_mouse_exited));
grabber->connect("gui_input", callable_mp(this, &EditorSpinSlider::_grabber_gui_input));
- mouse_over_spin = false;
- mouse_over_grabber = false;
- mousewheel_over_grabber = false;
- grabbing_grabber = false;
grabber_range = 1;
- value_input_just_closed = false;
- hide_slider = false;
- read_only = false;
}
diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h
index 4e52980804..405c3bfc22 100644
--- a/editor/editor_spin_slider.h
+++ b/editor/editor_spin_slider.h
@@ -41,24 +41,24 @@ class EditorSpinSlider : public Range {
String label;
String suffix;
int updown_offset;
- bool hover_updown;
- bool mouse_hover;
+ bool hover_updown = false;
+ bool mouse_hover = false;
TextureRect *grabber;
int grabber_range;
- bool mouse_over_spin;
- bool mouse_over_grabber;
- bool mousewheel_over_grabber;
+ bool mouse_over_spin = false;
+ bool mouse_over_grabber = false;
+ bool mousewheel_over_grabber = false;
- bool grabbing_grabber;
+ bool grabbing_grabber = false;
int grabbing_from;
float grabbing_ratio;
- bool grabbing_spinner_attempt;
- bool grabbing_spinner;
+ bool grabbing_spinner_attempt = false;
+ bool grabbing_spinner = false;
- bool read_only;
+ bool read_only = false;
float grabbing_spinner_dist_cache;
Vector2 grabbing_spinner_mouse_pos;
double pre_grab_value;
@@ -73,8 +73,8 @@ class EditorSpinSlider : public Range {
void _value_input_submitted(const String &);
void _value_focus_exited();
void _value_input_gui_input(const Ref<InputEvent> &p_event);
- bool hide_slider;
- bool flat;
+ bool hide_slider = false;
+ bool flat = false;
void _evaluate_input_text();
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 01757dd332..7eceebb38b 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -831,7 +831,12 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityXray"), SNAME("EditorIcons")));
- theme->set_constant("vseparation", "PopupMenu", (extra_spacing + default_margin_size + 1) * EDSCALE);
+ // Force the vseparation to be even so that the spacing on top and bottom is even.
+ // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided.
+ // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example)
+ int vsep_base = extra_spacing + default_margin_size + 2;
+ int force_even_vsep = vsep_base + (vsep_base % 2);
+ theme->set_constant("vseparation", "PopupMenu", force_even_vsep * EDSCALE);
theme->set_constant("item_start_padding", "PopupMenu", popup_menu_margin_size * EDSCALE);
theme->set_constant("item_end_padding", "PopupMenu", popup_menu_margin_size * EDSCALE);
diff --git a/editor/editor_vcs_interface.cpp b/editor/editor_vcs_interface.cpp
index 97611d9786..0954779300 100644
--- a/editor/editor_vcs_interface.cpp
+++ b/editor/editor_vcs_interface.cpp
@@ -153,7 +153,6 @@ String EditorVCSInterface::get_vcs_name() {
}
EditorVCSInterface::EditorVCSInterface() {
- is_initialized = false;
}
EditorVCSInterface::~EditorVCSInterface() {
diff --git a/editor/editor_vcs_interface.h b/editor/editor_vcs_interface.h
index 091936dadc..487625e84c 100644
--- a/editor/editor_vcs_interface.h
+++ b/editor/editor_vcs_interface.h
@@ -38,7 +38,7 @@
class EditorVCSInterface : public Object {
GDCLASS(EditorVCSInterface, Object)
- bool is_initialized;
+ bool is_initialized = false;
protected:
static EditorVCSInterface *singleton;
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 0a8d35aff1..df3e73267e 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -44,7 +44,7 @@
void ExportTemplateManager::_update_template_status() {
// Fetch installed templates from the file system.
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
Error err = da->change_dir(templates_dir);
@@ -62,7 +62,6 @@ void ExportTemplateManager::_update_template_status() {
}
}
da->list_dir_end();
- memdelete(da);
// Update the state of the current version.
String current_version = VERSION_FULL_CONFIG;
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index e8a2a46dd2..038cc2ab2f 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -525,16 +525,14 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
if (target_path.ends_with("/")) {
target_path = target_path.substr(0, target_path.length() - 1);
}
- DirAccess *dirAccess = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (dirAccess->file_exists(p_path)) {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->file_exists(p_path)) {
path = target_path;
- } else if (dirAccess->dir_exists(p_path)) {
+ } else if (da->dir_exists(p_path)) {
path = target_path + "/";
} else {
- memdelete(dirAccess);
ERR_FAIL_MSG(vformat("Cannot navigate to '%s' as it has not been found in the file system!", p_path));
}
- memdelete(dirAccess);
}
_set_current_path_text(path);
@@ -781,14 +779,14 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
icon = folder_icon;
if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) {
files->add_item(text, icon, true);
- files->set_item_metadata(files->get_item_count() - 1, favorite);
+ files->set_item_metadata(-1, favorite);
}
} else if (favorite.ends_with("/")) {
text = favorite.substr(0, favorite.length() - 1).get_file();
icon = folder_icon;
if (searched_string.length() == 0 || text.to_lower().find(searched_string) >= 0) {
files->add_item(text, icon, true);
- files->set_item_metadata(files->get_item_count() - 1, favorite);
+ files->set_item_metadata(-1, favorite);
}
} else {
int index;
@@ -842,9 +840,9 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
bd += "/";
}
- files->set_item_metadata(files->get_item_count() - 1, bd);
- files->set_item_selectable(files->get_item_count() - 1, false);
- files->set_item_icon_modulate(files->get_item_count() - 1, folder_color);
+ files->set_item_metadata(-1, bd);
+ files->set_item_selectable(-1, false);
+ files->set_item_icon_modulate(-1, folder_color);
}
bool reversed = file_sort == FILE_SORT_NAME_REVERSE;
@@ -854,8 +852,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
String dname = efd->get_subdir(i)->get_name();
files->add_item(dname, folder_icon, true);
- files->set_item_metadata(files->get_item_count() - 1, directory.plus_file(dname) + "/");
- files->set_item_icon_modulate(files->get_item_count() - 1, folder_color);
+ files->set_item_metadata(-1, directory.plus_file(dname) + "/");
+ files->set_item_icon_modulate(-1, folder_color);
if (cselection.has(dname)) {
files->select(files->get_item_count() - 1, false);
@@ -1171,7 +1169,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
_get_all_items_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), file_changed_paths, folder_changed_paths);
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Moving " + old_path + " -> " + new_path);
Error err = da->rename(old_path, new_path);
if (err == OK) {
@@ -1211,7 +1209,6 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
} else {
EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + "\n");
}
- memdelete(da);
}
void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const {
@@ -1230,7 +1227,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
return;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Duplicating " + old_path + " -> " + new_path);
Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path);
if (err == OK) {
@@ -1268,7 +1265,6 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
} else {
EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + "\n");
}
- memdelete(da);
}
void FileSystemDock::_update_resource_paths_after_move(const Map<String, String> &p_renames) const {
@@ -1418,12 +1414,11 @@ void FileSystemDock::_make_dir_confirm() {
directory = directory.get_base_dir();
}
print_verbose("Making folder " + dir_name + " in " + directory);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
Error err = da->change_dir(directory);
if (err == OK) {
err = da->make_dir(dir_name);
}
- memdelete(da);
if (err == OK) {
print_verbose("FileSystem: calling rescan.");
@@ -1464,13 +1459,11 @@ void FileSystemDock::_make_scene_confirm() {
scene_name = directory.plus_file(scene_name);
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(scene_name)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
int idx = EditorNode::get_singleton()->new_scene();
EditorNode::get_singleton()->get_editor_data().set_scene_path(idx, scene_name);
@@ -1533,7 +1526,7 @@ void FileSystemDock::_rename_operation_confirm() {
}
// Present a more user friendly warning for name conflict.
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
// Workaround case insensitivity on Windows.
if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) {
@@ -1541,10 +1534,8 @@ void FileSystemDock::_rename_operation_confirm() {
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
#endif
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
Map<String, String> file_renames;
Map<String, String> folder_renames;
@@ -1588,13 +1579,11 @@ void FileSystemDock::_duplicate_operation_confirm() {
String new_path = base_dir.plus_file(new_name);
// Present a more user friendly warning for name conflict
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
- memdelete(da);
return;
}
- memdelete(da);
_try_duplicate_item(to_duplicate, new_path);
@@ -2098,6 +2087,10 @@ void FileSystemDock::focus_on_filter() {
}
}
+ScriptCreateDialog *FileSystemDock::get_script_create_dialog() const {
+ return make_script_dialog;
+}
+
void FileSystemDock::set_file_list_display_mode(FileListDisplayMode p_mode) {
if (p_mode == file_list_display_mode) {
return;
@@ -2818,7 +2811,7 @@ void FileSystemDock::_get_imported_files(const String &p_path, Vector<String> &f
return;
}
- DirAccess *da = DirAccess::open(p_path);
+ DirAccessRef da = DirAccess::open(p_path);
da->list_dir_begin();
String n = da->get_next();
while (!n.is_empty()) {
@@ -3179,10 +3172,7 @@ FileSystemDock::FileSystemDock() {
searched_string = String();
uncollapsed_paths_before_search = Vector<String>();
- updating_tree = false;
tree_update_id = 0;
- initialized = false;
- import_dock_needs_update = false;
history_pos = 0;
history_max_size = 20;
@@ -3191,8 +3181,6 @@ FileSystemDock::FileSystemDock() {
display_mode = DISPLAY_MODE_TREE_ONLY;
old_display_mode = DISPLAY_MODE_TREE_ONLY;
file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS;
-
- always_show_folders = false;
}
FileSystemDock::~FileSystemDock() {
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index d457c6acd4..92dac374ec 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -154,7 +154,7 @@ private:
ShaderCreateDialog *make_shader_dialog;
CreateDialog *new_resource_dialog;
- bool always_show_folders;
+ bool always_show_folders = false;
class FileOrFolder {
public:
@@ -177,13 +177,13 @@ private:
String path;
- bool initialized;
+ bool initialized = false;
- bool updating_tree;
+ bool updating_tree = false;
int tree_update_id;
Tree *tree;
ItemList *files;
- bool import_dock_needs_update;
+ bool import_dock_needs_update = false;
bool holding_branch = false;
Vector<TreeItem *> tree_items_selected_on_drag_begin;
@@ -320,6 +320,8 @@ public:
void navigate_to_path(const String &p_path);
void focus_on_filter();
+ ScriptCreateDialog *get_script_create_dialog() const;
+
void fix_dependencies(const String &p_for_file);
int get_split_offset() { return split_box->get_split_offset(); }
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index eff9185c71..1ce363c651 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -612,8 +612,6 @@ FindInFilesPanel::FindInFilesPanel() {
_results_display->create_item(); // Root
vbc->add_child(_results_display);
- _with_replace = false;
-
{
_replace_container = memnew(HBoxContainer);
diff --git a/editor/find_in_files.h b/editor/find_in_files.h
index 1b6666b554..cf14f3d5c3 100644
--- a/editor/find_in_files.h
+++ b/editor/find_in_files.h
@@ -210,7 +210,7 @@ private:
ProgressBar *_progress_bar;
Map<String, TreeItem *> _file_items;
Map<TreeItem *, Result> _result_items;
- bool _with_replace;
+ bool _with_replace = false;
HBoxContainer *_replace_container;
LineEdit *_replace_line_edit;
diff --git a/editor/icons/StreamTexture.svg b/editor/icons/CompressedTexture2D.svg
index 068f65dead..068f65dead 100644
--- a/editor/icons/StreamTexture.svg
+++ b/editor/icons/CompressedTexture2D.svg
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index f0a2d7d553..2ecc483938 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -484,6 +484,14 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
}
+ } else if (p_edited_property == "embolden") {
+ if (font_preview->get_data_count() > 0) {
+ font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
+ }
+ } else if (p_edited_property == "transform") {
+ if (font_preview->get_data_count() > 0) {
+ font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
+ }
} else if (p_edited_property == "oversampling") {
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
@@ -924,6 +932,8 @@ void DynamicFontImportSettings::_re_import() {
main_settings["force_autohinter"] = import_settings_data->get("force_autohinter");
main_settings["hinting"] = import_settings_data->get("hinting");
main_settings["subpixel_positioning"] = import_settings_data->get("subpixel_positioning");
+ main_settings["embolden"] = import_settings_data->get("embolden");
+ main_settings["transform"] = import_settings_data->get("transform");
main_settings["oversampling"] = import_settings_data->get("oversampling");
main_settings["compress"] = import_settings_data->get("compress");
@@ -1275,6 +1285,8 @@ void DynamicFontImportSettings::open_settings(const String &p_path) {
font_preview->get_data(0)->set_force_autohinter(import_settings_data->get("force_autohinter"));
font_preview->get_data(0)->set_hinting((TextServer::Hinting)import_settings_data->get("hinting").operator int());
font_preview->get_data(0)->set_subpixel_positioning((TextServer::SubpixelPositioning)import_settings_data->get("subpixel_positioning").operator int());
+ font_preview->get_data(0)->set_embolden(import_settings_data->get("embolden"));
+ font_preview->get_data(0)->set_transform(import_settings_data->get("transform"));
font_preview->get_data(0)->set_oversampling(import_settings_data->get("oversampling"));
}
font_preview_label->add_theme_font_override("font", font_preview);
@@ -1334,6 +1346,8 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "compress", PROPERTY_HINT_NONE, ""), false));
diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp
index 70fc87ea3f..077b94bb4e 100644
--- a/editor/import/resource_importer_dynamic_font.cpp
+++ b/editor/import/resource_importer_dynamic_font.cpp
@@ -109,6 +109,8 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force_autohinter"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), 1));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), 0.f));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::TRANSFORM2D, "transform"), Transform2D()));
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), 0.0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress"), true));
@@ -186,6 +188,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
int hinting = p_options["hinting"];
int subpixel_positioning = p_options["subpixel_positioning"];
real_t oversampling = p_options["oversampling"];
+ real_t embolden = p_options["embolden"];
+ Transform2D transform = p_options["transform"];
// Load base font data.
Vector<uint8_t> data = FileAccess::get_file_as_array(p_source_file);
@@ -202,6 +206,8 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
font->set_fixed_size(0);
font->set_force_autohinter(autohinter);
font->set_subpixel_positioning((TextServer::SubpixelPositioning)subpixel_positioning);
+ font->set_embolden(embolden);
+ font->set_transform(transform);
font->set_hinting((TextServer::Hinting)hinting);
font->set_oversampling(oversampling);
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index 197cc49a95..9ddee9c058 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -85,16 +85,16 @@ void ResourceImporterLayeredTexture::get_recognized_extensions(List<String> *p_e
String ResourceImporterLayeredTexture::get_save_extension() const {
switch (mode) {
case MODE_CUBEMAP: {
- return "scube";
+ return "ccube";
} break;
case MODE_2D_ARRAY: {
- return "stexarray";
+ return "ctexarray";
} break;
case MODE_CUBEMAP_ARRAY: {
- return "scubearray";
+ return "ccubearray";
} break;
case MODE_3D: {
- return "stex3d";
+ return "ctex3d";
} break;
}
@@ -274,11 +274,11 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
f->store_32(0);
for (int i = 0; i < p_images.size(); i++) {
- ResourceImporterTexture::save_to_stex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
+ ResourceImporterTexture::save_to_ctex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
}
for (int i = 0; i < mipmap_images.size(); i++) {
- ResourceImporterTexture::save_to_stex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
+ ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
}
f->close();
@@ -393,7 +393,7 @@ Error ResourceImporterLayeredTexture::import(const String &p_source_file, const
texture_import->bptc_ldr = bptc_ldr;
texture_import->mipmaps = mipmaps;
texture_import->used_channels = used_channels;
- _check_compress_stex(texture_import);
+ _check_compress_ctex(texture_import);
if (r_metadata) {
Dictionary metadata;
metadata["vram_texture"] = compress_mode == COMPRESS_VRAM_COMPRESSED;
@@ -474,7 +474,7 @@ ResourceImporterLayeredTexture::ResourceImporterLayeredTexture() {
ResourceImporterLayeredTexture::~ResourceImporterLayeredTexture() {
}
-void ResourceImporterLayeredTexture::_check_compress_stex(Ref<LayeredTextureImport> r_texture_import) {
+void ResourceImporterLayeredTexture::_check_compress_ctex(Ref<LayeredTextureImport> r_texture_import) {
String extension = get_save_extension();
ERR_FAIL_NULL(r_texture_import->csource);
if (r_texture_import->compress_mode != COMPRESS_VRAM_COMPRESSED) {
diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h
index 58e5c47d8d..5791914a9b 100644
--- a/editor/import/resource_importer_layered_texture.h
+++ b/editor/import/resource_importer_layered_texture.h
@@ -87,7 +87,7 @@ protected:
static ResourceImporterLayeredTexture *singleton;
public:
- void _check_compress_stex(Ref<LayeredTextureImport> r_texture_import);
+ void _check_compress_ctex(Ref<LayeredTextureImport> r_texture_import);
static ResourceImporterLayeredTexture *get_singleton() { return singleton; }
virtual String get_importer_name() const override;
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index e672fe2dee..1dec4b00bb 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -225,7 +225,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo
}
}
-void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
+void ResourceImporterTexture::save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
switch (p_compress_mode) {
case COMPRESS_LOSSLESS: {
bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png") ||
@@ -317,7 +317,7 @@ void ResourceImporterTexture::save_to_stex_format(FileAccess *f, const Ref<Image
}
}
-void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
+void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE);
ERR_FAIL_NULL(f);
f->store_8('G');
@@ -394,7 +394,7 @@ void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String
Image::UsedChannels used_channels = image->detect_used_channels(csource);
- save_to_stex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality);
+ save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality);
memdelete(f);
}
@@ -540,19 +540,19 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
if (!bptc_ldr && can_s3tc && is_ldr) {
image_compress_mode = Image::COMPRESS_S3TC;
}
- _save_stex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".s3tc.ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("s3tc");
formats_imported.push_back("s3tc");
}
if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc2")) {
- _save_stex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".etc2.ctex", compress_mode, lossy, Image::COMPRESS_ETC2, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("etc2");
formats_imported.push_back("etc2");
}
if (ProjectSettings::get_singleton()->get("rendering/textures/vram_compression/import_etc")) {
- _save_stex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".etc.ctex", compress_mode, lossy, Image::COMPRESS_ETC, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, true, mipmap_limit, normal_image, roughness_channel);
r_platform_variants->push_back("etc");
formats_imported.push_back("etc");
}
@@ -562,7 +562,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String
}
} else {
//import normally
- _save_stex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
+ _save_ctex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel);
}
if (r_metadata) {
diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h
index bd43eaef58..b3a68260fc 100644
--- a/editor/import/resource_importer_texture.h
+++ b/editor/import/resource_importer_texture.h
@@ -74,10 +74,10 @@ protected:
static ResourceImporterTexture *singleton;
static const char *compression_formats[];
- void _save_stex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
+ void _save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
public:
- static void save_to_stex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
+ static void save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
static ResourceImporterTexture *get_singleton() { return singleton; }
virtual String get_importer_name() const override;
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 72cc33048c..9f1daac69f 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -128,7 +128,7 @@ void ImportDock::set_edit_path(const String &p_path) {
for (const Pair<String, String> &E : importer_names) {
import_as->add_item(E.first);
- import_as->set_item_metadata(import_as->get_item_count() - 1, E.second);
+ import_as->set_item_metadata(-1, E.second);
if (E.second == importer_name) {
import_as->select(import_as->get_item_count() - 1);
}
@@ -149,7 +149,7 @@ void ImportDock::set_edit_path(const String &p_path) {
void ImportDock::_add_keep_import_option(const String &p_importer_name) {
import_as->add_separator();
import_as->add_item(TTR("Keep File (No Import)"));
- import_as->set_item_metadata(import_as->get_item_count() - 1, "keep");
+ import_as->set_item_metadata(-1, "keep");
if (p_importer_name == "keep") {
import_as->select(import_as->get_item_count() - 1);
}
@@ -286,7 +286,7 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
for (const Pair<String, String> &E : importer_names) {
import_as->add_item(E.first);
- import_as->set_item_metadata(import_as->get_item_count() - 1, E.second);
+ import_as->set_item_metadata(-1, E.second);
if (E.second == params->importer->get_importer_name()) {
import_as->select(import_as->get_item_count() - 1);
}
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index a766650cd9..77594dde78 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -473,7 +473,6 @@ void LocalizationEditor::_bind_methods() {
LocalizationEditor::LocalizationEditor() {
undo_redo = EditorNode::get_undo_redo();
- updating_translations = false;
localization_changed = "localization_changed";
TabContainer *translations = memnew(TabContainer);
diff --git a/editor/localization_editor.h b/editor/localization_editor.h
index bde1b894e2..3424ba7c55 100644
--- a/editor/localization_editor.h
+++ b/editor/localization_editor.h
@@ -56,7 +56,7 @@ class LocalizationEditor : public VBoxContainer {
EditorFileDialog *pot_generate_dialog;
UndoRedo *undo_redo;
- bool updating_translations;
+ bool updating_translations = false;
String localization_changed;
void _translation_file_open();
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index d5e7c312d9..02cc95e14a 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -50,7 +50,7 @@ void PluginConfigDialog::_on_confirmed() {
String path = "res://addons/" + subfolder_edit->get_text();
if (!_edit_mode) {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (!d || d->make_dir_recursive(path) != OK) {
return;
}
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index fba6d8e57f..ab8e2ca54a 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -897,11 +897,6 @@ void AnimationPlayerEditor::_update_player() {
}
void AnimationPlayerEditor::_update_animation_list_icons() {
- List<StringName> animlist;
- if (player) {
- player->get_animation_list(&animlist);
- }
-
for (int i = 0; i < animation->get_item_count(); i++) {
String name = animation->get_item_text(i);
@@ -1675,11 +1670,11 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
onion_skinning->set_tooltip(TTR("Onion Skinning Options"));
onion_skinning->get_popup()->add_separator(TTR("Directions"));
onion_skinning->get_popup()->add_check_item(TTR("Past"), ONION_SKINNING_PAST);
- onion_skinning->get_popup()->set_item_checked(onion_skinning->get_popup()->get_item_count() - 1, true);
+ onion_skinning->get_popup()->set_item_checked(-1, true);
onion_skinning->get_popup()->add_check_item(TTR("Future"), ONION_SKINNING_FUTURE);
onion_skinning->get_popup()->add_separator(TTR("Depth"));
onion_skinning->get_popup()->add_radio_check_item(TTR("1 step"), ONION_SKINNING_1_STEP);
- onion_skinning->get_popup()->set_item_checked(onion_skinning->get_popup()->get_item_count() - 1, true);
+ onion_skinning->get_popup()->set_item_checked(-1, true);
onion_skinning->get_popup()->add_radio_check_item(TTR("2 steps"), ONION_SKINNING_2_STEPS);
onion_skinning->get_popup()->add_radio_check_item(TTR("3 steps"), ONION_SKINNING_3_STEPS);
onion_skinning->get_popup()->add_separator();
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 2f94176e2a..bd0c1afd19 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -346,29 +346,21 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
state_machine_draw->update();
}
- //put ibeam (text cursor) over names to make it clearer that they are editable
if (mm.is_valid()) {
state_machine_draw->grab_focus();
- bool over_text_now = false;
String new_over_node = StringName();
int new_over_node_what = -1;
if (tool_select->is_pressed()) {
- for (int i = node_rects.size() - 1; i >= 0; i--) { //inverse to draw order
-
- if (node_rects[i].name.has_point(mm->get_position())) {
- over_text_now = true;
- break;
- }
-
+ for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order.
if (node_rects[i].node.has_point(mm->get_position())) {
new_over_node = node_rects[i].node_name;
if (node_rects[i].play.has_point(mm->get_position())) {
new_over_node_what = 0;
- }
- if (node_rects[i].edit.has_point(mm->get_position())) {
+ } else if (node_rects[i].edit.has_point(mm->get_position())) {
new_over_node_what = 1;
}
+ break;
}
}
}
@@ -378,16 +370,6 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
over_node_what = new_over_node_what;
state_machine_draw->update();
}
-
- if (over_text != over_text_now) {
- if (over_text_now) {
- state_machine_draw->set_default_cursor_shape(CURSOR_IBEAM);
- } else {
- state_machine_draw->set_default_cursor_shape(CURSOR_ARROW);
- }
-
- over_text = over_text_now;
- }
}
Ref<InputEventPanGesture> pan_gesture = p_event;
@@ -397,6 +379,23 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
}
}
+Control::CursorShape AnimationNodeStateMachineEditor::get_cursor_shape(const Point2 &p_pos) const {
+ // Put ibeam (text cursor) over names to make it clearer that they are editable.
+ Transform2D xform = panel->get_transform() * state_machine_draw->get_transform();
+ Point2 pos = xform.xform_inv(p_pos);
+ Control::CursorShape cursor_shape = get_default_cursor_shape();
+
+ for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order.
+ if (node_rects[i].node.has_point(pos)) {
+ if (node_rects[i].name.has_point(pos)) {
+ cursor_shape = Control::CURSOR_IBEAM;
+ }
+ break;
+ }
+ }
+ return cursor_shape;
+}
+
void AnimationNodeStateMachineEditor::_file_opened(const String &p_file) {
file_loaded = ResourceLoader::load(p_file);
if (file_loaded.is_valid()) {
@@ -1287,6 +1286,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
panel = memnew(PanelContainer);
panel->set_clip_contents(true);
+ panel->set_mouse_filter(Control::MOUSE_FILTER_PASS);
add_child(panel);
panel->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -1295,6 +1295,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
state_machine_draw->connect("gui_input", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_gui_input));
state_machine_draw->connect("draw", callable_mp(this, &AnimationNodeStateMachineEditor::_state_machine_draw));
state_machine_draw->set_focus_mode(FOCUS_ALL);
+ state_machine_draw->set_mouse_filter(Control::MOUSE_FILTER_PASS);
state_machine_play_pos = memnew(Control);
state_machine_draw->add_child(state_machine_play_pos);
@@ -1347,8 +1348,6 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() {
open_file->connect("file_selected", callable_mp(this, &AnimationNodeStateMachineEditor::_file_opened));
undo_redo = EditorNode::get_undo_redo();
- over_text = false;
-
over_node_what = -1;
dragging_selected_attempt = false;
connecting = false;
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index 208bd27f8e..03991d00f9 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -138,7 +138,6 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
StringName selected_transition_from;
StringName selected_transition_to;
- bool over_text;
StringName over_node;
int over_node_what;
@@ -185,6 +184,7 @@ public:
static AnimationNodeStateMachineEditor *get_singleton() { return singleton; }
virtual bool can_edit(const Ref<AnimationNode> &p_node) override;
virtual void edit(const Ref<AnimationNode> &p_node) override;
+ virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override;
AnimationNodeStateMachineEditor();
};
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 50f253b167..fd9b665b20 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -1145,7 +1145,7 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const
String name = cat["name"];
int id = cat["id"];
categories->add_item(name);
- categories->set_item_metadata(categories->get_item_count() - 1, id);
+ categories->set_item_metadata(-1, id);
category_map[cat["id"]] = name;
}
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 75f97efdbc..4ee4eb86af 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1139,6 +1139,8 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
}
}
}
+ snap_target[0] = SNAP_TARGET_NONE;
+ snap_target[1] = SNAP_TARGET_NONE;
drag_type = DRAG_NONE;
viewport->update();
return true;
diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp
index 501becac57..c8d5aa3fdc 100644
--- a/editor/plugins/debugger_editor_plugin.cpp
+++ b/editor/plugins/debugger_editor_plugin.cpp
@@ -63,30 +63,24 @@ DebuggerEditorPlugin::DebuggerEditorPlugin(MenuButton *p_debug_menu) {
PopupMenu *p = debug_menu->get_popup();
p->set_hide_on_checkable_item_selection(false);
p->add_check_shortcut(ED_SHORTCUT("editor/deploy_with_remote_debug", TTR("Deploy with Remote Debug")), RUN_DEPLOY_REMOTE_DEBUG);
- p->set_item_tooltip(
- p->get_item_count() - 1,
+ p->set_item_tooltip(-1,
TTR("When this option is enabled, using one-click deploy will make the executable attempt to connect to this computer's IP so the running project can be debugged.\nThis option is intended to be used for remote debugging (typically with a mobile device).\nYou don't need to enable it to use the GDScript debugger locally."));
p->add_check_shortcut(ED_SHORTCUT("editor/small_deploy_with_network_fs", TTR("Small Deploy with Network Filesystem")), RUN_FILE_SERVER);
- p->set_item_tooltip(
- p->get_item_count() - 1,
+ p->set_item_tooltip(-1,
TTR("When this option is enabled, using one-click deploy for Android will only export an executable without the project data.\nThe filesystem will be provided from the project by the editor over the network.\nOn Android, deploying will use the USB cable for faster performance. This option speeds up testing for projects with large assets."));
p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("editor/visible_collision_shapes", TTR("Visible Collision Shapes")), RUN_DEBUG_COLLISONS);
- p->set_item_tooltip(
- p->get_item_count() - 1,
+ p->set_item_tooltip(-1,
TTR("When this option is enabled, collision shapes and raycast nodes (for 2D and 3D) will be visible in the running project."));
p->add_check_shortcut(ED_SHORTCUT("editor/visible_navigation", TTR("Visible Navigation")), RUN_DEBUG_NAVIGATION);
- p->set_item_tooltip(
- p->get_item_count() - 1,
+ p->set_item_tooltip(-1,
TTR("When this option is enabled, navigation meshes and polygons will be visible in the running project."));
p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("editor/sync_scene_changes", TTR("Synchronize Scene Changes")), RUN_LIVE_DEBUG);
- p->set_item_tooltip(
- p->get_item_count() - 1,
+ p->set_item_tooltip(-1,
TTR("When this option is enabled, any changes made to the scene in the editor will be replicated in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled."));
p->add_check_shortcut(ED_SHORTCUT("editor/sync_script_changes", TTR("Synchronize Script Changes")), RUN_RELOAD_SCRIPTS);
- p->set_item_tooltip(
- p->get_item_count() - 1,
+ p->set_item_tooltip(-1,
TTR("When this option is enabled, any script that is saved will be reloaded in the running project.\nWhen used remotely on a device, this is more efficient when the network filesystem option is enabled."));
// Multi-instance, start/stop
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
index 293d1c3913..35cbff53f4 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp
@@ -166,20 +166,20 @@ void GPUParticles3DEditorBase::_node_selected(const NodePath &p_path) {
return;
}
- VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(sel);
- if (!vi) {
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(sel);
+ if (!mi || mi->get_mesh().is_null()) {
EditorNode::get_singleton()->show_warning(vformat(TTR("\"%s\" doesn't contain geometry."), sel->get_name()));
return;
}
- geometry = vi->get_faces(VisualInstance3D::FACES_SOLID);
+ geometry = mi->get_mesh()->get_faces();
if (geometry.size() == 0) {
EditorNode::get_singleton()->show_warning(vformat(TTR("\"%s\" doesn't contain face geometry."), sel->get_name()));
return;
}
- Transform3D geom_xform = base_node->get_global_transform().affine_inverse() * vi->get_global_transform();
+ Transform3D geom_xform = base_node->get_global_transform().affine_inverse() * mi->get_global_transform();
int gc = geometry.size();
Face3 *w = geometry.ptrw();
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 64540ac157..8f285cb7f9 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -447,16 +447,16 @@ MeshInstance3DEditor::MeshInstance3DEditor() {
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("MeshInstance3D"), SNAME("EditorIcons")));
options->get_popup()->add_item(TTR("Create Trimesh Static Body"), MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
- options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a StaticBody3D and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection."));
+ options->get_popup()->set_item_tooltip(-1, TTR("Creates a StaticBody3D and assigns a polygon-based collision shape to it automatically.\nThis is the most accurate (but slowest) option for collision detection."));
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
- options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
+ options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection."));
options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE);
- options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
+ options->get_popup()->set_item_tooltip(-1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection."));
options->get_popup()->add_item(TTR("Create Simplified Convex Collision Sibling"), MENU_OPTION_CREATE_SIMPLIFIED_CONVEX_COLLISION_SHAPE);
- options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy."));
+ options->get_popup()->set_item_tooltip(-1, TTR("Creates a simplified convex collision shape.\nThis is similar to single collision shape, but can result in a simpler geometry in some cases, at the cost of accuracy."));
options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES);
- options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision."));
+ options->get_popup()->set_item_tooltip(-1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between a single convex collision and a polygon-based collision."));
options->get_popup()->add_separator();
options->get_popup()->add_item(TTR("Create Navigation Mesh"), MENU_OPTION_CREATE_NAVMESH);
options->get_popup()->add_separator();
diff --git a/editor/plugins/multimesh_editor_plugin.cpp b/editor/plugins/multimesh_editor_plugin.cpp
index 72f3b6a06e..850c673c12 100644
--- a/editor/plugins/multimesh_editor_plugin.cpp
+++ b/editor/plugins/multimesh_editor_plugin.cpp
@@ -105,9 +105,9 @@ void MultiMeshEditor::_populate() {
return;
}
- GeometryInstance3D *ss_instance = Object::cast_to<MeshInstance3D>(ss_node);
+ MeshInstance3D *ss_instance = Object::cast_to<MeshInstance3D>(ss_node);
- if (!ss_instance) {
+ if (!ss_instance || !ss_instance->get_mesh().is_valid()) {
err_dialog->set_text(TTR("Surface source is invalid (no geometry)."));
err_dialog->popup_centered();
return;
@@ -115,7 +115,7 @@ void MultiMeshEditor::_populate() {
Transform3D geom_xform = node->get_global_transform().affine_inverse() * ss_instance->get_global_transform();
- Vector<Face3> geometry = ss_instance->get_faces(VisualInstance3D::FACES_SOLID);
+ Vector<Face3> geometry = ss_instance->get_mesh()->get_faces();
if (geometry.size() == 0) {
err_dialog->set_text(TTR("Surface source is invalid (no faces)."));
diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 8aa8ba1f00..51e2f6ff00 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -3177,13 +3177,8 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
continue;
}
- Vector2 dir;
- dir[j] = 1.0;
- Vector2 ta, tb;
int j_n1 = (j + 1) % 3;
int j_n2 = (j + 2) % 3;
- ta[j_n1] = 1.0;
- tb[j_n2] = 1.0;
for (int k = 0; k < 4; k++) {
Vector3 from = aabb.position, to = aabb.position;
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index d506a1f3ab..2da5978fab 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1881,7 +1881,7 @@ void ScriptEditor::_update_members_overview() {
String name = functions[i].get_slice(":", 0);
if (filter.is_empty() || filter.is_subsequence_ofn(name)) {
members_overview->add_item(name);
- members_overview->set_item_metadata(members_overview->get_item_count() - 1, functions[i].get_slice(":", 1).to_int() - 1);
+ members_overview->set_item_metadata(-1, functions[i].get_slice(":", 1).to_int() - 1);
}
}
@@ -2139,7 +2139,7 @@ void ScriptEditor::_update_script_names() {
for (int i = 0; i < sedata_filtered.size(); i++) {
script_list->add_item(sedata_filtered[i].name, sedata_filtered[i].icon);
if (sedata_filtered[i].tool) {
- script_list->set_item_icon_modulate(script_list->get_item_count() - 1, tool_color);
+ script_list->set_item_icon_modulate(-1, tool_color);
}
int index = script_list->get_item_count() - 1;
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 10b6129864..30ca1c605f 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -579,7 +579,7 @@ void ScriptTextEditor::_update_bookmark_list() {
}
bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - `" + line + "`");
- bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]);
+ bookmarks_menu->set_item_metadata(-1, bookmark_list[i]);
}
}
@@ -731,7 +731,7 @@ void ScriptTextEditor::_update_breakpoint_list() {
}
breakpoints_menu->add_item(String::num((int)breakpoint_list[i] + 1) + " - `" + line + "`");
- breakpoints_menu->set_item_metadata(breakpoints_menu->get_item_count() - 1, breakpoint_list[i]);
+ breakpoints_menu->set_item_metadata(-1, breakpoint_list[i]);
}
}
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 382138a995..02f11bb82f 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -647,7 +647,7 @@ void ShaderEditor::_update_bookmark_list() {
}
bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - \"" + line + "\"");
- bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]);
+ bookmarks_menu->set_item_metadata(-1, bookmark_list[i]);
}
}
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index c8db16d3be..4a63080747 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -847,7 +847,7 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
at = at->get_atlas();
}
- tree->set_item_tooltip(tree->get_item_count() - 1, tooltip);
+ tree->set_item_tooltip(-1, tooltip);
}
if (sel == i) {
tree->select(tree->get_item_count() - 1);
diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp
index 940f269803..34f3ec73c0 100644
--- a/editor/plugins/text_editor.cpp
+++ b/editor/plugins/text_editor.cpp
@@ -179,7 +179,7 @@ void TextEditor::_update_bookmark_list() {
}
bookmarks_menu->add_item(String::num((int)bookmark_list[i] + 1) + " - \"" + line + "\"");
- bookmarks_menu->set_item_metadata(bookmarks_menu->get_item_count() - 1, bookmark_list[i]);
+ bookmarks_menu->set_item_metadata(-1, bookmark_list[i]);
}
}
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index 0f8c8c616c..086588f5a5 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.cpp
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -241,7 +241,7 @@ void AtlasMergingDialog::update_tile_set(Ref<TileSet> p_tile_set) {
if (texture.is_valid()) {
String item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id);
atlas_merging_atlases_list->add_item(item_text, texture);
- atlas_merging_atlases_list->set_item_metadata(atlas_merging_atlases_list->get_item_count() - 1, source_id);
+ atlas_merging_atlases_list->set_item_metadata(-1, source_id);
}
}
}
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 4a0fc0b29f..8d8c65f2c4 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -188,7 +188,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
}
sources_list->add_item(item_text, texture);
- sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id);
+ sources_list->set_item_metadata(-1, source_id);
}
if (sources_list->get_item_count() > 0) {
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 49e589c9ef..8b0b184f54 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -182,7 +182,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) {
}
sources_list->add_item(item_text, texture);
- sources_list->set_item_metadata(sources_list->get_item_count() - 1, source_id);
+ sources_list->set_item_metadata(-1, source_id);
}
// Set again the current selected item if needed.
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 17db955cc7..9963ac0232 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -1128,9 +1128,6 @@ ProjectExportDialog::ProjectExportDialog() {
// Script export parameters.
- updating_script_key = false;
- updating_enc_filters = false;
-
VBoxContainer *sec_vb = memnew(VBoxContainer);
sec_vb->set_name(TTR("Encryption"));
@@ -1153,7 +1150,7 @@ ProjectExportDialog::ProjectExportDialog() {
enc_ex_filters = memnew(LineEdit);
enc_ex_filters->connect("text_changed", callable_mp(this, &ProjectExportDialog::_enc_filters_changed));
sec_vb->add_margin_child(
- TTR("Filters to exclude files/folders\n(comma-separated, e.g: *.stex, *.import, music/*)"),
+ TTR("Filters to exclude files/folders\n(comma-separated, e.g: *.ctex, *.import, music/*)"),
enc_ex_filters);
script_key = memnew(LineEdit);
@@ -1195,8 +1192,6 @@ ProjectExportDialog::ProjectExportDialog() {
// Export buttons, dialogs and errors.
- updating = false;
-
get_cancel_button()->set_text(TTR("Close"));
get_ok_button()->set_text(TTR("Export PCK/ZIP..."));
export_button = add_button(TTR("Export Project..."), !DisplayServer::get_singleton()->get_swap_cancel_ok(), "export");
diff --git a/editor/project_export.h b/editor/project_export.h
index 569563ba55..057fd31168 100644
--- a/editor/project_export.h
+++ b/editor/project_export.h
@@ -71,7 +71,7 @@ private:
CheckButton *runnable;
Button *button_export;
- bool updating;
+ bool updating = false;
AcceptDialog *error_dialog;
ConfirmationDialog *delete_confirm;
@@ -152,8 +152,8 @@ private:
void _update_feature_list();
void _custom_features_changed(const String &p_text);
- bool updating_script_key;
- bool updating_enc_filters;
+ bool updating_script_key = false;
+ bool updating_enc_filters = false;
void _enc_pck_changed(bool p_pressed);
void _enc_directory_changed(bool p_pressed);
void _enc_filters_changed(const String &p_text);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 78f6fe58d0..35902fd354 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -147,7 +147,7 @@ private:
}
String _test_path() {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String valid_path, valid_install_path;
if (d->change_dir(project_path->get_text()) == OK) {
valid_path = project_path->get_text();
@@ -165,7 +165,6 @@ private:
if (valid_path.is_empty()) {
set_message(TTR("The path specified doesn't exist."), MESSAGE_ERROR);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
@@ -179,7 +178,6 @@ private:
if (valid_install_path.is_empty()) {
set_message(TTR("The path specified doesn't exist."), MESSAGE_ERROR, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
@@ -194,7 +192,6 @@ private:
unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io);
if (!pkg) {
set_message(TTR("Error opening package file (it's not in ZIP format)."), MESSAGE_ERROR);
- memdelete(d);
get_ok_button()->set_disabled(true);
unzClose(pkg);
return "";
@@ -215,7 +212,6 @@ private:
if (ret == UNZ_END_OF_LIST_OF_FILE) {
set_message(TTR("Invalid \".zip\" project file; it doesn't contain a \"project.godot\" file."), MESSAGE_ERROR);
- memdelete(d);
get_ok_button()->set_disabled(true);
unzClose(pkg);
return "";
@@ -242,14 +238,12 @@ private:
if (!is_folder_empty) {
set_message(TTR("Please choose an empty folder."), MESSAGE_WARNING, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
} else {
set_message(TTR("Please choose a \"project.godot\" or \".zip\" file."), MESSAGE_ERROR);
- memdelete(d);
install_path_container->hide();
get_ok_button()->set_disabled(true);
return "";
@@ -257,7 +251,6 @@ private:
} else if (valid_path.ends_with("zip")) {
set_message(TTR("This directory already contains a Godot project."), MESSAGE_ERROR, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(true);
return "";
}
@@ -282,7 +275,6 @@ private:
if (!is_folder_empty) {
set_message(TTR("The selected path is not empty. Choosing an empty folder is highly recommended."), MESSAGE_WARNING);
- memdelete(d);
get_ok_button()->set_disabled(false);
return valid_path;
}
@@ -290,7 +282,6 @@ private:
set_message("");
set_message("", MESSAGE_SUCCESS, INSTALL_PATH);
- memdelete(d);
get_ok_button()->set_disabled(false);
return valid_path;
}
@@ -389,7 +380,7 @@ private:
return;
}
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (d->change_dir(project_path->get_text()) == OK) {
if (!d->dir_exists(project_name_no_edges)) {
if (d->make_dir(project_name_no_edges) == OK) {
@@ -408,8 +399,6 @@ private:
dialog_error->popup_centered();
}
}
-
- memdelete(d);
}
void _text_changed(const String &p_text) {
@@ -551,14 +540,11 @@ private:
if (path.is_empty() || path == zip_root || !zip_root.is_subsequence_of(path)) {
//
} else if (path.ends_with("/")) { // a dir
-
path = path.substr(0, path.length() - 1);
String rel_path = path.substr(zip_root.length());
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->make_dir(dir.plus_file(rel_path));
- memdelete(da);
-
} else {
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
@@ -620,9 +606,8 @@ private:
void _remove_created_folder() {
if (!created_folder_path.is_empty()) {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
d->remove(created_folder_path);
- memdelete(d);
create_dir->set_disabled(false);
created_folder_path = "";
@@ -725,10 +710,9 @@ public:
project_path->set_text(fav_dir);
fdialog->set_current_dir(fav_dir);
} else {
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
project_path->set_text(d->get_current_dir());
fdialog->set_current_dir(d->get_current_dir());
- memdelete(d);
}
String proj = TTR("New Game Project");
project_name->set_text(proj);
@@ -2411,12 +2395,11 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
return;
}
Set<String> folders_set;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < p_files.size(); i++) {
String file = p_files[i];
folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
}
- memdelete(da);
if (folders_set.size() > 0) {
PackedStringArray folders;
for (Set<String>::Element *E = folders_set.front(); E; E = E->next()) {
@@ -2425,7 +2408,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
bool confirm = true;
if (folders.size() == 1) {
- DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (dir->change_dir(folders[0]) == OK) {
dir->list_dir_begin();
String file = dir->get_next();
@@ -2437,7 +2420,6 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
}
dir->list_dir_end();
}
- memdelete(dir);
}
if (confirm) {
multi_scan_ask->get_ok_button()->disconnect("pressed", callable_mp(this, &ProjectManager::_scan_multiple_folders));
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index 0282504c70..52fb0d4f4e 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -907,7 +907,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
}
}
- if (!is_custom_resource && !ClassDB::can_instantiate(t)) {
+ if (!is_custom_resource && (!ClassDB::can_instantiate(t) || ClassDB::is_virtual(t))) {
continue;
}
@@ -1771,9 +1771,6 @@ void CustomPropertyEditor::_bind_methods() {
}
CustomPropertyEditor::CustomPropertyEditor() {
- read_only = false;
- updating = false;
-
value_vbox = memnew(VBoxContainer);
add_child(value_vbox);
diff --git a/editor/property_editor.h b/editor/property_editor.h
index c4287dc115..73306e0bc2 100644
--- a/editor/property_editor.h
+++ b/editor/property_editor.h
@@ -119,7 +119,7 @@ class CustomPropertyEditor : public PopupPanel {
TextureRect *texture_preview;
ColorPicker *color_picker;
TextEdit *text_edit;
- bool read_only;
+ bool read_only = false;
bool picking_viewport;
GridContainer *checks20gc;
CheckBox *checks20[20];
@@ -132,7 +132,7 @@ class CustomPropertyEditor : public PopupPanel {
Object *owner;
- bool updating;
+ bool updating = false;
PropertyValueEvaluator *evaluator;
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index 453ecb6b24..1ac15a0a9d 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -589,7 +589,6 @@ PropertySelector::PropertySelector() {
search_options->connect("cell_selected", callable_mp(this, &PropertySelector::_item_selected));
search_options->set_hide_root(true);
search_options->set_hide_folding(true);
- virtuals_only = false;
help_bit = memnew(EditorHelpBit);
vbc->add_margin_child(TTR("Description:"), help_bit);
diff --git a/editor/property_selector.h b/editor/property_selector.h
index 1e8c6300a0..7e629a847e 100644
--- a/editor/property_selector.h
+++ b/editor/property_selector.h
@@ -56,7 +56,7 @@ class PropertySelector : public ConfirmationDialog {
String base_type;
ObjectID script;
Object *instance;
- bool virtuals_only;
+ bool virtuals_only = false;
Vector<Variant::Type> type_filter;
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index 4e64aba1db..53da945868 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -245,8 +245,6 @@ void EditorQuickOpen::_bind_methods() {
}
EditorQuickOpen::EditorQuickOpen() {
- allow_multi_select = false;
-
VBoxContainer *vbc = memnew(VBoxContainer);
vbc->connect("theme_changed", callable_mp(this, &EditorQuickOpen::_theme_changed));
add_child(vbc);
diff --git a/editor/quick_open.h b/editor/quick_open.h
index dc485a7c86..f50f09604c 100644
--- a/editor/quick_open.h
+++ b/editor/quick_open.h
@@ -42,7 +42,7 @@ class EditorQuickOpen : public ConfirmationDialog {
LineEdit *search_box;
Tree *search_options;
StringName base_type;
- bool allow_multi_select;
+ bool allow_multi_select = false;
Vector<String> files;
OAHashMap<String, Ref<Texture2D>> icons;
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 571b87a0aa..8d7916685a 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -2551,7 +2551,7 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_
menu_properties->clear();
for (const String &p : valid_properties) {
menu_properties->add_item(capitalize ? p.capitalize() : p);
- menu_properties->set_item_metadata(menu_properties->get_item_count() - 1, p);
+ menu_properties->set_item_metadata(-1, p);
}
menu_properties->reset_size();
@@ -3497,8 +3497,6 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
menu_subresources->set_name("Sub-Resources");
menu_subresources->connect("id_pressed", callable_mp(this, &SceneTreeDock::_tool_selected), make_binds(false));
menu->add_child(menu_subresources);
- first_enter = true;
- restore_script_editor_on_drag = false;
menu_properties = memnew(PopupMenu);
add_child(menu_properties);
@@ -3512,9 +3510,6 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
set_process_input(true);
set_process(true);
- profile_allow_editing = true;
- profile_allow_script_editing = true;
-
EDITOR_DEF("interface/editors/show_scene_tree_root_selection", true);
EDITOR_DEF("interface/editors/derive_script_globals_by_name", true);
EDITOR_DEF("_use_favorites_root_selection", false);
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 2a98c469dc..938f83725d 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -105,7 +105,7 @@ class SceneTreeDock : public VBoxContainer {
Vector<ObjectID> subresources;
- bool restore_script_editor_on_drag;
+ bool restore_script_editor_on_drag = false;
bool reset_create_dialog = false;
int current_option;
@@ -166,7 +166,7 @@ class SceneTreeDock : public VBoxContainer {
PopupMenu *menu_properties;
ConfirmationDialog *clear_inherit_confirm;
- bool first_enter;
+ bool first_enter = true;
void _create();
void _do_create(Node *p_parent);
@@ -261,8 +261,8 @@ class SceneTreeDock : public VBoxContainer {
void _create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap);
void _create_remap_for_resource(RES p_resource, Map<RES, RES> &r_remap);
- bool profile_allow_editing;
- bool profile_allow_script_editing;
+ bool profile_allow_editing = true;
+ bool profile_allow_script_editing = true;
static void _update_configuration_warning();
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index c6a8a928db..3b8c540592 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -1197,17 +1197,11 @@ void SceneTreeEditor::_bind_methods() {
}
SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_open_instance) {
- connect_to_script_mode = false;
- connecting_signal = false;
undo_redo = nullptr;
- tree_dirty = true;
selected = nullptr;
- marked_selectable = false;
- marked_children_selectable = false;
can_rename = p_can_rename;
can_open_instance = p_can_open_instance;
- display_foreign = false;
editor_selection = nullptr;
if (p_label) {
@@ -1249,11 +1243,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
add_child(warning);
warning->set_title(TTR("Node Configuration Warning!"));
- show_enabled_subscene = false;
-
last_hash = 0;
- pending_test_update = false;
- updating_tree = false;
blocked = 0;
update_timer = memnew(Timer);
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index f700182681..2466b8576a 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -65,8 +65,8 @@ class SceneTreeEditor : public Control {
AcceptDialog *warning;
bool auto_expand_selected = true;
- bool connect_to_script_mode;
- bool connecting_signal;
+ bool connect_to_script_mode = false;
+ bool connecting_signal = false;
int blocked;
@@ -92,18 +92,18 @@ class SceneTreeEditor : public Control {
bool can_rename;
bool can_open_instance;
- bool updating_tree;
- bool show_enabled_subscene;
+ bool updating_tree = false;
+ bool show_enabled_subscene = false;
void _renamed();
UndoRedo *undo_redo;
Set<Node *> marked;
- bool marked_selectable;
- bool marked_children_selectable;
- bool display_foreign;
- bool tree_dirty;
- bool pending_test_update;
+ bool marked_selectable = false;
+ bool marked_children_selectable = false;
+ bool display_foreign = false;
+ bool tree_dirty = true;
+ bool pending_test_update = false;
static void _bind_methods();
void _cell_button_pressed(Object *p_item, int p_column, int p_id);
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index bf43e11cdb..baafef8639 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -247,23 +247,22 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
return TTR("Path is not local.");
}
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (d->change_dir(p.get_base_dir()) != OK) {
- memdelete(d);
- return TTR("Base path is invalid.");
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->change_dir(p.get_base_dir()) != OK) {
+ return TTR("Base path is invalid.");
+ }
}
- memdelete(d);
- // Check if file exists.
- DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (f->dir_exists(p)) {
- memdelete(f);
- return TTR("A directory with the same name exists.");
- } else if (p_file_must_exist && !f->file_exists(p)) {
- memdelete(f);
- return TTR("File does not exist.");
+ {
+ // Check if file exists.
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (da->dir_exists(p)) {
+ return TTR("A directory with the same name exists.");
+ } else if (p_file_must_exist && !da->file_exists(p)) {
+ return TTR("File does not exist.");
+ }
}
- memdelete(f);
// Check file extension.
String extension = p.get_extension();
@@ -556,13 +555,12 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
}
// Check if file exists.
- DirAccess *f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
- if (f->file_exists(p)) {
+ if (da->file_exists(p)) {
is_new_script_created = false;
_msg_path_valid(true, TTR("File exists, it will be reused."));
}
- memdelete(f);
is_path_valid = true;
_update_dialog();
@@ -643,7 +641,7 @@ void ScriptCreateDialog::_update_template_menu() {
if (!templates_found.is_empty()) {
if (!separator) {
template_menu->add_separator();
- template_menu->set_item_text(template_menu->get_item_count() - 1, display_name);
+ template_menu->set_item_text(-1, display_name);
separator = true;
}
for (ScriptLanguage::ScriptTemplate &t : templates_found) {
@@ -838,7 +836,7 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c
String dir_path = p_dir.plus_file(p_object);
- DirAccess *d = DirAccess::open(dir_path);
+ DirAccessRef d = DirAccess::open(dir_path);
if (d) {
d->list_dir_begin();
String file = d->get_next();
@@ -849,7 +847,6 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c
file = d->get_next();
}
d->list_dir_end();
- memdelete(d);
}
return user_templates;
}
@@ -1029,7 +1026,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
hb->add_child(parent_browse_button);
gc->add_child(memnew(Label(TTR("Inherits:"))));
gc->add_child(hb);
- is_browsing_parent = false;
/* Class Name */
@@ -1040,8 +1036,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
gc->add_child(class_name);
/* Templates */
-
- is_using_templates = true;
gc->add_child(memnew(Label(TTR("Template:"))));
HBoxContainer *template_hb = memnew(HBoxContainer);
template_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -1082,7 +1076,6 @@ ScriptCreateDialog::ScriptCreateDialog() {
Label *label = memnew(Label(TTR("Path:")));
gc->add_child(label);
gc->add_child(hb);
- re_check_path = false;
path_controls[0] = label;
path_controls[1] = hb;
@@ -1119,17 +1112,4 @@ ScriptCreateDialog::ScriptCreateDialog() {
set_hide_on_ok(false);
set_title(TTR("Attach Node Script"));
-
- is_parent_name_valid = false;
- is_class_name_valid = false;
- is_path_valid = false;
-
- has_named_classes = false;
- supports_built_in = false;
- can_inherit_from_file = false;
- is_built_in = false;
- built_in_enabled = true;
- load_enabled = true;
-
- is_new_script_created = true;
}
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index 5c0f51812f..d7c43f322c 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -66,25 +66,23 @@ class ScriptCreateDialog : public ConfirmationDialog {
VBoxContainer *path_vb;
AcceptDialog *alert;
CreateDialog *select_class;
- bool path_valid;
- bool create_new;
- bool is_browsing_parent;
+ bool is_browsing_parent = false;
String template_inactive_message;
String initial_bp;
- bool is_new_script_created;
- bool is_path_valid;
- bool has_named_classes;
- bool supports_built_in;
- bool can_inherit_from_file;
- bool is_parent_name_valid;
- bool is_class_name_valid;
- bool is_built_in;
- bool is_using_templates;
- bool built_in_enabled;
- bool load_enabled;
+ bool is_new_script_created = true;
+ bool is_path_valid = false;
+ bool has_named_classes = false;
+ bool supports_built_in = false;
+ bool can_inherit_from_file = false;
+ bool is_parent_name_valid = false;
+ bool is_class_name_valid = false;
+ bool is_built_in = false;
+ bool is_using_templates = true;
+ bool built_in_enabled = true;
+ bool load_enabled = true;
int current_language;
int default_language;
- bool re_check_path;
+ bool re_check_path = false;
Control *path_controls[2];
Control *name_controls[2];
diff --git a/editor/translations/extract.py b/editor/translations/extract.py
index 2594629e5c..65d1341e9e 100755
--- a/editor/translations/extract.py
+++ b/editor/translations/extract.py
@@ -2,6 +2,7 @@
import fnmatch
import os
+import re
import shutil
import subprocess
import sys
@@ -31,6 +32,15 @@ for root, dirnames, filenames in os.walk("."):
matches.sort()
+remaps = {}
+remap_re = re.compile(r'capitalize_string_remaps\["(.+)"\] = "(.+)";')
+with open("editor/editor_property_name_processor.cpp") as f:
+ for line in f:
+ m = remap_re.search(line)
+ if m:
+ remaps[m.group(1)] = m.group(2)
+
+
unique_str = []
unique_loc = {}
ctx_group = {} # Store msgctx, msg, and locations.
@@ -53,6 +63,43 @@ msgstr ""
"""
+# Regex "(?P<name>(?:[^"\\]|\\.)*)" creates a group named `name` that matches a string.
+message_patterns = {
+ re.compile(r'RTR\("(?P<message>(?:[^"\\]|\\.)*)"(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'): False,
+ re.compile(r'TTR\("(?P<message>(?:[^"\\]|\\.)*)"(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'): False,
+ re.compile(r'TTRC\("(?P<message>(?:[^"\\]|\\.)*)"\)'): False,
+ re.compile(
+ r'TTRN\("(?P<message>(?:[^"\\]|\\.)*)", "(?P<plural_message>(?:[^"\\]|\\.)*)",[^,)]+?(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'
+ ): False,
+ re.compile(
+ r'RTRN\("(?P<message>(?:[^"\\]|\\.)*)", "(?P<plural_message>(?:[^"\\]|\\.)*)",[^,)]+?(?:, "(?P<context>(?:[^"\\]|\\.)*)")?\)'
+ ): False,
+ re.compile(r'_initial_set\("(?P<message>[^"]+?)",'): True,
+ re.compile(r'GLOBAL_DEF(?:_RST)?\("(?P<message>[^".]+?)",'): True,
+ re.compile(r'EDITOR_DEF(?:_RST)?\("(?P<message>[^"]+?)",'): True,
+ re.compile(r'ADD_PROPERTY\(PropertyInfo\(Variant::[A-Z]+,\s*"(?P<message>[^"]+?)",'): True,
+ re.compile(r'ADD_GROUP\("(?P<message>[^"]+?)",'): False,
+}
+
+
+# See String::camelcase_to_underscore().
+capitalize_re = re.compile(r"(?<=\D)(?=\d)|(?<=\d)(?=\D([a-z]|\d))")
+
+
+def _process_editor_string(name):
+ # See String::capitalize().
+ # fmt: off
+ capitalized = " ".join(
+ part.title()
+ for part in capitalize_re.sub("_", name).replace("_", " ").split()
+ )
+ # fmt: on
+ # See EditorStringProcessor::process_string().
+ for key, value in remaps.items():
+ capitalized = capitalized.replace(key, value)
+ return capitalized
+
+
def _write_message(msgctx, msg, msg_plural, location):
global main_po
main_po += "#: " + location + "\n"
@@ -180,11 +227,6 @@ def _extract_translator_comment(line, is_block_translator_comment):
def process_file(f, fname):
-
- global main_po, unique_str, unique_loc
-
- patterns = ['RTR("', 'TTR("', 'TTRC("', 'TTRN("', 'RTRN("']
-
l = f.readline()
lc = 1
reading_translator_comment = False
@@ -207,86 +249,58 @@ def process_file(f, fname):
if not reading_translator_comment:
translator_comment = translator_comment[:-1] # Remove extra \n at the end.
- idx = 0
- pos = 0
-
- while not reading_translator_comment and pos >= 0:
- # Loop until a pattern is found. If not, next line.
- pos = l.find(patterns[idx], pos)
- if pos == -1:
- if idx < len(patterns) - 1:
- idx += 1
- pos = 0
- continue
- pos += len(patterns[idx])
-
- # Read msg until "
- msg = ""
- while pos < len(l) and (l[pos] != '"' or l[pos - 1] == "\\"):
- msg += l[pos]
- pos += 1
-
- # Read plural.
- msg_plural = ""
- if patterns[idx] in ['TTRN("', 'RTRN("']:
- pos = l.find('"', pos + 1)
- pos += 1
- while pos < len(l) and (l[pos] != '"' or l[pos - 1] == "\\"):
- msg_plural += l[pos]
- pos += 1
-
- # Read context.
- msgctx = ""
- pos += 1
- read_ctx = False
- while pos < len(l):
- if l[pos] == ")":
- break
- elif l[pos] == '"':
- read_ctx = True
- break
- pos += 1
-
- pos += 1
- if read_ctx:
- while pos < len(l) and (l[pos] != '"' or l[pos - 1] == "\\"):
- msgctx += l[pos]
- pos += 1
-
- # File location.
- location = os.path.relpath(fname).replace("\\", "/")
- if line_nb:
- location += ":" + str(lc)
-
- # Write translator comment.
- _write_translator_comment(msgctx, msg, translator_comment)
+ if not reading_translator_comment:
+ for pattern, is_property_path in message_patterns.items():
+ for m in pattern.finditer(l):
+ location = os.path.relpath(fname).replace("\\", "/")
+ if line_nb:
+ location += ":" + str(lc)
+
+ groups = m.groupdict("")
+ msg = groups.get("message", "")
+ msg_plural = groups.get("plural_message", "")
+ msgctx = groups.get("context", "")
+
+ if is_property_path:
+ for part in msg.split("/"):
+ _add_message(_process_editor_string(part), msg_plural, msgctx, location, translator_comment)
+ else:
+ _add_message(msg, msg_plural, msgctx, location, translator_comment)
translator_comment = ""
- if msgctx != "":
- # If it's a new context or a new message within an existing context, then write new msgid.
- # Else add location to existing msgid.
- if not msgctx in ctx_group:
- _write_message(msgctx, msg, msg_plural, location)
- ctx_group[msgctx] = {msg: [location]}
- elif not msg in ctx_group[msgctx]:
- _write_message(msgctx, msg, msg_plural, location)
- ctx_group[msgctx][msg] = [location]
- elif not location in ctx_group[msgctx][msg]:
- _add_additional_location(msgctx, msg, location)
- ctx_group[msgctx][msg].append(location)
- else:
- if not msg in unique_str:
- _write_message(msgctx, msg, msg_plural, location)
- unique_str.append(msg)
- unique_loc[msg] = [location]
- elif not location in unique_loc[msg]:
- _add_additional_location(msgctx, msg, location)
- unique_loc[msg].append(location)
-
l = f.readline()
lc += 1
+def _add_message(msg, msg_plural, msgctx, location, translator_comment):
+ global main_po, unique_str, unique_loc
+
+ # Write translator comment.
+ _write_translator_comment(msgctx, msg, translator_comment)
+ translator_comment = ""
+
+ if msgctx != "":
+ # If it's a new context or a new message within an existing context, then write new msgid.
+ # Else add location to existing msgid.
+ if not msgctx in ctx_group:
+ _write_message(msgctx, msg, msg_plural, location)
+ ctx_group[msgctx] = {msg: [location]}
+ elif not msg in ctx_group[msgctx]:
+ _write_message(msgctx, msg, msg_plural, location)
+ ctx_group[msgctx][msg] = [location]
+ elif not location in ctx_group[msgctx][msg]:
+ _add_additional_location(msgctx, msg, location)
+ ctx_group[msgctx][msg].append(location)
+ else:
+ if not msg in unique_str:
+ _write_message(msgctx, msg, msg_plural, location)
+ unique_str.append(msg)
+ unique_loc[msg] = [location]
+ elif not location in unique_loc[msg]:
+ _add_additional_location(msgctx, msg, location)
+ unique_loc[msg].append(location)
+
+
print("Updating the editor.pot template...")
for fname in matches:
diff --git a/main/main.cpp b/main/main.cpp
index 97794ece1a..ccd48a9343 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2099,9 +2099,8 @@ bool Main::start() {
checked_paths.insert(path);
// Create the module documentation directory if it doesn't exist
- DirAccess *da = DirAccess::create_for_path(path);
+ DirAccessRef da = DirAccess::create_for_path(path);
err = da->make_dir_recursive(path);
- memdelete(da);
ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create directory: " + path + ": " + itos(err));
print_line("Loading docs from: " + path);
@@ -2112,9 +2111,8 @@ bool Main::start() {
String index_path = doc_tool_path.plus_file("doc/classes");
// Create the main documentation directory if it doesn't exist
- DirAccess *da = DirAccess::create_for_path(index_path);
+ DirAccessRef da = DirAccess::create_for_path(index_path);
err = da->make_dir_recursive(index_path);
- memdelete(da);
ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create index directory: " + index_path + ": " + itos(err));
print_line("Loading classes from: " + index_path);
@@ -2452,15 +2450,13 @@ bool Main::start() {
int sep = local_game_path.rfind("/");
if (sep == -1) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
local_game_path = da->get_current_dir().plus_file(local_game_path);
- memdelete(da);
} else {
- DirAccess *da = DirAccess::open(local_game_path.substr(0, sep));
+ DirAccessRef da = DirAccess::open(local_game_path.substr(0, sep));
if (da) {
local_game_path = da->get_current_dir().plus_file(
local_game_path.substr(sep + 1, local_game_path.length()));
- memdelete(da);
}
}
}
diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/osx_template.app/Contents/Info.plist
index 43399ec6ce..542146cdb8 100644
--- a/misc/dist/osx_template.app/Contents/Info.plist
+++ b/misc/dist/osx_template.app/Contents/Info.plist
@@ -10,8 +10,6 @@
<string>$name</string>
<key>CFBundleDisplayName</key>
<string>$name</string>
- <key>CFBundleGetInfoString</key>
- <string>$info</string>
<key>CFBundleIconFile</key>
<string>icon.icns</string>
<key>CFBundleIdentifier</key>
diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist
index 221c4b7a81..886df87cc6 100644
--- a/misc/dist/osx_tools.app/Contents/Info.plist
+++ b/misc/dist/osx_tools.app/Contents/Info.plist
@@ -8,8 +8,6 @@
<string>Godot</string>
<key>CFBundleName</key>
<string>Godot</string>
- <key>CFBundleGetInfoString</key>
- <string>(c) 2007-2022 Juan Linietsky, Ariel Manzur &amp; Godot Engine contributors</string>
<key>CFBundleIconFile</key>
<string>Godot.icns</string>
<key>CFBundleIdentifier</key>
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index fec2d3137c..be9bf9538f 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -303,17 +303,19 @@ void CSGShape3D::_update_shape() {
ERR_CONTINUE(mat < -1 || mat >= face_count.size());
int idx = mat == -1 ? face_count.size() - 1 : mat;
- Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
+ if (n->faces[i].smooth) {
+ Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
- for (int j = 0; j < 3; j++) {
- Vector3 v = n->faces[i].vertices[j];
- Vector3 add;
- if (vec_map.lookup(v, add)) {
- add += p.normal;
- } else {
- add = p.normal;
+ for (int j = 0; j < 3; j++) {
+ Vector3 v = n->faces[i].vertices[j];
+ Vector3 add;
+ if (vec_map.lookup(v, add)) {
+ add += p.normal;
+ } else {
+ add = p.normal;
+ }
+ vec_map.set(v, add);
}
- vec_map.set(v, add);
}
face_count.write[idx]++;
@@ -491,10 +493,6 @@ Vector<Vector3> CSGShape3D::get_brush_faces() {
return faces;
}
-Vector<Face3> CSGShape3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void CSGShape3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PARENTED: {
@@ -1534,6 +1532,9 @@ CSGBrush *CSGTorus3D::_build_brush() {
for (int i = 0; i < sides; i++) {
float inci = float(i) / sides;
float inci_n = float((i + 1)) / sides;
+ if (i == sides - 1) {
+ inci_n = 0;
+ }
float angi = inci * Math_TAU;
float angi_n = inci_n * Math_TAU;
@@ -1544,6 +1545,9 @@ CSGBrush *CSGTorus3D::_build_brush() {
for (int j = 0; j < ring_sides; j++) {
float incj = float(j) / ring_sides;
float incj_n = float((j + 1)) / ring_sides;
+ if (j == ring_sides - 1) {
+ incj_n = 0;
+ }
float angj = incj * Math_TAU;
float angj_n = incj_n * Math_TAU;
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index d16250e30d..4721d0c11c 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -128,7 +128,6 @@ public:
virtual Vector<Vector3> get_brush_faces();
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_use_collision(bool p_enable);
bool is_using_collision() const;
diff --git a/modules/csg/register_types.cpp b/modules/csg/register_types.cpp
index f01907bef3..f8db42b1a9 100644
--- a/modules/csg/register_types.cpp
+++ b/modules/csg/register_types.cpp
@@ -36,8 +36,8 @@
void register_csg_types() {
#ifndef _3D_DISABLED
- GDREGISTER_VIRTUAL_CLASS(CSGShape3D);
- GDREGISTER_VIRTUAL_CLASS(CSGPrimitive3D);
+ GDREGISTER_ABSTRACT_CLASS(CSGShape3D);
+ GDREGISTER_ABSTRACT_CLASS(CSGPrimitive3D);
GDREGISTER_CLASS(CSGMesh3D);
GDREGISTER_CLASS(CSGSphere3D);
GDREGISTER_CLASS(CSGBox3D);
diff --git a/modules/enet/register_types.cpp b/modules/enet/register_types.cpp
index 36a4e6e6e7..ebc5d95348 100644
--- a/modules/enet/register_types.cpp
+++ b/modules/enet/register_types.cpp
@@ -44,7 +44,7 @@ void register_enet_types() {
}
GDREGISTER_CLASS(ENetMultiplayerPeer);
- GDREGISTER_VIRTUAL_CLASS(ENetPacketPeer);
+ GDREGISTER_ABSTRACT_CLASS(ENetPacketPeer);
GDREGISTER_CLASS(ENetConnection);
}
diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp
index 63fec6db8c..b5b51403f7 100644
--- a/modules/minimp3/audio_stream_mp3.cpp
+++ b/modules/minimp3/audio_stream_mp3.cpp
@@ -83,7 +83,7 @@ void AudioStreamPlaybackMP3::start(float p_from_pos) {
active = true;
seek(p_from_pos);
loops = 0;
- _begin_resample();
+ begin_resample();
}
void AudioStreamPlaybackMP3::stop() {
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index ee218cb1f8..d4b623b2ea 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -511,8 +511,9 @@ namespace Godot
/// Returns the result of the spherical linear interpolation between
/// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
///
- /// This method also handles interpolating the lengths if the input vectors have different lengths.
- /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp].
+ /// This method also handles interpolating the lengths if the input vectors
+ /// have different lengths. For the special case of one or both input vectors
+ /// having zero length, this method behaves like <see cref="Lerp"/>.
/// </summary>
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 45e5287610..eddfa76f10 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -551,8 +551,9 @@ namespace Godot
/// Returns the result of the spherical linear interpolation between
/// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
///
- /// This method also handles interpolating the lengths if the input vectors have different lengths.
- /// For the special case of one or both input vectors having zero length, this method behaves like [method lerp].
+ /// This method also handles interpolating the lengths if the input vectors
+ /// have different lengths. For the special case of one or both input vectors
+ /// having zero length, this method behaves like <see cref="Lerp"/>.
/// </summary>
/// <param name="to">The destination vector for interpolation.</param>
/// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 4cd4772d2c..424b74906f 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -643,9 +643,8 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const
// Create destination directory if needed
if (!DirAccess::exists(dst_dir)) {
- DirAccess *da = DirAccess::create_for_path(dst_dir);
+ DirAccessRef da = DirAccess::create_for_path(dst_dir);
Error err = da->make_dir_recursive(dst_dir);
- memdelete(da);
if (err != OK) {
ERR_PRINT("Failed to create destination directory for the API assemblies. Error: " + itos(err) + ".");
diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml
index 1160061e04..74f708bc95 100644
--- a/modules/openxr/doc_classes/OpenXRInterface.xml
+++ b/modules/openxr/doc_classes/OpenXRInterface.xml
@@ -10,4 +10,31 @@
<tutorials>
<link title="OpenXR documentation">$DOCS_URL/tutorials/vr/openxr/index.html</link>
</tutorials>
+ <signals>
+ <signal name="pose_recentered">
+ <description>
+ Informs the user queued a recenter of the player position.
+ </description>
+ </signal>
+ <signal name="session_begun">
+ <description>
+ Informs our OpenXR session has been started.
+ </description>
+ </signal>
+ <signal name="session_focussed">
+ <description>
+ Informs our OpenXR session now has focus.
+ </description>
+ </signal>
+ <signal name="session_stopping">
+ <description>
+ Informs our OpenXR session is stopping.
+ </description>
+ </signal>
+ <signal name="session_visible">
+ <description>
+ Informs our OpenXR session is now visible (output is being sent to the HMD).
+ </description>
+ </signal>
+ </signals>
</class>
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index e3da214cc8..4d533337f3 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -48,6 +48,8 @@
#include "extensions/openxr_vulkan_extension.h"
#endif
+#include "modules/openxr/openxr_interface.h"
+
OpenXRAPI *OpenXRAPI::singleton = nullptr;
void OpenXRAPI::setup_global_defs() {
@@ -877,7 +879,9 @@ bool OpenXRAPI::on_state_ready() {
wrapper->on_state_ready();
}
- // TODO emit signal
+ if (xr_interface) {
+ xr_interface->on_state_ready();
+ }
// TODO Tell android
@@ -889,6 +893,13 @@ bool OpenXRAPI::on_state_synchronized() {
print_line("On state synchronized");
#endif
+ // Just in case, see if we already have active trackers...
+ List<RID> trackers;
+ tracker_owner.get_owned_list(&trackers);
+ for (int i = 0; i < trackers.size(); i++) {
+ tracker_check_profile(trackers[i]);
+ }
+
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
wrapper->on_state_synchronized();
}
@@ -905,7 +916,9 @@ bool OpenXRAPI::on_state_visible() {
wrapper->on_state_visible();
}
- // TODO emit signal
+ if (xr_interface) {
+ xr_interface->on_state_visible();
+ }
return true;
}
@@ -919,7 +932,9 @@ bool OpenXRAPI::on_state_focused() {
wrapper->on_state_focused();
}
- // TODO emit signal
+ if (xr_interface) {
+ xr_interface->on_state_focused();
+ }
return true;
}
@@ -929,7 +944,9 @@ bool OpenXRAPI::on_state_stopping() {
print_line("On state stopping");
#endif
- // TODO emit signal
+ if (xr_interface) {
+ xr_interface->on_state_stopping();
+ }
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
wrapper->on_state_stopping();
@@ -1081,6 +1098,10 @@ void OpenXRAPI::finish() {
destroy_instance();
}
+void OpenXRAPI::set_xr_interface(OpenXRInterface *p_xr_interface) {
+ xr_interface = p_xr_interface;
+}
+
void OpenXRAPI::register_extension_wrapper(OpenXRExtensionWrapper *p_extension_wrapper) {
registered_extension_wrappers.push_back(p_extension_wrapper);
}
@@ -1204,20 +1225,38 @@ bool OpenXRAPI::poll_events() {
handled |= wrapper->on_event_polled(runtimeEvent);
}
switch (runtimeEvent.type) {
- // case XR_TYPE_EVENT_DATA_EVENTS_LOST: {
- // } break;
- // case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR: {
- // } break;
- // case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: {
- // } break;
+ case XR_TYPE_EVENT_DATA_EVENTS_LOST: {
+ XrEventDataEventsLost *event = (XrEventDataEventsLost *)&runtimeEvent;
+
+ // We probably didn't poll fast enough, just output warning
+ WARN_PRINT("OpenXR EVENT: " + itos(event->lostEventCount) + " event data lost!");
+ } break;
+ case XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR: {
+ // XrEventDataVisibilityMaskChangedKHR *event = (XrEventDataVisibilityMaskChangedKHR *)&runtimeEvent;
+
+ // TODO implement this in the future, we should call xrGetVisibilityMaskKHR to obtain a mask,
+ // this will allow us to prevent rendering the part of our view which is never displayed giving us
+ // a decent performance improvement.
+
+ print_verbose("OpenXR EVENT: STUB: visibility mask changed");
+ } break;
+ case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: {
+ XrEventDataInstanceLossPending *event = (XrEventDataInstanceLossPending *)&runtimeEvent;
+
+ // TODO We get this event if we're about to loose our OpenXR instance.
+ // We should queue exiting Godot at this point.
+
+ print_verbose("OpenXR EVENT: instance loss pending at " + itos(event->lossTime));
+ return false;
+ } break;
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
XrEventDataSessionStateChanged *event = (XrEventDataSessionStateChanged *)&runtimeEvent;
session_state = event->state;
if (session_state >= XR_SESSION_STATE_MAX_ENUM) {
- print_line("OpenXR EVENT: session state changed to UNKNOWN -", session_state);
+ print_verbose("OpenXR EVENT: session state changed to UNKNOWN - " + itos(session_state));
} else {
- print_line("OpenXR EVENT: session state changed to", OpenXRUtil::get_session_state_name(session_state));
+ print_verbose("OpenXR EVENT: session state changed to " + OpenXRUtil::get_session_state_name(session_state));
switch (session_state) {
case XR_SESSION_STATE_IDLE:
@@ -1249,13 +1288,29 @@ bool OpenXRAPI::poll_events() {
}
}
} break;
- // case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: {
- // } break;
- // case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: {
- // } break;
+ case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: {
+ XrEventDataReferenceSpaceChangePending *event = (XrEventDataReferenceSpaceChangePending *)&runtimeEvent;
+
+ print_verbose("OpenXR EVENT: reference space type " + OpenXRUtil::get_reference_space_name(event->referenceSpaceType) + " change pending!");
+ if (event->poseValid && xr_interface) {
+ xr_interface->on_pose_recentered();
+ }
+ } break;
+ case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: {
+ print_verbose("OpenXR EVENT: interaction profile changed!");
+
+ XrEventDataInteractionProfileChanged *event = (XrEventDataInteractionProfileChanged *)&runtimeEvent;
+
+ List<RID> trackers;
+ tracker_owner.get_owned_list(&trackers);
+ for (int i = 0; i < trackers.size(); i++) {
+ tracker_check_profile(trackers[i], event->session);
+ }
+
+ } break;
default:
if (!handled) {
- print_line("OpenXR Unhandled event type", OpenXRUtil::get_structure_type_name(runtimeEvent.type));
+ print_verbose("OpenXR Unhandled event type " + OpenXRUtil::get_structure_type_name(runtimeEvent.type));
}
break;
}
@@ -1348,9 +1403,21 @@ void OpenXRAPI::pre_render() {
XrResult result = xrWaitFrame(session, &frame_wait_info, &frame_state);
if (XR_FAILED(result)) {
print_line("OpenXR: xrWaitFrame() was not successful [", get_error_string(result), "]");
+
+ // reset just in case
+ frame_state.predictedDisplayTime = 0;
+ frame_state.predictedDisplayPeriod = 0;
+ frame_state.shouldRender = false;
+
return;
}
+ if (frame_state.predictedDisplayPeriod > 500000000) {
+ // display period more then 0.5 seconds? must be wrong data
+ print_verbose("OpenXR resetting invalid display period " + rtos(frame_state.predictedDisplayPeriod));
+ frame_state.predictedDisplayPeriod = 0;
+ }
+
for (OpenXRExtensionWrapper *wrapper : registered_extension_wrappers) {
wrapper->on_pre_render();
}
@@ -1691,38 +1758,97 @@ void OpenXRAPI::parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_l
}
}
-RID OpenXRAPI::path_create(const String p_name) {
- ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, RID());
+RID OpenXRAPI::get_tracker_rid(XrPath p_path) {
+ List<RID> current;
+ tracker_owner.get_owned_list(&current);
+ for (int i = 0; i < current.size(); i++) {
+ Tracker *tracker = tracker_owner.get_or_null(current[i]);
+ if (tracker && tracker->toplevel_path == p_path) {
+ return current[i];
+ }
+ }
- // Encoding our path as a RID is probably overkill but it does future proof this
- // Note that we only do this for XrPaths that we access from outside of this class!
+ return RID();
+}
- Path new_path;
+RID OpenXRAPI::tracker_create(const String p_name) {
+ ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, RID());
- print_line("Parsing path ", p_name);
+ Tracker new_tracker;
+ new_tracker.name = p_name;
+ new_tracker.toplevel_path = XR_NULL_PATH;
+ new_tracker.active_profile_rid = RID();
- XrResult result = xrStringToPath(instance, p_name.utf8().get_data(), &new_path.path);
+ XrResult result = xrStringToPath(instance, p_name.utf8().get_data(), &new_tracker.toplevel_path);
if (XR_FAILED(result)) {
print_line("OpenXR: failed to get path for ", p_name, "! [", get_error_string(result), "]");
return RID();
}
- return xr_path_owner.make_rid(new_path);
+ return tracker_owner.make_rid(new_tracker);
}
-void OpenXRAPI::path_free(RID p_path) {
- Path *path = xr_path_owner.get_or_null(p_path);
- ERR_FAIL_NULL(path);
+String OpenXRAPI::tracker_get_name(RID p_tracker) {
+ if (p_tracker.is_null()) {
+ return String("None");
+ }
+
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL_V(tracker, String());
+
+ return tracker->name;
+}
+
+void OpenXRAPI::tracker_check_profile(RID p_tracker, XrSession p_session) {
+ if (p_session == XR_NULL_HANDLE) {
+ p_session = session;
+ }
+
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL(tracker);
+
+ if (tracker->toplevel_path == XR_NULL_PATH) {
+ // no path, how was this even created?
+ return;
+ }
+
+ XrInteractionProfileState profile_state = {
+ XR_TYPE_INTERACTION_PROFILE_STATE, // type
+ nullptr, // next
+ XR_NULL_PATH // interactionProfile
+ };
+
+ XrResult result = xrGetCurrentInteractionProfile(p_session, tracker->toplevel_path, &profile_state);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: Failed to get interaction profile for", itos(tracker->toplevel_path), "[", get_error_string(result), "]");
+ return;
+ }
+
+ XrPath new_profile = profile_state.interactionProfile;
+ XrPath was_profile = get_interaction_profile_path(tracker->active_profile_rid);
+ if (was_profile != new_profile) {
+ tracker->active_profile_rid = get_interaction_profile_rid(new_profile);
+
+ if (xr_interface) {
+ xr_interface->tracker_profile_changed(p_tracker, tracker->active_profile_rid);
+ }
+ }
+}
+
+void OpenXRAPI::tracker_free(RID p_tracker) {
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL(tracker);
// there is nothing to free here
- xr_path_owner.free(p_path);
+ tracker_owner.free(p_tracker);
}
RID OpenXRAPI::action_set_create(const String p_name, const String p_localized_name, const int p_priority) {
ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, RID());
ActionSet action_set;
+ action_set.name = p_name;
action_set.is_attached = false;
// create our action set...
@@ -1737,7 +1863,7 @@ RID OpenXRAPI::action_set_create(const String p_name, const String p_localized_n
copy_string_to_char_buffer(p_name, action_set_info.actionSetName, XR_MAX_ACTION_SET_NAME_SIZE);
copy_string_to_char_buffer(p_localized_name, action_set_info.localizedActionSetName, XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE);
- print_line("Creating action set ", action_set_info.actionSetName, " - ", action_set_info.localizedActionSetName, " (", itos(action_set_info.priority), ")");
+ // print_line("Creating action set ", action_set_info.actionSetName, " - ", action_set_info.localizedActionSetName, " (", itos(action_set_info.priority), ")");
XrResult result = xrCreateActionSet(instance, &action_set_info, &action_set.handle);
if (XR_FAILED(result)) {
@@ -1748,6 +1874,17 @@ RID OpenXRAPI::action_set_create(const String p_name, const String p_localized_n
return action_set_owner.make_rid(action_set);
}
+String OpenXRAPI::action_set_get_name(RID p_action_set) {
+ if (p_action_set.is_null()) {
+ return String("None");
+ }
+
+ ActionSet *action_set = action_set_owner.get_or_null(p_action_set);
+ ERR_FAIL_NULL_V(action_set, String());
+
+ return action_set->name;
+}
+
bool OpenXRAPI::action_set_attach(RID p_action_set) {
ActionSet *action_set = action_set_owner.get_or_null(p_action_set);
ERR_FAIL_NULL_V(action_set, false);
@@ -1776,6 +1913,24 @@ bool OpenXRAPI::action_set_attach(RID p_action_set) {
action_set->is_attached = true;
+ /* For debugging:
+ print_verbose("Attached set " + action_set->name);
+ List<RID> action_rids;
+ action_owner.get_owned_list(&action_rids);
+ for (int i = 0; i < action_rids.size(); i++) {
+ Action * action = action_owner.get_or_null(action_rids[i]);
+ if (action && action->action_set_rid == p_action_set) {
+ print_verbose(" - Action " + action->name + ": " + OpenXRUtil::get_action_type_name(action->action_type));
+ for (int j = 0; j < action->trackers.size(); j++) {
+ Tracker * tracker = tracker_owner.get_or_null(action->trackers[j].tracker_rid);
+ if (tracker) {
+ print_verbose(" - " + tracker->name);
+ }
+ }
+ }
+ }
+ */
+
return true;
}
@@ -1790,14 +1945,29 @@ void OpenXRAPI::action_set_free(RID p_action_set) {
action_set_owner.free(p_action_set);
}
-RID OpenXRAPI::action_create(RID p_action_set, const String p_name, const String p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<RID> &p_toplevel_paths) {
+RID OpenXRAPI::get_action_rid(XrAction p_action) {
+ List<RID> current;
+ action_owner.get_owned_list(&current);
+ for (int i = 0; i < current.size(); i++) {
+ Action *action = action_owner.get_or_null(current[i]);
+ if (action && action->handle == p_action) {
+ return current[i];
+ }
+ }
+
+ return RID();
+}
+
+RID OpenXRAPI::action_create(RID p_action_set, const String p_name, const String p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<RID> &p_trackers) {
ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, RID());
Action action;
+ action.name = p_name;
ActionSet *action_set = action_set_owner.get_or_null(p_action_set);
ERR_FAIL_NULL_V(action_set, RID());
ERR_FAIL_COND_V(action_set->handle == XR_NULL_HANDLE, RID());
+ action.action_set_rid = p_action_set;
switch (p_action_type) {
case OpenXRAction::OPENXR_ACTION_BOOL:
@@ -1821,17 +1991,17 @@ RID OpenXRAPI::action_create(RID p_action_set, const String p_name, const String
}
Vector<XrPath> toplevel_paths;
- for (int i = 0; i < p_toplevel_paths.size(); i++) {
- Path *xr_path = xr_path_owner.get_or_null(p_toplevel_paths[i]);
- if (xr_path != nullptr && xr_path->path != XR_NULL_PATH) {
- PathWithSpace path_with_space = {
- xr_path->path, // toplevel_path
+ for (int i = 0; i < p_trackers.size(); i++) {
+ Tracker *tracker = tracker_owner.get_or_null(p_trackers[i]);
+ if (tracker != nullptr && tracker->toplevel_path != XR_NULL_PATH) {
+ ActionTracker action_tracker = {
+ p_trackers[i], // tracker
XR_NULL_HANDLE, // space
false // was_location_valid
};
- action.toplevel_paths.push_back(path_with_space);
+ action.trackers.push_back(action_tracker);
- toplevel_paths.push_back(xr_path->path);
+ toplevel_paths.push_back(tracker->toplevel_path);
}
}
@@ -1848,7 +2018,7 @@ RID OpenXRAPI::action_create(RID p_action_set, const String p_name, const String
copy_string_to_char_buffer(p_name, action_info.actionName, XR_MAX_ACTION_NAME_SIZE);
copy_string_to_char_buffer(p_localized_name, action_info.localizedActionName, XR_MAX_LOCALIZED_ACTION_NAME_SIZE);
- print_line("Creating action ", action_info.actionName, action_info.localizedActionName, action_info.countSubactionPaths);
+ // print_line("Creating action ", action_info.actionName, action_info.localizedActionName, action_info.countSubactionPaths);
XrResult result = xrCreateAction(action_set->handle, &action_info, &action.handle);
if (XR_FAILED(result)) {
@@ -1859,6 +2029,17 @@ RID OpenXRAPI::action_create(RID p_action_set, const String p_name, const String
return action_owner.make_rid(action);
}
+String OpenXRAPI::action_get_name(RID p_action) {
+ if (p_action.is_null()) {
+ return String("None");
+ }
+
+ Action *action = action_owner.get_or_null(p_action);
+ ERR_FAIL_NULL_V(action, String());
+
+ return action->name;
+}
+
void OpenXRAPI::action_free(RID p_action) {
Action *action = action_owner.get_or_null(p_action);
ERR_FAIL_NULL(action);
@@ -1870,55 +2051,139 @@ void OpenXRAPI::action_free(RID p_action) {
action_owner.free(p_action);
}
-bool OpenXRAPI::suggest_bindings(const String p_interaction_profile, const Vector<Binding> p_bindings) {
- ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, false);
+RID OpenXRAPI::get_interaction_profile_rid(XrPath p_path) {
+ List<RID> current;
+ interaction_profile_owner.get_owned_list(&current);
+ for (int i = 0; i < current.size(); i++) {
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(current[i]);
+ if (ip && ip->path == p_path) {
+ return current[i];
+ }
+ }
+
+ return RID();
+}
+
+XrPath OpenXRAPI::get_interaction_profile_path(RID p_interaction_profile) {
+ if (p_interaction_profile.is_null()) {
+ return XR_NULL_PATH;
+ }
+
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile);
+ ERR_FAIL_NULL_V(ip, XR_NULL_PATH);
- XrPath interaction_profile;
- Vector<XrActionSuggestedBinding> bindings;
+ return ip->path;
+}
- XrResult result = xrStringToPath(instance, p_interaction_profile.utf8().get_data(), &interaction_profile);
+RID OpenXRAPI::interaction_profile_create(const String p_name) {
+ InteractionProfile new_interaction_profile;
+
+ XrResult result = xrStringToPath(instance, p_name.utf8().get_data(), &new_interaction_profile.path);
if (XR_FAILED(result)) {
- print_line("OpenXR: failed to get path for ", p_interaction_profile, "! [", get_error_string(result), "]");
- return false;
+ print_line("OpenXR: failed to get path for ", p_name, "! [", get_error_string(result), "]");
+ return RID();
}
- for (int i = 0; i < p_bindings.size(); i++) {
- XrActionSuggestedBinding binding;
+ RID existing_ip = get_interaction_profile_rid(new_interaction_profile.path);
+ if (existing_ip.is_valid()) {
+ return existing_ip;
+ }
- Action *action = action_owner.get_or_null(p_bindings[i].action);
- if (action == nullptr || action->handle == XR_NULL_HANDLE) {
- // just skip it
- continue;
- }
+ new_interaction_profile.name = p_name;
+ return interaction_profile_owner.make_rid(new_interaction_profile);
+}
- binding.action = action->handle;
+String OpenXRAPI::interaction_profile_get_name(RID p_interaction_profile) {
+ if (p_interaction_profile.is_null()) {
+ return String("None");
+ }
- result = xrStringToPath(instance, p_bindings[i].path.utf8().get_data(), &binding.binding);
- if (XR_FAILED(result)) {
- print_line("OpenXR: failed to get path for ", p_bindings[i].path, "! [", get_error_string(result), "]");
- continue;
- }
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile);
+ ERR_FAIL_NULL_V(ip, String());
+
+ return ip->name;
+}
+
+void OpenXRAPI::interaction_profile_clear_bindings(RID p_interaction_profile) {
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile);
+ ERR_FAIL_NULL(ip);
+
+ ip->bindings.clear();
+}
+
+bool OpenXRAPI::interaction_profile_add_binding(RID p_interaction_profile, RID p_action, const String p_path) {
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile);
+ ERR_FAIL_NULL_V(ip, false);
+
+ XrActionSuggestedBinding binding;
+
+ Action *action = action_owner.get_or_null(p_action);
+ ERR_FAIL_COND_V(action == nullptr || action->handle == XR_NULL_HANDLE, false);
- bindings.push_back(binding);
+ binding.action = action->handle;
+
+ XrResult result = xrStringToPath(instance, p_path.utf8().get_data(), &binding.binding);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: failed to get path for ", p_path, "! [", get_error_string(result), "]");
+ return false;
}
+ ip->bindings.push_back(binding);
+
+ return true;
+}
+
+bool OpenXRAPI::interaction_profile_suggest_bindings(RID p_interaction_profile) {
+ ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, false);
+
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile);
+ ERR_FAIL_NULL_V(ip, false);
+
const XrInteractionProfileSuggestedBinding suggested_bindings = {
XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING, // type
nullptr, // next
- interaction_profile, // interactionProfile
- uint32_t(bindings.size()), // countSuggestedBindings
- bindings.ptr() // suggestedBindings
+ ip->path, // interactionProfile
+ uint32_t(ip->bindings.size()), // countSuggestedBindings
+ ip->bindings.ptr() // suggestedBindings
};
- result = xrSuggestInteractionProfileBindings(instance, &suggested_bindings);
- if (XR_FAILED(result)) {
- print_line("OpenXR: failed to suggest bindings for ", p_interaction_profile, "! [", get_error_string(result), "]");
+ XrResult result = xrSuggestInteractionProfileBindings(instance, &suggested_bindings);
+ if (result == XR_ERROR_PATH_UNSUPPORTED) {
+ // this is fine, not all runtimes support all devices.
+ print_verbose("OpenXR Interaction profile " + ip->name + " is not supported on this runtime");
+ } else if (XR_FAILED(result)) {
+ print_line("OpenXR: failed to suggest bindings for ", ip->name, "! [", get_error_string(result), "]");
// reporting is enough...
}
+ /* For debugging:
+ print_verbose("Suggested bindings for " + ip->name);
+ for (int i = 0; i < ip->bindings.size(); i++) {
+ uint32_t strlen;
+ char path[XR_MAX_PATH_LENGTH];
+
+ String action_name = action_get_name(get_action_rid(ip->bindings[i].action));
+
+ XrResult result = xrPathToString(instance, ip->bindings[i].binding, XR_MAX_PATH_LENGTH, &strlen, path);
+ if (XR_FAILED(result)) {
+ print_line("OpenXR: failed to retrieve bindings for ", action_name, "! [", get_error_string(result), "]");
+ }
+ print_verbose(" - " + action_name + " => " + String(path));
+ }
+ */
+
return true;
}
+void OpenXRAPI::interaction_profile_free(RID p_interaction_profile) {
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(p_interaction_profile);
+ ERR_FAIL_NULL(ip);
+
+ ip->bindings.clear();
+
+ interaction_profile_owner.free(p_interaction_profile);
+}
+
bool OpenXRAPI::sync_action_sets(const Vector<RID> p_active_sets) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
@@ -1955,12 +2220,12 @@ bool OpenXRAPI::sync_action_sets(const Vector<RID> p_active_sets) {
return true;
}
-bool OpenXRAPI::get_action_bool(RID p_action, RID p_path) {
+bool OpenXRAPI::get_action_bool(RID p_action, RID p_tracker) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
Action *action = action_owner.get_or_null(p_action);
ERR_FAIL_NULL_V(action, false);
- Path *path = xr_path_owner.get_or_null(p_path);
- ERR_FAIL_NULL_V(path, false);
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL_V(tracker, false);
if (!running) {
return false;
@@ -1972,7 +2237,7 @@ bool OpenXRAPI::get_action_bool(RID p_action, RID p_path) {
XR_TYPE_ACTION_STATE_GET_INFO, // type
nullptr, // next
action->handle, // action
- path->path // subactionPath
+ tracker->toplevel_path // subactionPath
};
XrActionStateBoolean result_state;
@@ -1987,12 +2252,12 @@ bool OpenXRAPI::get_action_bool(RID p_action, RID p_path) {
return result_state.isActive && result_state.currentState;
}
-float OpenXRAPI::get_action_float(RID p_action, RID p_path) {
+float OpenXRAPI::get_action_float(RID p_action, RID p_tracker) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, 0.0);
Action *action = action_owner.get_or_null(p_action);
ERR_FAIL_NULL_V(action, 0.0);
- Path *path = xr_path_owner.get_or_null(p_path);
- ERR_FAIL_NULL_V(path, 0.0);
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL_V(tracker, 0.0);
if (!running) {
return 0.0;
@@ -2004,7 +2269,7 @@ float OpenXRAPI::get_action_float(RID p_action, RID p_path) {
XR_TYPE_ACTION_STATE_GET_INFO, // type
nullptr, // next
action->handle, // action
- path->path // subactionPath
+ tracker->toplevel_path // subactionPath
};
XrActionStateFloat result_state;
@@ -2019,12 +2284,12 @@ float OpenXRAPI::get_action_float(RID p_action, RID p_path) {
return result_state.isActive ? result_state.currentState : 0.0;
}
-Vector2 OpenXRAPI::get_action_vector2(RID p_action, RID p_path) {
+Vector2 OpenXRAPI::get_action_vector2(RID p_action, RID p_tracker) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, Vector2());
Action *action = action_owner.get_or_null(p_action);
ERR_FAIL_NULL_V(action, Vector2());
- Path *path = xr_path_owner.get_or_null(p_path);
- ERR_FAIL_NULL_V(path, Vector2());
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL_V(tracker, Vector2());
if (!running) {
return Vector2();
@@ -2036,7 +2301,7 @@ Vector2 OpenXRAPI::get_action_vector2(RID p_action, RID p_path) {
XR_TYPE_ACTION_STATE_GET_INFO, // type
nullptr, // next
action->handle, // action
- path->path // subactionPath
+ tracker->toplevel_path // subactionPath
};
XrActionStateVector2f result_state;
@@ -2051,12 +2316,12 @@ Vector2 OpenXRAPI::get_action_vector2(RID p_action, RID p_path) {
return result_state.isActive ? Vector2(result_state.currentState.x, result_state.currentState.y) : Vector2();
}
-XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_path, Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity) {
+XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_tracker, Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, XRPose::XR_TRACKING_CONFIDENCE_NONE);
Action *action = action_owner.get_or_null(p_action);
ERR_FAIL_NULL_V(action, XRPose::XR_TRACKING_CONFIDENCE_NONE);
- Path *path = xr_path_owner.get_or_null(p_path);
- ERR_FAIL_NULL_V(path, XRPose::XR_TRACKING_CONFIDENCE_NONE);
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL_V(tracker, XRPose::XR_TRACKING_CONFIDENCE_NONE);
if (!running) {
return XRPose::XR_TRACKING_CONFIDENCE_NONE;
@@ -2064,10 +2329,12 @@ XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_path,
ERR_FAIL_COND_V(action->action_type != XR_ACTION_TYPE_POSE_INPUT, XRPose::XR_TRACKING_CONFIDENCE_NONE);
+ // print_verbose("Checking " + action->name + " => " + tracker->name + " (" + itos(tracker->toplevel_path) + ")");
+
uint64_t index = 0xFFFFFFFF;
- uint64_t size = uint64_t(action->toplevel_paths.size());
+ uint64_t size = uint64_t(action->trackers.size());
for (uint64_t i = 0; i < size && index == 0xFFFFFFFF; i++) {
- if (action->toplevel_paths[i].toplevel_path == path->path) {
+ if (action->trackers[i].tracker_rid == p_tracker) {
index = i;
}
}
@@ -2077,14 +2344,19 @@ XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_path,
return XRPose::XR_TRACKING_CONFIDENCE_NONE;
}
- if (action->toplevel_paths[index].space == XR_NULL_HANDLE) {
+ XrTime display_time = get_next_frame_time();
+ if (display_time == 0) {
+ return XRPose::XR_TRACKING_CONFIDENCE_NONE;
+ }
+
+ if (action->trackers[index].space == XR_NULL_HANDLE) {
// if this is a pose we need to define spaces
XrActionSpaceCreateInfo action_space_info = {
XR_TYPE_ACTION_SPACE_CREATE_INFO, // type
nullptr, // next
action->handle, // action
- action->toplevel_paths[index].toplevel_path, // subactionPath
+ tracker->toplevel_path, // subactionPath
{
{ 0.0, 0.0, 0.0, 1.0 }, // orientation
{ 0.0, 0.0, 0.0 } // position
@@ -2098,11 +2370,9 @@ XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_path,
return XRPose::XR_TRACKING_CONFIDENCE_NONE;
}
- action->toplevel_paths.ptrw()[index].space = space;
+ action->trackers.ptrw()[index].space = space;
}
- XrTime display_time = get_next_frame_time();
-
XrSpaceVelocity velocity = {
XR_TYPE_SPACE_VELOCITY, // type
nullptr, // next
@@ -2121,7 +2391,7 @@ XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_path,
} // pose
};
- XrResult result = xrLocateSpace(action->toplevel_paths[index].space, play_space, display_time, &location);
+ XrResult result = xrLocateSpace(action->trackers[index].space, play_space, display_time, &location);
if (XR_FAILED(result)) {
print_line("OpenXR: failed to locate space! [", get_error_string(result), "]");
return XRPose::XR_TRACKING_CONFIDENCE_NONE;
@@ -2133,12 +2403,12 @@ XRPose::TrackingConfidence OpenXRAPI::get_action_pose(RID p_action, RID p_path,
return confidence;
}
-bool OpenXRAPI::trigger_haptic_pulse(RID p_action, RID p_path, float p_frequency, float p_amplitude, XrDuration p_duration_ns) {
+bool OpenXRAPI::trigger_haptic_pulse(RID p_action, RID p_tracker, float p_frequency, float p_amplitude, XrDuration p_duration_ns) {
ERR_FAIL_COND_V(session == XR_NULL_HANDLE, false);
Action *action = action_owner.get_or_null(p_action);
ERR_FAIL_NULL_V(action, false);
- Path *path = xr_path_owner.get_or_null(p_path);
- ERR_FAIL_NULL_V(path, false);
+ Tracker *tracker = tracker_owner.get_or_null(p_tracker);
+ ERR_FAIL_NULL_V(tracker, false);
if (!running) {
return false;
@@ -2150,7 +2420,7 @@ bool OpenXRAPI::trigger_haptic_pulse(RID p_action, RID p_path, float p_frequency
XR_TYPE_HAPTIC_ACTION_INFO, // type
nullptr, // next
action->handle, // action
- path->path // subactionPath
+ tracker->toplevel_path // subactionPath
};
XrHapticVibration vibration = {
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index 33b503543a..e20826c849 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -55,12 +55,16 @@
// forward declarations, we don't want to include these fully
class OpenXRVulkanExtension;
+class OpenXRInterface;
class OpenXRAPI {
private:
// our singleton
static OpenXRAPI *singleton;
+ // linked XR interface
+ OpenXRInterface *xr_interface = nullptr;
+
// layers
uint32_t num_layer_properties = 0;
XrApiLayerProperties *layer_properties = nullptr;
@@ -148,29 +152,45 @@ private:
bool release_image(XrSwapchain p_swapchain);
// action map
- struct Path {
- XrPath path;
+ struct Tracker { // Trackers represent tracked physical objects such as controllers, pucks, etc.
+ String name; // Name for this tracker (i.e. "/user/hand/left")
+ XrPath toplevel_path; // OpenXR XrPath for this tracker
+ RID active_profile_rid; // RID of the active profile for this tracker
};
- RID_Owner<Path, true> xr_path_owner;
+ RID_Owner<Tracker, true> tracker_owner;
+ RID get_tracker_rid(XrPath p_path);
- struct ActionSet {
- bool is_attached;
- XrActionSet handle;
+ struct ActionSet { // Action sets define a set of actions that can be enabled together
+ String name; // Name for this action set (i.e. "godot_action_set")
+ bool is_attached; // If true our action set has been attached to the session and can no longer be modified
+ XrActionSet handle; // OpenXR handle for this action set
};
RID_Owner<ActionSet, true> action_set_owner;
- struct PathWithSpace {
- XrPath toplevel_path;
- XrSpace space;
- bool was_location_valid;
+ struct ActionTracker { // Links and action to a tracker
+ RID tracker_rid; // RID of the tracker
+ XrSpace space; // Optional space for pose actions
+ bool was_location_valid; // If true the last position we obtained was valid
};
- struct Action {
- XrActionType action_type;
- Vector<PathWithSpace> toplevel_paths;
- XrAction handle;
+ struct Action { // Actions define the inputs and outputs in OpenXR
+ RID action_set_rid; // RID of the action set this action belongs to
+ String name; // Name for this action (i.e. "aim_pose")
+ XrActionType action_type; // Type of action (bool, float, etc.)
+ Vector<ActionTracker> trackers; // The trackers this action can be used with
+ XrAction handle; // OpenXR handle for this action
};
RID_Owner<Action, true> action_owner;
+ RID get_action_rid(XrAction p_action);
+
+ struct InteractionProfile { // Interaction profiles define suggested bindings between the physical inputs on controller types and our actions
+ String name; // Name of the interaction profile (i.e. "/interaction_profiles/valve/index_controller")
+ XrPath path; // OpenXR path for this profile
+ Vector<XrActionSuggestedBinding> bindings; // OpenXR action bindings
+ };
+ RID_Owner<InteractionProfile, true> interaction_profile_owner;
+ RID get_interaction_profile_rid(XrPath p_path);
+ XrPath get_interaction_profile_path(RID p_interaction_profile);
// state changes
bool poll_events();
@@ -209,6 +229,7 @@ public:
String get_error_string(XrResult result);
String get_swapchain_format_name(int64_t p_swapchain_format) const;
+ void set_xr_interface(OpenXRInterface *p_xr_interface);
void register_extension_wrapper(OpenXRExtensionWrapper *p_extension_wrapper);
bool is_initialized();
@@ -233,26 +254,34 @@ public:
// action map
String get_default_action_map_resource_name();
- RID path_create(const String p_name);
- void path_free(RID p_path);
+
+ RID tracker_create(const String p_name);
+ String tracker_get_name(RID p_tracker);
+ void tracker_check_profile(RID p_tracker, XrSession p_session = XR_NULL_HANDLE);
+ void tracker_free(RID p_tracker);
+
RID action_set_create(const String p_name, const String p_localized_name, const int p_priority);
+ String action_set_get_name(RID p_action_set);
bool action_set_attach(RID p_action_set);
void action_set_free(RID p_action_set);
- RID action_create(RID p_action_set, const String p_name, const String p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<RID> &p_toplevel_paths);
+
+ RID action_create(RID p_action_set, const String p_name, const String p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<RID> &p_trackers);
+ String action_get_name(RID p_action);
void action_free(RID p_action);
- struct Binding {
- RID action;
- String path;
- };
- bool suggest_bindings(const String p_interaction_profile, const Vector<Binding> p_bindings);
+ RID interaction_profile_create(const String p_name);
+ String interaction_profile_get_name(RID p_interaction_profile);
+ void interaction_profile_clear_bindings(RID p_interaction_profile);
+ bool interaction_profile_add_binding(RID p_interaction_profile, RID p_action, const String p_path);
+ bool interaction_profile_suggest_bindings(RID p_interaction_profile);
+ void interaction_profile_free(RID p_interaction_profile);
bool sync_action_sets(const Vector<RID> p_active_sets);
- bool get_action_bool(RID p_action, RID p_path);
- float get_action_float(RID p_action, RID p_path);
- Vector2 get_action_vector2(RID p_action, RID p_path);
- XRPose::TrackingConfidence get_action_pose(RID p_action, RID p_path, Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
- bool trigger_haptic_pulse(RID p_action, RID p_path, float p_frequency, float p_amplitude, XrDuration p_duration_ns);
+ bool get_action_bool(RID p_action, RID p_tracker);
+ float get_action_float(RID p_action, RID p_tracker);
+ Vector2 get_action_vector2(RID p_action, RID p_tracker);
+ XRPose::TrackingConfidence get_action_pose(RID p_action, RID p_tracker, Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
+ bool trigger_haptic_pulse(RID p_action, RID p_tracker, float p_frequency, float p_amplitude, XrDuration p_duration_ns);
OpenXRAPI();
~OpenXRAPI();
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 394f634687..39f9153f0d 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -35,7 +35,12 @@
#include "servers/rendering/rendering_server_globals.h"
void OpenXRInterface::_bind_methods() {
- // todo
+ // lifecycle signals
+ ADD_SIGNAL(MethodInfo("session_begun"));
+ ADD_SIGNAL(MethodInfo("session_stopping"));
+ ADD_SIGNAL(MethodInfo("session_focussed"));
+ ADD_SIGNAL(MethodInfo("session_visible"));
+ ADD_SIGNAL(MethodInfo("pose_recentered"));
}
StringName OpenXRInterface::get_name() const {
@@ -46,6 +51,18 @@ uint32_t OpenXRInterface::get_capabilities() const {
return XRInterface::XR_VR + XRInterface::XR_STEREO;
};
+PackedStringArray OpenXRInterface::get_suggested_tracker_names() const {
+ // These are hardcoded in OpenXR, note that they will only be available if added to our action map
+
+ PackedStringArray arr = {
+ "left_hand", // /user/hand/left is mapped to our defaults
+ "right_hand", // /user/hand/right is mapped to our defaults
+ "/user/treadmill"
+ };
+
+ return arr;
+}
+
XRInterface::TrackingStatus OpenXRInterface::get_tracking_status() const {
return tracking_state;
}
@@ -64,8 +81,9 @@ void OpenXRInterface::_load_action_map() {
// This allow us to process the relevant actions each frame.
// just in case clean up
- free_action_sets();
free_trackers();
+ free_interaction_profiles();
+ free_action_sets();
Ref<OpenXRActionMap> action_map;
if (Engine::get_singleton()->is_editor_hint()) {
@@ -95,7 +113,7 @@ void OpenXRInterface::_load_action_map() {
// process our action map
if (action_map.is_valid()) {
- Map<Ref<OpenXRAction>, RID> action_rids;
+ Map<Ref<OpenXRAction>, Action *> xr_actions;
Array action_sets = action_map->get_action_sets();
for (int i = 0; i < action_sets.size(); i++) {
@@ -112,18 +130,16 @@ void OpenXRInterface::_load_action_map() {
Ref<OpenXRAction> xr_action = actions[j];
PackedStringArray toplevel_paths = xr_action->get_toplevel_paths();
- Vector<RID> toplevel_rids;
Vector<Tracker *> trackers;
for (int k = 0; k < toplevel_paths.size(); k++) {
- Tracker *tracker = get_tracker(toplevel_paths[k]);
+ Tracker *tracker = find_tracker(toplevel_paths[k], true);
if (tracker) {
- toplevel_rids.push_back(tracker->path_rid);
trackers.push_back(tracker);
}
}
- Action *action = create_action(action_set, xr_action->get_name(), xr_action->get_localized_name(), xr_action->get_action_type(), toplevel_rids);
+ Action *action = create_action(action_set, xr_action->get_name(), xr_action->get_localized_name(), xr_action->get_action_type(), trackers);
if (action) {
// we link our actions back to our trackers so we know which actions to check when we're processing our trackers
for (int t = 0; t < trackers.size(); t++) {
@@ -131,7 +147,7 @@ void OpenXRInterface::_load_action_map() {
}
// add this to our map for creating our interaction profiles
- action_rids[xr_action] = action->action_rid;
+ xr_actions[xr_action] = action;
}
}
}
@@ -139,30 +155,38 @@ void OpenXRInterface::_load_action_map() {
// now do our suggestions
Array interaction_profiles = action_map->get_interaction_profiles();
for (int i = 0; i < interaction_profiles.size(); i++) {
- Vector<OpenXRAPI::Binding> bindings;
Ref<OpenXRInteractionProfile> xr_interaction_profile = interaction_profiles[i];
+ // Note, we can only have one entry per interaction profile so if it already exists we clear it out
+ RID ip = openxr_api->interaction_profile_create(xr_interaction_profile->get_interaction_profile_path());
+ openxr_api->interaction_profile_clear_bindings(ip);
+
Array xr_bindings = xr_interaction_profile->get_bindings();
for (int j = 0; j < xr_bindings.size(); j++) {
Ref<OpenXRIPBinding> xr_binding = xr_bindings[j];
Ref<OpenXRAction> xr_action = xr_binding->get_action();
- OpenXRAPI::Binding binding;
- if (action_rids.has(xr_action)) {
- binding.action = action_rids[xr_action];
+ Action *action = nullptr;
+ if (xr_actions.has(xr_action)) {
+ action = xr_actions[xr_action];
} else {
print_line("Action ", xr_action->get_name(), " isn't part of an action set!");
continue;
}
- PackedStringArray xr_paths = xr_binding->get_paths();
- for (int k = 0; k < xr_paths.size(); k++) {
- binding.path = xr_paths[k];
- bindings.push_back(binding);
+ PackedStringArray paths = xr_binding->get_paths();
+ for (int k = 0; k < paths.size(); k++) {
+ openxr_api->interaction_profile_add_binding(ip, action->action_rid, paths[k]);
}
}
- openxr_api->suggest_bindings(xr_interaction_profile->get_interaction_profile_path(), bindings);
+ // Now submit our suggestions
+ openxr_api->interaction_profile_suggest_bindings(ip);
+
+ // And record it in our array so we can clean it up later on
+ if (interaction_profiles.has(ip)) {
+ interaction_profiles.push_back(ip);
+ }
}
}
}
@@ -193,15 +217,16 @@ void OpenXRInterface::free_action_sets() {
for (int i = 0; i < action_sets.size(); i++) {
ActionSet *action_set = action_sets[i];
- openxr_api->path_free(action_set->action_set_rid);
free_actions(action_set);
+ openxr_api->action_set_free(action_set->action_set_rid);
+
memfree(action_set);
}
action_sets.clear();
}
-OpenXRInterface::Action *OpenXRInterface::create_action(ActionSet *p_action_set, const String &p_action_name, const String &p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<RID> p_toplevel_paths) {
+OpenXRInterface::Action *OpenXRInterface::create_action(ActionSet *p_action_set, const String &p_action_name, const String &p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<Tracker *> p_trackers) {
ERR_FAIL_NULL_V(openxr_api, nullptr);
for (int i = 0; i < p_action_set->actions.size(); i++) {
@@ -211,10 +236,31 @@ OpenXRInterface::Action *OpenXRInterface::create_action(ActionSet *p_action_set,
}
}
+ Vector<RID> tracker_rids;
+ for (int i = 0; i < p_trackers.size(); i++) {
+ tracker_rids.push_back(p_trackers[i]->tracker_rid);
+ }
+
Action *action = memnew(Action);
- action->action_name = p_action_name;
+ if (p_action_type == OpenXRAction::OPENXR_ACTION_POSE) {
+ // We can't have dual action names in OpenXR hence we added _pose,
+ // but default, aim and grip and default pose action names in Godot so rename them on the tracker.
+ // NOTE need to decide on whether we should keep the naming convention or rename it on Godots side
+ if (p_action_name == "default_pose") {
+ action->action_name = "default";
+ } else if (p_action_name == "aim_pose") {
+ action->action_name = "aim";
+ } else if (p_action_name == "grip_pose") {
+ action->action_name = "grip";
+ } else {
+ action->action_name = p_action_name;
+ }
+ } else {
+ action->action_name = p_action_name;
+ }
+
action->action_type = p_action_type;
- action->action_rid = openxr_api->action_create(p_action_set->action_set_rid, p_action_name, p_localized_name, p_action_type, p_toplevel_paths);
+ action->action_rid = openxr_api->action_create(p_action_set->action_set_rid, p_action_name, p_localized_name, p_action_type, tracker_rids);
p_action_set->actions.push_back(action);
return action;
@@ -248,7 +294,7 @@ void OpenXRInterface::free_actions(ActionSet *p_action_set) {
p_action_set->actions.clear();
}
-OpenXRInterface::Tracker *OpenXRInterface::get_tracker(const String &p_path_name) {
+OpenXRInterface::Tracker *OpenXRInterface::find_tracker(const String &p_tracker_name, bool p_create) {
XRServer *xr_server = XRServer::get_singleton();
ERR_FAIL_NULL_V(xr_server, nullptr);
ERR_FAIL_NULL_V(openxr_api, nullptr);
@@ -256,52 +302,72 @@ OpenXRInterface::Tracker *OpenXRInterface::get_tracker(const String &p_path_name
Tracker *tracker = nullptr;
for (int i = 0; i < trackers.size(); i++) {
tracker = trackers[i];
- if (tracker->path_name == p_path_name) {
+ if (tracker->tracker_name == p_tracker_name) {
return tracker;
}
}
+ if (!p_create) {
+ return nullptr;
+ }
+
+ // Create our RID
+ RID tracker_rid = openxr_api->tracker_create(p_tracker_name);
+ ERR_FAIL_COND_V(tracker_rid.is_null(), nullptr);
+
// create our positional tracker
Ref<XRPositionalTracker> positional_tracker;
positional_tracker.instantiate();
// We have standardised some names to make things nicer to the user so lets recognise the toplevel paths related to these.
- if (p_path_name == "/user/hand/left") {
+ if (p_tracker_name == "/user/hand/left") {
positional_tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER);
positional_tracker->set_tracker_name("left_hand");
positional_tracker->set_tracker_desc("Left hand controller");
positional_tracker->set_tracker_hand(XRPositionalTracker::TRACKER_HAND_LEFT);
- } else if (p_path_name == "/user/hand/right") {
+ } else if (p_tracker_name == "/user/hand/right") {
positional_tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER);
positional_tracker->set_tracker_name("right_hand");
positional_tracker->set_tracker_desc("Right hand controller");
positional_tracker->set_tracker_hand(XRPositionalTracker::TRACKER_HAND_RIGHT);
} else {
positional_tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER);
- positional_tracker->set_tracker_name(p_path_name);
- positional_tracker->set_tracker_desc(p_path_name);
+ positional_tracker->set_tracker_name(p_tracker_name);
+ positional_tracker->set_tracker_desc(p_tracker_name);
}
+ positional_tracker->set_tracker_profile(INTERACTION_PROFILE_NONE);
xr_server->add_tracker(positional_tracker);
// create a new entry
tracker = memnew(Tracker);
- tracker->path_name = p_path_name;
- tracker->path_rid = openxr_api->path_create(p_path_name);
+ tracker->tracker_name = p_tracker_name;
+ tracker->tracker_rid = tracker_rid;
tracker->positional_tracker = positional_tracker;
+ tracker->interaction_profile = RID();
trackers.push_back(tracker);
return tracker;
}
-OpenXRInterface::Tracker *OpenXRInterface::find_tracker(const String &p_positional_tracker_name) {
- for (int i = 0; i < trackers.size(); i++) {
- Tracker *tracker = trackers[i];
- if (tracker->positional_tracker.is_valid() && tracker->positional_tracker->get_tracker_name() == p_positional_tracker_name) {
- return tracker;
+void OpenXRInterface::tracker_profile_changed(RID p_tracker, RID p_interaction_profile) {
+ Tracker *tracker = nullptr;
+ for (int i = 0; i < trackers.size() && tracker == nullptr; i++) {
+ if (trackers[i]->tracker_rid == p_tracker) {
+ tracker = trackers[i];
}
}
+ ERR_FAIL_NULL(tracker);
- return nullptr;
+ tracker->interaction_profile = p_interaction_profile;
+
+ if (p_interaction_profile.is_null()) {
+ print_verbose("OpenXR: Interaction profile for " + tracker->tracker_name + " changed to " + INTERACTION_PROFILE_NONE);
+ tracker->positional_tracker->set_tracker_profile(INTERACTION_PROFILE_NONE);
+ } else {
+ String name = openxr_api->interaction_profile_get_name(p_interaction_profile);
+ print_verbose("OpenXR: Interaction profile for " + tracker->tracker_name + " changed to " + name);
+ tracker->positional_tracker->set_tracker_profile(name);
+ }
}
void OpenXRInterface::link_action_to_tracker(Tracker *p_tracker, Action *p_action) {
@@ -314,40 +380,43 @@ void OpenXRInterface::handle_tracker(Tracker *p_tracker) {
ERR_FAIL_NULL(openxr_api);
ERR_FAIL_COND(p_tracker->positional_tracker.is_null());
- // handle all the actions
+ // Note, which actions are actually bound to inputs are handled by our interaction profiles however interaction
+ // profiles are suggested bindings for controller types we know about. OpenXR runtimes can stray away from these
+ // and rebind them or even offer bindings to controllers that are not known to us.
+
+ // We don't really have a consistant way to detect whether a controller is active however as long as it is
+ // unbound it seems to be unavailable, so far unknown controller seem to mimic one of the profiles we've
+ // supplied.
+ if (p_tracker->interaction_profile.is_null()) {
+ return;
+ }
+
+ // We check all actions that are related to our tracker.
for (int i = 0; i < p_tracker->actions.size(); i++) {
Action *action = p_tracker->actions[i];
switch (action->action_type) {
case OpenXRAction::OPENXR_ACTION_BOOL: {
- bool pressed = openxr_api->get_action_bool(action->action_rid, p_tracker->path_rid);
+ bool pressed = openxr_api->get_action_bool(action->action_rid, p_tracker->tracker_rid);
p_tracker->positional_tracker->set_input(action->action_name, Variant(pressed));
} break;
case OpenXRAction::OPENXR_ACTION_FLOAT: {
- real_t value = openxr_api->get_action_float(action->action_rid, p_tracker->path_rid);
+ real_t value = openxr_api->get_action_float(action->action_rid, p_tracker->tracker_rid);
p_tracker->positional_tracker->set_input(action->action_name, Variant(value));
} break;
case OpenXRAction::OPENXR_ACTION_VECTOR2: {
- Vector2 value = openxr_api->get_action_vector2(action->action_rid, p_tracker->path_rid);
+ Vector2 value = openxr_api->get_action_vector2(action->action_rid, p_tracker->tracker_rid);
p_tracker->positional_tracker->set_input(action->action_name, Variant(value));
} break;
case OpenXRAction::OPENXR_ACTION_POSE: {
Transform3D transform;
Vector3 linear, angular;
- XRPose::TrackingConfidence confidence = openxr_api->get_action_pose(action->action_rid, p_tracker->path_rid, transform, linear, angular);
+
+ XRPose::TrackingConfidence confidence = openxr_api->get_action_pose(action->action_rid, p_tracker->tracker_rid, transform, linear, angular);
+
if (confidence != XRPose::XR_TRACKING_CONFIDENCE_NONE) {
- String name;
- // We can't have dual action names in OpenXR hence we added _pose, but default, aim and grip and default pose action names in Godot so rename them on the tracker.
- // NOTE need to decide on whether we should keep the naming convention or rename it on Godots side
- if (action->action_name == "default_pose") {
- name = "default";
- } else if (action->action_name == "aim_pose") {
- name = "aim";
- } else if (action->action_name == "grip_pose") {
- name = "grip";
- } else {
- name = action->action_name;
- }
- p_tracker->positional_tracker->set_pose(name, transform, linear, angular, confidence);
+ p_tracker->positional_tracker->set_pose(action->action_name, transform, linear, angular, confidence);
+ } else {
+ p_tracker->positional_tracker->invalidate_pose(action->action_name);
}
} break;
default: {
@@ -368,7 +437,7 @@ void OpenXRInterface::trigger_haptic_pulse(const String &p_action_name, const St
XrDuration duration = XrDuration(p_duration_sec * 1000000000.0); // seconds -> nanoseconds
- openxr_api->trigger_haptic_pulse(action->action_rid, tracker->path_rid, p_frequency, p_amplitude, duration);
+ openxr_api->trigger_haptic_pulse(action->action_rid, tracker->tracker_rid, p_frequency, p_amplitude, duration);
}
void OpenXRInterface::free_trackers() {
@@ -379,7 +448,7 @@ void OpenXRInterface::free_trackers() {
for (int i = 0; i < trackers.size(); i++) {
Tracker *tracker = trackers[i];
- openxr_api->path_free(tracker->path_rid);
+ openxr_api->tracker_free(tracker->tracker_rid);
xr_server->remove_tracker(tracker->positional_tracker);
tracker->positional_tracker.unref();
@@ -388,6 +457,15 @@ void OpenXRInterface::free_trackers() {
trackers.clear();
}
+void OpenXRInterface::free_interaction_profiles() {
+ ERR_FAIL_NULL(openxr_api);
+
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ openxr_api->interaction_profile_free(interaction_profiles[i]);
+ }
+ interaction_profiles.clear();
+}
+
bool OpenXRInterface::initialise_on_startup() const {
if (openxr_api == nullptr) {
return false;
@@ -447,14 +525,14 @@ void OpenXRInterface::uninitialize() {
// end the session if we need to?
// cleanup stuff
- free_action_sets();
free_trackers();
+ free_interaction_profiles();
+ free_action_sets();
XRServer *xr_server = XRServer::get_singleton();
if (xr_server) {
if (head.is_valid()) {
xr_server->remove_tracker(head);
-
head.unref();
}
}
@@ -649,8 +727,31 @@ void OpenXRInterface::end_frame() {
}
}
+void OpenXRInterface::on_state_ready() {
+ emit_signal(SNAME("session_begun"));
+}
+
+void OpenXRInterface::on_state_visible() {
+ emit_signal(SNAME("session_visible"));
+}
+
+void OpenXRInterface::on_state_focused() {
+ emit_signal(SNAME("session_focussed"));
+}
+
+void OpenXRInterface::on_state_stopping() {
+ emit_signal(SNAME("session_stopping"));
+}
+
+void OpenXRInterface::on_pose_recentered() {
+ emit_signal(SNAME("pose_recentered"));
+}
+
OpenXRInterface::OpenXRInterface() {
openxr_api = OpenXRAPI::get_singleton();
+ if (openxr_api) {
+ openxr_api->set_xr_interface(this);
+ }
// while we don't have head tracking, don't put the headset on the floor...
_set_default_pos(head_transform, 1.0, 0);
@@ -659,5 +760,12 @@ OpenXRInterface::OpenXRInterface() {
}
OpenXRInterface::~OpenXRInterface() {
- openxr_api = nullptr;
+ if (is_initialized()) {
+ uninitialize();
+ }
+
+ if (openxr_api) {
+ openxr_api->set_xr_interface(nullptr);
+ openxr_api = nullptr;
+ }
}
diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h
index ede7d481d2..421838e445 100644
--- a/modules/openxr/openxr_interface.h
+++ b/modules/openxr/openxr_interface.h
@@ -37,6 +37,9 @@
#include "action_map/openxr_action_map.h"
#include "openxr_api.h"
+// declare some default strings
+#define INTERACTION_PROFILE_NONE "/interaction_profiles/none"
+
class OpenXRInterface : public XRInterface {
GDCLASS(OpenXRInterface, XRInterface);
@@ -54,40 +57,43 @@ private:
void _load_action_map();
- struct Action {
- String action_name;
- OpenXRAction::ActionType action_type;
- RID action_rid;
+ struct Action { // An action we've registered with OpenXR
+ String action_name; // Name of our action as presented to Godot (can be altered from the action map)
+ OpenXRAction::ActionType action_type; // The action type of this action
+ RID action_rid; // RID of the action registered with our OpenXR API
};
- struct ActionSet {
- String action_set_name;
- bool is_active;
- RID action_set_rid;
- Vector<Action *> actions;
+ struct ActionSet { // An action set we've registered with OpenXR
+ String action_set_name; // Name of our action set
+ bool is_active; // If true this action set is active and we will sync it
+ Vector<Action *> actions; // List of actions in this action set
+ RID action_set_rid; // RID of the action registered with our OpenXR API
};
- struct Tracker {
- String path_name;
- RID path_rid;
- Ref<XRPositionalTracker> positional_tracker;
- Vector<Action *> actions;
+ struct Tracker { // A tracker we've registered with OpenXR
+ String tracker_name; // Name of our tracker (can be altered from the action map)
+ Vector<Action *> actions; // Actions related to this tracker
+ Ref<XRPositionalTracker> positional_tracker; // Our positional tracker object that holds our tracker state
+ RID tracker_rid; // RID of the tracker registered with our OpenXR API
+ RID interaction_profile; // RID of the interaction profile bound to this tracker (can be null)
};
Vector<ActionSet *> action_sets;
+ Vector<RID> interaction_profiles;
Vector<Tracker *> trackers;
ActionSet *create_action_set(const String &p_action_set_name, const String &p_localized_name, const int p_priority);
void free_action_sets();
- Action *create_action(ActionSet *p_action_set, const String &p_action_name, const String &p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<RID> p_toplevel_paths);
+ Action *create_action(ActionSet *p_action_set, const String &p_action_name, const String &p_localized_name, OpenXRAction::ActionType p_action_type, const Vector<Tracker *> p_trackers);
Action *find_action(const String &p_action_name);
void free_actions(ActionSet *p_action_set);
- Tracker *get_tracker(const String &p_path_name);
- Tracker *find_tracker(const String &p_positional_tracker_name);
+ Tracker *find_tracker(const String &p_tracker_name, bool p_create = false);
void link_action_to_tracker(Tracker *p_tracker, Action *p_action);
void handle_tracker(Tracker *p_tracker);
void free_trackers();
+ void free_interaction_profiles();
+
void _set_default_pos(Transform3D &p_transform, double p_world_scale, uint64_t p_eye);
protected:
@@ -97,6 +103,7 @@ public:
virtual StringName get_name() const override;
virtual uint32_t get_capabilities() const override;
+ virtual PackedStringArray get_suggested_tracker_names() const override;
virtual TrackingStatus get_tracking_status() const override;
bool initialise_on_startup() const;
@@ -122,6 +129,13 @@ public:
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void end_frame() override;
+ void on_state_ready();
+ void on_state_visible();
+ void on_state_focused();
+ void on_state_stopping();
+ void on_pose_recentered();
+ void tracker_profile_changed(RID p_tracker, RID p_interaction_profile);
+
OpenXRInterface();
~OpenXRInterface();
};
diff --git a/modules/openxr/openxr_util.cpp b/modules/openxr/openxr_util.cpp
index e515336daa..230b10c5f1 100644
--- a/modules/openxr/openxr_util.cpp
+++ b/modules/openxr/openxr_util.cpp
@@ -278,6 +278,20 @@ String OpenXRUtil::get_session_state_name(XrSessionState p_session_state) {
}
}
+String OpenXRUtil::get_action_type_name(XrActionType p_action_type) {
+ switch (p_action_type) {
+ ENUM_TO_STRING_CASE(XR_ACTION_TYPE_BOOLEAN_INPUT)
+ ENUM_TO_STRING_CASE(XR_ACTION_TYPE_FLOAT_INPUT)
+ ENUM_TO_STRING_CASE(XR_ACTION_TYPE_VECTOR2F_INPUT)
+ ENUM_TO_STRING_CASE(XR_ACTION_TYPE_POSE_INPUT)
+ ENUM_TO_STRING_CASE(XR_ACTION_TYPE_VIBRATION_OUTPUT)
+ ENUM_TO_STRING_CASE(XR_ACTION_TYPE_MAX_ENUM)
+ default: {
+ return String("Action type ") + String::num_int64(int64_t(p_action_type));
+ } break;
+ }
+}
+
String OpenXRUtil::make_xr_version_string(XrVersion p_version) {
String version;
diff --git a/modules/openxr/openxr_util.h b/modules/openxr/openxr_util.h
index 1261268376..4371b74d2f 100644
--- a/modules/openxr/openxr_util.h
+++ b/modules/openxr/openxr_util.h
@@ -40,6 +40,7 @@ public:
static String get_reference_space_name(XrReferenceSpaceType p_reference_space);
static String get_structure_type_name(XrStructureType p_structure_type);
static String get_session_state_name(XrSessionState p_session_state);
+ static String get_action_type_name(XrActionType p_action_type);
static String make_xr_version_string(XrVersion p_version);
};
diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp
index 86ff368619..7a74c8c089 100644
--- a/modules/openxr/register_types.cpp
+++ b/modules/openxr/register_types.cpp
@@ -75,9 +75,18 @@ void register_openxr_types() {
void unregister_openxr_types() {
if (openxr_interface.is_valid()) {
+ // uninitialise just in case
+ if (openxr_interface->is_initialized()) {
+ openxr_interface->uninitialize();
+ }
+
// unregister our interface from the XR server
- if (XRServer::get_singleton()) {
- XRServer::get_singleton()->remove_interface(openxr_interface);
+ XRServer *xr_server = XRServer::get_singleton();
+ if (xr_server) {
+ if (xr_server->get_primary_interface() == openxr_interface) {
+ xr_server->set_primary_interface(Ref<XRInterface>());
+ }
+ xr_server->remove_interface(openxr_interface);
}
// and release
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 1b4512dc60..7fd9cd42ed 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -704,7 +704,7 @@ String TextServerAdvanced::tag_to_name(int32_t p_tag) const {
/* Font Glyph Rendering */
/*************************************************************************/
-_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const {
+_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret;
ret.index = -1;
@@ -769,8 +769,11 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_
}
texsize = next_power_of_2(texsize);
-
- texsize = MIN(texsize, 4096);
+ if (p_msdf) {
+ texsize = MIN(texsize, 2048);
+ } else {
+ texsize = MIN(texsize, 1024);
+ }
FontTexture tex;
tex.texture_w = texsize;
@@ -935,10 +938,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
FontTexture &tex = p_data->textures.write[tex_pos.index];
@@ -1013,13 +1016,13 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
// Fit character in char texture.
@@ -1155,6 +1158,16 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d
}
}
+ if (p_font_data->embolden != 0.f) {
+ FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64).
+ FT_Outline_Embolden(&fd->face->glyph->outline, strength);
+ }
+
+ if (p_font_data->transform != Transform2D()) {
+ FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
+ FT_Outline_Transform(&fd->face->glyph->outline, &mat);
+ }
+
if (!outline) {
if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
@@ -1874,6 +1887,44 @@ TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positionin
return fd->subpixel_positioning;
}
+void TextServerAdvanced::font_set_embolden(RID p_font_rid, float p_strength) {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->embolden != p_strength) {
+ _font_clear_cache(fd);
+ fd->embolden = p_strength;
+ }
+}
+
+float TextServerAdvanced::font_get_embolden(RID p_font_rid) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0.f);
+
+ MutexLock lock(fd->mutex);
+ return fd->embolden;
+}
+
+void TextServerAdvanced::font_set_transform(RID p_font_rid, Transform2D p_transform) {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->transform != p_transform) {
+ _font_clear_cache(fd);
+ fd->transform = p_transform;
+ }
+}
+
+Transform2D TextServerAdvanced::font_get_transform(RID p_font_rid) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, Transform2D());
+
+ MutexLock lock(fd->mutex);
+ return fd->transform;
+}
+
void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -2275,6 +2326,20 @@ void TextServerAdvanced::font_remove_glyph(RID p_font_rid, const Vector2i &p_siz
fd->cache[size]->glyph_map.erase(p_glyph);
}
+float TextServerAdvanced::_get_extra_advance(RID p_font_rid, int p_font_size) const {
+ const FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0.0);
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size(fd, p_font_size);
+
+ if (fd->embolden != 0.0) {
+ return fd->embolden * float(size.x) / 64.0;
+ } else {
+ return 0.0;
+ }
+}
+
Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Vector2());
@@ -2289,12 +2354,17 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, i
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
+ Vector2 ea;
+ if (fd->embolden != 0.0) {
+ ea.x = fd->embolden * float(size.x) / 64.0;
+ }
+
if (fd->msdf) {
- return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size;
+ return (gl[p_glyph].advance + ea) * (float)p_size / (float)fd->msdf_source_size;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
- return gl[p_glyph].advance.round();
+ return (gl[p_glyph].advance + ea).round();
} else {
- return gl[p_glyph].advance;
+ return gl[p_glyph].advance + ea;
}
}
@@ -4420,9 +4490,9 @@ Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char
float scale = font_get_scale(p_font, p_font_size);
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
if (subpos) {
- gl.advance = glyph_pos[0].x_advance / (64.0 / scale);
+ gl.advance = glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size);
} else {
- gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale));
+ gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale) + _get_extra_advance(p_font, p_font_size));
}
} else {
gl.advance = -Math::round(glyph_pos[0].y_advance / (64.0 / scale));
@@ -4499,6 +4569,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
float scale = font_get_scale(f, fs);
float sp_sp = font_get_spacing(f, fs, SPACING_SPACE);
float sp_gl = font_get_spacing(f, fs, SPACING_GLYPH);
+ float ea = _get_extra_advance(f, fs);
bool subpos = (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_HALF) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE);
ERR_FAIL_COND(hb_font == nullptr);
@@ -4577,9 +4648,9 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star
if (gl.index != 0) {
if (p_sd->orientation == ORIENTATION_HORIZONTAL) {
if (subpos) {
- gl.advance = glyph_pos[i].x_advance / (64.0 / scale);
+ gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea;
} else {
- gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale));
+ gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale) + ea);
}
} else {
gl.advance = -Math::round(glyph_pos[i].y_advance / (64.0 / scale));
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 7841a15cd3..e5958fc162 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -177,6 +177,8 @@ class TextServerAdvanced : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates;
float oversampling = 0.f;
+ float embolden = 0.f;
+ Transform2D transform;
uint32_t style_flags = 0;
String font_name;
@@ -208,7 +210,7 @@ class TextServerAdvanced : public TextServer {
}
};
- _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const;
+ _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
@@ -240,6 +242,8 @@ class TextServerAdvanced : public TextServer {
}
}
+ _FORCE_INLINE_ float _get_extra_advance(RID p_font_rid, int p_font_size) const;
+
// Shaped text cache data.
struct ShapedTextDataAdvanced : public ShapedTextData {
@@ -383,6 +387,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
+ virtual float font_get_embolden(RID p_font_rid) const override;
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
+ virtual Transform2D font_get_transform(RID p_font_rid) const override;
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index e6f9bcf131..0d7a9d0db8 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -155,7 +155,7 @@ String TextServerFallback::tag_to_name(int32_t p_tag) const {
/* Font Glyph Rendering */
/*************************************************************************/
-_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const {
+_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const {
FontTexturePosition ret;
ret.index = -1;
@@ -221,7 +221,11 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_
texsize = next_power_of_2(texsize);
- texsize = MIN(texsize, 4096);
+ if (p_msdf) {
+ texsize = MIN(texsize, 2048);
+ } else {
+ texsize = MIN(texsize, 1024);
+ }
FontTexture tex;
tex.texture_w = texsize;
@@ -386,10 +390,10 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, 4, Image::FORMAT_RGBA8, mw, mh, true);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
FontTexture &tex = p_data->textures.write[tex_pos.index];
@@ -464,13 +468,13 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
int mw = w + p_rect_margin * 2;
int mh = h + p_rect_margin * 2;
- ERR_FAIL_COND_V(mw > 4096, FontGlyph());
- ERR_FAIL_COND_V(mh > 4096, FontGlyph());
+ ERR_FAIL_COND_V(mw > 1024, FontGlyph());
+ ERR_FAIL_COND_V(mh > 1024, FontGlyph());
int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2;
Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8;
- FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh);
+ FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false);
ERR_FAIL_COND_V(tex_pos.index < 0, FontGlyph());
// Fit character in char texture.
@@ -586,6 +590,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
flags |= FT_LOAD_COLOR;
}
+ glyph_index = FT_Get_Char_Index(fd->face, glyph_index);
+
FT_Fixed v, h;
FT_Get_Advance(fd->face, glyph_index, flags, &h);
FT_Get_Advance(fd->face, glyph_index, flags | FT_LOAD_VERTICAL_LAYOUT, &v);
@@ -606,6 +612,16 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d
}
}
+ if (p_font_data->embolden != 0.f) {
+ FT_Pos strength = p_font_data->embolden * p_size.x * 4; // 26.6 fractional units (1 / 64).
+ FT_Outline_Embolden(&fd->face->glyph->outline, strength);
+ }
+
+ if (p_font_data->transform != Transform2D()) {
+ FT_Matrix mat = { FT_Fixed(p_font_data->transform[0][0] * 65536), FT_Fixed(p_font_data->transform[0][1] * 65536), FT_Fixed(p_font_data->transform[1][0] * 65536), FT_Fixed(p_font_data->transform[1][1] * 65536) }; // 16.16 fractional units (1 / 65536).
+ FT_Outline_Transform(&fd->face->glyph->outline, &mat);
+ }
+
if (!outline) {
if (!p_font_data->msdf) {
error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
@@ -1044,6 +1060,44 @@ TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positionin
return fd->subpixel_positioning;
}
+void TextServerFallback::font_set_embolden(RID p_font_rid, float p_strength) {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->embolden != p_strength) {
+ _font_clear_cache(fd);
+ fd->embolden = p_strength;
+ }
+}
+
+float TextServerFallback::font_get_embolden(RID p_font_rid) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, 0.f);
+
+ MutexLock lock(fd->mutex);
+ return fd->embolden;
+}
+
+void TextServerFallback::font_set_transform(RID p_font_rid, Transform2D p_transform) {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->transform != p_transform) {
+ _font_clear_cache(fd);
+ fd->transform = p_transform;
+ }
+}
+
+Transform2D TextServerFallback::font_get_transform(RID p_font_rid) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, Transform2D());
+
+ MutexLock lock(fd->mutex);
+ return fd->transform;
+}
+
void TextServerFallback::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -1459,12 +1513,17 @@ Vector2 TextServerFallback::font_get_glyph_advance(RID p_font_rid, int p_size, i
const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
+ Vector2 ea;
+ if (fd->embolden != 0.0) {
+ ea.x = fd->embolden * float(size.x) / 64.0;
+ }
+
if (fd->msdf) {
- return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size;
+ return (gl[p_glyph].advance + ea) * (float)p_size / (float)fd->msdf_source_size;
} else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_DISABLED) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x > SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) {
- return gl[p_glyph].advance.round();
+ return (gl[p_glyph].advance + ea).round();
} else {
- return gl[p_glyph].advance;
+ return gl[p_glyph].advance + ea;
}
}
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index 91afd02ae9..d4c7b5666e 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -142,6 +142,8 @@ class TextServerFallback : public TextServer {
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
Dictionary variation_coordinates;
float oversampling = 0.f;
+ float embolden = 0.f;
+ Transform2D transform;
uint32_t style_flags = 0;
String font_name;
@@ -172,7 +174,7 @@ class TextServerFallback : public TextServer {
}
};
- _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height) const;
+ _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const;
#ifdef MODULE_MSDFGEN_ENABLED
_FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const;
#endif
@@ -294,6 +296,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const override;
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
+ virtual float font_get_embolden(RID p_font_rid) const override;
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
+ virtual Transform2D font_get_transform(RID p_font_rid) const override;
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp
index 6fae049056..a2e59c9cdf 100644
--- a/modules/visual_script/editor/visual_script_editor.cpp
+++ b/modules/visual_script/editor/visual_script_editor.cpp
@@ -4725,8 +4725,6 @@ VisualScriptEditor::VisualScriptEditor() {
undo_redo = EditorNode::get_singleton()->get_undo_redo();
- updating_members = false;
-
set_process_input(true);
default_value_edit = memnew(CustomPropertyEditor);
diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h
index e178f5cf72..5b355a71df 100644
--- a/modules/visual_script/editor/visual_script_editor.h
+++ b/modules/visual_script/editor/visual_script_editor.h
@@ -148,7 +148,7 @@ class VisualScriptEditor : public ScriptEditorBase {
void _update_graph_connections();
void _update_graph(int p_only_id = -1);
- bool updating_members;
+ bool updating_members = false;
void _update_members();
String _sanitized_variant_text(const StringName &property_name);
diff --git a/modules/visual_script/register_types.cpp b/modules/visual_script/register_types.cpp
index e7b5f58174..d19870921d 100644
--- a/modules/visual_script/register_types.cpp
+++ b/modules/visual_script/register_types.cpp
@@ -53,10 +53,10 @@ void register_visual_script_types() {
ScriptServer::register_language(visual_script_language);
GDREGISTER_CLASS(VisualScript);
- GDREGISTER_VIRTUAL_CLASS(VisualScriptNode);
+ GDREGISTER_ABSTRACT_CLASS(VisualScriptNode);
GDREGISTER_CLASS(VisualScriptFunctionState);
GDREGISTER_CLASS(VisualScriptFunction);
- GDREGISTER_VIRTUAL_CLASS(VisualScriptLists);
+ GDREGISTER_ABSTRACT_CLASS(VisualScriptLists);
GDREGISTER_CLASS(VisualScriptComposeArray);
GDREGISTER_CLASS(VisualScriptOperator);
GDREGISTER_CLASS(VisualScriptVariableSet);
diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp
index a79e6df521..fef159bf87 100644
--- a/modules/visual_script/visual_script_expression.cpp
+++ b/modules/visual_script/visual_script_expression.cpp
@@ -176,7 +176,7 @@ PropertyInfo VisualScriptExpression::get_output_value_port_info(int p_idx) const
}
String VisualScriptExpression::get_caption() const {
- return TTR("Expression");
+ return RTR("Expression");
}
String VisualScriptExpression::get_text() const {
diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp
index fd1861abc4..d28744a09f 100644
--- a/modules/visual_script/visual_script_flow_control.cpp
+++ b/modules/visual_script/visual_script_flow_control.cpp
@@ -70,7 +70,7 @@ PropertyInfo VisualScriptReturn::get_output_value_port_info(int p_idx) const {
}
String VisualScriptReturn::get_caption() const {
- return TTR("Return");
+ return RTR("Return");
}
String VisualScriptReturn::get_text() const {
@@ -201,11 +201,11 @@ PropertyInfo VisualScriptCondition::get_output_value_port_info(int p_idx) const
}
String VisualScriptCondition::get_caption() const {
- return TTR("Condition");
+ return RTR("Condition");
}
String VisualScriptCondition::get_text() const {
- return TTR("if (cond) is:");
+ return RTR("if (cond) is:");
}
void VisualScriptCondition::_bind_methods() {
@@ -281,11 +281,11 @@ PropertyInfo VisualScriptWhile::get_output_value_port_info(int p_idx) const {
}
String VisualScriptWhile::get_caption() const {
- return TTR("While");
+ return RTR("While");
}
String VisualScriptWhile::get_text() const {
- return TTR("while (cond):");
+ return RTR("while (cond):");
}
void VisualScriptWhile::_bind_methods() {
@@ -364,11 +364,11 @@ PropertyInfo VisualScriptIterator::get_output_value_port_info(int p_idx) const {
}
String VisualScriptIterator::get_caption() const {
- return TTR("Iterator");
+ return RTR("Iterator");
}
String VisualScriptIterator::get_text() const {
- return TTR("for (elem) in (input):");
+ return RTR("for (elem) in (input):");
}
void VisualScriptIterator::_bind_methods() {
@@ -478,11 +478,11 @@ PropertyInfo VisualScriptSequence::get_output_value_port_info(int p_idx) const {
}
String VisualScriptSequence::get_caption() const {
- return TTR("Sequence");
+ return RTR("Sequence");
}
String VisualScriptSequence::get_text() const {
- return TTR("in order:");
+ return RTR("in order:");
}
void VisualScriptSequence::set_steps(int p_steps) {
@@ -587,11 +587,11 @@ PropertyInfo VisualScriptSwitch::get_output_value_port_info(int p_idx) const {
}
String VisualScriptSwitch::get_caption() const {
- return TTR("Switch");
+ return RTR("Switch");
}
String VisualScriptSwitch::get_text() const {
- return TTR("'input' is:");
+ return RTR("'input' is:");
}
class VisualScriptNodeInstanceSwitch : public VisualScriptNodeInstance {
@@ -720,14 +720,14 @@ PropertyInfo VisualScriptTypeCast::get_output_value_port_info(int p_idx) const {
}
String VisualScriptTypeCast::get_caption() const {
- return TTR("Type Cast");
+ return RTR("Type Cast");
}
String VisualScriptTypeCast::get_text() const {
if (!script.is_empty()) {
- return vformat(TTR("Is %s?"), script.get_file());
+ return vformat(RTR("Is %s?"), script.get_file());
} else {
- return vformat(TTR("Is %s?"), base_type);
+ return vformat(RTR("Is %s?"), base_type);
}
}
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index a63f3edc0d..2c9d23e457 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -33,6 +33,7 @@
#include "core/config/engine.h"
#include "core/io/resource_loader.h"
#include "core/os/os.h"
+#include "core/templates/local_vector.h"
#include "scene/main/node.h"
#include "scene/main/scene_tree.h"
#include "visual_script_nodes.h"
@@ -261,13 +262,13 @@ String VisualScriptFunctionCall::get_text() const {
String text;
if (call_mode == CALL_MODE_BASIC_TYPE) {
- text = vformat(TTR("On %s"), Variant::get_type_name(basic_type));
+ text = vformat(RTR("On %s"), Variant::get_type_name(basic_type));
} else if (call_mode == CALL_MODE_INSTANCE) {
- text = vformat(TTR("On %s"), base_type);
+ text = vformat(RTR("On %s"), base_type);
} else if (call_mode == CALL_MODE_NODE_PATH) {
text = "[" + String(base_path.simplified()) + "]";
} else if (call_mode == CALL_MODE_SELF) {
- text = TTR("On Self");
+ text = RTR("On Self");
} else if (call_mode == CALL_MODE_SINGLETON) {
text = String(singleton) + ":" + String(function) + "()";
}
@@ -1032,18 +1033,18 @@ PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) cons
}
String VisualScriptPropertySet::get_caption() const {
- static const char *opname[ASSIGN_OP_MAX] = {
- TTRC("Set %s"),
- TTRC("Add %s"),
- TTRC("Subtract %s"),
- TTRC("Multiply %s"),
- TTRC("Divide %s"),
- TTRC("Mod %s"),
- TTRC("ShiftLeft %s"),
- TTRC("ShiftRight %s"),
- TTRC("BitAnd %s"),
- TTRC("BitOr %s"),
- TTRC("BitXor %s")
+ static const LocalVector<String> opname = {
+ RTR("Set %s"),
+ RTR("Add %s"),
+ RTR("Subtract %s"),
+ RTR("Multiply %s"),
+ RTR("Divide %s"),
+ RTR("Mod %s"),
+ RTR("ShiftLeft %s"),
+ RTR("ShiftRight %s"),
+ RTR("BitAnd %s"),
+ RTR("BitOr %s"),
+ RTR("BitXor %s"),
};
String prop = property;
@@ -1051,7 +1052,7 @@ String VisualScriptPropertySet::get_caption() const {
prop += "." + String(index);
}
- return vformat(TTRGET(opname[assign_op]), prop);
+ return vformat(opname[assign_op], prop);
}
String VisualScriptPropertySet::get_text() const {
@@ -1059,13 +1060,13 @@ String VisualScriptPropertySet::get_text() const {
return "";
}
if (call_mode == CALL_MODE_BASIC_TYPE) {
- return vformat(TTR("On %s"), Variant::get_type_name(basic_type));
+ return vformat(RTR("On %s"), Variant::get_type_name(basic_type));
} else if (call_mode == CALL_MODE_INSTANCE) {
- return vformat(TTR("On %s"), base_type);
+ return vformat(RTR("On %s"), base_type);
} else if (call_mode == CALL_MODE_NODE_PATH) {
return " [" + String(base_path.simplified()) + "]";
} else {
- return TTR("On Self");
+ return RTR("On Self");
}
}
@@ -1776,18 +1777,18 @@ String VisualScriptPropertyGet::get_caption() const {
prop += "." + String(index);
}
- return vformat(TTR("Get %s"), prop);
+ return vformat(RTR("Get %s"), prop);
}
String VisualScriptPropertyGet::get_text() const {
if (call_mode == CALL_MODE_BASIC_TYPE) {
- return vformat(TTR("On %s"), Variant::get_type_name(basic_type));
+ return vformat(RTR("On %s"), Variant::get_type_name(basic_type));
} else if (call_mode == CALL_MODE_INSTANCE) {
- return vformat(TTR("On %s"), base_type);
+ return vformat(RTR("On %s"), base_type);
} else if (call_mode == CALL_MODE_NODE_PATH) {
return " [" + String(base_path.simplified()) + "]";
} else {
- return TTR("On Self");
+ return RTR("On Self");
}
}
@@ -2303,7 +2304,7 @@ PropertyInfo VisualScriptEmitSignal::get_output_value_port_info(int p_idx) const
}
String VisualScriptEmitSignal::get_caption() const {
- return vformat(TTR("Emit %s"), name);
+ return vformat(RTR("Emit %s"), name);
}
void VisualScriptEmitSignal::set_signal(const StringName &p_type) {
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 204b416c7d..b65b9f090a 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -204,7 +204,7 @@ PropertyInfo VisualScriptFunction::get_output_value_port_info(int p_idx) const {
}
String VisualScriptFunction::get_caption() const {
- return TTR("Function");
+ return RTR("Function");
}
String VisualScriptFunction::get_text() const {
@@ -767,7 +767,7 @@ PropertyInfo VisualScriptComposeArray::get_output_value_port_info(int p_idx) con
}
String VisualScriptComposeArray::get_caption() const {
- return TTR("Compose Array");
+ return RTR("Compose Array");
}
String VisualScriptComposeArray::get_text() const {
@@ -1186,11 +1186,11 @@ PropertyInfo VisualScriptSelect::get_output_value_port_info(int p_idx) const {
}
String VisualScriptSelect::get_caption() const {
- return TTR("Select");
+ return RTR("Select");
}
String VisualScriptSelect::get_text() const {
- return TTR("a if cond, else b");
+ return RTR("a if cond, else b");
}
void VisualScriptSelect::set_typed(Variant::Type p_op) {
@@ -1284,7 +1284,7 @@ PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) cons
}
String VisualScriptVariableGet::get_caption() const {
- return vformat(TTR("Get %s"), variable);
+ return vformat(RTR("Get %s"), variable);
}
void VisualScriptVariableGet::set_variable(StringName p_variable) {
@@ -1394,7 +1394,7 @@ PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) cons
}
String VisualScriptVariableSet::get_caption() const {
- return vformat(TTR("Set %s"), variable);
+ return vformat(RTR("Set %s"), variable);
}
void VisualScriptVariableSet::set_variable(StringName p_variable) {
@@ -1501,7 +1501,7 @@ PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const {
}
String VisualScriptConstant::get_caption() const {
- return TTR("Constant");
+ return RTR("Constant");
}
void VisualScriptConstant::set_constant_type(Variant::Type p_type) {
@@ -1628,7 +1628,7 @@ PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const {
}
String VisualScriptPreload::get_caption() const {
- return TTR("Preload");
+ return RTR("Preload");
}
void VisualScriptPreload::set_preload(const Ref<Resource> &p_preload) {
@@ -1708,7 +1708,7 @@ PropertyInfo VisualScriptIndexGet::get_output_value_port_info(int p_idx) const {
}
String VisualScriptIndexGet::get_caption() const {
- return TTR("Get Index");
+ return RTR("Get Index");
}
class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance {
@@ -1775,7 +1775,7 @@ PropertyInfo VisualScriptIndexSet::get_output_value_port_info(int p_idx) const {
}
String VisualScriptIndexSet::get_caption() const {
- return TTR("Set Index");
+ return RTR("Set Index");
}
class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance {
@@ -1836,7 +1836,7 @@ PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) c
}
String VisualScriptGlobalConstant::get_caption() const {
- return TTR("Global Constant");
+ return RTR("Global Constant");
}
void VisualScriptGlobalConstant::set_global_constant(int p_which) {
@@ -1922,7 +1922,7 @@ PropertyInfo VisualScriptClassConstant::get_output_value_port_info(int p_idx) co
}
String VisualScriptClassConstant::get_caption() const {
- return TTR("Class Constant");
+ return RTR("Class Constant");
}
void VisualScriptClassConstant::set_class_constant(const StringName &p_which) {
@@ -2047,7 +2047,7 @@ PropertyInfo VisualScriptBasicTypeConstant::get_output_value_port_info(int p_idx
}
String VisualScriptBasicTypeConstant::get_caption() const {
- return TTR("Basic Constant");
+ return RTR("Basic Constant");
}
String VisualScriptBasicTypeConstant::get_text() const {
@@ -2212,7 +2212,7 @@ PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) con
}
String VisualScriptMathConstant::get_caption() const {
- return TTR("Math Constant");
+ return RTR("Math Constant");
}
void VisualScriptMathConstant::set_math_constant(MathConstant p_which) {
@@ -2304,7 +2304,7 @@ PropertyInfo VisualScriptEngineSingleton::get_output_value_port_info(int p_idx)
}
String VisualScriptEngineSingleton::get_caption() const {
- return TTR("Get Engine Singleton");
+ return RTR("Get Engine Singleton");
}
void VisualScriptEngineSingleton::set_singleton(const String &p_string) {
@@ -2414,7 +2414,7 @@ PropertyInfo VisualScriptSceneNode::get_output_value_port_info(int p_idx) const
}
String VisualScriptSceneNode::get_caption() const {
- return TTR("Get Scene Node");
+ return RTR("Get Scene Node");
}
void VisualScriptSceneNode::set_node_path(const NodePath &p_path) {
@@ -2605,7 +2605,7 @@ PropertyInfo VisualScriptSceneTree::get_output_value_port_info(int p_idx) const
}
String VisualScriptSceneTree::get_caption() const {
- return TTR("Get Scene Tree");
+ return RTR("Get Scene Tree");
}
class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance {
@@ -2692,7 +2692,7 @@ PropertyInfo VisualScriptResourcePath::get_output_value_port_info(int p_idx) con
}
String VisualScriptResourcePath::get_caption() const {
- return TTR("Resource Path");
+ return RTR("Resource Path");
}
void VisualScriptResourcePath::set_resource_path(const String &p_path) {
@@ -2774,7 +2774,7 @@ PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const {
}
String VisualScriptSelf::get_caption() const {
- return TTR("Get Self");
+ return RTR("Get Self");
}
class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance {
@@ -2944,7 +2944,7 @@ String VisualScriptCustomNode::get_caption() const {
if (GDVIRTUAL_CALL(_get_caption, ret)) {
return ret;
}
- return TTR("CustomNode");
+ return RTR("CustomNode");
}
String VisualScriptCustomNode::get_text() const {
@@ -3138,7 +3138,7 @@ PropertyInfo VisualScriptSubCall::get_output_value_port_info(int p_idx) const {
}
String VisualScriptSubCall::get_caption() const {
- return TTR("SubCall");
+ return RTR("SubCall");
}
String VisualScriptSubCall::get_text() const {
@@ -3349,7 +3349,7 @@ PropertyInfo VisualScriptConstructor::get_output_value_port_info(int p_idx) cons
}
String VisualScriptConstructor::get_caption() const {
- return vformat(TTR("Construct %s"), Variant::get_type_name(type));
+ return vformat(RTR("Construct %s"), Variant::get_type_name(type));
}
String VisualScriptConstructor::get_category() const {
@@ -3466,7 +3466,7 @@ PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const {
}
String VisualScriptLocalVar::get_caption() const {
- return TTR("Get Local Var");
+ return RTR("Get Local Var");
}
String VisualScriptLocalVar::get_category() const {
@@ -3569,7 +3569,7 @@ PropertyInfo VisualScriptLocalVarSet::get_output_value_port_info(int p_idx) cons
}
String VisualScriptLocalVarSet::get_caption() const {
- return TTR("Set Local Var");
+ return RTR("Set Local Var");
}
String VisualScriptLocalVarSet::get_text() const {
@@ -3693,7 +3693,7 @@ PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) cons
}
String VisualScriptInputAction::get_caption() const {
- return vformat(TTR("Action %s"), name);
+ return vformat(RTR("Action %s"), name);
}
String VisualScriptInputAction::get_category() const {
@@ -3847,7 +3847,7 @@ PropertyInfo VisualScriptDeconstruct::get_output_value_port_info(int p_idx) cons
}
String VisualScriptDeconstruct::get_caption() const {
- return vformat(TTR("Deconstruct %s"), Variant::get_type_name(type));
+ return vformat(RTR("Deconstruct %s"), Variant::get_type_name(type));
}
String VisualScriptDeconstruct::get_category() const {
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index fbd5ad35ab..dcd8815394 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -68,7 +68,7 @@ PropertyInfo VisualScriptYield::get_output_value_port_info(int p_idx) const {
}
String VisualScriptYield::get_caption() const {
- return yield_mode == YIELD_RETURN ? TTR("Yield") : TTR("Wait");
+ return yield_mode == YIELD_RETURN ? RTR("Yield") : RTR("Wait");
}
String VisualScriptYield::get_text() const {
@@ -77,13 +77,13 @@ String VisualScriptYield::get_text() const {
return "";
break;
case YIELD_FRAME:
- return TTR("Next Frame");
+ return RTR("Next Frame");
break;
case YIELD_PHYSICS_FRAME:
- return TTR("Next Physics Frame");
+ return RTR("Next Physics Frame");
break;
case YIELD_WAIT:
- return vformat(TTR("%s sec(s)"), rtos(wait_time));
+ return vformat(RTR("%s sec(s)"), rtos(wait_time));
break;
}
@@ -335,13 +335,18 @@ PropertyInfo VisualScriptYieldSignal::get_output_value_port_info(int p_idx) cons
}
String VisualScriptYieldSignal::get_caption() const {
- static const char *cname[3] = {
- TTRC("WaitSignal"),
- TTRC("WaitNodeSignal"),
- TTRC("WaitInstanceSignal"),
- };
-
- return TTRGET(cname[call_mode]);
+ switch (call_mode) {
+ case CALL_MODE_SELF: {
+ return RTR("WaitSignal");
+ } break;
+ case CALL_MODE_NODE_PATH: {
+ return RTR("WaitNodeSignal");
+ } break;
+ case CALL_MODE_INSTANCE: {
+ return RTR("WaitInstanceSignal");
+ } break;
+ }
+ return String();
}
String VisualScriptYieldSignal::get_text() const {
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 049d816a5a..5ff5b2339c 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -166,7 +166,7 @@ void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) {
active = true;
seek(p_from_pos);
loops = 0;
- _begin_resample();
+ begin_resample();
}
void AudioStreamPlaybackOGGVorbis::stop() {
diff --git a/modules/webrtc/register_types.cpp b/modules/webrtc/register_types.cpp
index e6a8dcc31a..283e421e11 100644
--- a/modules/webrtc/register_types.cpp
+++ b/modules/webrtc/register_types.cpp
@@ -47,7 +47,7 @@ void register_webrtc_types() {
ClassDB::register_custom_instance_class<WebRTCPeerConnection>();
GDREGISTER_CLASS(WebRTCPeerConnectionExtension);
- GDREGISTER_VIRTUAL_CLASS(WebRTCDataChannel);
+ GDREGISTER_ABSTRACT_CLASS(WebRTCDataChannel);
GDREGISTER_CLASS(WebRTCDataChannelExtension);
GDREGISTER_CLASS(WebRTCMultiplayerPeer);
diff --git a/modules/websocket/register_types.cpp b/modules/websocket/register_types.cpp
index 1e9a4c0392..ff900f496f 100644
--- a/modules/websocket/register_types.cpp
+++ b/modules/websocket/register_types.cpp
@@ -63,7 +63,7 @@ void register_websocket_types() {
WSLServer::make_default();
#endif
- GDREGISTER_VIRTUAL_CLASS(WebSocketMultiplayerPeer);
+ GDREGISTER_ABSTRACT_CLASS(WebSocketMultiplayerPeer);
ClassDB::register_custom_instance_class<WebSocketServer>();
ClassDB::register_custom_instance_class<WebSocketClient>();
ClassDB::register_custom_instance_class<WebSocketPeer>();
diff --git a/modules/webxr/register_types.cpp b/modules/webxr/register_types.cpp
index 78fed3fbd6..a15dc93248 100644
--- a/modules/webxr/register_types.cpp
+++ b/modules/webxr/register_types.cpp
@@ -38,7 +38,7 @@ Ref<WebXRInterfaceJS> webxr;
#endif
void register_webxr_types() {
- GDREGISTER_VIRTUAL_CLASS(WebXRInterface);
+ GDREGISTER_ABSTRACT_CLASS(WebXRInterface);
#ifdef JAVASCRIPT_ENABLED
webxr.instantiate();
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index ca6a45cb83..4220c57cae 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -1387,6 +1387,7 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
Vector<String> string_table;
String package_name = p_preset->get("package/name");
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
for (uint32_t i = 0; i < string_count; i++) {
uint32_t offset = decode_uint32(&r_manifest[string_table_begins + i * 4]);
@@ -1401,9 +1402,8 @@ void EditorExportPlatformAndroid::_fix_resources(const Ref<EditorExportPreset> &
} else {
String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_");
- String prop = "application/config/name_" + lang;
- if (ProjectSettings::get_singleton()->has_setting(prop)) {
- str = ProjectSettings::get_singleton()->get(prop);
+ if (appnames.has(lang)) {
+ str = appnames[lang];
} else {
str = get_project_name(package_name);
}
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index 9598d2f9fd..ab915a5f85 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -75,11 +75,10 @@ String _get_android_orientation_label(DisplayServer::ScreenOrientation screen_or
// Utility method used to create a directory.
Error create_directory(const String &p_dir) {
if (!DirAccess::exists(p_dir)) {
- DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'.");
Error err = filesystem_da->make_dir_recursive(p_dir);
ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'.");
- memdelete(filesystem_da);
}
return OK;
}
@@ -161,6 +160,7 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
return ERR_CANT_OPEN;
}
da->list_dir_begin();
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
while (true) {
String file = da->get_next();
if (file.is_empty()) {
@@ -171,10 +171,9 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
continue;
}
String locale = file.replace("values-", "").replace("-r", "_");
- String property_name = "application/config/name_" + locale;
String locale_directory = "res://android/build/res/" + file + "/godot_project_name_string.xml";
- if (ProjectSettings::get_singleton()->has_setting(property_name)) {
- String locale_project_name = ProjectSettings::get_singleton()->get(property_name);
+ if (appnames.has(locale)) {
+ String locale_project_name = appnames[locale];
String processed_xml_string = vformat(godot_project_name_xml_string, _android_xml_escape(locale_project_name));
print_verbose("Storing project name for locale " + locale + " under " + locale_directory);
store_string_at_path(locale_directory, processed_xml_string);
diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp
index 2eaf5e47ac..26c5acb13e 100644
--- a/platform/iphone/export/export_plugin.cpp
+++ b/platform/iphone/export/export_plugin.cpp
@@ -92,13 +92,10 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/targeted_device_family", PROPERTY_HINT_ENUM, "iPhone,iPad,iPhone & iPad"), 2));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
Vector<PluginConfigIOS> found_plugins = get_plugins();
for (int i = 0; i < found_plugins.size(); i++) {
@@ -139,8 +136,11 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "user_data/accessible_from_itunes_sharing"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photolibrary_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need access to the photo library"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photolibrary_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_120x120", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone/iPod Touch with Retina display
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "icons/iphone_180x180", PROPERTY_HINT_FILE, "*.png"), "")); // Home screen on iPhone with Retina HD display
@@ -200,8 +200,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$modules_buildgrp", p_config.modules_buildgrp) + "\n";
} else if (lines[i].find("$name") != -1) {
strnew += lines[i].replace("$name", p_config.pkg_name) + "\n";
- } else if (lines[i].find("$info") != -1) {
- strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
} else if (lines[i].find("$bundle_identifier") != -1) {
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (lines[i].find("$short_version") != -1) {
@@ -210,8 +208,6 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
} else if (lines[i].find("$signature") != -1) {
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
- } else if (lines[i].find("$copyright") != -1) {
- strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].find("$team_id") != -1) {
strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
} else if (lines[i].find("$default_build_config") != -1) {
@@ -534,7 +530,7 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
String json_description = "{\"images\":[";
String sizes;
- DirAccess *da = DirAccess::open(p_iconset_dir);
+ DirAccessRef da = DirAccess::open(p_iconset_dir);
ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
@@ -574,7 +570,6 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
}
if (err) {
- memdelete(da);
String err_str = String("Failed to export icon(" + String(info.preset_key) + "): '" + icon_path + "'.");
ERR_PRINT(err_str.utf8().get_data());
return err;
@@ -592,7 +587,6 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
json_description += String("}");
}
json_description += "]}";
- memdelete(da);
FileAccess *json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
ERR_FAIL_COND_V(!json_file, ERR_CANT_CREATE);
@@ -678,7 +672,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
}
Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) {
- DirAccess *da = DirAccess::open(p_dest_dir);
+ DirAccessRef da = DirAccess::open(p_dest_dir);
ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'.");
for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
@@ -716,7 +710,6 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
err = da->copy(loading_screen_file, p_dest_dir + info.export_name);
}
if (err) {
- memdelete(da);
String err_str = String("Failed to export loading screen (") + info.preset_key + ") from path '" + loading_screen_file + "'.";
ERR_PRINT(err_str.utf8().get_data());
return err;
@@ -764,7 +757,6 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
}
}
}
- memdelete(da);
return OK;
}
@@ -970,21 +962,15 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese
}
Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) {
- DirAccess *filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
-
String binary_name = p_out_dir.get_file().get_basename();
- DirAccess *da = DirAccess::create_for_path(p_asset);
+ DirAccessRef da = DirAccess::create_for_path(p_asset);
if (!da) {
- memdelete(filesystem_da);
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + ".");
}
bool file_exists = da->file_exists(p_asset);
bool dir_exists = da->dir_exists(p_asset);
if (!file_exists && !dir_exists) {
- memdelete(da);
- memdelete(filesystem_da);
return ERR_FILE_NOT_FOUND;
}
@@ -1044,19 +1030,18 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
destination = p_out_dir.plus_file(asset_path);
}
+ DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
+
if (!filesystem_da->dir_exists(destination_dir)) {
Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
if (make_dir_err) {
- memdelete(da);
- memdelete(filesystem_da);
return make_dir_err;
}
}
Error err = dir_exists ? da->copy_dir(p_asset, destination) : da->copy(p_asset, destination);
- memdelete(da);
if (err) {
- memdelete(filesystem_da);
return err;
}
IOSExportAsset exported_asset = { binary_name.plus_file(asset_path), p_is_framework, p_should_embed };
@@ -1121,8 +1106,6 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
}
}
- memdelete(filesystem_da);
-
return OK;
}
@@ -1427,29 +1410,29 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return ERR_FILE_BAD_PATH;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (da) {
- String current_dir = da->get_current_dir();
-
- // remove leftovers from last export so they don't interfere
- // in case some files are no longer needed
- if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
- da->erase_contents_recursive();
- }
- if (da->change_dir(dest_dir + binary_name) == OK) {
- da->erase_contents_recursive();
- }
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da) {
+ String current_dir = da->get_current_dir();
+
+ // remove leftovers from last export so they don't interfere
+ // in case some files are no longer needed
+ if (da->change_dir(dest_dir + binary_name + ".xcodeproj") == OK) {
+ da->erase_contents_recursive();
+ }
+ if (da->change_dir(dest_dir + binary_name) == OK) {
+ da->erase_contents_recursive();
+ }
- da->change_dir(current_dir);
+ da->change_dir(current_dir);
- if (!da->dir_exists(dest_dir + binary_name)) {
- Error err = da->make_dir(dest_dir + binary_name);
- if (err) {
- memdelete(da);
- return err;
+ if (!da->dir_exists(dest_dir + binary_name)) {
+ Error err = da->make_dir(dest_dir + binary_name);
+ if (err) {
+ return err;
+ }
}
}
- memdelete(da);
}
if (ep.step("Making .pck", 0)) {
@@ -1470,9 +1453,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
print_line("Static framework: " + library_to_use);
String pkg_name;
- if (p_preset->get("application/name") != "") {
- pkg_name = p_preset->get("application/name"); // app_name
- } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
+ if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
} else {
pkg_name = "Unnamed";
@@ -1507,7 +1488,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Vector<IOSExportAsset> assets;
- DirAccess *tmp_app_path = DirAccess::create_for_path(dest_dir);
+ DirAccessRef tmp_app_path = DirAccess::create_for_path(dest_dir);
ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE);
print_line("Unzipping...");
@@ -1586,7 +1567,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (dir_err) {
ERR_PRINT("Can't create '" + dir_name + "'.");
unzClose(src_pkg_zip);
- memdelete(tmp_app_path);
return ERR_CANT_CREATE;
}
}
@@ -1596,7 +1576,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!f) {
ERR_PRINT("Can't write '" + file + "'.");
unzClose(src_pkg_zip);
- memdelete(tmp_app_path);
return ERR_CANT_CREATE;
};
f->store_buffer(data.ptr(), data.size());
@@ -1619,28 +1598,48 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!found_library) {
ERR_PRINT("Requested template library '" + library_to_use + "' not found. It might be missing from your template archive.");
- memdelete(tmp_app_path);
return ERR_FILE_NOT_FOUND;
}
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
+ Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized");
+ Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized");
+ Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized");
+
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
if (translations.size() > 0) {
{
String fname = dest_dir + binary_name + "/en.lproj";
tmp_app_path->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
+ f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
+ f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";");
}
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
if (tr.is_valid()) {
- String fname = dest_dir + binary_name + "/" + tr->get_locale() + ".lproj";
+ String lang = tr->get_locale();
+ String fname = dest_dir + binary_name + "/" + lang + ".lproj";
tmp_app_path->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
- String prop = "application/config/name_" + tr->get_locale();
- if (ProjectSettings::get_singleton()->has_setting(prop)) {
- f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
+ if (appnames.has(lang)) {
+ f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
+ }
+ if (camera_usage_descriptions.has(lang)) {
+ f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (microphone_usage_descriptions.has(lang)) {
+ f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (photolibrary_usage_descriptions.has(lang)) {
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";");
}
}
}
@@ -1656,7 +1655,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Error lib_copy_err = tmp_app_path->copy(static_lib_path, dest_lib_file_path);
if (lib_copy_err != OK) {
ERR_PRINT("Can't copy '" + static_lib_path + "'.");
- memdelete(tmp_app_path);
return lib_copy_err;
}
}
@@ -1667,7 +1665,6 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!tmp_app_path->dir_exists(iconset_dir)) {
err = tmp_app_path->make_dir_recursive(iconset_dir);
}
- memdelete(tmp_app_path);
if (err) {
return err;
}
@@ -1677,43 +1674,43 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
return err;
}
- bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard");
+ {
+ bool use_storyboard = p_preset->get("storyboard/use_launch_screen_storyboard");
- String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
- String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
+ String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
+ String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
- DirAccess *launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (!launch_screen_da) {
- return ERR_CANT_CREATE;
- }
+ if (!launch_screen_da) {
+ return ERR_CANT_CREATE;
+ }
- if (use_storyboard) {
- print_line("Using Launch Storyboard");
+ if (use_storyboard) {
+ print_line("Using Launch Storyboard");
- if (launch_screen_da->change_dir(launch_image_path) == OK) {
- launch_screen_da->erase_contents_recursive();
- launch_screen_da->remove(launch_image_path);
- }
+ if (launch_screen_da->change_dir(launch_image_path) == OK) {
+ launch_screen_da->erase_contents_recursive();
+ launch_screen_da->remove(launch_image_path);
+ }
- err = _export_loading_screen_file(p_preset, splash_image_path);
- } else {
- print_line("Using Launch Images");
+ err = _export_loading_screen_file(p_preset, splash_image_path);
+ } else {
+ print_line("Using Launch Images");
- const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard";
+ const String launch_screen_path = dest_dir + binary_name + "/Launch Screen.storyboard";
- launch_screen_da->remove(launch_screen_path);
+ launch_screen_da->remove(launch_screen_path);
- if (launch_screen_da->change_dir(splash_image_path) == OK) {
- launch_screen_da->erase_contents_recursive();
- launch_screen_da->remove(splash_image_path);
- }
+ if (launch_screen_da->change_dir(splash_image_path) == OK) {
+ launch_screen_da->erase_contents_recursive();
+ launch_screen_da->remove(splash_image_path);
+ }
- err = _export_loading_screen_images(p_preset, launch_image_path);
+ err = _export_loading_screen_images(p_preset, launch_image_path);
+ }
}
- memdelete(launch_screen_da);
-
if (err) {
return err;
}
@@ -1732,15 +1729,17 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
memdelete(f);
#ifdef OSX_ENABLED
- if (ep.step("Code-signing dylibs", 2)) {
- return ERR_SKIP;
+ {
+ if (ep.step("Code-signing dylibs", 2)) {
+ return ERR_SKIP;
+ }
+ DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
+ ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
+ CodesignData codesign_data(p_preset, p_debug);
+ err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
+ memdelete(dylibs_dir);
+ ERR_FAIL_COND_V(err, err);
}
- DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
- ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
- CodesignData codesign_data(p_preset, p_debug);
- err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
- memdelete(dylibs_dir);
- ERR_FAIL_COND_V(err, err);
if (ep.step("Making .xcarchive", 3)) {
return ERR_SKIP;
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index 56cb49318c..1d990b5625 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -259,11 +259,9 @@ Error OSIPhone::shell_open(String p_uri) {
}
void OSIPhone::set_user_data_dir(String p_dir) {
- DirAccess *da = DirAccess::open(p_dir);
-
+ DirAccessRef da = DirAccess::open(p_dir);
user_data_dir = da->get_current_dir();
printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data());
- memdelete(da);
}
String OSIPhone::get_user_data_dir() const {
diff --git a/platform/javascript/api/api.cpp b/platform/javascript/api/api.cpp
index 4190b24b8e..46a0a816bf 100644
--- a/platform/javascript/api/api.cpp
+++ b/platform/javascript/api/api.cpp
@@ -37,8 +37,8 @@ static JavaScript *javascript_eval;
void register_javascript_api() {
JavaScriptToolsEditorPlugin::initialize();
- GDREGISTER_VIRTUAL_CLASS(JavaScriptObject);
- GDREGISTER_VIRTUAL_CLASS(JavaScript);
+ GDREGISTER_ABSTRACT_CLASS(JavaScriptObject);
+ GDREGISTER_ABSTRACT_CLASS(JavaScript);
javascript_eval = memnew(JavaScript);
Engine::get_singleton()->add_singleton(Engine::Singleton("JavaScript", javascript_eval));
}
diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp
index bea54ae1cb..0442a1eaeb 100644
--- a/platform/javascript/api/javascript_tools_editor_plugin.cpp
+++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp
@@ -124,7 +124,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z
}
void JavaScriptToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zipFile p_zip) {
- DirAccess *dir = DirAccess::open(p_path);
+ DirAccessRef dir = DirAccess::open(p_path);
if (!dir) {
WARN_PRINT("Unable to open directory for zipping: " + p_path);
return;
diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp
index c7e503732d..e7855acf60 100644
--- a/platform/javascript/export/export_plugin.cpp
+++ b/platform/javascript/export/export_plugin.cpp
@@ -252,7 +252,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
// Custom offline page
const String offline_page = p_preset->get("progressive_web_app/offline_page");
if (!offline_page.is_empty()) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
const String offline_dest = dir.plus_file(name + ".offline.html");
err = da->copy(ProjectSettings::get_singleton()->globalize_path(offline_page), offline_dest);
if (err != OK) {
@@ -445,18 +445,18 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + pck_path);
return error;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- for (int i = 0; i < shared_objects.size(); i++) {
- String dst = base_dir.plus_file(shared_objects[i].path.get_file());
- error = da->copy(shared_objects[i].path, dst);
- if (error != OK) {
- EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + shared_objects[i].path.get_file());
- memdelete(da);
- return error;
+
+ {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < shared_objects.size(); i++) {
+ String dst = base_dir.plus_file(shared_objects[i].path.get_file());
+ error = da->copy(shared_objects[i].path, dst);
+ if (error != OK) {
+ EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + shared_objects[i].path.get_file());
+ return error;
+ }
}
}
- memdelete(da);
- da = nullptr;
// Extract templates.
error = _extract_template(template_path, base_dir, base_name, pwa);
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 6461a3d9fe..86874687ad 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -399,9 +399,11 @@ static String get_mountpoint(const String &p_path) {
}
Error OS_LinuxBSD::move_to_trash(const String &p_path) {
+ String path = p_path.rstrip("/"); // Strip trailing slash when path points to a directory
+
int err_code;
List<String> args;
- args.push_back(p_path);
+ args.push_back(path);
args.push_front("trash"); // The command is `gio trash <file_name>` so we need to add it to args.
Error result = execute("gio", args, nullptr, &err_code); // For GNOME based machines.
if (result == OK && !err_code) {
@@ -431,14 +433,14 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// If the commands `kioclient5`, `gio` or `gvfs-trash` don't exist on the system we do it manually.
String trash_path = "";
- String mnt = get_mountpoint(p_path);
+ String mnt = get_mountpoint(path);
// If there is a directory "[Mountpoint]/.Trash-[UID], use it as the trash can.
if (!mnt.is_empty()) {
- String path(mnt + "/.Trash-" + itos(getuid()));
+ String mountpoint_trash_path(mnt + "/.Trash-" + itos(getuid()));
struct stat s;
- if (!stat(path.utf8().get_data(), &s)) {
- trash_path = path;
+ if (!stat(mountpoint_trash_path.utf8().get_data(), &s)) {
+ trash_path = mountpoint_trash_path;
}
}
@@ -469,18 +471,15 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Issue an error if trash can is not created properly.
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"");
err = dir_access->make_dir_recursive(trash_path + "/files");
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "/files\"");
err = dir_access->make_dir_recursive(trash_path + "/info");
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "/info\"");
}
// The trash can is successfully created, now we check that we don't exceed our file name length limit.
// If the file name is too long trim it so we can add the identifying number and ".trashinfo".
// Assumes that the file name length limit is 255 characters.
- String file_name = p_path.get_file();
- if (file_name.length() == 0) {
- file_name = p_path.get_base_dir().get_file();
- }
+ String file_name = path.get_file();
if (file_name.length() > 240) {
file_name = file_name.substr(0, file_name.length() - 15);
}
@@ -503,29 +502,31 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
}
file_name = fn;
+ String renamed_path = path.get_base_dir() + "/" + file_name;
+
// Generates the .trashinfo file
OS::Date date = OS::get_singleton()->get_date(false);
OS::Time time = OS::get_singleton()->get_time(false);
String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.minute);
timestamp = vformat("%s%02d", timestamp, time.second); // vformat only supports up to 6 arguments.
- String trash_info = "[Trash Info]\nPath=" + p_path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
+ String trash_info = "[Trash Info]\nPath=" + path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;
FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\"");
file->store_string(trash_info);
file->close();
// Rename our resource before moving it to the trash can.
DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\"");
+ err = dir_access->rename(path, renamed_path);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + path + "\" to \"" + renamed_path + "\"");
}
// Move the given resource to the trash can.
// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
List<String> mv_args;
- mv_args.push_back(p_path.get_base_dir() + "/" + file_name);
+ mv_args.push_back(renamed_path);
mv_args.push_back(trash_path + "/files");
{
int retval;
@@ -533,11 +534,10 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Issue an error if "mv" failed to move the given resource to the trash can.
if (err != OK || retval != 0) {
- ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_path + "/files\"");
- DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- err = dir_access->rename(p_path.get_base_dir() + "/" + file_name, p_path);
- memdelete(dir_access);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename " + p_path.get_base_dir() + "/" + file_name + " back to its original name:" + p_path);
+ ERR_PRINT("move_to_trash: Could not move the resource \"" + path + "\" to the trash can \"" + trash_path + "/files\"");
+ DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ err = dir_access->rename(renamed_path, path);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename \"" + renamed_path + "\" back to its original name: \"" + path + "\"");
return FAILED;
}
}
diff --git a/platform/osx/export/codesign.cpp b/platform/osx/export/codesign.cpp
index 1a2ad2bee6..b609a21c44 100644
--- a/platform/osx/export/codesign.cpp
+++ b/platform/osx/export/codesign.cpp
@@ -1208,7 +1208,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
String id;
String main_exe = p_exe_path;
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (!da) {
r_error_msg = TTR("Can't get filesystem access.");
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access.");
@@ -1522,7 +1522,7 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
}
Error CodeSign::codesign(bool p_use_hardened_runtime, bool p_force, const String &p_path, const String &p_ent_path, String &r_error_msg) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (!da) {
r_error_msg = TTR("Can't get filesystem access.");
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access.");
diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp
index 4d0fc9add6..0f4477d312 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/osx/export/export_plugin.cpp
@@ -72,8 +72,6 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
@@ -81,18 +79,30 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/location_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the location information"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/location_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/address_book_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the address book"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/address_book_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/calendar_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the calendar"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/calendar_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photos_library_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the photo library"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photos_library_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/desktop_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Desktop folder"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/desktop_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/documents_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Documents folder"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/documents_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/downloads_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Downloads folder"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/downloads_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/network_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use network volumes"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/network_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/removable_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary()));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), ""));
@@ -316,9 +326,7 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
if (lines[i].find("$binary") != -1) {
strnew += lines[i].replace("$binary", p_binary) + "\n";
} else if (lines[i].find("$name") != -1) {
- strnew += lines[i].replace("$name", p_binary) + "\n";
- } else if (lines[i].find("$info") != -1) {
- strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
+ strnew += lines[i].replace("$name", ProjectSettings::get_singleton()->get("application/config/name")) + "\n";
} else if (lines[i].find("$bundle_identifier") != -1) {
strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (lines[i].find("$short_version") != -1) {
@@ -713,9 +721,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64";
String pkg_name;
- if (p_preset->get("application/name") != "") {
- pkg_name = p_preset->get("application/name"); // app_name
- } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
+ if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
} else {
pkg_name = "Unnamed";
@@ -781,24 +787,112 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
}
+ Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
+ Dictionary microphone_usage_descriptions = p_preset->get("privacy/microphone_usage_description_localized");
+ Dictionary camera_usage_descriptions = p_preset->get("privacy/camera_usage_description_localized");
+ Dictionary location_usage_descriptions = p_preset->get("privacy/location_usage_description_localized");
+ Dictionary address_book_usage_descriptions = p_preset->get("privacy/address_book_usage_description_localized");
+ Dictionary calendar_usage_descriptions = p_preset->get("privacy/calendar_usage_description_localized");
+ Dictionary photos_library_usage_descriptions = p_preset->get("privacy/photos_library_usage_description_localized");
+ Dictionary desktop_folder_usage_descriptions = p_preset->get("privacy/desktop_folder_usage_description_localized");
+ Dictionary documents_folder_usage_descriptions = p_preset->get("privacy/documents_folder_usage_description_localized");
+ Dictionary downloads_folder_usage_descriptions = p_preset->get("privacy/downloads_folder_usage_description_localized");
+ Dictionary network_volumes_usage_descriptions = p_preset->get("privacy/network_volumes_usage_description_localized");
+ Dictionary removable_volumes_usage_descriptions = p_preset->get("privacy/removable_volumes_usage_description_localized");
+ Dictionary copyrights = p_preset->get("application/copyright_localized");
+
Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations");
if (translations.size() > 0) {
{
String fname = tmp_app_path_name + "/Contents/Resources/en.lproj";
tmp_app_dir->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
+ if (!((String)p_preset->get("privacy/microphone_usage_description")).is_empty()) {
+ f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/camera_usage_description")).is_empty()) {
+ f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/location_usage_description")).is_empty()) {
+ f->store_line("NSLocationUsageDescription = \"" + p_preset->get("privacy/location_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/address_book_usage_description")).is_empty()) {
+ f->store_line("NSContactsUsageDescription = \"" + p_preset->get("privacy/address_book_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/calendar_usage_description")).is_empty()) {
+ f->store_line("NSCalendarsUsageDescription = \"" + p_preset->get("privacy/calendar_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/photos_library_usage_description")).is_empty()) {
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photos_library_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/desktop_folder_usage_description")).is_empty()) {
+ f->store_line("NSDesktopFolderUsageDescription = \"" + p_preset->get("privacy/desktop_folder_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/documents_folder_usage_description")).is_empty()) {
+ f->store_line("NSDocumentsFolderUsageDescription = \"" + p_preset->get("privacy/documents_folder_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/downloads_folder_usage_description")).is_empty()) {
+ f->store_line("NSDownloadsFolderUsageDescription = \"" + p_preset->get("privacy/downloads_folder_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/network_volumes_usage_description")).is_empty()) {
+ f->store_line("NSNetworkVolumesUsageDescription = \"" + p_preset->get("privacy/network_volumes_usage_description").operator String() + "\";");
+ }
+ if (!((String)p_preset->get("privacy/removable_volumes_usage_description")).is_empty()) {
+ f->store_line("NSRemovableVolumesUsageDescription = \"" + p_preset->get("privacy/removable_volumes_usage_description").operator String() + "\";");
+ }
+ f->store_line("NSHumanReadableCopyright = \"" + p_preset->get("application/copyright").operator String() + "\";");
}
for (const String &E : translations) {
Ref<Translation> tr = ResourceLoader::load(E);
if (tr.is_valid()) {
- String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj";
+ String lang = tr->get_locale();
+ String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj";
tmp_app_dir->make_dir_recursive(fname);
FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
- String prop = "application/config/name_" + tr->get_locale();
- if (ProjectSettings::get_singleton()->has_setting(prop)) {
- f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get(prop).operator String() + "\";");
+ f->store_line("/* Localized versions of Info.plist keys */");
+ f->store_line("");
+ if (appnames.has(lang)) {
+ f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
+ }
+ if (microphone_usage_descriptions.has(lang)) {
+ f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (camera_usage_descriptions.has(lang)) {
+ f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (location_usage_descriptions.has(lang)) {
+ f->store_line("NSLocationUsageDescription = \"" + location_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (address_book_usage_descriptions.has(lang)) {
+ f->store_line("NSContactsUsageDescription = \"" + address_book_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (calendar_usage_descriptions.has(lang)) {
+ f->store_line("NSCalendarsUsageDescription = \"" + calendar_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (photos_library_usage_descriptions.has(lang)) {
+ f->store_line("NSPhotoLibraryUsageDescription = \"" + photos_library_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (desktop_folder_usage_descriptions.has(lang)) {
+ f->store_line("NSDesktopFolderUsageDescription = \"" + desktop_folder_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (documents_folder_usage_descriptions.has(lang)) {
+ f->store_line("NSDocumentsFolderUsageDescription = \"" + documents_folder_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (downloads_folder_usage_descriptions.has(lang)) {
+ f->store_line("NSDownloadsFolderUsageDescription = \"" + downloads_folder_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (network_volumes_usage_descriptions.has(lang)) {
+ f->store_line("NSNetworkVolumesUsageDescription = \"" + network_volumes_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (removable_volumes_usage_descriptions.has(lang)) {
+ f->store_line("NSRemovableVolumesUsageDescription = \"" + removable_volumes_usage_descriptions[lang].operator String() + "\";");
+ }
+ if (copyrights.has(lang)) {
+ f->store_line("NSHumanReadableCopyright = \"" + copyrights[lang].operator String() + "\";");
}
}
}
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index a02b5f48a1..ab28a83806 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -39,10 +39,6 @@ AABB CPUParticles3D::get_aabb() const {
return AABB();
}
-Vector<Face3> CPUParticles3D::get_faces(uint32_t p_usage_particle_flags) const {
- return Vector<Face3>();
-}
-
void CPUParticles3D::set_emitting(bool p_emitting) {
if (emitting == p_emitting) {
return;
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index bd736bdf24..5eeb5e75d3 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -201,7 +201,6 @@ protected:
public:
AABB get_aabb() const override;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index dfac9055f5..8d0edfd1f3 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -152,10 +152,6 @@ AABB Decal::get_aabb() const {
return aabb;
}
-Vector<Face3> Decal::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void Decal::_validate_property(PropertyInfo &property) const {
if (!distance_fade_enabled && (property.name == "distance_fade_begin" || property.name == "distance_fade_length")) {
property.usage = PROPERTY_USAGE_NO_EDITOR;
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index 740dd2c407..d5990272c6 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -104,7 +104,6 @@ public:
uint32_t get_cull_mask() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
Decal();
~Decal();
diff --git a/scene/3d/fog_volume.h b/scene/3d/fog_volume.h
index 68d5c58169..556a92ad3f 100644
--- a/scene/3d/fog_volume.h
+++ b/scene/3d/fog_volume.h
@@ -62,7 +62,6 @@ public:
Ref<Material> get_material() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
TypedArray<String> get_configuration_warnings() const override;
FogVolume();
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 4e35f37291..9fe2210de6 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -36,10 +36,6 @@ AABB GPUParticles3D::get_aabb() const {
return AABB();
}
-Vector<Face3> GPUParticles3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void GPUParticles3D::set_emitting(bool p_emitting) {
RS::get_singleton()->particles_set_emitting(particles, p_emitting);
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index 54ae84628a..f3eb52d124 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -98,7 +98,6 @@ protected:
public:
AABB get_aabb() const override;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h
index b6de1d83fc..fdd2fa4b18 100644
--- a/scene/3d/gpu_particles_collision_3d.h
+++ b/scene/3d/gpu_particles_collision_3d.h
@@ -50,8 +50,6 @@ public:
void set_cull_mask(uint32_t p_cull_mask);
uint32_t get_cull_mask() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
-
~GPUParticlesCollision3D();
};
@@ -274,8 +272,6 @@ public:
void set_directionality(real_t p_directionality);
real_t get_directionality() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
-
~GPUParticlesAttractor3D();
};
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index f2021aa3d5..e7e164d7da 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -156,10 +156,6 @@ AABB Light3D::get_aabb() const {
return AABB();
}
-Vector<Face3> Light3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void Light3D::set_bake_mode(BakeMode p_mode) {
bake_mode = p_mode;
RS::get_singleton()->light_set_bake_mode(light, RS::LightBakeMode(p_mode));
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 11a9fcfc55..ed9e0bdfff 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -138,7 +138,6 @@ public:
Ref<Texture2D> get_projector() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
Light3D();
~Light3D();
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 07f41c0bf9..c74654b4bd 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -1263,10 +1263,6 @@ AABB LightmapGI::get_aabb() const {
return AABB();
}
-Vector<Face3> LightmapGI::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void LightmapGI::set_use_denoiser(bool p_enable) {
use_denoiser = p_enable;
}
diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h
index 66acf4f487..d29d7a7c28 100644
--- a/scene/3d/lightmap_gi.h
+++ b/scene/3d/lightmap_gi.h
@@ -267,7 +267,6 @@ public:
GenerateProbes get_generate_probes() const;
AABB get_aabb() const override;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr);
LightmapGI();
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index fddfa17dbb..31c33a6b61 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -219,18 +219,6 @@ AABB MeshInstance3D::get_aabb() const {
return AABB();
}
-Vector<Face3> MeshInstance3D::get_faces(uint32_t p_usage_flags) const {
- if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING))) {
- return Vector<Face3>();
- }
-
- if (mesh.is_null()) {
- return Vector<Face3>();
- }
-
- return mesh->get_faces();
-}
-
Node *MeshInstance3D::create_trimesh_collision_node() {
if (mesh.is_null()) {
return nullptr;
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 03ee3cd608..0bf5c32410 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -93,7 +93,6 @@ public:
void create_debug_tangents();
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
MeshInstance3D();
~MeshInstance3D();
diff --git a/scene/3d/multimesh_instance_3d.cpp b/scene/3d/multimesh_instance_3d.cpp
index 34b1e86435..d197388fad 100644
--- a/scene/3d/multimesh_instance_3d.cpp
+++ b/scene/3d/multimesh_instance_3d.cpp
@@ -49,10 +49,6 @@ Ref<MultiMesh> MultiMeshInstance3D::get_multimesh() const {
return multimesh;
}
-Vector<Face3> MultiMeshInstance3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
AABB MultiMeshInstance3D::get_aabb() const {
if (multimesh.is_null()) {
return AABB();
diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h
index d03b24eb4e..111f1e9c09 100644
--- a/scene/3d/multimesh_instance_3d.h
+++ b/scene/3d/multimesh_instance_3d.h
@@ -44,8 +44,6 @@ protected:
// bind helpers
public:
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
-
void set_multimesh(const Ref<MultiMesh> &p_multimesh);
Ref<MultiMesh> get_multimesh() const;
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index 855922c341..b82f05544b 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -433,10 +433,6 @@ AABB OccluderInstance3D::get_aabb() const {
return AABB();
}
-Vector<Face3> OccluderInstance3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void OccluderInstance3D::set_occluder(const Ref<Occluder3D> &p_occluder) {
if (occluder == p_occluder) {
return;
diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h
index 669ddba775..ed6610074e 100644
--- a/scene/3d/occluder_instance_3d.h
+++ b/scene/3d/occluder_instance_3d.h
@@ -194,7 +194,6 @@ public:
Ref<Occluder3D> get_occluder() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_bake_mask(uint32_t p_mask);
uint32_t get_bake_mask() const;
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index be655e71db..1bebd8e335 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -178,10 +178,6 @@ AABB ReflectionProbe::get_aabb() const {
return aabb;
}
-Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void ReflectionProbe::_validate_property(PropertyInfo &property) const {
if (property.name == "interior/ambient_color" || property.name == "interior/ambient_color_energy") {
if (ambient_mode != AMBIENT_COLOR) {
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index d0643496a4..424976d895 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -113,7 +113,6 @@ public:
UpdateMode get_update_mode() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
ReflectionProbe();
~ReflectionProbe();
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index ce281c79bc..514bd4aba0 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -177,10 +177,6 @@ AABB SpriteBase3D::get_aabb() const {
return aabb;
}
-Vector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
if (triangle_mesh.is_valid()) {
return triangle_mesh;
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 985103e190..92dbef0855 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -137,7 +137,7 @@ public:
virtual Rect2 get_item_rect() const = 0;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
+
Ref<TriangleMesh> generate_triangle_mesh() const;
SpriteBase3D();
diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp
index 11367d7ca9..41cd604a4f 100644
--- a/scene/3d/visible_on_screen_notifier_3d.cpp
+++ b/scene/3d/visible_on_screen_notifier_3d.cpp
@@ -89,10 +89,6 @@ void VisibleOnScreenNotifier3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("screen_exited"));
}
-Vector<Face3> VisibleOnScreenNotifier3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
VisibleOnScreenNotifier3D::VisibleOnScreenNotifier3D() {
RID notifier = RS::get_singleton()->visibility_notifier_create();
RS::get_singleton()->visibility_notifier_set_aabb(notifier, aabb);
diff --git a/scene/3d/visible_on_screen_notifier_3d.h b/scene/3d/visible_on_screen_notifier_3d.h
index 852c7e2ed3..fe17f1e444 100644
--- a/scene/3d/visible_on_screen_notifier_3d.h
+++ b/scene/3d/visible_on_screen_notifier_3d.h
@@ -57,8 +57,6 @@ public:
virtual AABB get_aabb() const override;
bool is_on_screen() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
-
VisibleOnScreenNotifier3D();
~VisibleOnScreenNotifier3D();
};
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index d8dffe6c7d..b8a68cdca9 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -32,6 +32,14 @@
#include "scene/scene_string_names.h"
+AABB VisualInstance3D::get_aabb() const {
+ AABB ret;
+ if (GDVIRTUAL_CALL(_get_aabb, ret)) {
+ return ret;
+ }
+ return AABB();
+}
+
AABB VisualInstance3D::get_transformed_aabb() const {
return get_global_transform().xform(get_aabb());
}
@@ -115,6 +123,7 @@ void VisualInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance3D::get_transformed_aabb);
+ GDVIRTUAL_BIND(_get_aabb);
ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask");
}
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index 02f62b41e5..1c044ba681 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -49,6 +49,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ GDVIRTUAL0RC(AABB, _get_aabb)
public:
enum GetFacesFlags {
FACES_SOLID = 1, // solid geometry
@@ -58,8 +59,7 @@ public:
};
RID get_instance() const;
- virtual AABB get_aabb() const = 0;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const = 0;
+ virtual AABB get_aabb() const;
virtual AABB get_transformed_aabb() const; // helper
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index bfe3c80a4f..6840d15f78 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -450,10 +450,6 @@ AABB VoxelGI::get_aabb() const {
return AABB(-extents, extents * 2);
}
-Vector<Face3> VoxelGI::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
TypedArray<String> VoxelGI::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h
index 3678bd4f3b..e1a38dd7a0 100644
--- a/scene/3d/voxel_gi.h
+++ b/scene/3d/voxel_gi.h
@@ -149,7 +149,6 @@ public:
void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
TypedArray<String> get_configuration_warnings() const override;
diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp
index 46fe832cf5..42adc1ea02 100644
--- a/scene/animation/root_motion_view.cpp
+++ b/scene/animation/root_motion_view.cpp
@@ -166,10 +166,6 @@ AABB RootMotionView::get_aabb() const {
return AABB(Vector3(-radius, 0, -radius), Vector3(radius * 2, 0.001, radius * 2));
}
-Vector<Face3> RootMotionView::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void RootMotionView::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_animation_path", "path"), &RootMotionView::set_animation_path);
ClassDB::bind_method(D_METHOD("get_animation_path"), &RootMotionView::get_animation_path);
diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h
index e8b141c1fd..8cb8ea8a9a 100644
--- a/scene/animation/root_motion_view.h
+++ b/scene/animation/root_motion_view.h
@@ -71,7 +71,6 @@ public:
bool get_zero_y() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
RootMotionView();
~RootMotionView();
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 678229683f..e71ab64535 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -176,7 +176,7 @@ void FileDialog::update_dir() {
if (dir_access->get_current_dir().is_network_share_path()) {
_update_drives(false);
drives->add_item(RTR("Network"));
- drives->set_item_disabled(drives->get_item_count() - 1, true);
+ drives->set_item_disabled(-1, true);
drives->select(drives->get_item_count() - 1);
} else {
drives->select(dir_access->get_current_drive());
@@ -919,9 +919,9 @@ void FileDialog::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir"), "set_current_dir", "get_current_dir");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file"), "set_current_file", "get_current_file");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path"), "set_current_path", "get_current_path");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_path", "get_current_path");
ADD_SIGNAL(MethodInfo("file_selected", PropertyInfo(Variant::STRING, "path")));
ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths")));
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 36a6b262b0..7a50efe40f 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -70,7 +70,6 @@ private:
Button *makedir;
Access access = ACCESS_RESOURCES;
- //Button *action;
VBoxContainer *vbox;
FileMode mode;
LineEdit *dir;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index ab21c747cf..1394b4192f 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1170,7 +1170,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
if (connecting) {
force_connection_drag_end();
} else {
- emit_signal(SNAME("popup_request"), get_screen_position() + b->get_position());
+ emit_signal(SNAME("popup_request"), b->get_position());
}
}
}
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index e83524b06c..8c0f696a9f 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -83,6 +83,9 @@ int ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
}
void ItemList::set_item_text(int p_idx, const String &p_text) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].text = p_text;
@@ -97,6 +100,9 @@ String ItemList::get_item_text(int p_idx) const {
}
void ItemList::set_item_text_direction(int p_idx, Control::TextDirection p_text_direction) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (items[p_idx].text_direction != p_text_direction) {
@@ -119,6 +125,9 @@ void ItemList::clear_item_opentype_features(int p_idx) {
}
void ItemList::set_item_opentype_feature(int p_idx, const String &p_name, int p_value) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_idx].opentype_features.has(tag) || (int)items[p_idx].opentype_features[tag] != p_value) {
@@ -138,6 +147,9 @@ int ItemList::get_item_opentype_feature(int p_idx, const String &p_name) const {
}
void ItemList::set_item_language(int p_idx, const String &p_language) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
if (items[p_idx].language != p_language) {
items.write[p_idx].language = p_language;
@@ -152,6 +164,9 @@ String ItemList::get_item_language(int p_idx) const {
}
void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip_enabled = p_enabled;
}
@@ -162,6 +177,9 @@ bool ItemList::is_item_tooltip_enabled(int p_idx) const {
}
void ItemList::set_item_tooltip(int p_idx, const String &p_tooltip) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip = p_tooltip;
@@ -175,6 +193,9 @@ String ItemList::get_item_tooltip(int p_idx) const {
}
void ItemList::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon = p_icon;
@@ -189,6 +210,9 @@ Ref<Texture2D> ItemList::get_item_icon(int p_idx) const {
}
void ItemList::set_item_icon_transposed(int p_idx, const bool p_transposed) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon_transposed = p_transposed;
@@ -203,6 +227,9 @@ bool ItemList::is_item_icon_transposed(int p_idx) const {
}
void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon_region = p_region;
@@ -217,6 +244,9 @@ Rect2 ItemList::get_item_icon_region(int p_idx) const {
}
void ItemList::set_item_icon_modulate(int p_idx, const Color &p_modulate) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon_modulate = p_modulate;
@@ -230,6 +260,9 @@ Color ItemList::get_item_icon_modulate(int p_idx) const {
}
void ItemList::set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_color) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].custom_bg = p_custom_bg_color;
@@ -243,6 +276,9 @@ Color ItemList::get_item_custom_bg_color(int p_idx) const {
}
void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].custom_fg = p_custom_fg_color;
@@ -256,6 +292,9 @@ Color ItemList::get_item_custom_fg_color(int p_idx) const {
}
void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture2D> &p_tag_icon) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tag_icon = p_tag_icon;
@@ -270,6 +309,9 @@ Ref<Texture2D> ItemList::get_item_tag_icon(int p_idx) const {
}
void ItemList::set_item_selectable(int p_idx, bool p_selectable) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].selectable = p_selectable;
@@ -281,6 +323,9 @@ bool ItemList::is_item_selectable(int p_idx) const {
}
void ItemList::set_item_disabled(int p_idx, bool p_disabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].disabled = p_disabled;
@@ -293,6 +338,9 @@ bool ItemList::is_item_disabled(int p_idx) const {
}
void ItemList::set_item_metadata(int p_idx, const Variant &p_metadata) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].metadata = p_metadata;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 840c3d5c31..4220066b20 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -999,6 +999,9 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu,
/* Methods to modify existing items. */
void PopupMenu::set_item_text(int p_idx, const String &p_text) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].text = p_text;
items.write[p_idx].xl_text = atr(p_text);
@@ -1009,6 +1012,9 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) {
}
void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_text_direction) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (items[p_item].text_direction != p_text_direction) {
@@ -1019,6 +1025,9 @@ void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_tex
}
void PopupMenu::clear_item_opentype_features(int p_item) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
items.write[p_item].opentype_features.clear();
items.write[p_item].dirty = true;
@@ -1026,6 +1035,9 @@ void PopupMenu::clear_item_opentype_features(int p_item) {
}
void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int p_value) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_item].opentype_features.has(tag) || (int)items[p_item].opentype_features[tag] != p_value) {
@@ -1036,6 +1048,9 @@ void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int
}
void PopupMenu::set_item_language(int p_item, const String &p_language) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
if (items[p_item].language != p_language) {
items.write[p_item].language = p_language;
@@ -1045,6 +1060,9 @@ void PopupMenu::set_item_language(int p_item, const String &p_language) {
}
void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon = p_icon;
@@ -1053,6 +1071,9 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
}
void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checked = p_checked;
@@ -1062,6 +1083,9 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
}
void PopupMenu::set_item_id(int p_idx, int p_id) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].id = p_id;
@@ -1070,6 +1094,9 @@ void PopupMenu::set_item_id(int p_idx, int p_id) {
}
void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].accel = p_accel;
items.write[p_idx].dirty = true;
@@ -1079,6 +1106,9 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
}
void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].metadata = p_meta;
control->update();
@@ -1086,6 +1116,9 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
}
void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].disabled = p_disabled;
control->update();
@@ -1093,6 +1126,9 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
}
void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].submenu = p_submenu;
control->update();
@@ -1201,6 +1237,9 @@ int PopupMenu::get_item_state(int p_idx) const {
}
void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].separator = p_separator;
control->update();
@@ -1212,24 +1251,36 @@ bool PopupMenu::is_item_separator(int p_idx) const {
}
void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
control->update();
}
void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
control->update();
}
void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip = p_tooltip;
control->update();
}
void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
if (items[p_idx].shortcut.is_valid()) {
_unref_shortcut(items[p_idx].shortcut);
@@ -1246,6 +1297,9 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
}
void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].h_ofs = p_offset;
control->update();
@@ -1253,12 +1307,18 @@ void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
}
void PopupMenu::set_item_multistate(int p_idx, int p_state) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].state = p_state;
control->update();
}
void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].shortcut_is_disabled = p_disabled;
control->update();
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 879f25c8d8..2fb6452a97 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -40,6 +40,9 @@ TypedArray<String> Range::get_configuration_warnings() const {
return warnings;
}
+void Range::_value_changed(double p_value) {
+ GDVIRTUAL_CALL(_value_changed, p_value);
+}
void Range::_value_changed_notify() {
_value_changed(shared->val);
emit_signal(SNAME("value_changed"), shared->val);
@@ -279,6 +282,8 @@ void Range::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_greater"), "set_allow_greater", "is_greater_allowed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_lesser"), "set_allow_lesser", "is_lesser_allowed");
+ GDVIRTUAL_BIND(_value_changed);
+
ADD_LINKED_PROPERTY("min_value", "value");
ADD_LINKED_PROPERTY("min_value", "max_value");
ADD_LINKED_PROPERTY("min_value", "page");
diff --git a/scene/gui/range.h b/scene/gui/range.h
index c27eeee13c..597c50ca26 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -62,12 +62,14 @@ class Range : public Control {
void _validate_values();
protected:
- virtual void _value_changed(double) {}
+ virtual void _value_changed(double p_value);
static void _bind_methods();
bool _rounded_values = false;
+ GDVIRTUAL1(_value_changed, double)
+
public:
void set_value(double p_val);
void set_min(double p_min);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index bad7be7d42..0a36176c98 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -902,9 +902,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
for (int i = 0; i < gl_size; i++) {
Item *it = _get_item_at_pos(it_from, it_to, glyphs[i].start);
int size = _find_outline_size(it, p_outline_size);
- Color font_color = _find_outline_color(it, p_outline_color);
+ Color font_color = _find_color(it, p_base_color);
+ Color font_outline_color = _find_outline_color(it, p_outline_color);
Color font_shadow_color = p_font_shadow_color;
- if ((size <= 0 || font_color.a == 0) && (font_shadow_color.a == 0)) {
+ if ((size <= 0 || font_outline_color.a == 0) && (font_shadow_color.a == 0)) {
gloff.x += glyphs[i].advance;
continue;
}
@@ -950,11 +951,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
faded_visibility -= (float)(glyphs[i].start - fade->starting_index) / (float)fade->length;
faded_visibility = faded_visibility < 0.0f ? 0.0f : faded_visibility;
}
- font_color.a = faded_visibility;
+ font_outline_color.a = faded_visibility;
font_shadow_color.a = faded_visibility;
}
- bool visible = (font_color.a != 0) || (font_shadow_color.a != 0);
+ bool visible = (font_outline_color.a != 0) || (font_shadow_color.a != 0);
for (int j = 0; j < fx_stack.size(); j++) {
ItemFX *item_fx = fx_stack[j];
@@ -1024,18 +1025,20 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
// Draw glyph outlines.
+ const Color modulated_outline_color = font_outline_color * Color(1, 1, 1, font_color.a);
+ const Color modulated_shadow_color = font_shadow_color * Color(1, 1, 1, font_color.a);
for (int j = 0; j < glyphs[i].repeat; j++) {
if (visible) {
bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (processed_glyphs_ol >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_ol < total_glyphs - visible_glyphs));
if (!skip && frid != RID()) {
- if (font_shadow_color.a > 0) {
- TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color);
+ if (modulated_shadow_color.a > 0) {
+ TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color);
}
- if (font_shadow_color.a > 0 && p_shadow_outline_size > 0) {
- TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color);
+ if (modulated_shadow_color.a > 0 && p_shadow_outline_size > 0) {
+ TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color);
}
- if (font_color.a != 0.0 && size > 0) {
- TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, font_color);
+ if (modulated_outline_color.a != 0.0 && size > 0) {
+ TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, modulated_outline_color);
}
}
processed_glyphs_ol++;
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 5fd31c5416..e50d7e765c 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -39,7 +39,7 @@ Size2 SpinBox::get_minimum_size() const {
return ms;
}
-void SpinBox::_value_changed(double) {
+void SpinBox::_value_changed(double p_value) {
String value = TS->format_number(String::num(get_value(), Math::range_step_decimals(get_step())));
if (!prefix.is_empty()) {
value = prefix + " " + value;
@@ -48,6 +48,7 @@ void SpinBox::_value_changed(double) {
value += " " + suffix;
}
line_edit->set_text(value);
+ Range::_value_changed(p_value);
}
void SpinBox::_text_submitted(const String &p_string) {
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 0691a4b48d..a15e3fe5f5 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -47,7 +47,7 @@ class SpinBox : public Range {
void _release_mouse();
void _text_submitted(const String &p_string);
- virtual void _value_changed(double) override;
+ virtual void _value_changed(double p_value) override;
void _text_changed(const String &p_string);
String prefix;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 05fda7128c..3c80e3f987 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4469,7 +4469,11 @@ int TextEdit::get_visible_line_count() const {
int TextEdit::get_visible_line_count_in_range(int p_from_line, int p_to_line) const {
ERR_FAIL_INDEX_V(p_from_line, text.size(), 0);
ERR_FAIL_INDEX_V(p_to_line, text.size(), 0);
- ERR_FAIL_COND_V(p_from_line > p_to_line, 0);
+
+ // So we can handle inputs in whatever order
+ if (p_from_line > p_to_line) {
+ SWAP(p_from_line, p_to_line);
+ }
/* Returns the total number of (lines + wrapped - hidden). */
if (!_is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) {
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 4a6ba98c4f..fb5d57ab9e 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -300,9 +300,9 @@ void register_scene_types() {
GDREGISTER_CLASS(Object);
GDREGISTER_CLASS(Node);
- GDREGISTER_VIRTUAL_CLASS(InstancePlaceholder);
+ GDREGISTER_ABSTRACT_CLASS(InstancePlaceholder);
- GDREGISTER_VIRTUAL_CLASS(Viewport);
+ GDREGISTER_ABSTRACT_CLASS(Viewport);
GDREGISTER_CLASS(SubViewport);
GDREGISTER_CLASS(ViewportTexture);
GDREGISTER_CLASS(HTTPRequest);
@@ -324,11 +324,11 @@ void register_scene_types() {
GDREGISTER_CLASS(Control);
GDREGISTER_CLASS(Button);
GDREGISTER_CLASS(Label);
- GDREGISTER_VIRTUAL_CLASS(ScrollBar);
+ GDREGISTER_ABSTRACT_CLASS(ScrollBar);
GDREGISTER_CLASS(HScrollBar);
GDREGISTER_CLASS(VScrollBar);
GDREGISTER_CLASS(ProgressBar);
- GDREGISTER_VIRTUAL_CLASS(Slider);
+ GDREGISTER_ABSTRACT_CLASS(Slider);
GDREGISTER_CLASS(HSlider);
GDREGISTER_CLASS(VSlider);
GDREGISTER_CLASS(Popup);
@@ -349,19 +349,19 @@ void register_scene_types() {
GDREGISTER_CLASS(AspectRatioContainer);
GDREGISTER_CLASS(TabContainer);
GDREGISTER_CLASS(TabBar);
- GDREGISTER_VIRTUAL_CLASS(Separator);
+ GDREGISTER_ABSTRACT_CLASS(Separator);
GDREGISTER_CLASS(HSeparator);
GDREGISTER_CLASS(VSeparator);
GDREGISTER_CLASS(TextureButton);
GDREGISTER_CLASS(Container);
- GDREGISTER_VIRTUAL_CLASS(BoxContainer);
+ GDREGISTER_ABSTRACT_CLASS(BoxContainer);
GDREGISTER_CLASS(HBoxContainer);
GDREGISTER_CLASS(VBoxContainer);
GDREGISTER_CLASS(GridContainer);
GDREGISTER_CLASS(CenterContainer);
GDREGISTER_CLASS(ScrollContainer);
GDREGISTER_CLASS(PanelContainer);
- GDREGISTER_VIRTUAL_CLASS(FlowContainer);
+ GDREGISTER_ABSTRACT_CLASS(FlowContainer);
GDREGISTER_CLASS(HFlowContainer);
GDREGISTER_CLASS(VFlowContainer);
@@ -384,7 +384,7 @@ void register_scene_types() {
GDREGISTER_CLASS(SyntaxHighlighter);
GDREGISTER_CLASS(CodeHighlighter);
- GDREGISTER_VIRTUAL_CLASS(TreeItem);
+ GDREGISTER_ABSTRACT_CLASS(TreeItem);
GDREGISTER_CLASS(OptionButton);
GDREGISTER_CLASS(SpinBox);
GDREGISTER_CLASS(ColorPicker);
@@ -398,7 +398,7 @@ void register_scene_types() {
GDREGISTER_CLASS(MarginContainer);
GDREGISTER_CLASS(SubViewportContainer);
- GDREGISTER_VIRTUAL_CLASS(SplitContainer);
+ GDREGISTER_ABSTRACT_CLASS(SplitContainer);
GDREGISTER_CLASS(HSplitContainer);
GDREGISTER_CLASS(VSplitContainer);
@@ -418,7 +418,7 @@ void register_scene_types() {
GDREGISTER_CLASS(AnimationPlayer);
GDREGISTER_CLASS(Tween);
- GDREGISTER_VIRTUAL_CLASS(Tweener);
+ GDREGISTER_ABSTRACT_CLASS(Tweener);
GDREGISTER_CLASS(PropertyTweener);
GDREGISTER_CLASS(IntervalTweener);
GDREGISTER_CLASS(CallbackTweener);
@@ -453,9 +453,9 @@ void register_scene_types() {
#ifndef _3D_DISABLED
GDREGISTER_CLASS(Node3D);
- GDREGISTER_VIRTUAL_CLASS(Node3DGizmo);
+ GDREGISTER_ABSTRACT_CLASS(Node3DGizmo);
GDREGISTER_CLASS(Skin);
- GDREGISTER_VIRTUAL_CLASS(SkinReference);
+ GDREGISTER_ABSTRACT_CLASS(SkinReference);
GDREGISTER_CLASS(Skeleton3D);
GDREGISTER_CLASS(ImporterMesh);
GDREGISTER_CLASS(ImporterMeshInstance3D);
@@ -464,22 +464,22 @@ void register_scene_types() {
GDREGISTER_CLASS(Camera3D);
GDREGISTER_CLASS(AudioListener3D);
GDREGISTER_CLASS(XRCamera3D);
- GDREGISTER_VIRTUAL_CLASS(XRNode3D);
+ GDREGISTER_ABSTRACT_CLASS(XRNode3D);
GDREGISTER_CLASS(XRController3D);
GDREGISTER_CLASS(XRAnchor3D);
GDREGISTER_CLASS(XROrigin3D);
GDREGISTER_CLASS(MeshInstance3D);
GDREGISTER_CLASS(OccluderInstance3D);
- GDREGISTER_VIRTUAL_CLASS(Occluder3D);
+ GDREGISTER_ABSTRACT_CLASS(Occluder3D);
GDREGISTER_CLASS(ArrayOccluder3D);
GDREGISTER_CLASS(QuadOccluder3D);
GDREGISTER_CLASS(BoxOccluder3D);
GDREGISTER_CLASS(SphereOccluder3D);
GDREGISTER_CLASS(PolygonOccluder3D);
- GDREGISTER_VIRTUAL_CLASS(SpriteBase3D);
+ GDREGISTER_ABSTRACT_CLASS(SpriteBase3D);
GDREGISTER_CLASS(Sprite3D);
GDREGISTER_CLASS(AnimatedSprite3D);
- GDREGISTER_VIRTUAL_CLASS(Light3D);
+ GDREGISTER_ABSTRACT_CLASS(Light3D);
GDREGISTER_CLASS(DirectionalLight3D);
GDREGISTER_CLASS(OmniLight3D);
GDREGISTER_CLASS(SpotLight3D);
@@ -490,14 +490,14 @@ void register_scene_types() {
GDREGISTER_CLASS(LightmapGI);
GDREGISTER_CLASS(LightmapGIData);
GDREGISTER_CLASS(LightmapProbe);
- GDREGISTER_VIRTUAL_CLASS(Lightmapper);
+ GDREGISTER_ABSTRACT_CLASS(Lightmapper);
GDREGISTER_CLASS(GPUParticles3D);
- GDREGISTER_VIRTUAL_CLASS(GPUParticlesCollision3D);
+ GDREGISTER_ABSTRACT_CLASS(GPUParticlesCollision3D);
GDREGISTER_CLASS(GPUParticlesCollisionBox3D);
GDREGISTER_CLASS(GPUParticlesCollisionSphere3D);
GDREGISTER_CLASS(GPUParticlesCollisionSDF3D);
GDREGISTER_CLASS(GPUParticlesCollisionHeightField3D);
- GDREGISTER_VIRTUAL_CLASS(GPUParticlesAttractor3D);
+ GDREGISTER_ABSTRACT_CLASS(GPUParticlesAttractor3D);
GDREGISTER_CLASS(GPUParticlesAttractorBox3D);
GDREGISTER_CLASS(GPUParticlesAttractorSphere3D);
GDREGISTER_CLASS(GPUParticlesAttractorVectorField3D);
@@ -509,8 +509,8 @@ void register_scene_types() {
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(CollisionObject3D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D);
+ GDREGISTER_ABSTRACT_CLASS(CollisionObject3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsBody3D);
GDREGISTER_CLASS(StaticBody3D);
GDREGISTER_CLASS(AnimatableBody3D);
GDREGISTER_CLASS(RigidDynamicBody3D);
@@ -542,7 +542,7 @@ void register_scene_types() {
GDREGISTER_CLASS(FogMaterial);
GDREGISTER_CLASS(RemoteTransform3D);
- GDREGISTER_VIRTUAL_CLASS(Joint3D);
+ GDREGISTER_ABSTRACT_CLASS(Joint3D);
GDREGISTER_CLASS(PinJoint3D);
GDREGISTER_CLASS(HingeJoint3D);
GDREGISTER_CLASS(SliderJoint3D);
@@ -560,14 +560,14 @@ void register_scene_types() {
GDREGISTER_CLASS(Shader);
GDREGISTER_CLASS(VisualShader);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNode);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNode);
GDREGISTER_CLASS(VisualShaderNodeCustom);
GDREGISTER_CLASS(VisualShaderNodeInput);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeOutput);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeResizableBase);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeGroupBase);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeConstant);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeVectorBase);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeOutput);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeResizableBase);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeGroupBase);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeConstant);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeVectorBase);
GDREGISTER_CLASS(VisualShaderNodeComment);
GDREGISTER_CLASS(VisualShaderNodeFloatConstant);
GDREGISTER_CLASS(VisualShaderNodeIntConstant);
@@ -607,11 +607,11 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeTexture);
GDREGISTER_CLASS(VisualShaderNodeCurveTexture);
GDREGISTER_CLASS(VisualShaderNodeCurveXYZTexture);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeSample3D);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeSample3D);
GDREGISTER_CLASS(VisualShaderNodeTexture2DArray);
GDREGISTER_CLASS(VisualShaderNodeTexture3D);
GDREGISTER_CLASS(VisualShaderNodeCubemap);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeUniform);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeUniform);
GDREGISTER_CLASS(VisualShaderNodeUniformRef);
GDREGISTER_CLASS(VisualShaderNodeFloatUniform);
GDREGISTER_CLASS(VisualShaderNodeIntUniform);
@@ -634,7 +634,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeCompare);
GDREGISTER_CLASS(VisualShaderNodeMultiplyAdd);
GDREGISTER_CLASS(VisualShaderNodeBillboard);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeVarying);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeVarying);
GDREGISTER_CLASS(VisualShaderNodeVaryingSetter);
GDREGISTER_CLASS(VisualShaderNodeVaryingGetter);
@@ -645,7 +645,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeSDFRaymarch);
GDREGISTER_CLASS(VisualShaderNodeParticleOutput);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeParticleEmitter);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeParticleEmitter);
GDREGISTER_CLASS(VisualShaderNodeParticleSphereEmitter);
GDREGISTER_CLASS(VisualShaderNodeParticleBoxEmitter);
GDREGISTER_CLASS(VisualShaderNodeParticleRingEmitter);
@@ -657,7 +657,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeParticleEmit);
GDREGISTER_CLASS(ShaderMaterial);
- GDREGISTER_VIRTUAL_CLASS(CanvasItem);
+ GDREGISTER_ABSTRACT_CLASS(CanvasItem);
GDREGISTER_CLASS(CanvasTexture);
GDREGISTER_CLASS(CanvasItemMaterial);
SceneTree::add_idle_callback(CanvasItemMaterial::flush_changes);
@@ -676,8 +676,8 @@ void register_scene_types() {
GDREGISTER_CLASS(Line2D);
GDREGISTER_CLASS(MeshInstance2D);
GDREGISTER_CLASS(MultiMeshInstance2D);
- GDREGISTER_VIRTUAL_CLASS(CollisionObject2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsBody2D);
+ GDREGISTER_ABSTRACT_CLASS(CollisionObject2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsBody2D);
GDREGISTER_CLASS(StaticBody2D);
GDREGISTER_CLASS(AnimatableBody2D);
GDREGISTER_CLASS(RigidDynamicBody2D);
@@ -693,7 +693,7 @@ void register_scene_types() {
GDREGISTER_CLASS(Polygon2D);
GDREGISTER_CLASS(Skeleton2D);
GDREGISTER_CLASS(Bone2D);
- GDREGISTER_VIRTUAL_CLASS(Light2D);
+ GDREGISTER_ABSTRACT_CLASS(Light2D);
GDREGISTER_CLASS(PointLight2D);
GDREGISTER_CLASS(DirectionalLight2D);
GDREGISTER_CLASS(LightOccluder2D);
@@ -704,12 +704,12 @@ void register_scene_types() {
GDREGISTER_CLASS(Camera2D);
GDREGISTER_CLASS(AudioListener2D);
- GDREGISTER_VIRTUAL_CLASS(Joint2D);
+ GDREGISTER_ABSTRACT_CLASS(Joint2D);
GDREGISTER_CLASS(PinJoint2D);
GDREGISTER_CLASS(GrooveJoint2D);
GDREGISTER_CLASS(DampedSpringJoint2D);
GDREGISTER_CLASS(TileSet);
- GDREGISTER_VIRTUAL_CLASS(TileSetSource);
+ GDREGISTER_ABSTRACT_CLASS(TileSetSource);
GDREGISTER_CLASS(TileSetAtlasSource);
GDREGISTER_CLASS(TileSetScenesCollectionSource);
GDREGISTER_CLASS(TileMapPattern);
@@ -736,7 +736,7 @@ void register_scene_types() {
/* REGISTER RESOURCES */
- GDREGISTER_VIRTUAL_CLASS(Shader);
+ GDREGISTER_ABSTRACT_CLASS(Shader);
GDREGISTER_CLASS(ParticlesMaterial);
SceneTree::add_idle_callback(ParticlesMaterial::flush_changes);
ParticlesMaterial::init_shaders();
@@ -765,7 +765,7 @@ void register_scene_types() {
GDREGISTER_CLASS(RibbonTrailMesh);
GDREGISTER_CLASS(PointMesh);
GDREGISTER_VIRTUAL_CLASS(Material);
- GDREGISTER_VIRTUAL_CLASS(BaseMaterial3D);
+ GDREGISTER_ABSTRACT_CLASS(BaseMaterial3D);
GDREGISTER_CLASS(StandardMaterial3D);
GDREGISTER_CLASS(ORMMaterial3D);
SceneTree::add_idle_callback(BaseMaterial3D::flush_changes);
@@ -775,7 +775,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(Shape3D);
+ GDREGISTER_ABSTRACT_CLASS(Shape3D);
GDREGISTER_CLASS(SeparationRayShape3D);
GDREGISTER_CLASS(SphereShape3D);
GDREGISTER_CLASS(BoxShape3D);
@@ -820,14 +820,14 @@ void register_scene_types() {
GDREGISTER_CLASS(AnimatedTexture);
GDREGISTER_CLASS(CameraTexture);
GDREGISTER_VIRTUAL_CLASS(TextureLayered);
- GDREGISTER_VIRTUAL_CLASS(ImageTextureLayered);
+ GDREGISTER_ABSTRACT_CLASS(ImageTextureLayered);
GDREGISTER_VIRTUAL_CLASS(Texture3D);
GDREGISTER_CLASS(ImageTexture3D);
GDREGISTER_CLASS(CompressedTexture3D);
GDREGISTER_CLASS(Cubemap);
GDREGISTER_CLASS(CubemapArray);
GDREGISTER_CLASS(Texture2DArray);
- GDREGISTER_VIRTUAL_CLASS(CompressedTextureLayered);
+ GDREGISTER_ABSTRACT_CLASS(CompressedTextureLayered);
GDREGISTER_CLASS(CompressedCubemap);
GDREGISTER_CLASS(CompressedCubemapArray);
GDREGISTER_CLASS(CompressedTexture2DArray);
@@ -860,12 +860,12 @@ void register_scene_types() {
#ifndef _3D_DISABLED
GDREGISTER_CLASS(AudioStreamPlayer3D);
#endif
- GDREGISTER_VIRTUAL_CLASS(VideoStream);
+ GDREGISTER_ABSTRACT_CLASS(VideoStream);
GDREGISTER_CLASS(AudioStreamSample);
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(Shape2D);
+ GDREGISTER_ABSTRACT_CLASS(Shape2D);
GDREGISTER_CLASS(WorldBoundaryShape2D);
GDREGISTER_CLASS(SegmentShape2D);
GDREGISTER_CLASS(SeparationRayShape2D);
@@ -886,11 +886,11 @@ void register_scene_types() {
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(SceneState);
+ GDREGISTER_ABSTRACT_CLASS(SceneState);
GDREGISTER_CLASS(PackedScene);
GDREGISTER_CLASS(SceneTree);
- GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); // sorry, you can't create it
+ GDREGISTER_ABSTRACT_CLASS(SceneTreeTimer); // sorry, you can't create it
#ifndef DISABLE_DEPRECATED
// Dropped in 4.0, near approximation.
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 61114333fb..da37228ed9 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -103,7 +103,7 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi
return style;
}
-void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
+void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
scale = p_scale;
// Font colors
@@ -924,9 +924,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_stylebox("normal", "RichTextLabel", make_empty_stylebox(0, 0, 0, 0));
theme->set_font("normal_font", "RichTextLabel", Ref<Font>());
- theme->set_font("bold_font", "RichTextLabel", Ref<Font>());
- theme->set_font("italics_font", "RichTextLabel", Ref<Font>());
- theme->set_font("bold_italics_font", "RichTextLabel", Ref<Font>());
+ theme->set_font("bold_font", "RichTextLabel", bold_font);
+ theme->set_font("italics_font", "RichTextLabel", italics_font);
+ theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font);
theme->set_font("mono_font", "RichTextLabel", Ref<Font>());
theme->set_font_size("normal_font_size", "RichTextLabel", -1);
@@ -1025,6 +1025,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
+ Ref<Font> bold_font;
+ Ref<Font> bold_italics_font;
+ Ref<Font> italics_font;
float default_scale = CLAMP(p_scale, 0.5, 8.0);
if (p_font.is_valid()) {
@@ -1048,7 +1051,31 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
default_font = dynamic_font;
}
- fill_default_theme(t, default_font, default_icon, default_style, default_scale);
+ if (default_font.is_valid()) {
+ bold_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_embolden(1.2);
+ bold_font->add_data(data);
+ }
+
+ bold_italics_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_embolden(1.2);
+ data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
+ bold_italics_font->add_data(data);
+ }
+
+ italics_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
+ italics_font->add_data(data);
+ }
+ }
+
+ fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale);
Theme::set_default(t);
Theme::set_fallback_base_scale(default_scale);
diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h
index 28afd5f5e1..a9e21dda3f 100644
--- a/scene/resources/default_theme/default_theme.h
+++ b/scene/resources/default_theme/default_theme.h
@@ -35,7 +35,7 @@
const int default_font_size = 16;
-void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
+void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa);
void clear_default_theme();
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 5b57e93950..ce2a675854 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -61,6 +61,8 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
TS->font_set_hinting(cache[p_cache_index], hinting);
TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
+ TS->font_set_embolden(cache[p_cache_index], embolden);
+ TS->font_set_transform(cache[p_cache_index], transform);
TS->font_set_oversampling(cache[p_cache_index], oversampling);
}
}
@@ -105,6 +107,12 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("set_embolden", "strength"), &FontData::set_embolden);
+ ClassDB::bind_method(D_METHOD("get_embolden"), &FontData::get_embolden);
+
+ ClassDB::bind_method(D_METHOD("set_transform", "transform"), &FontData::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"), &FontData::get_transform);
+
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling);
ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling);
@@ -209,6 +217,8 @@ void FontData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01", PROPERTY_USAGE_STORAGE), "set_embolden", "get_embolden");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
@@ -439,6 +449,8 @@ void FontData::reset_state() {
msdf_pixel_range = 14;
msdf_size = 128;
fixed_size = 0;
+ embolden = 0.f;
+ transform = Transform2D();
oversampling = 0.f;
}
@@ -1385,6 +1397,36 @@ TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const {
return subpixel_positioning;
}
+void FontData::set_embolden(float p_strength) {
+ if (embolden != p_strength) {
+ embolden = p_strength;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_embolden(cache[i], embolden);
+ }
+ emit_changed();
+ }
+}
+
+float FontData::get_embolden() const {
+ return embolden;
+}
+
+void FontData::set_transform(Transform2D p_transform) {
+ if (transform != p_transform) {
+ transform = p_transform;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_transform(cache[i], transform);
+ }
+ emit_changed();
+ }
+}
+
+Transform2D FontData::get_transform() const {
+ return transform;
+}
+
void FontData::set_oversampling(real_t p_oversampling) {
if (oversampling != p_oversampling) {
oversampling = p_oversampling;
diff --git a/scene/resources/font.h b/scene/resources/font.h
index aaf0a7fe7b..0185b019f1 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -57,6 +57,8 @@ class FontData : public Resource {
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f;
+ real_t embolden = 0.f;
+ Transform2D transform;
// Cache.
mutable Vector<RID> cache;
@@ -122,6 +124,12 @@ public:
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
+ virtual void set_embolden(float p_strength);
+ virtual float get_embolden() const;
+
+ virtual void set_transform(Transform2D p_transform);
+ virtual Transform2D get_transform() const;
+
virtual void set_oversampling(real_t p_oversampling);
virtual real_t get_oversampling() const;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 6fb0c0468d..a0e6cc28ce 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -88,6 +88,37 @@ void Material::inspect_native_shader_code() {
}
}
+RID Material::get_shader_rid() const {
+ RID ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_shader_rid, ret)) {
+ return ret;
+ }
+ return RID();
+}
+Shader::Mode Material::get_shader_mode() const {
+ Shader::Mode ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_shader_mode, ret)) {
+ return ret;
+ }
+
+ return Shader::MODE_MAX;
+}
+
+bool Material::_can_do_next_pass() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_can_do_next_pass, ret)) {
+ return ret;
+ }
+ return false;
+}
+bool Material::_can_use_render_priority() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_can_use_render_priority, ret)) {
+ return ret;
+ }
+ return false;
+}
+
void Material::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass"), &Material::set_next_pass);
ClassDB::bind_method(D_METHOD("get_next_pass"), &Material::get_next_pass);
@@ -103,6 +134,11 @@ void Material::_bind_methods() {
BIND_CONSTANT(RENDER_PRIORITY_MAX);
BIND_CONSTANT(RENDER_PRIORITY_MIN);
+
+ GDVIRTUAL_BIND(_get_shader_rid)
+ GDVIRTUAL_BIND(_get_shader_mode)
+ GDVIRTUAL_BIND(_can_do_next_pass)
+ GDVIRTUAL_BIND(_can_use_render_priority)
}
Material::Material() {
diff --git a/scene/resources/material.h b/scene/resources/material.h
index a79f072f9a..07227c037c 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -51,11 +51,15 @@ class Material : public Resource {
protected:
_FORCE_INLINE_ RID _get_material() const { return material; }
static void _bind_methods();
- virtual bool _can_do_next_pass() const { return false; }
- virtual bool _can_use_render_priority() const { return false; }
+ virtual bool _can_do_next_pass() const;
+ virtual bool _can_use_render_priority() const;
void _validate_property(PropertyInfo &property) const override;
+ GDVIRTUAL0RC(RID, _get_shader_rid)
+ GDVIRTUAL0RC(Shader::Mode, _get_shader_mode)
+ GDVIRTUAL0RC(bool, _can_do_next_pass)
+ GDVIRTUAL0RC(bool, _can_use_render_priority)
public:
enum {
RENDER_PRIORITY_MAX = RS::MATERIAL_RENDER_PRIORITY_MAX,
@@ -68,9 +72,8 @@ public:
int get_render_priority() const;
virtual RID get_rid() const override;
- virtual RID get_shader_rid() const = 0;
-
- virtual Shader::Mode get_shader_mode() const = 0;
+ virtual RID get_shader_rid() const;
+ virtual Shader::Mode get_shader_mode() const;
Material();
virtual ~Material();
};
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 6b44b05e02..3c67a20f50 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -40,6 +40,122 @@
Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr;
+int Mesh::get_surface_count() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Mesh::surface_get_array_len(int p_idx) const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Mesh::surface_get_array_index_len(int p_idx) const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+Array Mesh::surface_get_arrays(int p_surface) const {
+ Array ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+Array Mesh::surface_get_blend_shape_arrays(int p_surface) const {
+ Array ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret)) {
+ return ret;
+ }
+
+ return Array();
+}
+
+Dictionary Mesh::surface_get_lods(int p_surface) const {
+ Dictionary ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret)) {
+ return ret;
+ }
+
+ return Dictionary();
+}
+
+uint32_t Mesh::surface_get_format(int p_idx) const {
+ uint32_t ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const {
+ uint32_t ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret)) {
+ return (Mesh::PrimitiveType)ret;
+ }
+
+ return PRIMITIVE_MAX;
+}
+
+void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material)) {
+ return;
+ }
+}
+
+Ref<Material> Mesh::surface_get_material(int p_idx) const {
+ Ref<Material> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret)) {
+ return ret;
+ }
+
+ return Ref<Material>();
+}
+
+int Mesh::get_blend_shape_count() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+StringName Mesh::get_blend_shape_name(int p_index) const {
+ StringName ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret)) {
+ return ret;
+ }
+
+ return StringName();
+}
+
+void Mesh::set_blend_shape_name(int p_index, const StringName &p_name) {
+ if (GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name)) {
+ return;
+ }
+}
+
+AABB Mesh::get_aabb() const {
+ AABB ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret)) {
+ return ret;
+ }
+
+ return AABB();
+}
+
Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
if (triangle_mesh.is_valid()) {
return triangle_mesh;
@@ -502,6 +618,21 @@ void Mesh::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
+
+ GDVIRTUAL_BIND(_get_surface_count)
+ GDVIRTUAL_BIND(_surface_get_array_len, "index")
+ GDVIRTUAL_BIND(_surface_get_array_index_len, "index")
+ GDVIRTUAL_BIND(_surface_get_arrays, "index")
+ GDVIRTUAL_BIND(_surface_get_blend_shape_arrays, "index")
+ GDVIRTUAL_BIND(_surface_get_lods, "index")
+ GDVIRTUAL_BIND(_surface_get_format, "index")
+ GDVIRTUAL_BIND(_surface_get_primitive_type, "index")
+ GDVIRTUAL_BIND(_surface_set_material, "index", "material")
+ GDVIRTUAL_BIND(_surface_get_material, "index")
+ GDVIRTUAL_BIND(_get_blend_shape_count)
+ GDVIRTUAL_BIND(_get_blend_shape_name, "index")
+ GDVIRTUAL_BIND(_set_blend_shape_name, "index", "name")
+ GDVIRTUAL_BIND(_get_aabb)
}
void Mesh::clear_cache() const {
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 08d834bdb9..652c045a24 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -45,9 +45,34 @@ class Mesh : public Resource {
mutable Vector<Vector3> debug_lines;
Size2i lightmap_size_hint;
+public:
+ enum PrimitiveType {
+ PRIMITIVE_POINTS = RenderingServer::PRIMITIVE_POINTS,
+ PRIMITIVE_LINES = RenderingServer::PRIMITIVE_LINES,
+ PRIMITIVE_LINE_STRIP = RenderingServer::PRIMITIVE_LINE_STRIP,
+ PRIMITIVE_TRIANGLES = RenderingServer::PRIMITIVE_TRIANGLES,
+ PRIMITIVE_TRIANGLE_STRIP = RenderingServer::PRIMITIVE_TRIANGLE_STRIP,
+ PRIMITIVE_MAX = RenderingServer::PRIMITIVE_MAX,
+ };
+
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(int, _get_surface_count)
+ GDVIRTUAL1RC(int, _surface_get_array_len, int)
+ GDVIRTUAL1RC(int, _surface_get_array_index_len, int)
+ GDVIRTUAL1RC(Array, _surface_get_arrays, int)
+ GDVIRTUAL1RC(Array, _surface_get_blend_shape_arrays, int)
+ GDVIRTUAL1RC(Dictionary, _surface_get_lods, int)
+ GDVIRTUAL1RC(uint32_t, _surface_get_format, int)
+ GDVIRTUAL1RC(uint32_t, _surface_get_primitive_type, int)
+ GDVIRTUAL2(_surface_set_material, int, Ref<Material>)
+ GDVIRTUAL1RC(Ref<Material>, _surface_get_material, int)
+ GDVIRTUAL0RC(int, _get_blend_shape_count)
+ GDVIRTUAL1RC(StringName, _get_blend_shape_name, int)
+ GDVIRTUAL2(_set_blend_shape_name, int, StringName)
+ GDVIRTUAL0RC(AABB, _get_aabb)
+
public:
enum {
NO_INDEX_ARRAY = RenderingServer::NO_INDEX_ARRAY,
@@ -120,28 +145,20 @@ public:
};
- enum PrimitiveType {
- PRIMITIVE_POINTS = RenderingServer::PRIMITIVE_POINTS,
- PRIMITIVE_LINES = RenderingServer::PRIMITIVE_LINES,
- PRIMITIVE_LINE_STRIP = RenderingServer::PRIMITIVE_LINE_STRIP,
- PRIMITIVE_TRIANGLES = RenderingServer::PRIMITIVE_TRIANGLES,
- PRIMITIVE_TRIANGLE_STRIP = RenderingServer::PRIMITIVE_TRIANGLE_STRIP,
- PRIMITIVE_MAX = RenderingServer::PRIMITIVE_MAX,
- };
-
- virtual int get_surface_count() const = 0;
- virtual int surface_get_array_len(int p_idx) const = 0;
- virtual int surface_get_array_index_len(int p_idx) const = 0;
- virtual Array surface_get_arrays(int p_surface) const = 0;
- virtual Array surface_get_blend_shape_arrays(int p_surface) const = 0;
- virtual Dictionary surface_get_lods(int p_surface) const = 0;
- virtual uint32_t surface_get_format(int p_idx) const = 0;
- virtual PrimitiveType surface_get_primitive_type(int p_idx) const = 0;
- virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) = 0;
- virtual Ref<Material> surface_get_material(int p_idx) const = 0;
- virtual int get_blend_shape_count() const = 0;
- virtual StringName get_blend_shape_name(int p_index) const = 0;
- virtual void set_blend_shape_name(int p_index, const StringName &p_name) = 0;
+ virtual int get_surface_count() const;
+ virtual int surface_get_array_len(int p_idx) const;
+ virtual int surface_get_array_index_len(int p_idx) const;
+ virtual Array surface_get_arrays(int p_surface) const;
+ virtual Array surface_get_blend_shape_arrays(int p_surface) const;
+ virtual Dictionary surface_get_lods(int p_surface) const;
+ virtual uint32_t surface_get_format(int p_idx) const;
+ virtual PrimitiveType surface_get_primitive_type(int p_idx) const;
+ virtual void surface_set_material(int p_idx, const Ref<Material> &p_material);
+ virtual Ref<Material> surface_get_material(int p_idx) const;
+ virtual int get_blend_shape_count() const;
+ virtual StringName get_blend_shape_name(int p_index) const;
+ virtual void set_blend_shape_name(int p_index, const StringName &p_name);
+ virtual AABB get_aabb() const;
Vector<Face3> get_faces() const;
Ref<TriangleMesh> generate_triangle_mesh() const;
@@ -153,8 +170,6 @@ public:
Ref<Mesh> create_outline(float p_margin) const;
- virtual AABB get_aabb() const = 0;
-
void set_lightmap_size_hint(const Size2i &p_size);
Size2i get_lightmap_size_hint() const;
void clear_cache() const;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 38acd0af0a..781e219f1f 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -36,11 +36,17 @@
*/
void PrimitiveMesh::_update() const {
Array arr;
- arr.resize(RS::ARRAY_MAX);
- _create_mesh_array(arr);
+ if (GDVIRTUAL_CALL(_create_mesh_array, arr)) {
+ ERR_FAIL_COND_MSG(arr.size() != RS::ARRAY_MAX, "_create_mesh_array must return an array of Mesh.ARRAY_MAX elements.");
+ } else {
+ arr.resize(RS::ARRAY_MAX);
+ _create_mesh_array(arr);
+ }
Vector<Vector3> points = arr[RS::ARRAY_VERTEX];
+ ERR_FAIL_COND_MSG(points.size() == 0, "_create_mesh_array must return at least a vertex array.");
+
aabb = AABB();
int pc = points.size();
@@ -210,6 +216,8 @@ void PrimitiveMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
+
+ GDVIRTUAL_BIND(_create_mesh_array);
}
void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 3fc5fd4a16..eef5eb3f7d 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -64,8 +64,9 @@ protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr) const = 0;
+ virtual void _create_mesh_array(Array &p_arr) const {}
void _request_update();
+ GDVIRTUAL0RC(Array, _create_mesh_array)
public:
virtual int get_surface_count() const override;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index d9ac967699..fd6f018651 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -908,10 +908,9 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
return ERR_CANT_CREATE;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(p_path);
da->rename(p_path + ".depren", p_path);
- memdelete(da);
return OK;
}
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 8e633a4075..54543782f6 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -71,6 +71,25 @@ float ProceduralSkyMaterial::get_sky_energy() const {
return sky_energy;
}
+void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) {
+ sky_cover = p_sky_cover;
+ RID tex_rid = p_sky_cover.is_valid() ? p_sky_cover->get_rid() : RID();
+ RS::get_singleton()->material_set_param(_get_material(), "sky_cover", tex_rid);
+}
+
+Ref<Texture2D> ProceduralSkyMaterial::get_sky_cover() const {
+ return sky_cover;
+}
+
+void ProceduralSkyMaterial::set_sky_cover_modulate(const Color &p_sky_cover_modulate) {
+ sky_cover_modulate = p_sky_cover_modulate;
+ RS::get_singleton()->material_set_param(_get_material(), "sky_cover_modulate", sky_cover_modulate);
+}
+
+Color ProceduralSkyMaterial::get_sky_cover_modulate() const {
+ return sky_cover_modulate;
+}
+
void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) {
ground_bottom_color = p_ground_bottom;
RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color);
@@ -156,6 +175,12 @@ void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy);
ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy);
+ ClassDB::bind_method(D_METHOD("set_sky_cover", "sky_cover"), &ProceduralSkyMaterial::set_sky_cover);
+ ClassDB::bind_method(D_METHOD("get_sky_cover"), &ProceduralSkyMaterial::get_sky_cover);
+
+ ClassDB::bind_method(D_METHOD("set_sky_cover_modulate", "color"), &ProceduralSkyMaterial::set_sky_cover_modulate);
+ ClassDB::bind_method(D_METHOD("get_sky_cover_modulate"), &ProceduralSkyMaterial::get_sky_cover_modulate);
+
ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color);
ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color);
@@ -179,6 +204,8 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color", "get_sky_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_cover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_sky_cover", "get_sky_cover");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_cover_modulate"), "set_sky_cover_modulate", "get_sky_cover_modulate");
ADD_GROUP("Ground", "ground_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color", "get_ground_bottom_color");
@@ -212,6 +239,8 @@ uniform vec4 sky_top_color : hint_color = vec4(0.385, 0.454, 0.55, 1.0);
uniform vec4 sky_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0);
uniform float sky_curve : hint_range(0, 1) = 0.15;
uniform float sky_energy = 1.0;
+uniform sampler2D sky_cover : hint_black_albedo;
+uniform vec4 sky_cover_modulate : hint_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 ground_bottom_color : hint_color = vec4(0.2, 0.169, 0.133, 1.0);
uniform vec4 ground_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0);
uniform float ground_curve : hint_range(0, 1) = 0.02;
@@ -265,6 +294,9 @@ void sky() {
}
}
+ vec4 sky_cover_texture = texture(sky_cover, SKY_COORDS);
+ sky += (sky_cover_texture.rgb * sky_cover_modulate.rgb) * sky_cover_texture.a * sky_cover_modulate.a * sky_energy;
+
c = (v_angle - (PI * 0.5)) / (PI * 0.5);
vec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0));
ground *= ground_energy;
@@ -281,6 +313,7 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() {
set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708));
set_sky_curve(0.15);
set_sky_energy(1.0);
+ set_sky_cover_modulate(Color(1, 1, 1));
set_ground_bottom_color(Color(0.2, 0.169, 0.133));
set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708));
diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h
index 7f421beb8d..5c791a185a 100644
--- a/scene/resources/sky_material.h
+++ b/scene/resources/sky_material.h
@@ -42,6 +42,8 @@ private:
Color sky_horizon_color;
float sky_curve;
float sky_energy;
+ Ref<Texture2D> sky_cover;
+ Color sky_cover_modulate;
Color ground_bottom_color;
Color ground_horizon_color;
@@ -72,6 +74,12 @@ public:
void set_sky_energy(float p_energy);
float get_sky_energy() const;
+ void set_sky_cover(const Ref<Texture2D> &p_sky_cover);
+ Ref<Texture2D> get_sky_cover() const;
+
+ void set_sky_cover_modulate(const Color &p_sky_cover_modulate);
+ Color get_sky_cover_modulate() const;
+
void set_ground_bottom_color(const Color &p_ground_bottom);
Color get_ground_bottom_color() const;
diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp
index 5afd424e03..fe52761482 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -34,10 +34,28 @@
#include <limits.h>
+float StyleBox::get_style_margin(Side p_side) const {
+ float ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_style_margin, p_side, ret)) {
+ return ret;
+ }
+ return 0;
+}
bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_test_mask, p_point, p_rect, ret)) {
+ return ret;
+ }
+
return true;
}
+void StyleBox::draw(RID p_canvas_item, const Rect2 &p_rect) const {
+ if (GDVIRTUAL_REQUIRED_CALL(_draw, p_canvas_item, p_rect)) {
+ return;
+ }
+}
+
void StyleBox::set_default_margin(Side p_side, float p_value) {
ERR_FAIL_INDEX((int)p_side, 4);
@@ -74,10 +92,19 @@ Point2 StyleBox::get_offset() const {
}
Size2 StyleBox::get_center_size() const {
+ Size2 ret;
+ if (GDVIRTUAL_CALL(_get_center_size, ret)) {
+ return ret;
+ }
+
return Size2();
}
Rect2 StyleBox::get_draw_rect(const Rect2 &p_rect) const {
+ Rect2 ret;
+ if (GDVIRTUAL_CALL(_get_draw_rect, p_rect, ret)) {
+ return ret;
+ }
return p_rect;
}
@@ -100,6 +127,12 @@ void StyleBox::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_right", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_RIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_top", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_TOP);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_bottom", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_BOTTOM);
+
+ GDVIRTUAL_BIND(_get_style_margin, "side")
+ GDVIRTUAL_BIND(_test_mask, "point", "rect")
+ GDVIRTUAL_BIND(_get_center_size)
+ GDVIRTUAL_BIND(_get_draw_rect, "rect")
+ GDVIRTUAL_BIND(_draw, "to_canvas_item", "rect")
}
StyleBox::StyleBox() {
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 4c41f42293..68ad41b69c 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -44,9 +44,15 @@ class StyleBox : public Resource {
float margin[4];
protected:
- virtual float get_style_margin(Side p_side) const = 0;
+ virtual float get_style_margin(Side p_side) const;
static void _bind_methods();
+ GDVIRTUAL1RC(float, _get_style_margin, Side)
+ GDVIRTUAL2RC(bool, _test_mask, Point2, Rect2)
+ GDVIRTUAL0RC(Size2, _get_center_size)
+ GDVIRTUAL1RC(Rect2, _get_draw_rect, Rect2)
+ GDVIRTUAL2C(_draw, RID, Rect2)
+
public:
virtual bool test_mask(const Point2 &p_point, const Rect2 &p_rect) const;
@@ -56,7 +62,7 @@ public:
virtual Size2 get_center_size() const;
virtual Rect2 get_draw_rect(const Rect2 &p_rect) const;
- virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const = 0;
+ virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const;
CanvasItem *get_current_item_drawn() const;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 1ab1d81355..1930fa2682 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -38,23 +38,61 @@
#include "scene/resources/bit_map.h"
#include "servers/camera/camera_feed.h"
+int Texture2D::get_width() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Texture2D::get_height() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
Size2 Texture2D::get_size() const {
return Size2(get_width(), get_height());
}
bool Texture2D::is_pixel_opaque(int p_x, int p_y) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_pixel_opaque, p_x, p_y, ret)) {
+ return ret;
+ }
+
+ return true;
+}
+bool Texture2D::has_alpha() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_has_alpha, ret)) {
+ return ret;
+ }
+
return true;
}
void Texture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
+ if (GDVIRTUAL_CALL(_draw, p_canvas_item, p_pos, p_modulate, p_transpose)) {
+ return;
+ }
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose);
}
void Texture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
+ if (GDVIRTUAL_CALL(_draw_rect, p_canvas_item, p_rect, p_tile, p_modulate, p_transpose)) {
+ return;
+ }
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose);
}
void Texture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const {
+ if (GDVIRTUAL_CALL(_draw_rect_region, p_canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_clip_uv)) {
+ return;
+ }
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, p_clip_uv);
}
@@ -75,6 +113,15 @@ void Texture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_image"), &Texture2D::get_image);
ADD_GROUP("", "");
+
+ GDVIRTUAL_BIND(_get_width);
+ GDVIRTUAL_BIND(_get_height);
+ GDVIRTUAL_BIND(_is_pixel_opaque, "x", "y");
+ GDVIRTUAL_BIND(_has_alpha);
+
+ GDVIRTUAL_BIND(_draw, "to_canvas_item", "pos", "modulate", "transpose")
+ GDVIRTUAL_BIND(_draw_rect, "to_canvas_item", "rect", "tile", "modulate", "transpose")
+ GDVIRTUAL_BIND(_draw_rect_region, "tp_canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv");
}
Texture2D::Texture2D() {
@@ -435,24 +482,24 @@ void CompressedTexture2D::set_path(const String &p_path, bool p_take_over) {
}
void CompressedTexture2D::_requested_3d(void *p_ud) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_3d_callback);
- request_3d_callback(stex);
+ request_3d_callback(ctex);
}
void CompressedTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_roughness_callback);
- request_roughness_callback(stex, p_normal_path, p_roughness_channel);
+ request_roughness_callback(ctex, p_normal_path, p_roughness_channel);
}
void CompressedTexture2D::_requested_normal(void *p_ud) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_normal_callback);
- request_normal_callback(stex);
+ request_normal_callback(ctex);
}
CompressedTexture2D::TextureFormatRequestCallback CompressedTexture2D::request_3d_callback = nullptr;
@@ -475,14 +522,14 @@ Error CompressedTexture2D::_load_data(const String &p_path, int &r_width, int &r
f->get_buffer(header, 4);
if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != '2') {
memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is corrupt (Bad header).");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is corrupt (Bad header).");
}
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
r_width = f->get_32();
r_height = f->get_32();
@@ -740,7 +787,7 @@ String ResourceFormatLoaderCompressedTexture2D::get_resource_type(const String &
////////////////////////////////////
-TypedArray<Image> Texture3D::_get_data() const {
+TypedArray<Image> Texture3D::_get_datai() const {
Vector<Ref<Image>> data = get_data();
TypedArray<Image> ret;
@@ -751,13 +798,73 @@ TypedArray<Image> Texture3D::_get_data() const {
return ret;
}
+Image::Format Texture3D::get_format() const {
+ Image::Format ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) {
+ return ret;
+ }
+ return Image::FORMAT_MAX;
+}
+
+int Texture3D::get_width() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Texture3D::get_height() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Texture3D::get_depth() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_depth, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+bool Texture3D::has_mipmaps() const {
+ bool ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+Vector<Ref<Image>> Texture3D::get_data() const {
+ TypedArray<Image> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_data, ret)) {
+ Vector<Ref<Image>> data;
+ data.resize(ret.size());
+ for (int i = 0; i < data.size(); i++) {
+ data.write[i] = ret[i];
+ }
+ return data;
+ }
+ return Vector<Ref<Image>>();
+}
void Texture3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format);
ClassDB::bind_method(D_METHOD("get_width"), &Texture3D::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &Texture3D::get_height);
ClassDB::bind_method(D_METHOD("get_depth"), &Texture3D::get_depth);
ClassDB::bind_method(D_METHOD("has_mipmaps"), &Texture3D::has_mipmaps);
- ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_data);
+ ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_datai);
+
+ GDVIRTUAL_BIND(_get_format);
+ GDVIRTUAL_BIND(_get_width);
+ GDVIRTUAL_BIND(_get_height);
+ GDVIRTUAL_BIND(_get_depth);
+ GDVIRTUAL_BIND(_has_mipmaps);
+ GDVIRTUAL_BIND(_get_data);
}
//////////////////////////////////////////
@@ -866,11 +973,11 @@ Error CompressedTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &
f->get_buffer(header, 4);
ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L', ERR_FILE_UNRECOGNIZED);
- //stored as stream textures (used for lossless and lossy compression)
+ //stored as compressed textures (used for lossless and lossy compression)
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
r_depth = f->get_32(); //depth
@@ -1022,7 +1129,7 @@ RES ResourceFormatLoaderCompressedTexture3D::load(const String &p_path, const St
}
void ResourceFormatLoaderCompressedTexture3D::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("stex3d");
+ p_extensions->push_back("ctex3d");
}
bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) const {
@@ -1030,7 +1137,7 @@ bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type)
}
String ResourceFormatLoaderCompressedTexture3D::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "stex3d") {
+ if (p_path.get_extension().to_lower() == "ctex3d") {
return "CompressedTexture3D";
}
return "";
@@ -2446,6 +2553,63 @@ AnimatedTexture::~AnimatedTexture() {
///////////////////////////////
+Image::Format TextureLayered::get_format() const {
+ Image::Format ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) {
+ return ret;
+ }
+ return Image::FORMAT_MAX;
+}
+
+TextureLayered::LayeredType TextureLayered::get_layered_type() const {
+ uint32_t ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_layered_type, ret)) {
+ return (LayeredType)ret;
+ }
+ return LAYERED_TYPE_2D_ARRAY;
+}
+
+int TextureLayered::get_width() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int TextureLayered::get_height() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int TextureLayered::get_layers() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_layers, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+bool TextureLayered::has_mipmaps() const {
+ bool ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+Ref<Image> TextureLayered::get_layer_data(int p_layer) const {
+ Ref<Image> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_layer_data, p_layer, ret)) {
+ return ret;
+ }
+ return Ref<Image>();
+}
+
void TextureLayered::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_format"), &TextureLayered::get_format);
ClassDB::bind_method(D_METHOD("get_layered_type"), &TextureLayered::get_layered_type);
@@ -2458,6 +2622,14 @@ void TextureLayered::_bind_methods() {
BIND_ENUM_CONSTANT(LAYERED_TYPE_2D_ARRAY);
BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP);
BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP_ARRAY);
+
+ GDVIRTUAL_BIND(_get_format);
+ GDVIRTUAL_BIND(_get_layered_type);
+ GDVIRTUAL_BIND(_get_width);
+ GDVIRTUAL_BIND(_get_height);
+ GDVIRTUAL_BIND(_get_layers);
+ GDVIRTUAL_BIND(_has_mipmaps);
+ GDVIRTUAL_BIND(_get_layer_data, "layer_index");
}
///////////////////////////////
@@ -2620,13 +2792,13 @@ Error CompressedTextureLayered::_load_data(const String &p_path, Vector<Ref<Imag
uint8_t header[4];
f->get_buffer(header, 4);
if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L') {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture layered file is corrupt (Bad header).");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture layered file is corrupt (Bad header).");
}
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
uint32_t layer_count = f->get_32(); //layer count
@@ -2767,26 +2939,26 @@ CompressedTextureLayered::~CompressedTextureLayered() {
/////////////////////////////////////////////////
RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- Ref<CompressedTextureLayered> st;
- if (p_path.get_extension().to_lower() == "stexarray") {
- Ref<CompressedTexture2DArray> s;
- s.instantiate();
- st = s;
- } else if (p_path.get_extension().to_lower() == "scube") {
- Ref<CompressedCubemap> s;
- s.instantiate();
- st = s;
- } else if (p_path.get_extension().to_lower() == "scubearray") {
- Ref<CompressedCubemapArray> s;
- s.instantiate();
- st = s;
+ Ref<CompressedTextureLayered> ct;
+ if (p_path.get_extension().to_lower() == "ctexarray") {
+ Ref<CompressedTexture2DArray> c;
+ c.instantiate();
+ ct = c;
+ } else if (p_path.get_extension().to_lower() == "ccube") {
+ Ref<CompressedCubemap> c;
+ c.instantiate();
+ ct = c;
+ } else if (p_path.get_extension().to_lower() == "ccubearray") {
+ Ref<CompressedCubemapArray> c;
+ c.instantiate();
+ ct = c;
} else {
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
return RES();
}
- Error err = st->load(p_path);
+ Error err = ct->load(p_path);
if (r_error) {
*r_error = err;
}
@@ -2794,13 +2966,13 @@ RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, con
return RES();
}
- return st;
+ return ct;
}
void ResourceFormatLoaderCompressedTextureLayered::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("stexarray");
- p_extensions->push_back("scube");
- p_extensions->push_back("scubearray");
+ p_extensions->push_back("ctexarray");
+ p_extensions->push_back("ccube");
+ p_extensions->push_back("ccubearray");
}
bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_type) const {
@@ -2808,13 +2980,13 @@ bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_
}
String ResourceFormatLoaderCompressedTextureLayered::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "stexarray") {
+ if (p_path.get_extension().to_lower() == "ctexarray") {
return "CompressedTexture2DArray";
}
- if (p_path.get_extension().to_lower() == "scube") {
+ if (p_path.get_extension().to_lower() == "ccube") {
return "CompressedCubemap";
}
- if (p_path.get_extension().to_lower() == "scubearray") {
+ if (p_path.get_extension().to_lower() == "ccubearray") {
return "CompressedCubemapArray";
}
return "";
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index a3c147610d..1e07b83547 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -57,14 +57,23 @@ class Texture2D : public Texture {
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(int, _get_width)
+ GDVIRTUAL0RC(int, _get_height)
+ GDVIRTUAL2RC(bool, _is_pixel_opaque, int, int)
+ GDVIRTUAL0RC(bool, _has_alpha)
+
+ GDVIRTUAL4C(_draw, RID, Point2, Color, bool)
+ GDVIRTUAL5C(_draw_rect, RID, Rect2, bool, Color, bool)
+ GDVIRTUAL6C(_draw_rect_region, RID, Rect2, Rect2, Color, bool, bool)
+
public:
- virtual int get_width() const = 0;
- virtual int get_height() const = 0;
+ virtual int get_width() const;
+ virtual int get_height() const;
virtual Size2 get_size() const;
virtual bool is_pixel_opaque(int p_x, int p_y) const;
- virtual bool has_alpha() const = 0;
+ virtual bool has_alpha() const;
virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const;
virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const;
@@ -300,6 +309,13 @@ class TextureLayered : public Texture {
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(Image::Format, _get_format)
+ GDVIRTUAL0RC(uint32_t, _get_layered_type)
+ GDVIRTUAL0RC(int, _get_width)
+ GDVIRTUAL0RC(int, _get_height)
+ GDVIRTUAL0RC(int, _get_layers)
+ GDVIRTUAL0RC(bool, _has_mipmaps)
+ GDVIRTUAL1RC(Ref<Image>, _get_layer_data, int)
public:
enum LayeredType {
LAYERED_TYPE_2D_ARRAY,
@@ -307,13 +323,15 @@ public:
LAYERED_TYPE_CUBEMAP_ARRAY
};
- virtual Image::Format get_format() const = 0;
- virtual LayeredType get_layered_type() const = 0;
- virtual int get_width() const = 0;
- virtual int get_height() const = 0;
- virtual int get_layers() const = 0;
- virtual bool has_mipmaps() const = 0;
- virtual Ref<Image> get_layer_data(int p_layer) const = 0;
+ virtual Image::Format get_format() const;
+ virtual LayeredType get_layered_type() const;
+ virtual int get_width() const;
+ virtual int get_height() const;
+ virtual int get_layers() const;
+ virtual bool has_mipmaps() const;
+ virtual Ref<Image> get_layer_data(int p_layer) const;
+
+ TextureLayered() {}
};
VARIANT_ENUM_CAST(TextureLayered::LayeredType)
@@ -474,15 +492,21 @@ class Texture3D : public Texture {
protected:
static void _bind_methods();
- TypedArray<Image> _get_data() const;
-
-public:
- virtual Image::Format get_format() const = 0;
- virtual int get_width() const = 0;
- virtual int get_height() const = 0;
- virtual int get_depth() const = 0;
- virtual bool has_mipmaps() const = 0;
- virtual Vector<Ref<Image>> get_data() const = 0;
+ TypedArray<Image> _get_datai() const;
+
+ GDVIRTUAL0RC(Image::Format, _get_format)
+ GDVIRTUAL0RC(int, _get_width)
+ GDVIRTUAL0RC(int, _get_height)
+ GDVIRTUAL0RC(int, _get_depth)
+ GDVIRTUAL0RC(bool, _has_mipmaps)
+ GDVIRTUAL0RC(TypedArray<Image>, _get_data)
+public:
+ virtual Image::Format get_format() const;
+ virtual int get_width() const;
+ virtual int get_height() const;
+ virtual int get_depth() const;
+ virtual bool has_mipmaps() const;
+ virtual Vector<Ref<Image>> get_data() const;
};
class ImageTexture3D : public Texture3D {
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
index b9eca14a4c..f38d0adfb2 100644
--- a/servers/audio/audio_effect.cpp
+++ b/servers/audio/audio_effect.cpp
@@ -30,5 +30,36 @@
#include "audio_effect.h"
+void AudioEffectInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
+ if (GDVIRTUAL_REQUIRED_CALL(_process, p_src_frames, p_dst_frames, p_frame_count)) {
+ return;
+ }
+}
+bool AudioEffectInstance::process_silence() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_process_silence, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void AudioEffectInstance::_bind_methods() {
+ GDVIRTUAL_BIND(_process, "src_buffer", "dst_buffer", "frame_count");
+ GDVIRTUAL_BIND(_process_silence);
+}
+
+////
+
+Ref<AudioEffectInstance> AudioEffect::instantiate() {
+ Ref<AudioEffectInstance> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_instantiate, ret)) {
+ return ret;
+ }
+ return Ref<AudioEffectInstance>();
+}
+void AudioEffect::_bind_methods() {
+ GDVIRTUAL_BIND(_instantiate);
+}
+
AudioEffect::AudioEffect() {
}
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 00a5d6c004..3a0578679d 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -33,20 +33,32 @@
#include "core/io/resource.h"
#include "core/math/audio_frame.h"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
class AudioEffectInstance : public RefCounted {
GDCLASS(AudioEffectInstance, RefCounted);
+protected:
+ GDVIRTUAL3(_process, GDNativeConstPtr<AudioFrame>, GDNativePtr<AudioFrame>, int)
+ GDVIRTUAL0RC(bool, _process_silence)
+ static void _bind_methods();
+
public:
- virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) = 0;
- virtual bool process_silence() const { return false; }
+ virtual void process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count);
+ virtual bool process_silence() const;
};
class AudioEffect : public Resource {
GDCLASS(AudioEffect, Resource);
+protected:
+ GDVIRTUAL0R(Ref<AudioEffectInstance>, _instantiate)
+ static void _bind_methods();
+
public:
- virtual Ref<AudioEffectInstance> instantiate() = 0;
+ virtual Ref<AudioEffectInstance> instantiate();
AudioEffect();
};
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index a710658bff..1ebd57fa7f 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -76,10 +76,10 @@ void AudioStreamPlayback::seek(float p_time) {
int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
int ret;
- if (GDVIRTUAL_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret)) {
+ if (GDVIRTUAL_REQUIRED_CALL(_mix, p_buffer, p_rate_scale, p_frames, ret)) {
return ret;
}
- WARN_PRINT_ONCE("AudioStreamPlayback::mix unimplemented!");
+
return 0;
}
@@ -94,7 +94,7 @@ void AudioStreamPlayback::_bind_methods() {
}
//////////////////////////////
-void AudioStreamPlaybackResampled::_begin_resample() {
+void AudioStreamPlaybackResampled::begin_resample() {
//clear cubic interpolation history
internal_buffer[0] = AudioFrame(0.0, 0.0);
internal_buffer[1] = AudioFrame(0.0, 0.0);
@@ -105,6 +105,30 @@ void AudioStreamPlaybackResampled::_begin_resample() {
mix_offset = 0;
}
+int AudioStreamPlaybackResampled::_mix_internal(AudioFrame *p_buffer, int p_frames) {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_mix_resampled, p_buffer, p_frames, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+float AudioStreamPlaybackResampled::get_stream_sampling_rate() {
+ float ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_stream_sampling_rate, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+void AudioStreamPlaybackResampled::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("begin_resample"), &AudioStreamPlaybackResampled::begin_resample);
+
+ GDVIRTUAL_BIND(_mix_resampled, "dst_buffer", "frame_count");
+ GDVIRTUAL_BIND(_get_stream_sampling_rate);
+}
+
int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
float target_rate = AudioServer::get_singleton()->get_mix_rate();
float playback_speed_scale = AudioServer::get_singleton()->get_playback_speed_scale();
@@ -315,7 +339,7 @@ void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
if (AudioDriver::get_singleton()->capture_start() == OK) {
active = true;
- _begin_resample();
+ begin_resample();
}
}
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index ce9bcabb9c..55031dec2c 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -81,10 +81,15 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
uint64_t mix_offset;
protected:
- void _begin_resample();
+ void begin_resample();
// Returns the number of frames that were mixed.
- virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) = 0;
- virtual float get_stream_sampling_rate() = 0;
+ virtual int _mix_internal(AudioFrame *p_buffer, int p_frames);
+ virtual float get_stream_sampling_rate();
+
+ GDVIRTUAL2R(int, _mix_resampled, GDNativePtr<AudioFrame>, int)
+ GDVIRTUAL0RC(float, _get_stream_sampling_rate)
+
+ static void _bind_methods();
public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index 6c917f3eb6..a3d615b925 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -169,7 +169,7 @@ float AudioStreamGeneratorPlayback::get_stream_sampling_rate() {
void AudioStreamGeneratorPlayback::start(float p_from_pos) {
if (mixed == 0.0) {
- _begin_resample();
+ begin_resample();
}
skips = 0;
active = true;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index f405dea770..6848620b48 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -110,7 +110,7 @@ void preregister_server_types() {
shader_types = memnew(ShaderTypes);
GDREGISTER_CLASS(TextServerManager);
- GDREGISTER_VIRTUAL_CLASS(TextServer);
+ GDREGISTER_ABSTRACT_CLASS(TextServer);
GDREGISTER_CLASS(TextServerExtension);
Engine::get_singleton()->add_singleton(Engine::Singleton("TextServerManager", TextServerManager::get_singleton(), "TextServerManager"));
@@ -119,20 +119,20 @@ void preregister_server_types() {
void register_server_types() {
OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback);
- GDREGISTER_VIRTUAL_CLASS(DisplayServer);
- GDREGISTER_VIRTUAL_CLASS(RenderingServer);
+ GDREGISTER_ABSTRACT_CLASS(DisplayServer);
+ GDREGISTER_ABSTRACT_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer);
- GDREGISTER_VIRTUAL_CLASS(PhysicsServer2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsServer3D);
- GDREGISTER_VIRTUAL_CLASS(NavigationServer2D);
- GDREGISTER_VIRTUAL_CLASS(NavigationServer3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D);
+ GDREGISTER_ABSTRACT_CLASS(NavigationServer2D);
+ GDREGISTER_ABSTRACT_CLASS(NavigationServer3D);
GDREGISTER_CLASS(XRServer);
GDREGISTER_CLASS(CameraServer);
- GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
+ GDREGISTER_ABSTRACT_CLASS(RenderingDevice);
- GDREGISTER_VIRTUAL_CLASS(XRInterface);
+ GDREGISTER_ABSTRACT_CLASS(XRInterface);
GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions.
GDREGISTER_CLASS(XRPose);
GDREGISTER_CLASS(XRPositionalTracker);
@@ -149,7 +149,7 @@ void register_server_types() {
GDREGISTER_CLASS(AudioBusLayout);
GDREGISTER_CLASS(AudioStreamGenerator);
- GDREGISTER_VIRTUAL_CLASS(AudioStreamGeneratorPlayback);
+ GDREGISTER_ABSTRACT_CLASS(AudioStreamGeneratorPlayback);
{
//audio effects
@@ -183,12 +183,12 @@ void register_server_types() {
GDREGISTER_CLASS(AudioEffectRecord);
GDREGISTER_CLASS(AudioEffectSpectrumAnalyzer);
- GDREGISTER_VIRTUAL_CLASS(AudioEffectSpectrumAnalyzerInstance);
+ GDREGISTER_ABSTRACT_CLASS(AudioEffectSpectrumAnalyzerInstance);
GDREGISTER_CLASS(AudioEffectCapture);
}
- GDREGISTER_VIRTUAL_CLASS(RenderingDevice);
+ GDREGISTER_ABSTRACT_CLASS(RenderingDevice);
GDREGISTER_CLASS(RDTextureFormat);
GDREGISTER_CLASS(RDTextureView);
GDREGISTER_CLASS(RDAttachmentFormat);
@@ -208,16 +208,16 @@ void register_server_types() {
GDREGISTER_CLASS(CameraFeed);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectBodyState2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectSpaceState2D);
GDREGISTER_CLASS(PhysicsRayQueryParameters2D);
GDREGISTER_CLASS(PhysicsPointQueryParameters2D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionParameters2D);
GDREGISTER_CLASS(PhysicsTestMotionResult2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectBodyState3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsDirectSpaceState3D);
GDREGISTER_CLASS(PhysicsRayQueryParameters3D);
GDREGISTER_CLASS(PhysicsPointQueryParameters3D);
GDREGISTER_CLASS(PhysicsShapeQueryParameters3D);
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index d39fe306f4..e8d2ff9c8a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -1170,7 +1170,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_light_data.direction[0] = world_direction.x;
sky_light_data.direction[1] = world_direction.y;
- sky_light_data.direction[2] = -world_direction.z;
+ sky_light_data.direction[2] = world_direction.z;
float sign = storage->light_is_negative(base) ? -1 : 1;
sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/sky.glsl
index b258e89c66..5b4594da99 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/sky.glsl
@@ -180,12 +180,11 @@ void main() {
cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projections[ViewIndex].x)) / params.projections[ViewIndex].y;
cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projections[ViewIndex].z)) / params.projections[ViewIndex].w;
cube_normal = mat3(params.orientation) * cube_normal;
- cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal);
vec2 uv = uv_interp * 0.5 + 0.5;
- vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
+ vec2 panorama_coords = vec2(atan(cube_normal.x, -cube_normal.z), acos(cube_normal.y));
if (panorama_coords.x < 0.0) {
panorama_coords.x += M_PI * 2.0;
@@ -200,13 +199,11 @@ void main() {
vec4 custom_fog = vec4(0.0);
#ifdef USE_CUBEMAP_PASS
- vec3 inverted_cube_normal = cube_normal;
- inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * params.luminance_multiplier;
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
#endif
#else
#ifdef USES_HALF_RES_COLOR
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 5792572dc1..1a10161a5b 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -88,6 +88,12 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid");
+ GDVIRTUAL_BIND(_font_set_embolden, "font_rid", "strength");
+ GDVIRTUAL_BIND(_font_get_embolden, "font_rid");
+
+ GDVIRTUAL_BIND(_font_set_transform, "font_rid", "transform");
+ GDVIRTUAL_BIND(_font_get_transform, "font_rid");
+
GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
@@ -527,6 +533,30 @@ TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioni
return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED;
}
+void TextServerExtension::font_set_embolden(RID p_font_rid, float p_strength) {
+ GDVIRTUAL_CALL(_font_set_embolden, p_font_rid, p_strength);
+}
+
+float TextServerExtension::font_get_embolden(RID p_font_rid) const {
+ float ret;
+ if (GDVIRTUAL_CALL(_font_get_embolden, p_font_rid, ret)) {
+ return ret;
+ }
+ return 0.f;
+}
+
+void TextServerExtension::font_set_transform(RID p_font_rid, Transform2D p_transform) {
+ GDVIRTUAL_CALL(_font_set_transform, p_font_rid, p_transform);
+}
+
+Transform2D TextServerExtension::font_get_transform(RID p_font_rid) const {
+ Transform2D ret;
+ if (GDVIRTUAL_CALL(_font_get_transform, p_font_rid, ret)) {
+ return ret;
+ }
+ return Transform2D();
+}
+
void TextServerExtension::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) {
GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index d185e44806..7d80467371 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -139,6 +139,16 @@ public:
GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning);
GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID);
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) override;
+ virtual float font_get_embolden(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_embolden, RID, float);
+ GDVIRTUAL1RC(float, _font_get_embolden, RID);
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) override;
+ virtual Transform2D font_get_transform(RID p_font_rid) const override;
+ GDVIRTUAL2(_font_set_transform, RID, Transform2D);
+ GDVIRTUAL1RC(Transform2D, _font_get_transform, RID);
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override;
GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index e84c0f05cc..d188076607 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -241,6 +241,12 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_subpixel_positioning", "font_rid", "subpixel_positioning"), &TextServer::font_set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("font_get_subpixel_positioning", "font_rid"), &TextServer::font_get_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("font_set_embolden", "font_rid", "strength"), &TextServer::font_set_embolden);
+ ClassDB::bind_method(D_METHOD("font_get_embolden", "font_rid"), &TextServer::font_get_embolden);
+
+ ClassDB::bind_method(D_METHOD("font_set_transform", "font_rid", "transform"), &TextServer::font_set_transform);
+ ClassDB::bind_method(D_METHOD("font_get_transform", "font_rid"), &TextServer::font_get_transform);
+
ClassDB::bind_method(D_METHOD("font_set_variation_coordinates", "font_rid", "variation_coordinates"), &TextServer::font_set_variation_coordinates);
ClassDB::bind_method(D_METHOD("font_get_variation_coordinates", "font_rid"), &TextServer::font_get_variation_coordinates);
diff --git a/servers/text_server.h b/servers/text_server.h
index 38ad496490..83dc3df56d 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -261,6 +261,12 @@ public:
virtual void font_set_subpixel_positioning(RID p_font_rid, SubpixelPositioning p_subpixel) = 0;
virtual SubpixelPositioning font_get_subpixel_positioning(RID p_font_rid) const = 0;
+ virtual void font_set_embolden(RID p_font_rid, float p_strength) = 0;
+ virtual float font_get_embolden(RID p_font_rid) const = 0;
+
+ virtual void font_set_transform(RID p_font_rid, Transform2D p_transform) = 0;
+ virtual Transform2D font_get_transform(RID p_font_rid) const = 0;
+
virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) = 0;
virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const = 0;
diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp
index 671eb7a111..4857167a8e 100644
--- a/servers/xr/xr_positional_tracker.cpp
+++ b/servers/xr/xr_positional_tracker.cpp
@@ -49,6 +49,10 @@ void XRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tracker_desc", "description"), &XRPositionalTracker::set_tracker_desc);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_tracker_desc", "get_tracker_desc");
+ ClassDB::bind_method(D_METHOD("get_tracker_profile"), &XRPositionalTracker::get_tracker_profile);
+ ClassDB::bind_method(D_METHOD("set_tracker_profile", "profile"), &XRPositionalTracker::set_tracker_profile);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "profile"), "set_tracker_profile", "get_tracker_profile");
+
ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRPositionalTracker::get_tracker_hand);
ClassDB::bind_method(D_METHOD("set_tracker_hand", "hand"), &XRPositionalTracker::set_tracker_hand);
ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Unknown,Left,Right"), "set_tracker_hand", "get_tracker_hand");
@@ -65,6 +69,7 @@ void XRPositionalTracker::_bind_methods() {
ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector")));
+ ADD_SIGNAL(MethodInfo("profile_changed", PropertyInfo(Variant::STRING, "role")));
};
void XRPositionalTracker::set_tracker_type(XRServer::TrackerType p_type) {
@@ -95,6 +100,18 @@ String XRPositionalTracker::get_tracker_desc() const {
return description;
}
+void XRPositionalTracker::set_tracker_profile(const String &p_profile) {
+ if (profile != p_profile) {
+ profile = p_profile;
+
+ emit_signal("profile_changed", profile);
+ }
+}
+
+String XRPositionalTracker::get_tracker_profile() const {
+ return profile;
+}
+
XRPositionalTracker::TrackerHand XRPositionalTracker::get_tracker_hand() const {
return hand;
};
diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h
index ccb30bbbe6..cd06d4a087 100644
--- a/servers/xr/xr_positional_tracker.h
+++ b/servers/xr/xr_positional_tracker.h
@@ -56,7 +56,8 @@ public:
private:
XRServer::TrackerType type; // type of tracker
StringName name; // (unique) name of the tracker
- String description; // description of the tracker, this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker
+ String description; // description of the tracker
+ String profile; // this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker
TrackerHand hand; // if known, the hand this tracker is held in
Map<StringName, Ref<XRPose>> poses;
@@ -72,6 +73,8 @@ public:
StringName get_tracker_name() const;
void set_tracker_desc(const String &p_desc);
String get_tracker_desc() const;
+ void set_tracker_profile(const String &p_profile);
+ String get_tracker_profile() const;
XRPositionalTracker::TrackerHand get_tracker_hand() const;
void set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand);
diff --git a/tests/core/math/test_vector2.h b/tests/core/math/test_vector2.h
index ff60467bf4..9b7800164a 100644
--- a/tests/core/math/test_vector2.h
+++ b/tests/core/math/test_vector2.h
@@ -90,6 +90,9 @@ TEST_CASE("[Vector2] Interpolation methods") {
Vector2(5, 0).slerp(Vector2(0, 5), 0.5).is_equal_approx(Vector2(5, 5) * Math_SQRT12),
"Vector2 slerp with non-normalized values should work as expected.");
CHECK_MESSAGE(
+ Vector2(1, 1).slerp(Vector2(2, 2), 0.5).is_equal_approx(Vector2(1.5, 1.5)),
+ "Vector2 slerp with colinear inputs should behave as expected.");
+ CHECK_MESSAGE(
Vector2().slerp(Vector2(), 0.5) == Vector2(),
"Vector2 slerp with both inputs as zero vectors should return a zero vector.");
CHECK_MESSAGE(
diff --git a/tests/core/math/test_vector3.h b/tests/core/math/test_vector3.h
index 847a7c0b3f..6f99fada2b 100644
--- a/tests/core/math/test_vector3.h
+++ b/tests/core/math/test_vector3.h
@@ -111,6 +111,9 @@ TEST_CASE("[Vector3] Interpolation methods") {
Vector3(5, 0, 0).slerp(Vector3(0, 3, 4), 0.5).is_equal_approx(Vector3(3.535533905029296875, 2.121320486068725586, 2.828427314758300781)),
"Vector3 slerp with non-normalized values should work as expected.");
CHECK_MESSAGE(
+ Vector3(1, 1, 1).slerp(Vector3(2, 2, 2), 0.5).is_equal_approx(Vector3(1.5, 1.5, 1.5)),
+ "Vector3 slerp with colinear inputs should behave as expected.");
+ CHECK_MESSAGE(
Vector3().slerp(Vector3(), 0.5) == Vector3(),
"Vector3 slerp with both inputs as zero vectors should return a zero vector.");
CHECK_MESSAGE(
diff --git a/tests/core/test_time.h b/tests/core/test_time.h
index 903ca9c001..bc341c73bd 100644
--- a/tests/core/test_time.h
+++ b/tests/core/test_time.h
@@ -79,6 +79,9 @@ TEST_CASE("[Time] Unix time conversion to/from datetime string") {
CHECK_MESSAGE(time->get_date_string_from_unix_time(1391904000) == "2014-02-09", "Time get_date_string_from_unix_time: The date for GODOT IS OPEN SOURCE without time is as expected.");
CHECK_MESSAGE(time->get_time_string_from_unix_time(79830) == "22:10:30", "Time get_time_string_from_unix_time: The time for GODOT IS OPEN SOURCE without date is as expected.");
CHECK_MESSAGE(time->get_datetime_string_from_unix_time(31494784780800) == "1000000-01-01T00:00:00", "Time get_datetime_string_from_unix_time: The timestamp for the year a million is as expected.");
+ CHECK_MESSAGE(time->get_offset_string_from_offset_minutes(0) == "+00:00", "Time get_offset_string_from_offset_minutes: The offset string is as expected.");
+ CHECK_MESSAGE(time->get_offset_string_from_offset_minutes(-600) == "-10:00", "Time get_offset_string_from_offset_minutes: The offset string is as expected.");
+ CHECK_MESSAGE(time->get_offset_string_from_offset_minutes(345) == "+05:45", "Time get_offset_string_from_offset_minutes: The offset string is as expected.");
}
TEST_CASE("[Time] Datetime dictionary conversion methods") {