summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig6
-rw-r--r--.github/workflows/javascript_builds.yml2
-rw-r--r--core/config/engine.cpp4
-rw-r--r--core/config/project_settings.cpp19
-rw-r--r--core/core_bind.cpp68
-rw-r--r--core/core_bind.h8
-rw-r--r--core/debugger/debugger_marshalls.cpp10
-rw-r--r--core/debugger/local_debugger.cpp6
-rw-r--r--core/debugger/remote_debugger.cpp14
-rw-r--r--core/extension/extension_api_dump.cpp96
-rw-r--r--core/extension/gdnative_interface.cpp3
-rw-r--r--core/extension/gdnative_interface.h2
-rw-r--r--core/extension/native_extension.cpp6
-rw-r--r--core/input/input.cpp9
-rw-r--r--core/input/input_map.cpp24
-rw-r--r--core/io/config_file.cpp8
-rw-r--r--core/io/dir_access.cpp17
-rw-r--r--core/io/http_client.cpp7
-rw-r--r--core/io/image_loader.cpp4
-rw-r--r--core/io/ip.cpp12
-rw-r--r--core/io/json.cpp11
-rw-r--r--core/io/marshalls.cpp18
-rw-r--r--core/io/multiplayer_api.cpp10
-rw-r--r--core/io/packed_data_container.cpp14
-rw-r--r--core/io/resource.cpp94
-rw-r--r--core/io/resource.h14
-rw-r--r--core/io/resource_format_binary.cpp244
-rw-r--r--core/io/resource_format_binary.h15
-rw-r--r--core/io/resource_importer.cpp42
-rw-r--r--core/io/resource_importer.h15
-rw-r--r--core/io/resource_loader.cpp138
-rw-r--r--core/io/resource_loader.h10
-rw-r--r--core/io/resource_saver.cpp19
-rw-r--r--core/io/resource_saver.h5
-rw-r--r--core/io/resource_uid.cpp262
-rw-r--r--core/io/resource_uid.h89
-rw-r--r--core/math/delaunay_3d.h3
-rw-r--r--core/math/dynamic_bvh.cpp2
-rw-r--r--core/math/expression.cpp4
-rw-r--r--core/math/face3.h4
-rw-r--r--core/math/geometry_3d.h2
-rw-r--r--core/math/math_defs.h2
-rw-r--r--core/math/quick_hull.cpp34
-rw-r--r--core/math/triangle_mesh.cpp12
-rw-r--r--core/math/vector2.h8
-rw-r--r--core/object/class_db.cpp83
-rw-r--r--core/object/class_db.h1
-rw-r--r--core/object/object.cpp49
-rw-r--r--core/object/object.h12
-rw-r--r--core/object/script_language.cpp54
-rw-r--r--core/object/undo_redo.cpp28
-rw-r--r--core/os/main_loop.cpp4
-rw-r--r--core/os/main_loop.h4
-rw-r--r--core/os/os.cpp4
-rw-r--r--core/os/os.h2
-rw-r--r--core/os/pool_allocator.h2
-rw-r--r--core/register_core_types.cpp12
-rw-r--r--core/string/node_path.cpp17
-rw-r--r--core/string/optimized_translation.cpp6
-rw-r--r--core/string/translation.cpp4
-rw-r--r--core/string/translation_po.cpp23
-rw-r--r--core/string/ustring.cpp7
-rw-r--r--core/templates/command_queue_mt.h2
-rw-r--r--core/templates/hashfuncs.h4
-rw-r--r--core/templates/rid_owner.h2
-rw-r--r--core/templates/set.h7
-rw-r--r--core/variant/binder_common.h6
-rw-r--r--core/variant/callable.cpp4
-rw-r--r--core/variant/method_ptrcall.h2
-rw-r--r--core/variant/variant.cpp6
-rw-r--r--core/variant/variant.h2
-rw-r--r--core/variant/variant_call.cpp55
-rw-r--r--core/variant/variant_parser.cpp14
-rw-r--r--core/variant/variant_setget.cpp12
-rw-r--r--core/variant/variant_utility.cpp4
-rw-r--r--doc/classes/@GlobalScope.xml2
-rw-r--r--doc/classes/AStar.xml2
-rw-r--r--doc/classes/Animation.xml2
-rw-r--r--doc/classes/AnimationTree.xml6
-rw-r--r--doc/classes/Area2D.xml4
-rw-r--r--doc/classes/Array.xml6
-rw-r--r--doc/classes/ArrayMesh.xml2
-rw-r--r--doc/classes/CPUParticles3D.xml19
-rw-r--r--doc/classes/Camera2D.xml2
-rw-r--r--doc/classes/Camera3D.xml16
-rw-r--r--doc/classes/CollisionObject2D.xml8
-rw-r--r--doc/classes/CollisionObject3D.xml8
-rw-r--r--doc/classes/Control.xml14
-rw-r--r--doc/classes/Directory.xml2
-rw-r--r--doc/classes/DisplayServer.xml10
-rw-r--r--doc/classes/EditorImportPlugin.xml2
-rw-r--r--doc/classes/EditorNode3DGizmo.xml127
-rw-r--r--doc/classes/EditorNode3DGizmoPlugin.xml93
-rw-r--r--doc/classes/EditorPlugin.xml2
-rw-r--r--doc/classes/Engine.xml2
-rw-r--r--doc/classes/Image.xml4
-rw-r--r--doc/classes/Input.xml2
-rw-r--r--doc/classes/Label.xml2
-rw-r--r--doc/classes/MethodTweener.xml2
-rw-r--r--doc/classes/MultiMesh.xml2
-rw-r--r--doc/classes/Node3D.xml41
-rw-r--r--doc/classes/OS.xml23
-rw-r--r--doc/classes/Object.xml8
-rw-r--r--doc/classes/PackedByteArray.xml36
-rw-r--r--doc/classes/PackedFloat32Array.xml2
-rw-r--r--doc/classes/PackedFloat64Array.xml2
-rw-r--r--doc/classes/PackedInt32Array.xml2
-rw-r--r--doc/classes/PackedInt64Array.xml2
-rw-r--r--doc/classes/ParticlesMaterial.xml17
-rw-r--r--doc/classes/RDShaderFile.xml6
-rw-r--r--doc/classes/RDShaderSPIRV.xml (renamed from doc/classes/RDShaderBytecode.xml)2
-rw-r--r--doc/classes/RenderingDevice.xml24
-rw-r--r--doc/classes/ResourceImporter.xml9
-rw-r--r--doc/classes/ResourceUID.xml81
-rw-r--r--doc/classes/RootMotionView.xml9
-rw-r--r--doc/classes/SceneTree.xml2
-rw-r--r--doc/classes/Skeleton2D.xml2
-rw-r--r--doc/classes/SkeletonModification2D.xml4
-rw-r--r--doc/classes/SkeletonModification2DCCDIK.xml2
-rw-r--r--doc/classes/SkeletonModification2DJiggle.xml12
-rw-r--r--doc/classes/SkeletonModification2DTwoBoneIK.xml2
-rw-r--r--doc/classes/SkeletonModificationStack2D.xml2
-rw-r--r--doc/classes/TextEdit.xml2
-rw-r--r--doc/classes/TileMap.xml6
-rw-r--r--doc/classes/TileSet.xml156
-rw-r--r--doc/classes/Tween.xml4
-rw-r--r--doc/classes/Tweener.xml2
-rw-r--r--drivers/unix/file_access_unix.cpp2
-rw-r--r--drivers/unix/net_socket_posix.cpp6
-rw-r--r--drivers/unix/os_unix.cpp4
-rw-r--r--drivers/unix/os_unix.h1
-rw-r--r--drivers/vulkan/SCsub2
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp525
-rw-r--r--drivers/vulkan/rendering_device_vulkan.h10
-rw-r--r--drivers/windows/file_access_windows.cpp2
-rw-r--r--editor/animation_bezier_editor.cpp9
-rw-r--r--editor/animation_track_editor.cpp58
-rw-r--r--editor/code_editor.cpp4
-rw-r--r--editor/connections_dialog.cpp8
-rw-r--r--editor/create_dialog.cpp3
-rw-r--r--editor/debugger/editor_debugger_inspector.cpp4
-rw-r--r--editor/debugger/editor_profiler.cpp5
-rw-r--r--editor/debugger/editor_visual_profiler.cpp20
-rw-r--r--editor/debugger/script_editor_debugger.cpp10
-rw-r--r--editor/dependency_editor.cpp29
-rw-r--r--editor/doc_tools.cpp138
-rw-r--r--editor/editor_audio_buses.cpp14
-rw-r--r--editor/editor_autoload_settings.cpp47
-rw-r--r--editor/editor_data.cpp38
-rw-r--r--editor/editor_export.cpp57
-rw-r--r--editor/editor_feature_profile.cpp13
-rw-r--r--editor/editor_file_dialog.cpp4
-rw-r--r--editor/editor_file_system.cpp235
-rw-r--r--editor/editor_file_system.h4
-rw-r--r--editor/editor_folding.cpp36
-rw-r--r--editor/editor_inspector.cpp129
-rw-r--r--editor/editor_layouts_dialog.cpp4
-rw-r--r--editor/editor_log.cpp64
-rw-r--r--editor/editor_log.h2
-rw-r--r--editor/editor_node.cpp102
-rw-r--r--editor/editor_path.cpp10
-rw-r--r--editor/editor_resource_picker.cpp20
-rw-r--r--editor/editor_run.cpp12
-rw-r--r--editor/editor_sectioned_inspector.cpp7
-rw-r--r--editor/editor_settings.cpp31
-rw-r--r--editor/filesystem_dock.cpp30
-rw-r--r--editor/groups_editor.cpp20
-rw-r--r--editor/icons/ImmediateGeometry3D.svg1
-rw-r--r--editor/import/editor_import_collada.cpp4
-rw-r--r--editor/import/resource_importer_obj.cpp5
-rw-r--r--editor/import/resource_importer_scene.cpp59
-rw-r--r--editor/import/resource_importer_scene.h3
-rw-r--r--editor/import/scene_import_settings.cpp32
-rw-r--r--editor/import/scene_importer_mesh.cpp8
-rw-r--r--editor/import_defaults_editor.cpp28
-rw-r--r--editor/import_dock.cpp100
-rw-r--r--editor/inspector_dock.cpp10
-rw-r--r--editor/localization_editor.cpp18
-rw-r--r--editor/multi_node_edit.cpp40
-rw-r--r--editor/plugin_config_dialog.cpp2
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp16
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp16
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp82
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp25
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp40
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp5
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp152
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.cpp57
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h13
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/editor_preview_plugins.cpp8
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/material_editor_plugin.cpp40
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/mesh_library_editor_plugin.cpp12
-rw-r--r--editor/plugins/node_3d_editor_gizmos.cpp (renamed from editor/node_3d_editor_gizmos.cpp)925
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h (renamed from editor/node_3d_editor_gizmos.h)257
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp1555
-rw-r--r--editor/plugins/node_3d_editor_plugin.h179
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp56
-rw-r--r--editor/plugins/path_3d_editor_plugin.h10
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp12
-rw-r--r--editor/plugins/root_motion_editor_plugin.cpp4
-rw-r--r--editor/plugins/script_editor_plugin.cpp36
-rw-r--r--editor/plugins/script_text_editor.cpp40
-rw-r--r--editor/plugins/shader_editor_plugin.cpp14
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp6
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp38
-rw-r--r--editor/plugins/texture_editor_plugin.cpp37
-rw-r--r--editor/plugins/texture_editor_plugin.h8
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp27
-rw-r--r--editor/plugins/theme_editor_plugin.cpp208
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp320
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.h86
-rw-r--r--editor/plugins/tiles/tile_atlas_view.h2
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp2
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp203
-rw-r--r--editor/plugins/tiles/tile_map_editor.h10
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.cpp476
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.h90
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp8
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h4
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp83
-rw-r--r--editor/plugins/tiles/tile_set_editor.h13
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp4
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h4
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp198
-rw-r--r--editor/project_export.cpp8
-rw-r--r--editor/project_manager.cpp27
-rw-r--r--editor/project_settings_editor.cpp15
-rw-r--r--editor/property_editor.cpp20
-rw-r--r--editor/property_selector.cpp48
-rw-r--r--editor/scene_tree_dock.cpp372
-rw-r--r--editor/scene_tree_dock.h10
-rw-r--r--editor/scene_tree_editor.cpp39
-rw-r--r--editor/scene_tree_editor.h3
-rw-r--r--editor/script_create_dialog.cpp14
-rw-r--r--editor/settings_config_dialog.cpp15
-rw-r--r--editor/translations/af.po4
-rw-r--r--editor/translations/ar.po30
-rw-r--r--editor/translations/az.po4
-rw-r--r--editor/translations/bg.po5
-rw-r--r--editor/translations/bn.po4
-rw-r--r--editor/translations/br.po4
-rw-r--r--editor/translations/ca.po5
-rw-r--r--editor/translations/cs.po15
-rw-r--r--editor/translations/da.po4
-rw-r--r--editor/translations/de.po5
-rw-r--r--editor/translations/editor.pot6
-rw-r--r--editor/translations/el.po5
-rw-r--r--editor/translations/eo.po4
-rw-r--r--editor/translations/es.po19
-rw-r--r--editor/translations/es_AR.po5
-rw-r--r--editor/translations/et.po12
-rw-r--r--editor/translations/eu.po4
-rw-r--r--editor/translations/fa.po4
-rw-r--r--editor/translations/fi.po5
-rw-r--r--editor/translations/fil.po4
-rw-r--r--editor/translations/fr.po17
-rw-r--r--editor/translations/ga.po4
-rw-r--r--editor/translations/gl.po4
-rw-r--r--editor/translations/he.po5
-rw-r--r--editor/translations/hi.po4
-rw-r--r--editor/translations/hr.po14
-rw-r--r--editor/translations/hu.po5
-rw-r--r--editor/translations/id.po5
-rw-r--r--editor/translations/is.po4
-rw-r--r--editor/translations/it.po204
-rw-r--r--editor/translations/ja.po5
-rw-r--r--editor/translations/ka.po4
-rw-r--r--editor/translations/km.po4
-rw-r--r--editor/translations/ko.po9
-rw-r--r--editor/translations/lt.po4
-rw-r--r--editor/translations/lv.po4
-rw-r--r--editor/translations/mi.po4
-rw-r--r--editor/translations/mk.po4
-rw-r--r--editor/translations/ml.po4
-rw-r--r--editor/translations/mr.po4
-rw-r--r--editor/translations/ms.po51
-rw-r--r--editor/translations/nb.po4
-rw-r--r--editor/translations/nl.po14
-rw-r--r--editor/translations/or.po4
-rw-r--r--editor/translations/pl.po13
-rw-r--r--editor/translations/pr.po4
-rw-r--r--editor/translations/pt.po5
-rw-r--r--editor/translations/pt_BR.po5
-rw-r--r--editor/translations/ro.po5
-rw-r--r--editor/translations/ru.po10
-rw-r--r--editor/translations/si.po4
-rw-r--r--editor/translations/sk.po5
-rw-r--r--editor/translations/sl.po5
-rw-r--r--editor/translations/sq.po4
-rw-r--r--editor/translations/sr_Cyrl.po4
-rw-r--r--editor/translations/sr_Latn.po4
-rw-r--r--editor/translations/sv.po4
-rw-r--r--editor/translations/ta.po4
-rw-r--r--editor/translations/te.po4
-rw-r--r--editor/translations/th.po5
-rw-r--r--editor/translations/tr.po5
-rw-r--r--editor/translations/tt.po4
-rw-r--r--editor/translations/tzm.po4
-rw-r--r--editor/translations/uk.po5
-rw-r--r--editor/translations/ur_PK.po4
-rw-r--r--editor/translations/vi.po4
-rw-r--r--editor/translations/zh_CN.po19
-rw-r--r--editor/translations/zh_HK.po4
-rw-r--r--editor/translations/zh_TW.po5
-rw-r--r--main/main.cpp18
-rw-r--r--main/main_timer_sync.cpp26
-rw-r--r--main/main_timer_sync.h22
-rw-r--r--main/performance.cpp8
-rw-r--r--main/performance.h12
-rw-r--r--misc/dist/windows/modpath.pas2
-rw-r--r--modules/camera/camera_osx.h2
-rw-r--r--modules/camera/camera_osx.mm2
-rw-r--r--modules/csg/csg.cpp14
-rw-r--r--modules/csg/csg_gizmos.cpp44
-rw-r--r--modules/csg/csg_gizmos.h22
-rw-r--r--modules/csg/csg_shape.cpp122
-rw-r--r--modules/fbx/data/fbx_mesh_data.cpp4
-rw-r--r--modules/fbx/fbx_parser/ByteSwapper.h2
-rw-r--r--modules/fbx/fbx_parser/FBXDocument.cpp2
-rw-r--r--modules/gdnative/gdnative.cpp16
-rw-r--r--modules/gdnative/gdnative/variant.cpp16
-rw-r--r--modules/gdnative/include/net/godot_webrtc.h5
-rw-r--r--modules/gdnative/nativescript/api_generator.cpp22
-rw-r--r--modules/gdnative/nativescript/nativescript.cpp6
-rw-r--r--modules/gdnative/register_types.cpp12
-rw-r--r--modules/gdnative/tests/test_variant.h4
-rw-r--r--modules/gdscript/doc_classes/@GDScript.xml10
-rw-r--r--modules/gdscript/editor/gdscript_highlighter.cpp36
-rw-r--r--modules/gdscript/gdscript.cpp70
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp55
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp16
-rw-r--r--modules/gdscript/gdscript_compiler.cpp3
-rw-r--r--modules/gdscript/gdscript_editor.cpp170
-rw-r--r--modules/gdscript/gdscript_function.cpp9
-rw-r--r--modules/gdscript/gdscript_parser.cpp27
-rw-r--r--modules/gdscript/gdscript_parser.h2
-rw-r--r--modules/gdscript/gdscript_utility_functions.cpp4
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp20
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp15
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp10
-rw-r--r--modules/gdscript/language_server/lsp.hpp52
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp14
-rw-r--r--modules/gdscript/tests/test_gdscript.cpp12
-rw-r--r--modules/glslang/register_types.cpp2
-rw-r--r--modules/gltf/gltf_document.cpp2
-rw-r--r--modules/gridmap/grid_map.cpp8
-rw-r--r--modules/gridmap/grid_map_editor_plugin.cpp19
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.cpp16
-rw-r--r--modules/mono/.editorconfig14
-rw-r--r--modules/mono/class_db_api_json.cpp38
-rw-r--r--modules/mono/csharp_script.cpp132
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj5
-rw-r--r--modules/mono/editor/GodotTools/.gitignore1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs34
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs14
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs8
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs36
-rw-r--r--modules/mono/editor/bindings_generator.cpp175
-rw-r--r--modules/mono/editor/bindings_generator.h30
-rw-r--r--modules/mono/editor/code_completion.cpp32
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs222
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs24
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs1
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs7
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs8
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs368
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs4
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs5
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs10
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs5
-rw-r--r--modules/mono/glue/base_object_glue.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp8
-rw-r--r--modules/navigation/nav_map.cpp6
-rw-r--r--modules/navigation/navigation_mesh_editor_plugin.cpp4
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp4
-rw-r--r--modules/text_server_adv/text_server_adv.cpp8
-rw-r--r--modules/text_server_fb/text_server_fb.cpp4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptCustomNode.xml40
-rw-r--r--modules/visual_script/visual_script.cpp130
-rw-r--r--modules/visual_script/visual_script_editor.cpp372
-rw-r--r--modules/visual_script/visual_script_editor.h6
-rw-r--r--modules/visual_script/visual_script_expression.cpp4
-rw-r--r--modules/visual_script/visual_script_flow_control.cpp4
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp188
-rw-r--r--modules/visual_script/visual_script_func_nodes.h2
-rw-r--r--modules/visual_script/visual_script_nodes.cpp90
-rw-r--r--modules/visual_script/visual_script_nodes.h2
-rw-r--r--modules/visual_script/visual_script_property_selector.cpp40
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp10
-rw-r--r--modules/webrtc/doc_classes/WebRTCDataChannel.xml7
-rw-r--r--modules/webrtc/library_godot_webrtc.js5
-rw-r--r--modules/webrtc/webrtc_data_channel.cpp1
-rw-r--r--modules/webrtc/webrtc_data_channel.h2
-rw-r--r--modules/webrtc/webrtc_data_channel_gdnative.cpp5
-rw-r--r--modules/webrtc/webrtc_data_channel_gdnative.h1
-rw-r--r--modules/webrtc/webrtc_data_channel_js.cpp5
-rw-r--r--modules/webrtc/webrtc_data_channel_js.h1
-rw-r--r--modules/webrtc/webrtc_multiplayer_peer.cpp34
-rw-r--r--modules/websocket/emws_client.cpp2
-rw-r--r--modules/websocket/websocket_multiplayer_peer.cpp6
-rw-r--r--modules/websocket/wsl_server.cpp12
-rw-r--r--modules/webxr/doc_classes/WebXRInterface.xml2
-rw-r--r--modules/webxr/webxr_interface_js.cpp21
-rw-r--r--modules/webxr/webxr_interface_js.h1
-rw-r--r--platform/android/display_server_android.cpp9
-rw-r--r--platform/android/display_server_android.h2
-rw-r--r--platform/android/export/export.cpp2
-rw-r--r--platform/android/java/app/gradle.properties25
-rw-r--r--platform/android/java/build.gradle2
-rw-r--r--platform/android/java/gradle.properties6
-rw-r--r--platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java2
-rw-r--r--platform/android/java_class_wrapper.cpp16
-rw-r--r--platform/android/os_android.cpp7
-rw-r--r--platform/android/os_android.h2
-rw-r--r--platform/iphone/display_server_iphone.h2
-rw-r--r--platform/iphone/display_server_iphone.mm6
-rw-r--r--platform/iphone/godot_view_gesture_recognizer.h2
-rw-r--r--platform/iphone/os_iphone.h5
-rw-r--r--platform/iphone/os_iphone.mm12
-rw-r--r--platform/javascript/display_server_javascript.cpp4
-rw-r--r--platform/javascript/display_server_javascript.h1
-rw-r--r--platform/javascript/js/libs/audio.worklet.js2
-rw-r--r--platform/javascript/os_javascript.cpp8
-rw-r--r--platform/javascript/os_javascript.h3
-rw-r--r--platform/linuxbsd/display_server_x11.cpp84
-rw-r--r--platform/linuxbsd/display_server_x11.h2
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp66
-rw-r--r--platform/linuxbsd/os_linuxbsd.h2
-rw-r--r--platform/osx/detect.py3
-rw-r--r--platform/osx/display_server_osx.h6
-rw-r--r--platform/osx/display_server_osx.mm264
-rw-r--r--platform/osx/export/export.cpp5
-rw-r--r--platform/osx/joypad_osx.cpp3
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm186
-rw-r--r--platform/windows/detect.py1
-rw-r--r--platform/windows/display_server_windows.cpp8
-rw-r--r--platform/windows/display_server_windows.h2
-rw-r--r--platform/windows/os_windows.cpp12
-rw-r--r--platform/windows/os_windows.h2
-rw-r--r--scene/2d/animated_sprite_2d.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp6
-rw-r--r--scene/2d/tile_map.cpp106
-rw-r--r--scene/2d/tile_map.h8
-rw-r--r--scene/3d/audio_stream_player_3d.cpp4
-rw-r--r--scene/3d/camera_3d.cpp8
-rw-r--r--scene/3d/collision_polygon_3d.cpp6
-rw-r--r--scene/3d/collision_shape_3d.cpp6
-rw-r--r--scene/3d/cpu_particles_3d.cpp76
-rw-r--r--scene/3d/cpu_particles_3d.h13
-rw-r--r--scene/3d/decal.cpp2
-rw-r--r--scene/3d/gpu_particles_3d.cpp2
-rw-r--r--scene/3d/gpu_particles_collision_3d.cpp24
-rw-r--r--scene/3d/light_3d.cpp4
-rw-r--r--scene/3d/lightmap_gi.cpp4
-rw-r--r--scene/3d/mesh_instance_3d.cpp8
-rw-r--r--scene/3d/navigation_region_3d.cpp6
-rw-r--r--scene/3d/node_3d.cpp153
-rw-r--r--scene/3d/node_3d.h20
-rw-r--r--scene/3d/occluder_instance_3d.cpp4
-rw-r--r--scene/3d/path_3d.cpp2
-rw-r--r--scene/3d/physics_body_3d.cpp15
-rw-r--r--scene/3d/physics_joint_3d.cpp20
-rw-r--r--scene/3d/proximity_group_3d.cpp1
-rw-r--r--scene/3d/ray_cast_3d.cpp6
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/3d/skeleton_3d.cpp14
-rw-r--r--scene/3d/soft_body_3d.cpp3
-rw-r--r--scene/3d/spring_arm_3d.cpp2
-rw-r--r--scene/3d/sprite_3d.cpp8
-rw-r--r--scene/3d/vehicle_body_3d.cpp4
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.cpp2
-rw-r--r--scene/3d/visual_instance_3d.cpp3
-rw-r--r--scene/3d/voxel_gi.cpp8
-rw-r--r--scene/3d/voxelizer.cpp6
-rw-r--r--scene/animation/animation_blend_space_2d.cpp6
-rw-r--r--scene/animation/animation_blend_tree.cpp12
-rw-r--r--scene/animation/animation_cache.cpp10
-rw-r--r--scene/animation/animation_node_state_machine.cpp11
-rw-r--r--scene/animation/animation_player.cpp26
-rw-r--r--scene/animation/animation_tree.cpp48
-rw-r--r--scene/animation/tween.cpp8
-rw-r--r--scene/debugger/scene_debugger.cpp9
-rw-r--r--scene/gui/code_edit.cpp25
-rw-r--r--scene/gui/control.cpp136
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/gui/file_dialog.cpp6
-rw-r--r--scene/gui/graph_edit.cpp76
-rw-r--r--scene/gui/menu_button.cpp54
-rw-r--r--scene/gui/menu_button.h4
-rw-r--r--scene/gui/popup.cpp1
-rw-r--r--scene/gui/popup_menu.cpp20
-rw-r--r--scene/gui/popup_menu.h1
-rw-r--r--scene/gui/rich_text_label.cpp42
-rw-r--r--scene/main/canvas_item.cpp15
-rw-r--r--scene/main/http_request.cpp10
-rw-r--r--scene/main/instance_placeholder.cpp22
-rw-r--r--scene/main/node.cpp62
-rw-r--r--scene/main/scene_tree.cpp42
-rw-r--r--scene/main/scene_tree.h24
-rw-r--r--scene/main/timer.cpp8
-rw-r--r--scene/main/timer.h10
-rw-r--r--scene/main/viewport.cpp45
-rw-r--r--scene/main/viewport.h8
-rw-r--r--scene/main/window.cpp8
-rw-r--r--scene/register_scene_types.cpp5
-rw-r--r--scene/resources/animation.h8
-rw-r--r--scene/resources/curve.cpp10
-rw-r--r--scene/resources/immediate_mesh.cpp2
-rw-r--r--scene/resources/material.cpp4
-rw-r--r--scene/resources/navigation_mesh.cpp8
-rw-r--r--scene/resources/packed_scene.cpp34
-rw-r--r--scene/resources/particles_material.cpp97
-rw-r--r--scene/resources/particles_material.h17
-rw-r--r--scene/resources/resource_format_text.cpp327
-rw-r--r--scene/resources/resource_format_text.h25
-rw-r--r--scene/resources/shader.cpp5
-rw-r--r--scene/resources/sky_material.cpp101
-rw-r--r--scene/resources/sky_material.h25
-rw-r--r--scene/resources/sprite_frames.cpp4
-rw-r--r--scene/resources/syntax_highlighter.cpp4
-rw-r--r--scene/resources/theme.cpp12
-rw-r--r--scene/resources/tile_set.cpp562
-rw-r--r--scene/resources/tile_set.h63
-rw-r--r--scene/resources/visual_shader.cpp60
-rw-r--r--scene/scene_string_names.cpp1
-rw-r--r--scene/scene_string_names.h1
-rw-r--r--servers/display_server.cpp2
-rw-r--r--servers/display_server.h2
-rw-r--r--servers/display_server_headless.h2
-rw-r--r--servers/physics_2d/body_2d_sw.cpp6
-rw-r--r--servers/physics_2d/step_2d_sw.cpp6
-rw-r--r--servers/physics_3d/collision_solver_3d_sat.cpp4
-rw-r--r--servers/physics_3d/joints/generic_6dof_joint_3d_sw.h4
-rw-r--r--servers/physics_3d/joints/slider_joint_3d_sw.cpp2
-rw-r--r--servers/physics_3d/shape_3d_sw.cpp4
-rw-r--r--servers/physics_3d/shape_3d_sw.h2
-rw-r--r--servers/physics_3d/soft_body_3d_sw.cpp4
-rw-r--r--servers/register_server_types.cpp2
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h2
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp241
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h90
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp13
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp3
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp155
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h10
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp49
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h3
-rw-r--r--servers/rendering/renderer_rd/shader_compiler_rd.cpp16
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp175
-rw-r--r--servers/rendering/renderer_rd/shader_rd.h2
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster.glsl228
-rw-r--r--servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl36
-rw-r--r--servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl74
-rw-r--r--servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl11
-rw-r--r--servers/rendering/renderer_rd/shaders/particles_copy.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl6
-rw-r--r--servers/rendering/renderer_scene_cull.cpp38
-rw-r--r--servers/rendering/rendering_device.cpp81
-rw-r--r--servers/rendering/rendering_device.h36
-rw-r--r--servers/rendering/rendering_device_binds.cpp4
-rw-r--r--servers/rendering/rendering_device_binds.h50
-rw-r--r--servers/rendering/shader_language.cpp107
-rw-r--r--servers/rendering/shader_language.h16
-rw-r--r--servers/rendering_server.cpp22
-rw-r--r--servers/xr/xr_interface.h2
-rw-r--r--tests/test_class_db.h62
-rw-r--r--tests/test_math.cpp4
-rw-r--r--tests/test_object.h4
-rw-r--r--tests/test_physics_2d.cpp2
-rw-r--r--tests/test_physics_3d.cpp4
-rw-r--r--tests/test_render.cpp12
-rw-r--r--thirdparty/enet/godot.cpp4
603 files changed, 12431 insertions, 7213 deletions
diff --git a/.editorconfig b/.editorconfig
index 7743622e78..92ee947a82 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -13,7 +13,7 @@ trim_trailing_whitespace = true
indent_style = space
indent_size = 4
-[{*.{py,cs},SConstruct,SCsub}]
+[{*.py,SConstruct,SCsub}]
indent_style = space
indent_size = 4
@@ -21,7 +21,3 @@ indent_size = 4
[*.{yml,yaml}]
indent_style = space
indent_size = 2
-
-[*.{csproj,props,targets,nuspec}]
-indent_style = space
-indent_size = 2
diff --git a/.github/workflows/javascript_builds.yml b/.github/workflows/javascript_builds.yml
index b4e7d0f681..ced2c36a91 100644
--- a/.github/workflows/javascript_builds.yml
+++ b/.github/workflows/javascript_builds.yml
@@ -4,7 +4,7 @@ on: [push, pull_request]
# Global Settings
env:
GODOT_BASE_BRANCH: master
- SCONSFLAGS: platform=javascript verbose=yes warnings=extra debug_symbols=no module_webxr_enabled=no --jobs=2
+ SCONSFLAGS: platform=javascript verbose=yes warnings=extra debug_symbols=no --jobs=2
SCONS_CACHE_LIMIT: 4096
EM_VERSION: 2.0.25
EM_CACHE_FOLDER: 'emsdk-cache'
diff --git a/core/config/engine.cpp b/core/config/engine.cpp
index ad31966a65..0b5b5627af 100644
--- a/core/config/engine.cpp
+++ b/core/config/engine.cpp
@@ -214,8 +214,8 @@ bool Engine::has_singleton(const String &p_name) const {
}
void Engine::get_singletons(List<Singleton> *p_singletons) {
- for (List<Singleton>::Element *E = singletons.front(); E; E = E->next()) {
- p_singletons->push_back(E->get());
+ for (const Singleton &E : singletons) {
+ p_singletons->push_back(E);
}
}
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 84860b648d..c5e6c6d685 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -700,9 +700,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
int count = 0;
for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
- for (List<String>::Element *F = E->get().front(); F; F = F->next()) {
- count++;
- }
+ count += E->get().size();
}
if (p_custom_features != String()) {
@@ -734,8 +732,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
}
for (Map<String, List<String>>::Element *E = props.front(); E; E = E->next()) {
- for (List<String>::Element *F = E->get().front(); F; F = F->next()) {
- String key = F->get();
+ for (String &key : E->get()) {
if (E->key() != "") {
key = E->key() + "/" + key;
}
@@ -803,8 +800,8 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
if (E->key() != "") {
file->store_string("[" + E->key() + "]\n\n");
}
- for (List<String>::Element *F = E->get().front(); F; F = F->next()) {
- String key = F->get();
+ for (const String &F : E->get()) {
+ String key = F;
if (E->key() != "") {
key = E->key() + "/" + key;
}
@@ -817,7 +814,7 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
String vstr;
VariantWriter::write_to_string(value, vstr);
- file->store_string(F->get().property_name_encode() + "=" + vstr + "\n");
+ file->store_string(F.property_name_encode() + "=" + vstr + "\n");
}
}
@@ -931,11 +928,11 @@ Vector<String> ProjectSettings::get_optimizer_presets() const {
ProjectSettings::get_singleton()->get_property_list(&pi);
Vector<String> names;
- for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
- if (!E->get().name.begins_with("optimizer_presets/")) {
+ for (const PropertyInfo &E : pi) {
+ if (!E.name.begins_with("optimizer_presets/")) {
continue;
}
- names.push_back(E->get().name.get_slicec('/', 1));
+ names.push_back(E.name.get_slicec('/', 1));
}
names.sort();
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 9a58528bd7..9e96d4b079 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -75,8 +75,8 @@ Vector<String> _ResourceLoader::get_recognized_extensions_for_type(const String
List<String> exts;
ResourceLoader::get_recognized_extensions_for_type(p_type, &exts);
Vector<String> ret;
- for (List<String>::Element *E = exts.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const String &E : exts) {
+ ret.push_back(E);
}
return ret;
@@ -91,8 +91,8 @@ PackedStringArray _ResourceLoader::get_dependencies(const String &p_path) {
ResourceLoader::get_dependencies(p_path, &deps);
PackedStringArray ret;
- for (List<String>::Element *E = deps.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const String &E : deps) {
+ ret.push_back(E);
}
return ret;
@@ -141,8 +141,8 @@ Vector<String> _ResourceSaver::get_recognized_extensions(const RES &p_resource)
List<String> exts;
ResourceSaver::get_recognized_extensions(p_resource, &exts);
Vector<String> ret;
- for (List<String>::Element *E = exts.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const String &E : exts) {
+ ret.push_back(E);
}
return ret;
}
@@ -196,6 +196,10 @@ int _OS::get_low_processor_usage_mode_sleep_usec() const {
return OS::get_singleton()->get_low_processor_usage_mode_sleep_usec();
}
+void _OS::alert(const String &p_alert, const String &p_title) {
+ OS::get_singleton()->alert(p_alert, p_title);
+}
+
String _OS::get_executable_path() const {
return OS::get_singleton()->get_executable_path();
}
@@ -264,8 +268,8 @@ String _OS::get_name() const {
Vector<String> _OS::get_cmdline_args() {
List<String> cmdline = OS::get_singleton()->get_cmdline_args();
Vector<String> cmdlinev;
- for (List<String>::Element *E = cmdline.front(); E; E = E->next()) {
- cmdlinev.push_back(E->get());
+ for (const String &E : cmdline) {
+ cmdlinev.push_back(E);
}
return cmdlinev;
@@ -351,20 +355,20 @@ void _OS::print_all_textures_by_size() {
List<Ref<Resource>> rsrc;
ResourceCache::get_cached_resources(&rsrc);
- for (List<Ref<Resource>>::Element *E = rsrc.front(); E; E = E->next()) {
- if (!E->get()->is_class("ImageTexture")) {
+ for (Ref<Resource> &res : rsrc) {
+ if (!res->is_class("ImageTexture")) {
continue;
}
- Size2 size = E->get()->call("get_size");
- int fmt = E->get()->call("get_format");
+ Size2 size = res->call("get_size");
+ int fmt = res->call("get_format");
_OSCoreBindImg img;
img.size = size;
img.fmt = fmt;
- img.path = E->get()->get_path();
+ img.path = res->get_path();
img.vram = Image::get_image_data_size(img.size.width, img.size.height, Image::Format(img.fmt));
- img.id = E->get()->get_instance_id();
+ img.id = res->get_instance_id();
total += img.vram;
imgs.push_back(img);
}
@@ -372,8 +376,8 @@ void _OS::print_all_textures_by_size() {
imgs.sort();
- for (List<_OSCoreBindImg>::Element *E = imgs.front(); E; E = E->next()) {
- total -= E->get().vram;
+ for (_OSCoreBindImg &E : imgs) {
+ total -= E.vram;
}
}
@@ -383,9 +387,7 @@ void _OS::print_resources_by_type(const Vector<String> &p_types) {
List<Ref<Resource>> resources;
ResourceCache::get_cached_resources(&resources);
- for (List<Ref<Resource>>::Element *E = resources.front(); E; E = E->next()) {
- Ref<Resource> r = E->get();
-
+ for (const Ref<Resource> &r : resources) {
bool found = false;
for (int i = 0; i < p_types.size(); i++) {
@@ -487,6 +489,8 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("open_midi_inputs"), &_OS::open_midi_inputs);
ClassDB::bind_method(D_METHOD("close_midi_inputs"), &_OS::close_midi_inputs);
+ ClassDB::bind_method(D_METHOD("alert", "text", "title"), &_OS::alert, DEFVAL("Alert!"));
+
ClassDB::bind_method(D_METHOD("set_low_processor_usage_mode", "enable"), &_OS::set_low_processor_usage_mode);
ClassDB::bind_method(D_METHOD("is_in_low_processor_usage_mode"), &_OS::is_in_low_processor_usage_mode);
@@ -1818,8 +1822,8 @@ PackedStringArray _ClassDB::get_class_list() const {
PackedStringArray ret;
ret.resize(classes.size());
int idx = 0;
- for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
- ret.set(idx++, E->get());
+ for (const StringName &E : classes) {
+ ret.set(idx++, E);
}
return ret;
@@ -1832,8 +1836,8 @@ PackedStringArray _ClassDB::get_inheriters_from_class(const StringName &p_class)
PackedStringArray ret;
ret.resize(classes.size());
int idx = 0;
- for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
- ret.set(idx++, E->get());
+ for (const StringName &E : classes) {
+ ret.set(idx++, E);
}
return ret;
@@ -1887,8 +1891,8 @@ Array _ClassDB::get_signal_list(StringName p_class, bool p_no_inheritance) const
ClassDB::get_signal_list(p_class, &signals, p_no_inheritance);
Array ret;
- for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- ret.push_back(E->get().operator Dictionary());
+ for (const MethodInfo &E : signals) {
+ ret.push_back(E.operator Dictionary());
}
return ret;
@@ -1898,8 +1902,8 @@ Array _ClassDB::get_property_list(StringName p_class, bool p_no_inheritance) con
List<PropertyInfo> plist;
ClassDB::get_property_list(p_class, &plist, p_no_inheritance);
Array ret;
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- ret.push_back(E->get().operator Dictionary());
+ for (const PropertyInfo &E : plist) {
+ ret.push_back(E.operator Dictionary());
}
return ret;
@@ -1931,12 +1935,12 @@ Array _ClassDB::get_method_list(StringName p_class, bool p_no_inheritance) const
ClassDB::get_method_list(p_class, &methods, p_no_inheritance);
Array ret;
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
+ for (const MethodInfo &E : methods) {
#ifdef DEBUG_METHODS_ENABLED
- ret.push_back(E->get().operator Dictionary());
+ ret.push_back(E.operator Dictionary());
#else
Dictionary dict;
- dict["name"] = E->get().name;
+ dict["name"] = E.name;
ret.push_back(dict);
#endif
}
@@ -1951,8 +1955,8 @@ PackedStringArray _ClassDB::get_integer_constant_list(const StringName &p_class,
PackedStringArray ret;
ret.resize(constants.size());
int idx = 0;
- for (List<String>::Element *E = constants.front(); E; E = E->next()) {
- ret.set(idx++, E->get());
+ for (const String &E : constants) {
+ ret.set(idx++, E);
}
return ret;
diff --git a/core/core_bind.h b/core/core_bind.h
index 673dbe32c4..1574c36d3c 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -58,9 +58,9 @@ public:
};
enum CacheMode {
- CACHE_MODE_IGNORE, //resource and subresources do not use path cache, no path is set into resource.
- CACHE_MODE_REUSE, //resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available
- CACHE_MODE_REPLACE, //resource and and subresource use path cache, but replace existing loaded resources when available with information from disk
+ CACHE_MODE_IGNORE, // Resource and subresources do not use path cache, no path is set into resource.
+ CACHE_MODE_REUSE, // Resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available.
+ CACHE_MODE_REPLACE, // Resource and subresource use path cache, but replace existing loaded resources when available with information from disk.
};
static _ResourceLoader *get_singleton() { return singleton; }
@@ -162,6 +162,8 @@ public:
void set_low_processor_usage_mode_sleep_usec(int p_usec);
int get_low_processor_usage_mode_sleep_usec() const;
+ void alert(const String &p_alert, const String &p_title = "ALERT!");
+
String get_executable_path() const;
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false);
int create_process(const String &p_path, const Vector<String> &p_arguments);
diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp
index 26f82c2658..2353a6ebf8 100644
--- a/core/debugger/debugger_marshalls.cpp
+++ b/core/debugger/debugger_marshalls.cpp
@@ -40,11 +40,11 @@ Array DebuggerMarshalls::ResourceUsage::serialize() {
Array arr;
arr.push_back(infos.size() * 4);
- for (List<ResourceInfo>::Element *E = infos.front(); E; E = E->next()) {
- arr.push_back(E->get().path);
- arr.push_back(E->get().format);
- arr.push_back(E->get().type);
- arr.push_back(E->get().vram);
+ for (const ResourceInfo &E : infos) {
+ arr.push_back(E.path);
+ arr.push_back(E.format);
+ arr.push_back(E.type);
+ arr.push_back(E.vram);
}
return arr;
}
diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp
index ab368471e4..24833711d5 100644
--- a/core/debugger/local_debugger.cpp
+++ b/core/debugger/local_debugger.cpp
@@ -320,13 +320,13 @@ void LocalDebugger::print_variables(const List<String> &names, const List<Varian
String value;
Vector<String> value_lines;
const List<Variant>::Element *V = values.front();
- for (const List<String>::Element *E = names.front(); E; E = E->next()) {
+ for (const String &E : names) {
value = String(V->get());
if (variable_prefix.is_empty()) {
- print_line(E->get() + ": " + String(V->get()));
+ print_line(E + ": " + String(V->get()));
} else {
- print_line(E->get() + ":");
+ print_line(E + ":");
value_lines = value.split("\n");
for (int i = 0; i < value_lines.size(); ++i) {
print_line(variable_prefix + value_lines[i]);
diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp
index bdbb7766fa..0add12ff3d 100644
--- a/core/debugger/remote_debugger.cpp
+++ b/core/debugger/remote_debugger.cpp
@@ -427,16 +427,16 @@ void RemoteDebugger::_send_resource_usage() {
List<RS::TextureInfo> tinfo;
RS::get_singleton()->texture_debug_usage(&tinfo);
- for (List<RS::TextureInfo>::Element *E = tinfo.front(); E; E = E->next()) {
+ for (const RS::TextureInfo &E : tinfo) {
DebuggerMarshalls::ResourceInfo info;
- info.path = E->get().path;
- info.vram = E->get().bytes;
- info.id = E->get().texture;
+ info.path = E.path;
+ info.vram = E.bytes;
+ info.id = E.texture;
info.type = "Texture";
- if (E->get().depth == 0) {
- info.format = itos(E->get().width) + "x" + itos(E->get().height) + " " + Image::get_format_name(E->get().format);
+ if (E.depth == 0) {
+ info.format = itos(E.width) + "x" + itos(E.height) + " " + Image::get_format_name(E.format);
} else {
- info.format = itos(E->get().width) + "x" + itos(E->get().height) + "x" + itos(E->get().depth) + " " + Image::get_format_name(E->get().format);
+ info.format = itos(E.width) + "x" + itos(E.height) + "x" + itos(E.depth) + " " + Image::get_format_name(E.format);
}
usage.infos.push_back(info);
}
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 3c132a619d..660e215478 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -94,8 +94,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{ Variant::NODE_PATH, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
{ Variant::RID, sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t), sizeof(uint64_t) },
{ Variant::OBJECT, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
- { Variant::CALLABLE, sizeof(Callable), sizeof(Callable), sizeof(Callable), sizeof(Callable) }, //harcoded align
- { Variant::SIGNAL, sizeof(Signal), sizeof(Signal), sizeof(Signal), sizeof(Signal) }, //harcoded align
+ { Variant::CALLABLE, sizeof(Callable), sizeof(Callable), sizeof(Callable), sizeof(Callable) }, // Hardcoded align.
+ { Variant::SIGNAL, sizeof(Signal), sizeof(Signal), sizeof(Signal), sizeof(Signal) }, // Hardcoded align.
{ Variant::DICTIONARY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
{ Variant::ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
{ Variant::PACKED_BYTE_ARRAY, ptrsize_32, ptrsize_64, ptrsize_32, ptrsize_64 },
@@ -146,7 +146,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
}
{
- //member offsets sizes
+ // Member offsets sizes.
struct {
Variant::Type type;
const char *member;
@@ -180,7 +180,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
{ Variant::QUATERNION, "w", 3 * sizeof(float), 3 * sizeof(float), 3 * sizeof(double), 3 * sizeof(double) },
{ Variant::AABB, "position", 0, 0, 0, 0 },
{ Variant::AABB, "size", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
- //rememer that basis vectors are flipped!
+ // Remember that basis vectors are flipped!
{ Variant::BASIS, "x", 0, 0, 0, 0 },
{ Variant::BASIS, "y", vec3_elems * sizeof(float), vec3_elems * sizeof(float), vec3_elems * sizeof(double), vec3_elems * sizeof(double) },
{ Variant::BASIS, "z", vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(float), vec3_elems * 2 * sizeof(double), vec3_elems * 2 * sizeof(double) },
@@ -251,7 +251,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
}
{
- // global enums and constants
+ // Global enums and constants.
Array constants;
Map<String, List<Pair<String, int>>> enum_list;
@@ -276,10 +276,10 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Dictionary d1;
d1["name"] = E->key();
Array values;
- for (List<Pair<String, int>>::Element *F = E->get().front(); F; F = F->next()) {
+ for (const Pair<String, int> &F : E->get()) {
Dictionary d2;
- d2["name"] = F->get().first;
- d2["value"] = F->get().second;
+ d2["name"] = F.first;
+ d2["value"] = F.second;
values.push_back(d2);
}
d1["values"] = values;
@@ -294,8 +294,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
List<StringName> utility_func_names;
Variant::get_utility_function_list(&utility_func_names);
- for (List<StringName>::Element *E = utility_func_names.front(); E; E = E->next()) {
- StringName name = E->get();
+ for (const StringName &name : utility_func_names) {
Dictionary func;
func["name"] = String(name);
if (Variant::has_utility_function_return_value(name)) {
@@ -363,8 +362,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
List<StringName> member_names;
Variant::get_member_list(type, &member_names);
- for (List<StringName>::Element *E = member_names.front(); E; E = E->next()) {
- StringName member_name = E->get();
+ for (const StringName &member_name : member_names) {
Dictionary d2;
d2["name"] = String(member_name);
d2["type"] = Variant::get_type_name(Variant::get_member_type(type, member_name));
@@ -380,8 +378,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
List<StringName> constant_names;
Variant::get_constants_for_type(type, &constant_names);
- for (List<StringName>::Element *E = constant_names.front(); E; E = E->next()) {
- StringName constant_name = E->get();
+ for (const StringName &constant_name : constant_names) {
Dictionary d2;
d2["name"] = String(constant_name);
Variant constant = Variant::get_constant_value(type, constant_name);
@@ -420,8 +417,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
List<StringName> method_names;
Variant::get_builtin_method_list(type, &method_names);
- for (List<StringName>::Element *E = method_names.front(); E; E = E->next()) {
- StringName method_name = E->get();
+ for (const StringName &method_name : method_names) {
Dictionary d2;
d2["name"] = String(method_name);
if (Variant::has_builtin_method_return_value(type, method_name)) {
@@ -503,9 +499,8 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
class_list.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = class_list.front(); E; E = E->next()) {
+ for (const StringName &class_name : class_list) {
Dictionary d;
- StringName class_name = E->get();
d["name"] = String(class_name);
d["is_refcounted"] = ClassDB::is_parent_class(class_name, "RefCounted");
d["is_instantiable"] = ClassDB::can_instantiate(class_name);
@@ -525,15 +520,15 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Array constants;
List<String> constant_list;
ClassDB::get_integer_constant_list(class_name, &constant_list, true);
- for (List<String>::Element *F = constant_list.front(); F; F = F->next()) {
- StringName enum_name = ClassDB::get_integer_constant_enum(class_name, F->get());
+ for (const String &F : constant_list) {
+ StringName enum_name = ClassDB::get_integer_constant_enum(class_name, F);
if (enum_name != StringName()) {
continue; //enums will be handled on their own
}
Dictionary d2;
- d2["name"] = String(F->get());
- d2["value"] = ClassDB::get_integer_constant(class_name, F->get());
+ d2["name"] = String(F);
+ d2["value"] = ClassDB::get_integer_constant(class_name, F);
constants.push_back(d2);
}
@@ -547,13 +542,13 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Array enums;
List<StringName> enum_list;
ClassDB::get_enum_list(class_name, &enum_list, true);
- for (List<StringName>::Element *F = enum_list.front(); F; F = F->next()) {
+ for (const StringName &F : enum_list) {
Dictionary d2;
- d2["name"] = String(F->get());
+ d2["name"] = String(F);
Array values;
List<StringName> enum_constant_list;
- ClassDB::get_enum_constants(class_name, F->get(), &enum_constant_list, true);
+ ClassDB::get_enum_constants(class_name, F, &enum_constant_list, true);
for (List<StringName>::Element *G = enum_constant_list.front(); G; G = G->next()) {
Dictionary d3;
d3["name"] = String(G->get());
@@ -575,14 +570,14 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Array methods;
List<MethodInfo> method_list;
ClassDB::get_method_list(class_name, &method_list, true);
- for (List<MethodInfo>::Element *F = method_list.front(); F; F = F->next()) {
- StringName method_name = F->get().name;
- if (F->get().flags & METHOD_FLAG_VIRTUAL) {
+ for (const MethodInfo &F : method_list) {
+ StringName method_name = F.name;
+ if (F.flags & METHOD_FLAG_VIRTUAL) {
//virtual method
- const MethodInfo &mi = F->get();
+ const MethodInfo &mi = F;
Dictionary d2;
d2["name"] = String(method_name);
- d2["is_const"] = (F->get().flags & METHOD_FLAG_CONST) ? true : false;
+ d2["is_const"] = (F.flags & METHOD_FLAG_CONST) ? true : false;
d2["is_vararg"] = false;
d2["is_virtual"] = true;
// virtual functions have no hash since no MethodBind is involved
@@ -619,7 +614,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
methods.push_back(d2);
- } else if (F->get().name.begins_with("_")) {
+ } else if (F.name.begins_with("_")) {
//hidden method, ignore
} else {
@@ -692,19 +687,19 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Array signals;
List<MethodInfo> signal_list;
ClassDB::get_signal_list(class_name, &signal_list, true);
- for (List<MethodInfo>::Element *F = signal_list.front(); F; F = F->next()) {
- StringName signal_name = F->get().name;
+ for (const MethodInfo &F : signal_list) {
+ StringName signal_name = F.name;
Dictionary d2;
d2["name"] = String(signal_name);
Array arguments;
- for (int i = 0; i < F->get().arguments.size(); i++) {
+ for (int i = 0; i < F.arguments.size(); i++) {
Dictionary d3;
- d3["name"] = F->get().arguments[i].name;
- Variant::Type type = F->get().arguments[i].type;
- if (F->get().arguments[i].class_name != StringName()) {
- d3["type"] = String(F->get().arguments[i].class_name);
+ d3["name"] = F.arguments[i].name;
+ Variant::Type type = F.arguments[i].type;
+ if (F.arguments[i].class_name != StringName()) {
+ d3["type"] = String(F.arguments[i].class_name);
} else if (type == Variant::NIL) {
d3["type"] = "Variant";
} else {
@@ -728,28 +723,28 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
Array properties;
List<PropertyInfo> property_list;
ClassDB::get_property_list(class_name, &property_list, true);
- for (List<PropertyInfo>::Element *F = property_list.front(); F; F = F->next()) {
- if (F->get().usage & PROPERTY_USAGE_CATEGORY || F->get().usage & PROPERTY_USAGE_GROUP || F->get().usage & PROPERTY_USAGE_SUBGROUP) {
+ for (const PropertyInfo &F : property_list) {
+ if (F.usage & PROPERTY_USAGE_CATEGORY || F.usage & PROPERTY_USAGE_GROUP || F.usage & PROPERTY_USAGE_SUBGROUP) {
continue; //not real properties
}
- if (F->get().name.begins_with("_")) {
+ if (F.name.begins_with("_")) {
continue; //hidden property
}
- StringName property_name = F->get().name;
+ StringName property_name = F.name;
Dictionary d2;
d2["name"] = String(property_name);
- if (F->get().class_name != StringName()) {
- d2["type"] = String(F->get().class_name);
- } else if (F->get().type == Variant::NIL && F->get().usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
+ if (F.class_name != StringName()) {
+ d2["type"] = String(F.class_name);
+ } else if (F.type == Variant::NIL && F.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
d2["type"] = "Variant";
} else {
- d2["type"] = Variant::get_type_name(F->get().type);
+ d2["type"] = Variant::get_type_name(F.type);
}
- d2["setter"] = ClassDB::get_property_setter(class_name, F->get().name);
- d2["getter"] = ClassDB::get_property_getter(class_name, F->get().name);
- d2["index"] = ClassDB::get_property_index(class_name, F->get().name);
+ d2["setter"] = ClassDB::get_property_setter(class_name, F.name);
+ d2["getter"] = ClassDB::get_property_getter(class_name, F.name);
+ d2["index"] = ClassDB::get_property_index(class_name, F.name);
properties.push_back(d2);
}
@@ -771,8 +766,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
List<Engine::Singleton> singleton_list;
Engine::get_singleton()->get_singletons(&singleton_list);
- for (List<Engine::Singleton>::Element *E = singleton_list.front(); E; E = E->next()) {
- const Engine::Singleton &s = E->get();
+ for (const Engine::Singleton &s : singleton_list) {
Dictionary d;
d["name"] = s.name;
if (s.class_name != StringName()) {
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index 8f68b8d848..88fff342ee 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -281,8 +281,9 @@ static GDNativeBool gdnative_variant_has_key(const GDNativeVariantPtr p_self, co
const Variant *self = (const Variant *)p_self;
const Variant *key = (const Variant *)p_key;
bool valid;
- return self->has_key(*key, valid);
+ bool ret = self->has_key(*key, valid);
*r_valid = valid;
+ return ret;
}
static void gdnative_variant_get_type_name(GDNativeVariantType p_type, GDNativeStringPtr r_ret) {
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index c1ebb3e76a..3e69a28d59 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -134,7 +134,7 @@ typedef void *GDNativeObjectPtr;
typedef void *GDNativeTypePtr;
typedef void *GDNativeMethodBindPtr;
typedef int64_t GDNativeInt;
-typedef uint32_t GDNativeBool;
+typedef uint8_t GDNativeBool;
typedef uint64_t GDObjectInstanceID;
/* VARIANT DATA I/O */
diff --git a/core/extension/native_extension.cpp b/core/extension/native_extension.cpp
index 65718a7507..16bc28e0a2 100644
--- a/core/extension/native_extension.cpp
+++ b/core/extension/native_extension.cpp
@@ -351,8 +351,8 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or
String library_path;
- for (List<String>::Element *E = libraries.front(); E; E = E->next()) {
- Vector<String> tags = E->get().split(".");
+ for (const String &E : libraries) {
+ Vector<String> tags = E.split(".");
bool all_tags_met = true;
for (int i = 0; i < tags.size(); i++) {
String tag = tags[i].strip_edges();
@@ -363,7 +363,7 @@ RES NativeExtensionResourceLoader::load(const String &p_path, const String &p_or
}
if (all_tags_met) {
- library_path = config->get_value("libraries", E->get());
+ library_path = config->get_value("libraries", E);
break;
}
}
diff --git a/core/input/input.cpp b/core/input/input.cpp
index f57985831a..c205726b0a 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -101,7 +101,7 @@ void Input::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action", "exact_match"), &Input::is_action_just_pressed, DEFVAL(false));
ClassDB::bind_method(D_METHOD("is_action_just_released", "action", "exact_match"), &Input::is_action_just_released, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_action_strength", "action", "exact_match"), &Input::get_action_strength, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action", "exact_match"), &Input::get_action_strength, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action", "exact_match"), &Input::get_action_raw_strength, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_axis", "negative_action", "positive_action"), &Input::get_axis);
ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f));
ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false));
@@ -169,13 +169,12 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S
String pf = p_function;
if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" ||
pf == "is_action_just_pressed" || pf == "is_action_just_released" ||
- pf == "get_action_strength" || pf == "get_axis" || pf == "get_vector")) {
+ pf == "get_action_strength" || pf == "get_action_raw_strength" ||
+ pf == "get_axis" || pf == "get_vector")) {
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- const PropertyInfo &pi = E->get();
-
+ for (const PropertyInfo &pi : pinfo) {
if (!pi.name.begins_with("input/")) {
continue;
}
diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp
index b5f067d499..6714705bb5 100644
--- a/core/input/input_map.cpp
+++ b/core/input/input_map.cpp
@@ -65,11 +65,11 @@ String InputMap::_suggest_actions(const StringName &p_action) const {
float closest_similarity = 0.0;
// Find the most action with the most similar name.
- for (List<StringName>::Element *E = actions.front(); E; E = E->next()) {
- const float similarity = String(E->get()).similarity(p_action);
+ for (const StringName &action : actions) {
+ const float similarity = String(action).similarity(p_action);
if (similarity > closest_similarity) {
- closest_action = E->get();
+ closest_action = action;
closest_similarity = similarity;
}
}
@@ -105,8 +105,8 @@ Array InputMap::_get_actions() {
return ret;
}
- for (const List<StringName>::Element *E = actions.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const StringName &E : actions) {
+ ret.push_back(E);
}
return ret;
@@ -129,13 +129,11 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re
ERR_FAIL_COND_V(!p_event.is_valid(), nullptr);
for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) {
- const Ref<InputEvent> e = E->get();
-
- int device = e->get_device();
+ int device = E->get()->get_device();
if (device == ALL_DEVICES || device == p_event->get_device()) {
- if (p_exact_match && e->is_match(p_event, true)) {
+ if (p_exact_match && E->get()->is_match(p_event, true)) {
return E;
- } else if (!p_exact_match && e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
+ } else if (!p_exact_match && E->get()->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) {
return E;
}
}
@@ -198,7 +196,7 @@ Array InputMap::_action_get_events(const StringName &p_action) {
const List<Ref<InputEvent>> *al = action_get_events(p_action);
if (al) {
for (const List<Ref<InputEvent>>::Element *E = al->front(); E; E = E->next()) {
- ret.push_back(E->get());
+ ret.push_back(E);
}
}
@@ -263,9 +261,7 @@ void InputMap::load_from_project_settings() {
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- const PropertyInfo &pi = E->get();
-
+ for (const PropertyInfo &pi : pinfo) {
if (!pi.name.begins_with("input/")) {
continue;
}
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index 10f68f3cef..aeaf25f321 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -40,8 +40,8 @@ PackedStringArray ConfigFile::_get_sections() const {
PackedStringArray arr;
arr.resize(s.size());
int idx = 0;
- for (const List<String>::Element *E = s.front(); E; E = E->next()) {
- arr.set(idx++, E->get());
+ for (const String &E : s) {
+ arr.set(idx++, E);
}
return arr;
@@ -53,8 +53,8 @@ PackedStringArray ConfigFile::_get_section_keys(const String &p_section) const {
PackedStringArray arr;
arr.resize(s.size());
int idx = 0;
- for (const List<String>::Element *E = s.front(); E; E = E->next()) {
- arr.set(idx++, E->get());
+ for (const String &E : s) {
+ arr.set(idx++, E);
}
return arr;
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index dfba00067f..8234adea06 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -93,8 +93,8 @@ static Error _erase_recursive(DirAccess *da) {
da->list_dir_end();
- for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
- Error err = da->change_dir(E->get());
+ for (const String &E : dirs) {
+ Error err = da->change_dir(E);
if (err == OK) {
err = _erase_recursive(da);
if (err) {
@@ -105,7 +105,7 @@ static Error _erase_recursive(DirAccess *da) {
if (err) {
return err;
}
- err = da->remove(da->get_current_dir().plus_file(E->get()));
+ err = da->remove(da->get_current_dir().plus_file(E));
if (err) {
return err;
}
@@ -114,8 +114,8 @@ static Error _erase_recursive(DirAccess *da) {
}
}
- for (List<String>::Element *E = files.front(); E; E = E->next()) {
- Error err = da->remove(da->get_current_dir().plus_file(E->get()));
+ for (const String &E : files) {
+ Error err = da->remove(da->get_current_dir().plus_file(E));
if (err) {
return err;
}
@@ -362,16 +362,15 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
list_dir_end();
- for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
- String rel_path = E->get();
+ for (const String &rel_path : dirs) {
String target_dir = p_to + rel_path;
if (!p_target_da->dir_exists(target_dir)) {
Error err = p_target_da->make_dir(target_dir);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + target_dir + "'.");
}
- Error err = change_dir(E->get());
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + E->get() + "'.");
+ Error err = change_dir(rel_path);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot change current directory to '" + rel_path + "'.");
err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags, p_copy_links);
if (err) {
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp
index 8000dd4290..5c1352c1b6 100644
--- a/core/io/http_client.cpp
+++ b/core/io/http_client.cpp
@@ -93,8 +93,7 @@ Dictionary HTTPClient::_get_response_headers_as_dictionary() {
List<String> rh;
get_response_headers(&rh);
Dictionary ret;
- for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
- const String &s = E->get();
+ for (const String &s : rh) {
int sp = s.find(":");
if (sp == -1) {
continue;
@@ -113,8 +112,8 @@ PackedStringArray HTTPClient::_get_response_headers() {
PackedStringArray ret;
ret.resize(rh.size());
int idx = 0;
- for (const List<String>::Element *E = rh.front(); E; E = E->next()) {
- ret.set(idx++, E->get());
+ for (const String &E : rh) {
+ ret.set(idx++, E);
}
return ret;
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index b45e9d26b1..b9fc416f65 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -35,8 +35,8 @@
bool ImageFormatLoader::recognize(const String &p_extension) const {
List<String> extensions;
get_recognized_extensions(&extensions);
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(p_extension) == 0) {
+ for (const String &E : extensions) {
+ if (E.nocasecmp_to(p_extension) == 0) {
return true;
}
}
diff --git a/core/io/ip.cpp b/core/io/ip.cpp
index 001b1c4757..cd1b6d1994 100644
--- a/core/io/ip.cpp
+++ b/core/io/ip.cpp
@@ -252,8 +252,8 @@ Array IP::_get_local_addresses() const {
Array addresses;
List<IPAddress> ip_addresses;
get_local_addresses(&ip_addresses);
- for (List<IPAddress>::Element *E = ip_addresses.front(); E; E = E->next()) {
- addresses.push_back(E->get());
+ for (const IPAddress &E : ip_addresses) {
+ addresses.push_back(E);
}
return addresses;
@@ -271,8 +271,8 @@ Array IP::_get_local_interfaces() const {
rc["index"] = c.index;
Array ips;
- for (const List<IPAddress>::Element *F = c.ip_addresses.front(); F; F = F->next()) {
- ips.push_front(F->get());
+ for (const IPAddress &F : c.ip_addresses) {
+ ips.push_front(F);
}
rc["addresses"] = ips;
@@ -286,8 +286,8 @@ void IP::get_local_addresses(List<IPAddress> *r_addresses) const {
Map<String, Interface_Info> interfaces;
get_local_interfaces(&interfaces);
for (Map<String, Interface_Info>::Element *E = interfaces.front(); E; E = E->next()) {
- for (const List<IPAddress>::Element *F = E->get().ip_addresses.front(); F; F = F->next()) {
- r_addresses->push_front(F->get());
+ for (const IPAddress &F : E->get().ip_addresses) {
+ r_addresses->push_front(F);
}
}
}
diff --git a/core/io/json.cpp b/core/io/json.cpp
index b3a2498212..5823afbdcd 100644
--- a/core/io/json.cpp
+++ b/core/io/json.cpp
@@ -121,14 +121,17 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_
keys.sort();
}
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- if (E != keys.front()) {
+ bool first_key = true;
+ for (const Variant &E : keys) {
+ if (first_key) {
+ first_key = false;
+ } else {
s += ",";
s += end_statement;
}
- s += _make_indent(p_indent, p_cur_indent + 1) + _stringify(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
+ s += _make_indent(p_indent, p_cur_indent + 1) + _stringify(String(E), p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
s += colon;
- s += _stringify(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
+ s += _stringify(d[E], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
}
s += end_statement + _make_indent(p_indent, p_cur_indent) + "}";
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp
index f342db2dad..4a1d3e5212 100644
--- a/core/io/marshalls.cpp
+++ b/core/io/marshalls.cpp
@@ -1358,8 +1358,8 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
obj->get_property_list(&props);
int pc = 0;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
pc++;
@@ -1372,15 +1372,15 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len += 4;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- _encode_string(E->get().name, buf, r_len);
+ _encode_string(E.name, buf, r_len);
int len;
- Error err = encode_variant(obj->get(E->get().name), buf, len, p_full_objects);
+ Error err = encode_variant(obj->get(E.name), buf, len, p_full_objects);
if (err) {
return err;
}
@@ -1418,7 +1418,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ for (const Variant &E : keys) {
/*
CharString utf8 = E->->utf8();
@@ -1433,13 +1433,13 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo
r_len++; //pad
*/
int len;
- encode_variant(E->get(), buf, len, p_full_objects);
+ encode_variant(E, buf, len, p_full_objects);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
r_len += len;
if (buf) {
buf += len;
}
- Variant *v = d.getptr(E->get());
+ Variant *v = d.getptr(E);
ERR_FAIL_COND_V(!v, ERR_BUG);
encode_variant(*v, buf, len, p_full_objects);
ERR_FAIL_COND_V(len % 4, ERR_BUG);
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index e99c60613a..80610e12cb 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -555,12 +555,12 @@ bool MultiplayerAPI::_send_confirm_path(Node *p_node, NodePath p_path, PathSentC
ofs += encode_cstring(path.get_data(), &packet.write[ofs]);
- for (List<int>::Element *E = peers_to_add.front(); E; E = E->next()) {
- network_peer->set_target_peer(E->get()); // To all of you.
+ for (int &E : peers_to_add) {
+ network_peer->set_target_peer(E); // To all of you.
network_peer->set_transfer_mode(MultiplayerPeer::TRANSFER_MODE_RELIABLE);
network_peer->put_packet(packet.ptr(), packet.size());
- psc->confirmed_peers.insert(E->get(), false); // Insert into confirmed, but as false since it was not confirmed.
+ psc->confirmed_peers.insert(E, false); // Insert into confirmed, but as false since it was not confirmed.
}
}
@@ -917,8 +917,8 @@ void MultiplayerAPI::_del_peer(int p_id) {
// Some refactoring is needed to make this faster and do paths GC.
List<NodePath> keys;
path_send_cache.get_key_list(&keys);
- for (List<NodePath>::Element *E = keys.front(); E; E = E->next()) {
- PathSentCache *psc = path_send_cache.getptr(E->get());
+ for (const NodePath &E : keys) {
+ PathSentCache *psc = path_send_cache.getptr(E);
psc->confirmed_peers.erase(p_id);
}
emit_signal(SNAME("network_peer_disconnected"), p_id);
diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp
index cf6a0b6027..4a76f0191d 100644
--- a/core/io/packed_data_container.cpp
+++ b/core/io/packed_data_container.cpp
@@ -268,21 +268,21 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd
d.get_key_list(&keys);
List<DictKey> sortk;
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ for (const Variant &key : keys) {
DictKey dk;
- dk.hash = E->get().hash();
- dk.key = E->get();
+ dk.hash = key.hash();
+ dk.key = key;
sortk.push_back(dk);
}
sortk.sort();
int idx = 0;
- for (List<DictKey>::Element *E = sortk.front(); E; E = E->next()) {
- encode_uint32(E->get().hash, &tmpdata.write[pos + 8 + idx * 12 + 0]);
- uint32_t ofs = _pack(E->get().key, tmpdata, string_cache);
+ for (const DictKey &E : sortk) {
+ encode_uint32(E.hash, &tmpdata.write[pos + 8 + idx * 12 + 0]);
+ uint32_t ofs = _pack(E.key, tmpdata, string_cache);
encode_uint32(ofs, &tmpdata.write[pos + 8 + idx * 12 + 4]);
- ofs = _pack(d[E->get().key], tmpdata, string_cache);
+ ofs = _pack(d[E.key], tmpdata, string_cache);
encode_uint32(ofs, &tmpdata.write[pos + 8 + idx * 12 + 8]);
idx++;
}
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index efa622d976..727611a573 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -33,6 +33,7 @@
#include "core/core_string_names.h"
#include "core/io/file_access.h"
#include "core/io/resource_loader.h"
+#include "core/math/math_funcs.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "scene/main/node.h" //only so casting works
@@ -94,12 +95,43 @@ String Resource::get_path() const {
return path_cache;
}
-void Resource::set_subindex(int p_sub_index) {
- subindex = p_sub_index;
+String Resource::generate_scene_unique_id() {
+ // Generate a unique enough hash, but still user-readable.
+ // If it's not unique it does not matter because the saver will try again.
+ OS::Date date = OS::get_singleton()->get_date();
+ OS::Time time = OS::get_singleton()->get_time();
+ uint32_t hash = hash_djb2_one_32(OS::get_singleton()->get_ticks_usec());
+ hash = hash_djb2_one_32(date.year, hash);
+ hash = hash_djb2_one_32(date.month, hash);
+ hash = hash_djb2_one_32(date.day, hash);
+ hash = hash_djb2_one_32(time.hour, hash);
+ hash = hash_djb2_one_32(time.minute, hash);
+ hash = hash_djb2_one_32(time.second, hash);
+ hash = hash_djb2_one_32(Math::rand(), hash);
+
+ static constexpr uint32_t characters = 5;
+ static constexpr uint32_t char_count = ('z' - 'a');
+ static constexpr uint32_t base = char_count + ('9' - '0');
+ String id;
+ for (uint32_t i = 0; i < characters; i++) {
+ uint32_t c = hash % base;
+ if (c < char_count) {
+ id += String::chr('a' + c);
+ } else {
+ id += String::chr('0' + (c - char_count));
+ }
+ hash /= base;
+ }
+
+ return id;
+}
+
+void Resource::set_scene_unique_id(const String &p_id) {
+ scene_unique_id = p_id;
}
-int Resource::get_subindex() const {
- return subindex;
+String Resource::get_scene_unique_id() const {
+ return scene_unique_id;
}
void Resource::set_name(const String &p_name) {
@@ -133,15 +165,15 @@ Error Resource::copy_from(const Ref<Resource> &p_resource) {
List<PropertyInfo> pi;
p_resource->get_property_list(&pi);
- for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : pi) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- if (E->get().name == "resource_path") {
+ if (E.name == "resource_path") {
continue; //do not change path
}
- set(E->get().name, p_resource->get(E->get().name));
+ set(E.name, p_resource->get(E.name));
}
return OK;
}
@@ -169,11 +201,11 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res
r->local_scene = p_for_scene;
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : plist) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant p = get(E->get().name);
+ Variant p = get(E.name);
if (p.get_type() == Variant::OBJECT) {
RES sr = p;
if (sr.is_valid()) {
@@ -189,7 +221,7 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res
}
}
- r->set(E->get().name, p);
+ r->set(E.name, p);
}
return r;
@@ -201,11 +233,11 @@ void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, R
local_scene = p_for_scene;
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : plist) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant p = get(E->get().name);
+ Variant p = get(E.name);
if (p.get_type() == Variant::OBJECT) {
RES sr = p;
if (sr.is_valid()) {
@@ -227,21 +259,21 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const {
Ref<Resource> r = (Resource *)ClassDB::instantiate(get_class());
ERR_FAIL_COND_V(r.is_null(), Ref<Resource>());
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : plist) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant p = get(E->get().name);
+ Variant p = get(E.name);
if ((p.get_type() == Variant::DICTIONARY || p.get_type() == Variant::ARRAY)) {
- r->set(E->get().name, p.duplicate(p_subresources));
- } else if (p.get_type() == Variant::OBJECT && (p_subresources || (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE))) {
+ r->set(E.name, p.duplicate(p_subresources));
+ } else if (p.get_type() == Variant::OBJECT && (p_subresources || (E.usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE))) {
RES sr = p;
if (sr.is_valid()) {
- r->set(E->get().name, sr->duplicate(p_subresources));
+ r->set(E.name, sr->duplicate(p_subresources));
}
} else {
- r->set(E->get().name, p);
+ r->set(E.name, p);
}
}
@@ -285,9 +317,9 @@ uint32_t Resource::hash_edited_version() const {
List<PropertyInfo> plist;
get_property_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (E->get().usage & PROPERTY_USAGE_STORAGE && E->get().type == Variant::OBJECT && E->get().hint == PROPERTY_HINT_RESOURCE_TYPE) {
- RES res = get(E->get().name);
+ for (const PropertyInfo &E : plist) {
+ if (E.usage & PROPERTY_USAGE_STORAGE && E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ RES res = get(E.name);
if (res.is_valid()) {
hash = hash_djb2_one_32(res->hash_edited_version(), hash);
}
@@ -350,8 +382,8 @@ bool Resource::is_translation_remapped() const {
#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
-void Resource::set_id_for_path(const String &p_path, int p_id) {
- if (p_id == -1) {
+void Resource::set_id_for_path(const String &p_path, const String &p_id) {
+ if (p_id == "") {
ResourceCache::path_cache_lock.write_lock();
ResourceCache::resource_path_cache[p_path].erase(get_path());
ResourceCache::path_cache_lock.write_unlock();
@@ -362,15 +394,15 @@ void Resource::set_id_for_path(const String &p_path, int p_id) {
}
}
-int Resource::get_id_for_path(const String &p_path) const {
+String Resource::get_id_for_path(const String &p_path) const {
ResourceCache::path_cache_lock.read_lock();
if (ResourceCache::resource_path_cache[p_path].has(get_path())) {
- int result = ResourceCache::resource_path_cache[p_path][get_path()];
+ String result = ResourceCache::resource_path_cache[p_path][get_path()];
ResourceCache::path_cache_lock.read_unlock();
return result;
} else {
ResourceCache::path_cache_lock.read_unlock();
- return -1;
+ return "";
}
}
#endif
@@ -414,7 +446,7 @@ Resource::~Resource() {
HashMap<String, Resource *> ResourceCache::resources;
#ifdef TOOLS_ENABLED
-HashMap<String, HashMap<String, int>> ResourceCache::resource_path_cache;
+HashMap<String, HashMap<String, String>> ResourceCache::resource_path_cache;
#endif
RWLock ResourceCache::lock;
diff --git a/core/io/resource.h b/core/io/resource.h
index 028fed1c6e..e864b371ad 100644
--- a/core/io/resource.h
+++ b/core/io/resource.h
@@ -31,6 +31,7 @@
#ifndef RESOURCE_H
#define RESOURCE_H
+#include "core/io/resource_uid.h"
#include "core/object/class_db.h"
#include "core/object/ref_counted.h"
#include "core/templates/safe_refcount.h"
@@ -59,7 +60,7 @@ private:
String name;
String path_cache;
- int subindex = 0;
+ String scene_unique_id;
virtual bool _use_builtin_script() const { return true; }
@@ -105,8 +106,9 @@ public:
virtual void set_path(const String &p_path, bool p_take_over = false);
String get_path() const;
- void set_subindex(int p_sub_index);
- int get_subindex() const;
+ static String generate_scene_unique_id();
+ void set_scene_unique_id(const String &p_id);
+ String get_scene_unique_id() const;
virtual Ref<Resource> duplicate(bool p_subresources = false) const;
Ref<Resource> duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache);
@@ -140,8 +142,8 @@ public:
#ifdef TOOLS_ENABLED
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
- void set_id_for_path(const String &p_path, int p_id);
- int get_id_for_path(const String &p_path) const;
+ void set_id_for_path(const String &p_path, const String &p_id);
+ String get_id_for_path(const String &p_path) const;
#endif
Resource();
@@ -156,7 +158,7 @@ class ResourceCache {
static RWLock lock;
static HashMap<String, Resource *> resources;
#ifdef TOOLS_ENABLED
- static HashMap<String, HashMap<String, int>> resource_path_cache; // each tscn has a set of resource paths and IDs
+ static HashMap<String, HashMap<String, String>> resource_path_cache; // Each tscn has a set of resource paths and IDs.
static RWLock path_cache_lock;
#endif // TOOLS_ENABLED
friend void unregister_core_types();
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 0e9815245f..a3ebc32cc5 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -84,9 +84,10 @@ enum {
OBJECT_EXTERNAL_RESOURCE = 1,
OBJECT_INTERNAL_RESOURCE = 2,
OBJECT_EXTERNAL_RESOURCE_INDEX = 3,
- //version 2: added 64 bits support for float and int
- //version 3: changed nodepath encoding
- FORMAT_VERSION = 3,
+ // Version 2: added 64 bits support for float and int.
+ // Version 3: changed nodepath encoding.
+ // Version 4: new string ID for ext/subresources, breaks forward compat.
+ FORMAT_VERSION = 4,
FORMAT_VERSION_CAN_RENAME_DEPS = 1,
FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3,
};
@@ -311,7 +312,14 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
} break;
case OBJECT_INTERNAL_RESOURCE: {
uint32_t index = f->get_32();
- String path = res_path + "::" + itos(index);
+ String path;
+
+ if (using_named_scene_ids) { // New format.
+ ERR_FAIL_INDEX_V((int)index, internal_resources.size(), ERR_PARSE_ERROR);
+ path = internal_resources[index].path;
+ } else {
+ path += res_path + "::" + itos(index);
+ }
//always use internal cache for loading internal resources
if (!internal_index_cache.has(path)) {
@@ -320,7 +328,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
} else {
r_v = internal_index_cache[path];
}
-
} break;
case OBJECT_EXTERNAL_RESOURCE: {
//old file format, still around for compatibility
@@ -378,7 +385,6 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
ERR_FAIL_V(ERR_FILE_CORRUPT);
} break;
}
-
} break;
case VARIANT_CALLABLE: {
r_v = Callable();
@@ -659,15 +665,17 @@ Error ResourceLoaderBinary::load() {
//maybe it is loaded already
String path;
- int subindex = 0;
+ String id;
if (!main) {
path = internal_resources[i].path;
if (path.begins_with("local://")) {
path = path.replace_first("local://", "");
- subindex = path.to_int();
+ id = path;
path = res_path + "::" + path;
+
+ internal_resources.write[i].path = path; // Update path.
}
if (cache_mode == ResourceFormatLoader::CACHE_MODE_REUSE) {
@@ -722,7 +730,7 @@ Error ResourceLoaderBinary::load() {
if (path != String() && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
r->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE); //if got here because the resource with same path has different type, replace it
}
- r->set_subindex(subindex);
+ r->set_scene_unique_id(id);
}
if (!main) {
@@ -808,13 +816,18 @@ String ResourceLoaderBinary::get_unicode_string() {
}
void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) {
- open(p_f);
+ open(p_f, false, true);
if (error) {
return;
}
for (int i = 0; i < external_resources.size(); i++) {
- String dep = external_resources[i].path;
+ String dep;
+ if (external_resources[i].uid != ResourceUID::INVALID_ID) {
+ dep = ResourceUID::get_singleton()->id_to_text(external_resources[i].uid);
+ } else {
+ dep = external_resources[i].path;
+ }
if (p_add_types && external_resources[i].type != String()) {
dep += "::" + external_resources[i].type;
@@ -824,7 +837,7 @@ void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dep
}
}
-void ResourceLoaderBinary::open(FileAccess *p_f) {
+void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_keep_uuid_paths) {
error = OK;
f = p_f;
@@ -879,10 +892,28 @@ void ResourceLoaderBinary::open(FileAccess *p_f) {
print_bl("type: " + type);
importmd_ofs = f->get_64();
- for (int i = 0; i < 14; i++) {
+ uint32_t flags = f->get_32();
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_NAMED_SCENE_IDS) {
+ using_named_scene_ids = true;
+ }
+ if (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS) {
+ using_uids = true;
+ }
+
+ if (using_uids) {
+ uid = f->get_64();
+ } else {
+ uid = ResourceUID::INVALID_ID;
+ }
+
+ for (int i = 0; i < 5; i++) {
f->get_32(); //skip a few reserved fields
}
+ if (p_no_resources) {
+ return;
+ }
+
uint32_t string_table_size = f->get_32();
string_map.resize(string_table_size);
for (uint32_t i = 0; i < string_table_size; i++) {
@@ -896,8 +927,18 @@ void ResourceLoaderBinary::open(FileAccess *p_f) {
for (uint32_t i = 0; i < ext_resources_size; i++) {
ExtResource er;
er.type = get_unicode_string();
-
er.path = get_unicode_string();
+ if (using_uids) {
+ er.uid = f->get_64();
+ if (!p_keep_uuid_paths && er.uid != ResourceUID::INVALID_ID) {
+ if (ResourceUID::get_singleton()->has_id(er.uid)) {
+ // If a UID is found and the path is valid, it will be used, otherwise, it falls back to the path.
+ er.path = ResourceUID::get_singleton()->get_id_path(er.uid);
+ } else {
+ WARN_PRINT(String(res_path + ": In external resource #" + itos(i) + ", invalid UUID: " + ResourceUID::get_singleton()->id_to_text(er.uid) + " - using text path instead: " + er.path).utf8().get_data());
+ }
+ }
+ }
external_resources.push_back(er);
}
@@ -1013,8 +1054,8 @@ void ResourceFormatLoaderBinary::get_recognized_extensions_for_type(const String
extensions.sort();
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- String ext = E->get().to_lower();
+ for (const String &E : extensions) {
+ String ext = E.to_lower();
p_extensions->push_back(ext);
}
}
@@ -1024,8 +1065,8 @@ void ResourceFormatLoaderBinary::get_recognized_extensions(List<String> *p_exten
ClassDB::get_resource_base_extensions(&extensions);
extensions.sort();
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- String ext = E->get().to_lower();
+ for (const String &E : extensions) {
+ String ext = E.to_lower();
p_extensions->push_back(ext);
}
}
@@ -1161,8 +1202,15 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
uint64_t importmd_ofs = f->get_64();
fw->store_64(0); //metadata offset
- for (int i = 0; i < 14; i++) {
- fw->store_32(0);
+ uint32_t flags = f->get_32();
+ bool using_uids = (flags & ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS);
+ uint64_t uid_data = f->get_64();
+
+ fw->store_32(flags);
+ fw->store_64(uid_data);
+
+ for (int i = 0; i < 5; i++) {
+ f->store_32(0); // reserved
f->get_32();
}
@@ -1183,6 +1231,16 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
String type = get_ustring(f);
String path = get_ustring(f);
+ if (using_uids) {
+ ResourceUID::ID uid = f->get_64();
+ if (uid != ResourceUID::INVALID_ID) {
+ if (ResourceUID::get_singleton()->has_id(uid)) {
+ // If a UID is found and the path is valid, it will be used, otherwise, it falls back to the path.
+ path = ResourceUID::get_singleton()->get_id_path(uid);
+ }
+ }
+ }
+
bool relative = false;
if (!path.begins_with("res://")) {
path = local_path.plus_file(path).simplify_path();
@@ -1194,6 +1252,8 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
path = np;
}
+ String full_path = path;
+
if (relative) {
//restore relative
path = local_path.path_to_file(path);
@@ -1201,6 +1261,11 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
save_ustring(fw, type);
save_ustring(fw, path);
+
+ if (using_uids) {
+ ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(full_path);
+ f->store_64(uid);
+ }
}
int64_t size_diff = (int64_t)fw->get_position() - (int64_t)f->get_position();
@@ -1256,6 +1321,28 @@ String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const
return ClassDB::get_compatibility_remapped_class(r);
}
+ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_path) const {
+ String ext = p_path.get_extension().to_lower();
+ if (!ClassDB::is_resource_extension(ext)) {
+ return ResourceUID::INVALID_ID;
+ }
+
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
+ if (!f) {
+ return ResourceUID::INVALID_ID; //could not read
+ }
+
+ 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
+ }
+ return loader.uid;
+}
+
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
@@ -1269,11 +1356,7 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes)
}
}
-void ResourceFormatSaverBinaryInstance::_write_variant(const Variant &p_property, const PropertyInfo &p_hint) {
- write_variant(f, p_property, resource_set, external_resources, string_map, p_hint);
-}
-
-void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
+void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
switch (p_property.get_type()) {
case Variant::NIL: {
f->store_32(VARIANT_NIL);
@@ -1492,13 +1575,13 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
f->store_32(OBJECT_EXTERNAL_RESOURCE_INDEX);
f->store_32(external_resources[res]);
} else {
- if (!resource_set.has(res)) {
+ if (!resource_map.has(res)) {
f->store_32(OBJECT_EMPTY);
ERR_FAIL_MSG("Resource was not pre cached for the resource section, most likely due to circular reference.");
}
f->store_32(OBJECT_INTERNAL_RESOURCE);
- f->store_32(res->get_subindex());
+ f->store_32(resource_map[res]);
//internal resource
}
@@ -1520,14 +1603,14 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ for (const Variant &E : keys) {
/*
- if (!_check_type(dict[E->get()]))
+ if (!_check_type(dict[E]))
continue;
*/
- write_variant(f, E->get(), resource_set, external_resources, string_map);
- write_variant(f, d[E->get()], resource_set, external_resources, string_map);
+ write_variant(f, E, resource_map, external_resources, string_map);
+ write_variant(f, d[E], resource_map, external_resources, string_map);
}
} break;
@@ -1536,7 +1619,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia
Array a = p_property;
f->store_32(uint32_t(a.size()));
for (int i = 0; i < a.size(); i++) {
- write_variant(f, a[i], resource_set, external_resources, string_map);
+ write_variant(f, a[i], resource_map, external_resources, string_map);
}
} break;
@@ -1677,15 +1760,15 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
res->get_property_list(&property_list);
- for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- if (E->get().usage & PROPERTY_USAGE_STORAGE) {
- Variant value = res->get(E->get().name);
- if (E->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
+ for (const PropertyInfo &E : property_list) {
+ if (E.usage & PROPERTY_USAGE_STORAGE) {
+ Variant value = res->get(E.name);
+ if (E.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
RES sres = value;
if (sres.is_valid()) {
NonPersistentKey npk;
npk.base = res;
- npk.property = E->get().name;
+ npk.property = E.name;
non_persistent_map[npk] = sres;
resource_set.insert(sres);
saved_resources.push_back(sres);
@@ -1715,9 +1798,9 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
Dictionary d = p_variant;
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- _find_resources(E->get());
- Variant v = d[E->get()];
+ for (const Variant &E : keys) {
+ _find_resources(E);
+ Variant v = d[E];
_find_resources(v);
}
} break;
@@ -1816,46 +1899,49 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
save_unicode_string(f, p_resource->get_class());
f->store_64(0); //offset to import metadata
- for (int i = 0; i < 14; i++) {
+ f->store_32(FORMAT_FLAG_NAMED_SCENE_IDS | FORMAT_FLAG_UIDS);
+ ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(p_path, true);
+ f->store_64(uid);
+ for (int i = 0; i < 5; i++) {
f->store_32(0); // reserved
}
List<ResourceData> resources;
{
- for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
+ for (const RES &E : saved_resources) {
ResourceData &rd = resources.push_back(ResourceData())->get();
- rd.type = E->get()->get_class();
+ rd.type = E->get_class();
List<PropertyInfo> property_list;
- E->get()->get_property_list(&property_list);
+ E->get_property_list(&property_list);
- for (List<PropertyInfo>::Element *F = property_list.front(); F; F = F->next()) {
- if (skip_editor && F->get().name.begins_with("__editor")) {
+ for (const PropertyInfo &F : property_list) {
+ if (skip_editor && F.name.begins_with("__editor")) {
continue;
}
- if ((F->get().usage & PROPERTY_USAGE_STORAGE)) {
+ if ((F.usage & PROPERTY_USAGE_STORAGE)) {
Property p;
- p.name_idx = get_string_index(F->get().name);
+ p.name_idx = get_string_index(F.name);
- if (F->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
+ if (F.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT) {
NonPersistentKey npk;
- npk.base = E->get();
- npk.property = F->get().name;
+ npk.base = E;
+ npk.property = F.name;
if (non_persistent_map.has(npk)) {
p.value = non_persistent_map[npk];
}
} else {
- p.value = E->get()->get(F->get().name);
+ p.value = E->get(F.name);
}
- Variant default_value = ClassDB::class_get_default_property_value(E->get()->get_class(), F->get().name);
+ Variant default_value = ClassDB::class_get_default_property_value(E->get_class(), F.name);
if (default_value.get_type() != Variant::NIL && bool(Variant::evaluate(Variant::OP_EQUAL, p.value, default_value))) {
continue;
}
- p.pi = F->get();
+ p.pi = F;
rd.properties.push_back(p);
}
@@ -1882,41 +1968,47 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
String path = save_order[i]->get_path();
path = relative_paths ? local_path.path_to_file(path) : path;
save_unicode_string(f, path);
+ ResourceUID::ID ruid = ResourceSaver::get_resource_id_for_path(save_order[i]->get_path(), false);
+ f->store_64(ruid);
}
// save internal resource table
f->store_32(saved_resources.size()); //amount of internal resources
Vector<uint64_t> ofs_pos;
- Set<int> used_indices;
+ Set<String> used_unique_ids;
- for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
- RES r = E->get();
+ for (RES &r : saved_resources) {
if (r->get_path() == "" || r->get_path().find("::") != -1) {
- if (r->get_subindex() != 0) {
- if (used_indices.has(r->get_subindex())) {
- r->set_subindex(0); //repeated
+ if (r->get_scene_unique_id() != "") {
+ if (used_unique_ids.has(r->get_scene_unique_id())) {
+ r->set_scene_unique_id("");
} else {
- used_indices.insert(r->get_subindex());
+ used_unique_ids.insert(r->get_scene_unique_id());
}
}
}
}
- for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
- RES r = E->get();
+ Map<RES, int> resource_map;
+ int res_index = 0;
+ for (RES &r : saved_resources) {
if (r->get_path() == "" || r->get_path().find("::") != -1) {
- if (r->get_subindex() == 0) {
- int new_subindex = 1;
- if (used_indices.size()) {
- new_subindex = used_indices.back()->get() + 1;
+ if (r->get_scene_unique_id() == "") {
+ String new_id;
+
+ while (true) {
+ new_id = r->get_class() + "_" + Resource::generate_scene_unique_id();
+ if (!used_unique_ids.has(new_id)) {
+ break;
+ }
}
- r->set_subindex(new_subindex);
- used_indices.insert(new_subindex);
+ r->set_scene_unique_id(new_id);
+ used_unique_ids.insert(new_id);
}
- save_unicode_string(f, "local://" + itos(r->get_subindex()));
+ save_unicode_string(f, "local://" + r->get_scene_unique_id());
if (takeover_paths) {
- r->set_path(p_path + "::" + itos(r->get_subindex()), true);
+ r->set_path(p_path + "::" + r->get_scene_unique_id(), true);
}
#ifdef TOOLS_ENABLED
r->set_edited(false);
@@ -1926,22 +2018,20 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
}
ofs_pos.push_back(f->get_position());
f->store_64(0); //offset in 64 bits
+ resource_map[r] = res_index++;
}
Vector<uint64_t> ofs_table;
//now actually save the resources
- for (List<ResourceData>::Element *E = resources.front(); E; E = E->next()) {
- ResourceData &rd = E->get();
-
+ for (const ResourceData &rd : resources) {
ofs_table.push_back(f->get_position());
save_unicode_string(f, rd.type);
f->store_32(rd.properties.size());
- for (List<Property>::Element *F = rd.properties.front(); F; F = F->next()) {
- Property &p = F->get();
+ for (const Property &p : rd.properties) {
f->store_32(p.name_idx);
- _write_variant(p.value, F->get().pi);
+ write_variant(f, p.value, resource_map, external_resources, string_map, p.pi);
}
}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index abc7403935..ac964d2053 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -47,6 +47,8 @@ class ResourceLoaderBinary {
uint64_t importmd_ofs = 0;
+ ResourceUID::ID uid = ResourceUID::INVALID_ID;
+
Vector<char> str_buf;
List<RES> resource_cache;
@@ -57,9 +59,12 @@ class ResourceLoaderBinary {
struct ExtResource {
String path;
String type;
+ ResourceUID::ID uid = ResourceUID::INVALID_ID;
RES cache;
};
+ bool using_named_scene_ids = false;
+ bool using_uids = false;
bool use_sub_threads = false;
float *progress = nullptr;
Vector<ExtResource> external_resources;
@@ -93,7 +98,7 @@ public:
void set_translation_remapped(bool p_remapped);
void set_remaps(const Map<String, String> &p_remaps) { remaps = p_remaps; }
- void open(FileAccess *p_f);
+ void open(FileAccess *p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
String recognize(FileAccess *p_f);
void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
@@ -108,6 +113,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
};
@@ -150,14 +156,17 @@ class ResourceFormatSaverBinaryInstance {
};
static void _pad_buffer(FileAccess *f, int p_bytes);
- void _write_variant(const Variant &p_property, const PropertyInfo &p_hint = PropertyInfo());
void _find_resources(const Variant &p_variant, bool p_main = false);
static void save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false);
int get_string_index(const String &p_string);
public:
+ enum {
+ FORMAT_FLAG_NAMED_SCENE_IDS = 1,
+ FORMAT_FLAG_UIDS = 2,
+ };
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
- static void write_variant(FileAccess *f, const Variant &p_property, Set<RES> &resource_set, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
+ static void write_variant(FileAccess *f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
};
class ResourceFormatSaverBinary : public ResourceFormatSaver {
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index b503655edd..1e166015b0 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -93,6 +93,8 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
r_path_and_type.type = ClassDB::get_compatibility_remapped_class(value);
} else if (assign == "importer") {
r_path_and_type.importer = value;
+ } else if (assign == "uid") {
+ r_path_and_type.uid = ResourceUID::get_singleton()->text_to_id(value);
} else if (assign == "group_file") {
r_path_and_type.group_file = value;
} else if (assign == "metadata") {
@@ -146,10 +148,10 @@ void ResourceFormatImporter::get_recognized_extensions(List<String> *p_extension
for (int i = 0; i < importers.size(); i++) {
List<String> local_exts;
importers[i]->get_recognized_extensions(&local_exts);
- for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
- if (!found.has(F->get())) {
- p_extensions->push_back(F->get());
- found.insert(F->get());
+ for (const String &F : local_exts) {
+ if (!found.has(F)) {
+ p_extensions->push_back(F);
+ found.insert(F);
}
}
}
@@ -175,10 +177,10 @@ void ResourceFormatImporter::get_recognized_extensions_for_type(const String &p_
List<String> local_exts;
importers[i]->get_recognized_extensions(&local_exts);
- for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
- if (!found.has(F->get())) {
- p_extensions->push_back(F->get());
- found.insert(F->get());
+ for (const String &F : local_exts) {
+ if (!found.has(F)) {
+ p_extensions->push_back(F);
+ found.insert(F);
}
}
}
@@ -336,6 +338,17 @@ String ResourceFormatImporter::get_resource_type(const String &p_path) const {
return pat.type;
}
+ResourceUID::ID ResourceFormatImporter::get_resource_uid(const String &p_path) const {
+ PathAndType pat;
+ Error err = _get_path_and_type(p_path, pat);
+
+ if (err != OK) {
+ return ResourceUID::INVALID_ID;
+ }
+
+ return pat.uid;
+}
+
Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) const {
PathAndType pat;
Error err = _get_path_and_type(p_path, pat);
@@ -372,8 +385,8 @@ void ResourceFormatImporter::get_importers_for_extension(const String &p_extensi
for (int i = 0; i < importers.size(); i++) {
List<String> local_exts;
importers[i]->get_recognized_extensions(&local_exts);
- for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
- if (p_extension.to_lower() == F->get()) {
+ for (const String &F : local_exts) {
+ if (p_extension.to_lower() == F) {
r_importers->push_back(importers[i]);
}
}
@@ -393,8 +406,8 @@ Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const St
for (int i = 0; i < importers.size(); i++) {
List<String> local_exts;
importers[i]->get_recognized_extensions(&local_exts);
- for (List<String>::Element *F = local_exts.front(); F; F = F->next()) {
- if (p_extension.to_lower() == F->get() && importers[i]->get_priority() > priority) {
+ for (const String &F : local_exts) {
+ if (p_extension.to_lower() == F && importers[i]->get_priority() > priority) {
importer = importers[i];
priority = importers[i]->get_priority();
}
@@ -445,3 +458,8 @@ ResourceFormatImporter *ResourceFormatImporter::singleton = nullptr;
ResourceFormatImporter::ResourceFormatImporter() {
singleton = this;
}
+
+void ResourceImporter::_bind_methods() {
+ BIND_ENUM_CONSTANT(IMPORT_ORDER_DEFAULT);
+ BIND_ENUM_CONSTANT(IMPORT_ORDER_SCENE);
+}
diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h
index 2ceeb176e5..a1cacbd306 100644
--- a/core/io/resource_importer.h
+++ b/core/io/resource_importer.h
@@ -42,6 +42,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
String importer;
String group_file;
Variant metadata;
+ uint64_t uid = ResourceUID::INVALID_ID;
};
Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid = nullptr) const;
@@ -63,6 +64,8 @@ public:
virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
+
virtual Variant get_resource_metadata(const String &p_path) const;
virtual bool is_import_valid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
@@ -96,6 +99,9 @@ public:
class ResourceImporter : public RefCounted {
GDCLASS(ResourceImporter, RefCounted);
+protected:
+ static void _bind_methods();
+
public:
virtual String get_importer_name() const = 0;
virtual String get_visible_name() const = 0;
@@ -103,7 +109,7 @@ public:
virtual String get_save_extension() const = 0;
virtual String get_resource_type() const = 0;
virtual float get_priority() const { return 1.0; }
- virtual int get_import_order() const { return 0; }
+ virtual int get_import_order() const { return IMPORT_ORDER_DEFAULT; }
virtual int get_format_version() const { return 0; }
struct ImportOption {
@@ -117,6 +123,11 @@ public:
ImportOption() {}
};
+ enum ImportOrder {
+ IMPORT_ORDER_DEFAULT = 0,
+ IMPORT_ORDER_SCENE = 100,
+ };
+
virtual bool has_advanced_options() const { return false; }
virtual void show_advanced_options(const String &p_path) {}
@@ -137,4 +148,6 @@ public:
virtual String get_import_settings_string() const { return String(); }
};
+VARIANT_ENUM_CAST(ResourceImporter::ImportOrder);
+
#endif // RESOURCE_IMPORTER_H
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index c5dfe1f2b0..d02d827443 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -58,8 +58,8 @@ bool ResourceFormatLoader::recognize_path(const String &p_path, const String &p_
get_recognized_extensions_for_type(p_for_type, &extensions);
}
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(extension) == 0) {
+ for (const String &E : extensions) {
+ if (E.nocasecmp_to(extension) == 0) {
return true;
}
}
@@ -84,6 +84,14 @@ String ResourceFormatLoader::get_resource_type(const String &p_path) const {
return "";
}
+ResourceUID::ID ResourceFormatLoader::get_resource_uid(const String &p_path) const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_resource_uid")) {
+ return get_script_instance()->call("_get_resource_uid", p_path);
+ }
+
+ return ResourceUID::INVALID_ID;
+}
+
void ResourceFormatLoader::get_recognized_extensions_for_type(const String &p_type, List<String> *p_extensions) const {
if (p_type == "" || handles_type(p_type)) {
get_recognized_extensions(p_extensions);
@@ -270,13 +278,18 @@ void ResourceLoader::_thread_load_function(void *p_userdata) {
thread_load_mutex->unlock();
}
-Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, ResourceFormatLoader::CacheMode p_cache_mode, const String &p_source_resource) {
- String local_path;
- if (p_path.is_rel_path()) {
- local_path = "res://" + p_path;
+static String _validate_local_path(const String &p_path) {
+ ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(p_path);
+ if (uid != ResourceUID::INVALID_ID) {
+ return ResourceUID::get_singleton()->get_id_path(uid);
+ } else if (p_path.is_rel_path()) {
+ return "res://" + p_path;
} else {
- local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ return ProjectSettings::get_singleton()->localize_path(p_path);
}
+}
+Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, ResourceFormatLoader::CacheMode p_cache_mode, const String &p_source_resource) {
+ String local_path = _validate_local_path(p_path);
thread_load_mutex->lock();
@@ -399,12 +412,7 @@ float ResourceLoader::_dependency_get_progress(const String &p_path) {
}
ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, float *r_progress) {
- String local_path;
- if (p_path.is_rel_path()) {
- local_path = "res://" + p_path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(p_path);
- }
+ String local_path = _validate_local_path(p_path);
thread_load_mutex->lock();
if (!thread_load_tasks.has(local_path)) {
@@ -424,12 +432,7 @@ ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const
}
RES ResourceLoader::load_threaded_get(const String &p_path, Error *r_error) {
- String local_path;
- if (p_path.is_rel_path()) {
- local_path = "res://" + p_path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(p_path);
- }
+ String local_path = _validate_local_path(p_path);
thread_load_mutex->lock();
if (!thread_load_tasks.has(local_path)) {
@@ -510,12 +513,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, Resour
*r_error = ERR_CANT_OPEN;
}
- String local_path;
- if (p_path.is_rel_path()) {
- local_path = "res://" + p_path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(p_path);
- }
+ String local_path = _validate_local_path(p_path);
if (p_cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
thread_load_mutex->lock();
@@ -612,12 +610,7 @@ RES ResourceLoader::load(const String &p_path, const String &p_type_hint, Resour
}
bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
- String local_path;
- if (p_path.is_rel_path()) {
- local_path = "res://" + p_path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(p_path);
- }
+ String local_path = _validate_local_path(p_path);
if (ResourceCache::has(local_path)) {
return true; // If cached, it probably exists
@@ -677,14 +670,7 @@ void ResourceLoader::remove_resource_format_loader(Ref<ResourceFormatLoader> p_f
}
int ResourceLoader::get_import_order(const String &p_path) {
- String path = _path_remap(p_path);
-
- String local_path;
- if (path.is_rel_path()) {
- local_path = "res://" + path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(path);
- }
+ String local_path = _path_remap(_validate_local_path(p_path));
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) {
@@ -702,14 +688,7 @@ int ResourceLoader::get_import_order(const String &p_path) {
}
String ResourceLoader::get_import_group_file(const String &p_path) {
- String path = _path_remap(p_path);
-
- String local_path;
- if (path.is_rel_path()) {
- local_path = "res://" + path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(path);
- }
+ String local_path = _path_remap(_validate_local_path(p_path));
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) {
@@ -727,14 +706,7 @@ String ResourceLoader::get_import_group_file(const String &p_path) {
}
bool ResourceLoader::is_import_valid(const String &p_path) {
- String path = _path_remap(p_path);
-
- String local_path;
- if (path.is_rel_path()) {
- local_path = "res://" + path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(path);
- }
+ String local_path = _path_remap(_validate_local_path(p_path));
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) {
@@ -752,14 +724,7 @@ bool ResourceLoader::is_import_valid(const String &p_path) {
}
bool ResourceLoader::is_imported(const String &p_path) {
- String path = _path_remap(p_path);
-
- String local_path;
- if (path.is_rel_path()) {
- local_path = "res://" + path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(path);
- }
+ String local_path = _path_remap(_validate_local_path(p_path));
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) {
@@ -777,14 +742,7 @@ bool ResourceLoader::is_imported(const String &p_path) {
}
void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
- String path = _path_remap(p_path);
-
- String local_path;
- if (path.is_rel_path()) {
- local_path = "res://" + path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(path);
- }
+ String local_path = _path_remap(_validate_local_path(p_path));
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) {
@@ -800,14 +758,7 @@ void ResourceLoader::get_dependencies(const String &p_path, List<String> *p_depe
}
Error ResourceLoader::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
- String path = _path_remap(p_path);
-
- String local_path;
- if (path.is_rel_path()) {
- local_path = "res://" + path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(path);
- }
+ String local_path = _path_remap(_validate_local_path(p_path));
for (int i = 0; i < loader_count; i++) {
if (!loader[i]->recognize_path(local_path)) {
@@ -825,12 +776,7 @@ Error ResourceLoader::rename_dependencies(const String &p_path, const Map<String
}
String ResourceLoader::get_resource_type(const String &p_path) {
- String local_path;
- if (p_path.is_rel_path()) {
- local_path = "res://" + p_path;
- } else {
- local_path = ProjectSettings::get_singleton()->localize_path(p_path);
- }
+ String local_path = _validate_local_path(p_path);
for (int i = 0; i < loader_count; i++) {
String result = loader[i]->get_resource_type(local_path);
@@ -842,6 +788,19 @@ String ResourceLoader::get_resource_type(const String &p_path) {
return "";
}
+ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
+ String local_path = _validate_local_path(p_path);
+
+ for (int i = 0; i < loader_count; i++) {
+ ResourceUID::ID id = loader[i]->get_resource_uid(local_path);
+ if (id != ResourceUID::INVALID_ID) {
+ return id;
+ }
+ }
+
+ return ResourceUID::INVALID_ID;
+}
+
String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_remapped) {
String new_path = p_path;
@@ -978,15 +937,15 @@ void ResourceLoader::load_translation_remaps() {
Dictionary remaps = ProjectSettings::get_singleton()->get("internationalization/locale/translation_remaps");
List<Variant> keys;
remaps.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- Array langs = remaps[E->get()];
+ for (const Variant &E : keys) {
+ Array langs = remaps[E];
Vector<String> lang_remaps;
lang_remaps.resize(langs.size());
for (int i = 0; i < langs.size(); i++) {
lang_remaps.write[i] = langs[i];
}
- translation_remaps[String(E->get())] = lang_remaps;
+ translation_remaps[String(E)] = lang_remaps;
}
}
@@ -1071,8 +1030,7 @@ void ResourceLoader::add_custom_loaders() {
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
- for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
- StringName class_name = E->get();
+ for (const StringName &class_name : global_classes) {
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
if (base_class == custom_loader_base_class) {
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index c656b9a69c..e525e80a9d 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -40,9 +40,9 @@ class ResourceFormatLoader : public RefCounted {
public:
enum CacheMode {
- CACHE_MODE_IGNORE, //resource and subresources do not use path cache, no path is set into resource.
- CACHE_MODE_REUSE, //resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available
- CACHE_MODE_REPLACE, //resource and and subresource use path cache, but replace existing loaded resources when available with information from disk
+ CACHE_MODE_IGNORE, // Resource and subresources do not use path cache, no path is set into resource.
+ CACHE_MODE_REUSE, // Resource and subresources use patch cache, reuse existing loaded resources instead of loading from disk when available.
+ CACHE_MODE_REPLACE, // Resource and subresource use path cache, but replace existing loaded resources when available with information from disk.
};
protected:
@@ -56,6 +56,7 @@ public:
virtual bool recognize_path(const String &p_path, const String &p_for_type = String()) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
virtual bool is_import_valid(const String &p_path) const { return true; }
@@ -107,7 +108,7 @@ private:
friend class ResourceFormatImporter;
friend class ResourceInteractiveLoader;
- //internal load function
+ // Internal load function.
static RES _load(const String &p_path, const String &p_original_path, const String &p_type_hint, ResourceFormatLoader::CacheMode p_cache_mode, Error *r_error, bool p_use_sub_threads, float *r_progress);
static ResourceLoadedCallback _loaded_callback;
@@ -157,6 +158,7 @@ public:
static void add_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader, bool p_at_front = false);
static void remove_resource_format_loader(Ref<ResourceFormatLoader> p_format_loader);
static String get_resource_type(const String &p_path);
+ static ResourceUID::ID get_resource_uid(const String &p_path);
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
static bool is_import_valid(const String &p_path);
diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp
index 80cb85fba3..564de5ee69 100644
--- a/core/io/resource_saver.cpp
+++ b/core/io/resource_saver.cpp
@@ -39,6 +39,7 @@ Ref<ResourceFormatSaver> ResourceSaver::saver[MAX_SAVERS];
int ResourceSaver::saver_count = 0;
bool ResourceSaver::timestamp_on_save = false;
ResourceSavedCallback ResourceSaver::save_callback = nullptr;
+ResourceSaverGetResourceIDForPath ResourceSaver::save_get_id_for_path = nullptr;
Error ResourceFormatSaver::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
if (get_script_instance() && get_script_instance()->has_method("_save")) {
@@ -94,8 +95,8 @@ Error ResourceSaver::save(const String &p_path, const RES &p_resource, uint32_t
bool recognized = false;
saver[i]->get_recognized_extensions(p_resource, &extensions);
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(extension) == 0) {
+ for (const String &E : extensions) {
+ if (E.nocasecmp_to(extension) == 0) {
recognized = true;
}
}
@@ -236,8 +237,7 @@ void ResourceSaver::add_custom_savers() {
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
- for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
- StringName class_name = E->get();
+ for (const StringName &class_name : global_classes) {
StringName base_class = ScriptServer::get_global_class_native_base(class_name);
if (base_class == custom_saver_base_class) {
@@ -259,3 +259,14 @@ void ResourceSaver::remove_custom_savers() {
remove_resource_format_saver(custom_savers[i]);
}
}
+
+ResourceUID::ID ResourceSaver::get_resource_id_for_path(const String &p_path, bool p_generate) {
+ if (save_get_id_for_path) {
+ return save_get_id_for_path(p_path, p_generate);
+ }
+ return ResourceUID::INVALID_ID;
+}
+
+void ResourceSaver::set_get_resource_id_for_path(ResourceSaverGetResourceIDForPath p_callback) {
+ save_get_id_for_path = p_callback;
+}
diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h
index 07154aac4d..2fc8d32126 100644
--- a/core/io/resource_saver.h
+++ b/core/io/resource_saver.h
@@ -48,6 +48,7 @@ public:
};
typedef void (*ResourceSavedCallback)(Ref<Resource> p_resource, const String &p_path);
+typedef ResourceUID::ID (*ResourceSaverGetResourceIDForPath)(const String &p_path, bool p_generate);
class ResourceSaver {
enum {
@@ -58,6 +59,7 @@ class ResourceSaver {
static int saver_count;
static bool timestamp_on_save;
static ResourceSavedCallback save_callback;
+ static ResourceSaverGetResourceIDForPath save_get_id_for_path;
static Ref<ResourceFormatSaver> _find_custom_resource_format_saver(String path);
@@ -80,7 +82,10 @@ public:
static void set_timestamp_on_save(bool p_timestamp) { timestamp_on_save = p_timestamp; }
static bool get_timestamp_on_save() { return timestamp_on_save; }
+ static ResourceUID::ID get_resource_id_for_path(const String &p_path, bool p_generate = false);
+
static void set_save_callback(ResourceSavedCallback p_callback);
+ static void set_get_resource_id_for_path(ResourceSaverGetResourceIDForPath p_callback);
static bool add_custom_resource_format_saver(String script_path);
static void remove_custom_resource_format_saver(String script_path);
diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp
new file mode 100644
index 0000000000..97d683f415
--- /dev/null
+++ b/core/io/resource_uid.cpp
@@ -0,0 +1,262 @@
+/*************************************************************************/
+/* resource_uid.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "resource_uid.h"
+#include "core/crypto/crypto.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
+
+static constexpr uint32_t char_count = ('z' - 'a');
+static constexpr uint32_t base = char_count + ('9' - '0');
+
+const char *ResourceUID::CACHE_FILE = "res://.godot/uid_cache.bin";
+
+String ResourceUID::id_to_text(ID p_id) const {
+ if (p_id < 0) {
+ return "uid://<invalid>";
+ }
+ String txt;
+
+ while (p_id) {
+ uint32_t c = p_id % base;
+ if (c < char_count) {
+ txt = String::chr('a' + c) + txt;
+ } else {
+ txt = String::chr('0' + (c - char_count)) + txt;
+ }
+ p_id /= base;
+ }
+
+ return "uid://" + txt;
+}
+
+ResourceUID::ID ResourceUID::text_to_id(const String &p_text) const {
+ if (!p_text.begins_with("uid://") || p_text == "uid://<invalid>") {
+ return INVALID_ID;
+ }
+
+ uint32_t l = p_text.length();
+ uint64_t uid = 0;
+ for (uint32_t i = 6; i < l; i++) {
+ uid *= base;
+ uint32_t c = p_text[i];
+ if (c >= 'a' && c <= 'z') {
+ uid += c - 'a';
+ } else if (c >= '0' && c <= '9') {
+ uid += c - '0' + char_count;
+ } else {
+ return INVALID_ID;
+ }
+ }
+ return ID(uid & 0x7FFFFFFFFFFFFFFF);
+}
+
+ResourceUID::ID ResourceUID::create_id() const {
+ mutex.lock();
+ if (crypto.is_null()) {
+ crypto = Ref<Crypto>(Crypto::create());
+ }
+ mutex.unlock();
+ while (true) {
+ PackedByteArray bytes = crypto->generate_random_bytes(8);
+ ERR_FAIL_COND_V(bytes.size() != 8, INVALID_ID);
+ const uint64_t *ptr64 = (const uint64_t *)bytes.ptr();
+ ID id = int64_t((*ptr64) & 0x7FFFFFFFFFFFFFFF);
+ mutex.lock();
+ bool exists = unique_ids.has(id);
+ mutex.unlock();
+ if (!exists) {
+ return id;
+ }
+ }
+}
+
+bool ResourceUID::has_id(ID p_id) const {
+ MutexLock l(mutex);
+ return unique_ids.has(p_id);
+}
+void ResourceUID::add_id(ID p_id, const String &p_path) {
+ MutexLock l(mutex);
+ ERR_FAIL_COND(unique_ids.has(p_id));
+ Cache c;
+ c.cs = p_path.utf8();
+ unique_ids[p_id] = c;
+ changed = true;
+}
+
+void ResourceUID::set_id(ID p_id, const String &p_path) {
+ MutexLock l(mutex);
+ ERR_FAIL_COND(!unique_ids.has(p_id));
+ CharString cs = p_path.utf8();
+ if (strcmp(cs.ptr(), unique_ids[p_id].cs.ptr()) != 0) {
+ unique_ids[p_id].cs = cs;
+ unique_ids[p_id].saved_to_cache = false; //changed
+ changed = true;
+ }
+}
+
+String ResourceUID::get_id_path(ID p_id) const {
+ MutexLock l(mutex);
+ ERR_FAIL_COND_V(!unique_ids.has(p_id), String());
+ const CharString &cs = unique_ids[p_id].cs;
+ String s(cs.ptr());
+ return s;
+}
+void ResourceUID::remove_id(ID p_id) {
+ MutexLock l(mutex);
+ ERR_FAIL_COND(!unique_ids.has(p_id));
+ unique_ids.erase(p_id);
+}
+
+Error ResourceUID::save_to_cache() {
+ if (!FileAccess::exists(CACHE_FILE)) {
+ DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ d->make_dir_recursive(String(CACHE_FILE).get_base_dir()); //ensure base dir exists
+ }
+
+ FileAccessRef f = FileAccess::open(CACHE_FILE, FileAccess::WRITE);
+ if (!f) {
+ return ERR_CANT_OPEN;
+ }
+
+ MutexLock l(mutex);
+ f->store_32(unique_ids.size());
+
+ cache_entries = 0;
+
+ for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
+ f->store_64(E.key());
+ uint32_t s = E.get().cs.length();
+ f->store_32(s);
+ f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
+ E.get().saved_to_cache = true;
+ cache_entries++;
+ }
+
+ changed = false;
+ return OK;
+}
+
+Error ResourceUID::load_from_cache() {
+ FileAccessRef f = FileAccess::open(CACHE_FILE, FileAccess::READ);
+ if (!f) {
+ return ERR_CANT_OPEN;
+ }
+
+ MutexLock l(mutex);
+ unique_ids.clear();
+
+ uint32_t entry_count = f->get_32();
+ for (uint32_t i = 0; i < entry_count; i++) {
+ int64_t id = f->get_64();
+ int32_t len = f->get_32();
+ Cache c;
+ c.cs.resize(len + 1);
+ ERR_FAIL_COND_V(c.cs.size() != len + 1, ERR_FILE_CORRUPT); // out of memory
+ c.cs[len] = 0;
+ int32_t rl = f->get_buffer((uint8_t *)c.cs.ptrw(), len);
+ ERR_FAIL_COND_V(rl != len, ERR_FILE_CORRUPT);
+
+ c.saved_to_cache = true;
+ unique_ids[id] = c;
+ }
+
+ cache_entries = entry_count;
+ changed = false;
+ return OK;
+}
+
+Error ResourceUID::update_cache() {
+ if (!changed) {
+ return OK;
+ }
+
+ if (cache_entries == 0) {
+ return save_to_cache();
+ }
+ MutexLock l(mutex);
+
+ FileAccess *f = nullptr;
+ for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
+ if (!E.get().saved_to_cache) {
+ if (f == nullptr) {
+ f = FileAccess::open(CACHE_FILE, FileAccess::READ_WRITE); //append
+ if (!f) {
+ return ERR_CANT_OPEN;
+ }
+ f->seek_end();
+ }
+ f->store_64(E.key());
+ uint32_t s = E.get().cs.length();
+ f->store_32(s);
+ f->store_buffer((const uint8_t *)E.get().cs.ptr(), s);
+ E.get().saved_to_cache = true;
+ cache_entries++;
+ }
+ }
+
+ if (f != nullptr) {
+ f->seek(0);
+ f->store_32(cache_entries); //update amount of entries
+ f->close();
+ memdelete(f);
+ }
+
+ changed = false;
+
+ return OK;
+}
+
+void ResourceUID::clear() {
+ cache_entries = 0;
+ unique_ids.clear();
+ changed = false;
+}
+void ResourceUID::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("id_to_text", "id"), &ResourceUID::id_to_text);
+ ClassDB::bind_method(D_METHOD("text_to_id", "text_id"), &ResourceUID::text_to_id);
+
+ ClassDB::bind_method(D_METHOD("create_id"), &ResourceUID::create_id);
+
+ ClassDB::bind_method(D_METHOD("has_id", "id"), &ResourceUID::has_id);
+ ClassDB::bind_method(D_METHOD("add_id", "id", "path"), &ResourceUID::add_id);
+ ClassDB::bind_method(D_METHOD("set_id", "id", "path"), &ResourceUID::set_id);
+ ClassDB::bind_method(D_METHOD("get_id_path", "id"), &ResourceUID::get_id_path);
+ ClassDB::bind_method(D_METHOD("remove_id", "id"), &ResourceUID::remove_id);
+
+ BIND_CONSTANT(INVALID_ID)
+}
+ResourceUID *ResourceUID::singleton = nullptr;
+ResourceUID::ResourceUID() {
+ ERR_FAIL_COND(singleton != nullptr);
+ singleton = this;
+}
+ResourceUID::~ResourceUID() {
+}
diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h
new file mode 100644
index 0000000000..b12138425a
--- /dev/null
+++ b/core/io/resource_uid.h
@@ -0,0 +1,89 @@
+/*************************************************************************/
+/* resource_uid.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 RESOURCE_UUID_H
+#define RESOURCE_UUID_H
+
+#include "core/object/ref_counted.h"
+#include "core/string/string_name.h"
+#include "core/templates/ordered_hash_map.h"
+
+class Crypto;
+class ResourceUID : public Object {
+ GDCLASS(ResourceUID, Object)
+public:
+ typedef int64_t ID;
+ enum {
+ INVALID_ID = -1
+ };
+
+ static const char *CACHE_FILE;
+
+private:
+ mutable Ref<Crypto> crypto;
+ Mutex mutex;
+ struct Cache {
+ CharString cs;
+ bool saved_to_cache = false;
+ };
+
+ OrderedHashMap<ID, Cache> unique_ids; //unique IDs and utf8 paths (less memory used)
+ static ResourceUID *singleton;
+
+ uint32_t cache_entries = 0;
+ bool changed = false;
+
+protected:
+ static void _bind_methods();
+
+public:
+ String id_to_text(ID p_id) const;
+ ID text_to_id(const String &p_text) const;
+
+ ID create_id() const;
+ bool has_id(ID p_id) const;
+ void add_id(ID p_id, const String &p_path);
+ void set_id(ID p_id, const String &p_path);
+ String get_id_path(ID p_id) const;
+ void remove_id(ID p_id);
+
+ Error load_from_cache();
+ Error save_to_cache();
+ Error update_cache();
+
+ void clear();
+
+ static ResourceUID *get_singleton() { return singleton; }
+
+ ResourceUID();
+ ~ResourceUID();
+};
+
+#endif // RESOURCEUUID_H
diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h
index 6f7209556e..81adf4d19a 100644
--- a/core/math/delaunay_3d.h
+++ b/core/math/delaunay_3d.h
@@ -375,8 +375,7 @@ public:
OutputSimplex *ret_simplicesw = ret_simplices.ptrw();
uint32_t simplices_written = 0;
- for (List<Simplex *>::Element *E = simplex_list.front(); E; E = E->next()) {
- Simplex *simplex = E->get();
+ for (Simplex *simplex : simplex_list) {
bool invalid = false;
for (int j = 0; j < 4; j++) {
if (simplex->points[j] >= point_count) {
diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp
index 8e596f0f9d..f3fb473981 100644
--- a/core/math/dynamic_bvh.cpp
+++ b/core/math/dynamic_bvh.cpp
@@ -181,7 +181,7 @@ DynamicBVH::Volume DynamicBVH::_bounds(Node **leaves, int p_count) {
void DynamicBVH::_bottom_up(Node **leaves, int p_count) {
while (p_count > 1) {
- real_t minsize = Math_INF;
+ real_t minsize = INFINITY;
int minidx[2] = { -1, -1 };
for (int i = 0; i < p_count; ++i) {
for (int j = i + 1; j < p_count; ++j) {
diff --git a/core/math/expression.cpp b/core/math/expression.cpp
index 0146c345f0..05f2c8dac9 100644
--- a/core/math/expression.cpp
+++ b/core/math/expression.cpp
@@ -397,10 +397,10 @@ Error Expression::_get_token(Token &r_token) {
r_token.value = Math_TAU;
} else if (id == "INF") {
r_token.type = TK_CONSTANT;
- r_token.value = Math_INF;
+ r_token.value = INFINITY;
} else if (id == "NAN") {
r_token.type = TK_CONSTANT;
- r_token.value = Math_NAN;
+ r_token.value = NAN;
} else if (id == "not") {
r_token.type = TK_OP_NOT;
} else if (id == "or") {
diff --git a/core/math/face3.h b/core/math/face3.h
index 5091b338ef..9e9026e54e 100644
--- a/core/math/face3.h
+++ b/core/math/face3.h
@@ -50,8 +50,8 @@ public:
/**
*
* @param p_plane plane used to split the face
- * @param p_res array of at least 3 faces, amount used in functio return
- * @param p_is_point_over array of at least 3 booleans, determining which face is over the plane, amount used in functio return
+ * @param p_res array of at least 3 faces, amount used in function return
+ * @param p_is_point_over array of at least 3 booleans, determining which face is over the plane, amount used in function return
* @param _epsilon constant used for numerical error rounding, to add "thickness" to the plane (so coplanar points can happen)
* @return amount of faces generated by the split, either 0 (means no split possible), 2 or 3
*/
diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h
index 4ef9b4dbe6..766689e222 100644
--- a/core/math/geometry_3d.h
+++ b/core/math/geometry_3d.h
@@ -40,7 +40,7 @@ class Geometry3D {
public:
static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) {
-// Do the function 'd' as defined by pb. I think is is dot product of some sort.
+// Do the function 'd' as defined by pb. I think it's a dot product of some sort.
#define d_of(m, n, o, p) ((m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z))
// Calculate the parametric position on the 2 curves, mua and mub.
diff --git a/core/math/math_defs.h b/core/math/math_defs.h
index df2223fb78..7692e1be47 100644
--- a/core/math/math_defs.h
+++ b/core/math/math_defs.h
@@ -43,8 +43,6 @@
#define Math_TAU 6.2831853071795864769252867666
#define Math_PI 3.1415926535897932384626433833
#define Math_E 2.7182818284590452353602874714
-#define Math_INF INFINITY
-#define Math_NAN NAN
#ifdef DEBUG_ENABLED
#define MATH_CHECKS
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index 0d77bfe933..0960fe19a6 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -192,9 +192,9 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
continue;
}
- for (List<Face>::Element *E = faces.front(); E; E = E->next()) {
- if (E->get().plane.distance_to(p_points[i]) > over_tolerance) {
- E->get().points_over.push_back(i);
+ for (Face &E : faces) {
+ if (E.plane.distance_to(p_points[i]) > over_tolerance) {
+ E.points_over.push_back(i);
break;
}
}
@@ -292,8 +292,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
//distribute points into new faces
- for (List<List<Face>::Element *>::Element *F = lit_faces.front(); F; F = F->next()) {
- Face &lf = F->get()->get();
+ for (List<Face>::Element *&F : lit_faces) {
+ Face &lf = F->get();
for (int i = 0; i < lf.points_over.size(); i++) {
if (lf.points_over[i] == f.points_over[next]) { //do not add current one
@@ -301,8 +301,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
}
Vector3 p = p_points[lf.points_over[i]];
- for (List<List<Face>::Element *>::Element *E = new_faces.front(); E; E = E->next()) {
- Face &f2 = E->get()->get();
+ for (List<Face>::Element *&E : new_faces) {
+ Face &f2 = E->get();
if (f2.plane.distance_to(p) > over_tolerance) {
f2.points_over.push_back(lf.points_over[i]);
break;
@@ -320,10 +320,10 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
//put faces that contain no points on the front
- for (List<List<Face>::Element *>::Element *E = new_faces.front(); E; E = E->next()) {
- Face &f2 = E->get()->get();
+ for (List<Face>::Element *&E : new_faces) {
+ Face &f2 = E->get();
if (f2.points_over.size() == 0) {
- faces.move_to_front(E->get());
+ faces.move_to_front(E);
}
}
@@ -336,19 +336,19 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
Map<Edge, RetFaceConnect> ret_edges;
List<Geometry3D::MeshData::Face> ret_faces;
- for (List<Face>::Element *E = faces.front(); E; E = E->next()) {
+ for (const Face &E : faces) {
Geometry3D::MeshData::Face f;
- f.plane = E->get().plane;
+ f.plane = E.plane;
for (int i = 0; i < 3; i++) {
- f.indices.push_back(E->get().vertices[i]);
+ f.indices.push_back(E.vertices[i]);
}
List<Geometry3D::MeshData::Face>::Element *F = ret_faces.push_back(f);
for (int i = 0; i < 3; i++) {
- uint32_t a = E->get().vertices[i];
- uint32_t b = E->get().vertices[(i + 1) % 3];
+ uint32_t a = E.vertices[i];
+ uint32_t b = E.vertices[(i + 1) % 3];
Edge e(a, b);
Map<Edge, RetFaceConnect>::Element *G = ret_edges.find(e);
@@ -439,8 +439,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry3D::MeshData &r_
r_mesh.faces.resize(ret_faces.size());
int idx = 0;
- for (List<Geometry3D::MeshData::Face>::Element *E = ret_faces.front(); E; E = E->next()) {
- r_mesh.faces.write[idx++] = E->get();
+ for (const Geometry3D::MeshData::Face &E : ret_faces) {
+ r_mesh.faces.write[idx++] = E;
}
r_mesh.edges.resize(ret_edges.size());
idx = 0;
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index 903d5951a8..bf06c848c5 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -32,9 +32,9 @@
#include "core/templates/sort_array.h"
-int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &max_depth, int &max_alloc) {
- if (p_depth > max_depth) {
- max_depth = p_depth;
+int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &r_max_depth, int &r_max_alloc) {
+ if (p_depth > r_max_depth) {
+ r_max_depth = p_depth;
}
if (p_size == 1) {
@@ -70,10 +70,10 @@ int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, in
} break;
}
- int left = _create_bvh(p_bvh, p_bb, p_from, p_size / 2, p_depth + 1, max_depth, max_alloc);
- int right = _create_bvh(p_bvh, p_bb, p_from + p_size / 2, p_size - p_size / 2, p_depth + 1, max_depth, max_alloc);
+ int left = _create_bvh(p_bvh, p_bb, p_from, p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
+ int right = _create_bvh(p_bvh, p_bb, p_from + p_size / 2, p_size - p_size / 2, p_depth + 1, r_max_depth, r_max_alloc);
- int index = max_alloc++;
+ int index = r_max_alloc++;
BVH *_new = &p_bvh[index];
_new->aabb = aabb;
_new->center = aabb.position + aabb.size * 0.5;
diff --git a/core/math/vector2.h b/core/math/vector2.h
index 78deb473b4..4d9f3126e9 100644
--- a/core/math/vector2.h
+++ b/core/math/vector2.h
@@ -300,6 +300,14 @@ struct Vector2i {
return p_idx ? y : x;
}
+ _FORCE_INLINE_ int min_axis() const {
+ return x < y ? 0 : 1;
+ }
+
+ _FORCE_INLINE_ int max_axis() const {
+ return x < y ? 1 : 0;
+ }
+
Vector2i min(const Vector2i &p_vector2i) const {
return Vector2(MIN(x, p_vector2i.x), MIN(y, p_vector2i.y));
}
diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp
index e2db5918e3..c6ba39be94 100644
--- a/core/object/class_db.cpp
+++ b/core/object/class_db.cpp
@@ -359,9 +359,9 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
//must be alphabetically sorted for hash to compute
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- ClassInfo *t = classes.getptr(E->get());
- ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E->get()) + "'.");
+ for (const StringName &E : names) {
+ ClassInfo *t = classes.getptr(E);
+ ERR_FAIL_COND_V_MSG(!t, 0, "Cannot get class '" + String(E) + "'.");
if (t->api != p_api || !t->exposed) {
continue;
}
@@ -388,8 +388,8 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
snames.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
- MethodBind *mb = t->method_map[F->get()];
+ for (const StringName &F : snames) {
+ MethodBind *mb = t->method_map[F];
hash = hash_djb2_one_64(mb->get_name().hash(), hash);
hash = hash_djb2_one_64(mb->get_argument_count(), hash);
hash = hash_djb2_one_64(mb->get_argument_type(-1), hash); //return
@@ -426,9 +426,9 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
snames.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
- hash = hash_djb2_one_64(F->get().hash(), hash);
- hash = hash_djb2_one_64(t->constant_map[F->get()], hash);
+ for (const StringName &F : snames) {
+ hash = hash_djb2_one_64(F.hash(), hash);
+ hash = hash_djb2_one_64(t->constant_map[F], hash);
}
}
@@ -444,9 +444,9 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
snames.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
- MethodInfo &mi = t->signal_map[F->get()];
- hash = hash_djb2_one_64(F->get().hash(), hash);
+ for (const StringName &F : snames) {
+ MethodInfo &mi = t->signal_map[F];
+ hash = hash_djb2_one_64(F.hash(), hash);
for (int i = 0; i < mi.arguments.size(); i++) {
hash = hash_djb2_one_64(mi.arguments[i].type, hash);
}
@@ -465,23 +465,23 @@ uint64_t ClassDB::get_api_hash(APIType p_api) {
snames.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
- PropertySetGet *psg = t->property_setget.getptr(F->get());
+ for (const StringName &F : snames) {
+ PropertySetGet *psg = t->property_setget.getptr(F);
ERR_FAIL_COND_V(!psg, 0);
- hash = hash_djb2_one_64(F->get().hash(), hash);
+ hash = hash_djb2_one_64(F.hash(), hash);
hash = hash_djb2_one_64(psg->setter.hash(), hash);
hash = hash_djb2_one_64(psg->getter.hash(), hash);
}
}
//property list
- for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) {
- hash = hash_djb2_one_64(F->get().name.hash(), hash);
- hash = hash_djb2_one_64(F->get().type, hash);
- hash = hash_djb2_one_64(F->get().hint, hash);
- hash = hash_djb2_one_64(F->get().hint_string.hash(), hash);
- hash = hash_djb2_one_64(F->get().usage, hash);
+ for (const PropertyInfo &F : t->property_list) {
+ hash = hash_djb2_one_64(F.name.hash(), hash);
+ hash = hash_djb2_one_64(F.type, hash);
+ hash = hash_djb2_one_64(F.hint, hash);
+ hash = hash_djb2_one_64(F.hint_string.hash(), hash);
+ hash = hash_djb2_one_64(F.usage, hash);
}
}
@@ -619,16 +619,16 @@ void ClassDB::get_method_list(const StringName &p_class, List<MethodInfo> *p_met
#ifdef DEBUG_METHODS_ENABLED
- for (List<MethodInfo>::Element *E = type->virtual_methods.front(); E; E = E->next()) {
- p_methods->push_back(E->get());
+ for (const MethodInfo &E : type->virtual_methods) {
+ p_methods->push_back(E);
}
- for (List<StringName>::Element *E = type->method_order.front(); E; E = E->next()) {
- if (p_exclude_from_properties && type->methods_in_properties.has(E->get())) {
+ for (const StringName &E : type->method_order) {
+ if (p_exclude_from_properties && type->methods_in_properties.has(E)) {
continue;
}
- MethodBind *method = type->method_map.get(E->get());
+ MethodBind *method = type->method_map.get(E);
MethodInfo minfo = info_from_bind(method);
p_methods->push_back(minfo);
@@ -763,8 +763,8 @@ void ClassDB::get_integer_constant_list(const StringName &p_class, List<String>
while (type) {
#ifdef DEBUG_METHODS_ENABLED
- for (List<StringName>::Element *E = type->constant_order.front(); E; E = E->next()) {
- p_constants->push_back(E->get());
+ for (const StringName &E : type->constant_order) {
+ p_constants->push_back(E);
}
#else
const StringName *K = nullptr;
@@ -1073,13 +1073,14 @@ void ClassDB::get_property_list(const StringName &p_class, List<PropertyInfo> *p
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
while (check) {
- for (List<PropertyInfo>::Element *E = check->property_list.front(); E; E = E->next()) {
+ for (const PropertyInfo &pi : check->property_list) {
if (p_validator) {
- PropertyInfo pi = E->get();
- p_validator->_validate_property(pi);
- p_list->push_back(pi);
+ // Making a copy as we may modify it.
+ PropertyInfo pi_mut = pi;
+ p_validator->_validate_property(pi_mut);
+ p_list->push_back(pi_mut);
} else {
- p_list->push_back(E->get());
+ p_list->push_back(pi);
}
}
@@ -1429,8 +1430,8 @@ void ClassDB::get_virtual_methods(const StringName &p_class, List<MethodInfo> *p
ClassInfo *type = classes.getptr(p_class);
ClassInfo *check = type;
while (check) {
- for (List<MethodInfo>::Element *E = check->virtual_methods.front(); E; E = E->next()) {
- p_methods->push_back(E->get());
+ for (const MethodInfo &E : check->virtual_methods) {
+ p_methods->push_back(E);
}
if (p_no_inheritance) {
@@ -1496,6 +1497,10 @@ void ClassDB::get_resource_base_extensions(List<String> *p_extensions) {
}
}
+bool ClassDB::is_resource_extension(const StringName &p_extension) {
+ return resource_base_extensions.has(p_extension);
+}
+
void ClassDB::get_extensions_for_type(const StringName &p_class, List<String> *p_extensions) {
const StringName *K = nullptr;
@@ -1530,11 +1535,11 @@ Variant ClassDB::class_get_default_property_value(const StringName &p_class, con
if (c) {
List<PropertyInfo> plist;
c->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) {
- if (!default_values[p_class].has(E->get().name)) {
- Variant v = c->get(E->get().name);
- default_values[p_class][E->get().name] = v;
+ for (const PropertyInfo &E : plist) {
+ if (E.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR)) {
+ if (!default_values[p_class].has(E.name)) {
+ Variant v = c->get(E.name);
+ default_values[p_class][E.name] = v;
}
}
}
diff --git a/core/object/class_db.h b/core/object/class_db.h
index fd574fd2d8..3a84e9ab38 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -396,6 +396,7 @@ public:
static void add_resource_base_extension(const StringName &p_extension, const StringName &p_class);
static void get_resource_base_extensions(List<String> *p_extensions);
static void get_extensions_for_type(const StringName &p_class, List<String> *p_extensions);
+ static bool is_resource_extension(const StringName &p_extension);
static void add_compatibility_class(const StringName &p_class, const StringName &p_fallback);
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 0644012318..d552d5e5e0 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -922,11 +922,11 @@ Variant Object::get_script() const {
return script;
}
-bool Object::has_meta(const String &p_name) const {
+bool Object::has_meta(const StringName &p_name) const {
return metadata.has(p_name);
}
-void Object::set_meta(const String &p_name, const Variant &p_value) {
+void Object::set_meta(const StringName &p_name, const Variant &p_value) {
if (p_value.get_type() == Variant::NIL) {
metadata.erase(p_name);
return;
@@ -935,12 +935,12 @@ void Object::set_meta(const String &p_name, const Variant &p_value) {
metadata[p_name] = p_value;
}
-Variant Object::get_meta(const String &p_name) const {
+Variant Object::get_meta(const StringName &p_name) const {
ERR_FAIL_COND_V_MSG(!metadata.has(p_name), Variant(), "The object does not have any 'meta' values with the key '" + p_name + "'.");
return metadata[p_name];
}
-void Object::remove_meta(const String &p_name) {
+void Object::remove_meta(const StringName &p_name) {
metadata.erase(p_name);
}
@@ -964,23 +964,23 @@ Array Object::_get_method_list_bind() const {
return ret;
}
-Vector<String> Object::_get_meta_list_bind() const {
- Vector<String> _metaret;
+Vector<StringName> Object::_get_meta_list_bind() const {
+ Vector<StringName> _metaret;
List<Variant> keys;
metadata.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- _metaret.push_back(E->get());
+ for (const Variant &E : keys) {
+ _metaret.push_back(E);
}
return _metaret;
}
-void Object::get_meta_list(List<String> *p_list) const {
+void Object::get_meta_list(List<StringName> *p_list) const {
List<Variant> keys;
metadata.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- p_list->push_back(E->get());
+ for (const Variant &E : keys) {
+ p_list->push_back(E);
}
}
@@ -1184,8 +1184,8 @@ Array Object::_get_signal_list() const {
get_signal_list(&signal_list);
Array ret;
- for (List<MethodInfo>::Element *E = signal_list.front(); E; E = E->next()) {
- ret.push_back(Dictionary(E->get()));
+ for (const MethodInfo &E : signal_list) {
+ ret.push_back(Dictionary(E));
}
return ret;
@@ -1197,8 +1197,7 @@ Array Object::_get_signal_connection_list(const String &p_signal) const {
Array ret;
- for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
- Connection &c = E->get();
+ for (const Connection &c : conns) {
if (c.signal.get_name() == p_signal) {
ret.push_back(c);
}
@@ -1297,8 +1296,8 @@ int Object::get_persistent_signal_connection_count() const {
}
void Object::get_signals_connected_to_this(List<Connection> *p_connections) const {
- for (const List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- p_connections->push_back(E->get());
+ for (const Connection &E : connections) {
+ p_connections->push_back(E);
}
}
@@ -1500,9 +1499,9 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- _clear_internal_resource_paths(E->get());
- _clear_internal_resource_paths(d[E->get()]);
+ for (const Variant &E : keys) {
+ _clear_internal_resource_paths(E);
+ _clear_internal_resource_paths(d[E]);
}
} break;
default: {
@@ -1531,8 +1530,8 @@ void Object::clear_internal_resource_paths() {
get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- _clear_internal_resource_paths(get(E->get().name));
+ for (const PropertyInfo &E : pinfo) {
+ _clear_internal_resource_paths(get(E.name));
}
}
@@ -1666,12 +1665,12 @@ void Object::get_translatable_strings(List<String> *p_strings) const {
List<PropertyInfo> plist;
get_property_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_INTERNATIONALIZED)) {
+ for (const PropertyInfo &E : plist) {
+ if (!(E.usage & PROPERTY_USAGE_INTERNATIONALIZED)) {
continue;
}
- String text = get(E->get().name);
+ String text = get(E.name);
if (text == "") {
continue;
diff --git a/core/object/object.h b/core/object/object.h
index 296e07983d..b7d0916a54 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -615,7 +615,7 @@ protected:
return &_class_name;
}
- Vector<String> _get_meta_list_bind() const;
+ Vector<StringName> _get_meta_list_bind() const;
Array _get_property_list_bind() const;
Array _get_method_list_bind() const;
@@ -743,11 +743,11 @@ public:
/* SCRIPT */
- bool has_meta(const String &p_name) const;
- void set_meta(const String &p_name, const Variant &p_value);
- void remove_meta(const String &p_name);
- Variant get_meta(const String &p_name) const;
- void get_meta_list(List<String> *p_list) const;
+ bool has_meta(const StringName &p_name) const;
+ void set_meta(const StringName &p_name, const Variant &p_value);
+ void remove_meta(const StringName &p_name);
+ Variant get_meta(const StringName &p_name) const;
+ void get_meta_list(List<StringName> *p_list) const;
#ifdef TOOLS_ENABLED
void set_edited(bool p_edited);
diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp
index 626a7413e7..0fb8c7350c 100644
--- a/core/object/script_language.cpp
+++ b/core/object/script_language.cpp
@@ -63,8 +63,8 @@ Array Script::_get_script_property_list() {
Array ret;
List<PropertyInfo> list;
get_script_property_list(&list);
- for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) {
- ret.append(E->get().operator Dictionary());
+ for (const PropertyInfo &E : list) {
+ ret.append(E.operator Dictionary());
}
return ret;
}
@@ -73,8 +73,8 @@ Array Script::_get_script_method_list() {
Array ret;
List<MethodInfo> list;
get_script_method_list(&list);
- for (List<MethodInfo>::Element *E = list.front(); E; E = E->next()) {
- ret.append(E->get().operator Dictionary());
+ for (const MethodInfo &E : list) {
+ ret.append(E.operator Dictionary());
}
return ret;
}
@@ -83,8 +83,8 @@ Array Script::_get_script_signal_list() {
Array ret;
List<MethodInfo> list;
get_script_signal_list(&list);
- for (List<MethodInfo>::Element *E = list.front(); E; E = E->next()) {
- ret.append(E->get().operator Dictionary());
+ for (const MethodInfo &E : list) {
+ ret.append(E.operator Dictionary());
}
return ret;
}
@@ -257,8 +257,8 @@ void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) {
classes.push_back(*K);
}
classes.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
- r_global_classes->push_back(E->get());
+ for (const StringName &E : classes) {
+ r_global_classes->push_back(E);
}
}
@@ -266,12 +266,12 @@ void ScriptServer::save_global_classes() {
List<StringName> gc;
get_global_class_list(&gc);
Array gcarr;
- for (List<StringName>::Element *E = gc.front(); E; E = E->next()) {
+ for (const StringName &E : gc) {
Dictionary d;
- d["class"] = E->get();
- d["language"] = global_classes[E->get()].language;
- d["path"] = global_classes[E->get()].path;
- d["base"] = global_classes[E->get()].base;
+ d["class"] = E;
+ d["language"] = global_classes[E].language;
+ d["path"] = global_classes[E].path;
+ d["base"] = global_classes[E].base;
gcarr.push_back(d);
}
@@ -297,10 +297,10 @@ void ScriptServer::save_global_classes() {
void ScriptInstance::get_property_state(List<Pair<StringName, Variant>> &state) {
List<PropertyInfo> pinfo;
get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().usage & PROPERTY_USAGE_STORAGE) {
+ for (const PropertyInfo &E : pinfo) {
+ if (E.usage & PROPERTY_USAGE_STORAGE) {
Pair<StringName, Variant> p;
- p.first = E->get().name;
+ p.first = E.name;
if (get(p.first, p.second)) {
state.push_back(p);
}
@@ -430,16 +430,16 @@ bool PlaceHolderScriptInstance::get(const StringName &p_name, Variant &r_ret) co
void PlaceHolderScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
if (script->is_placeholder_fallback_enabled()) {
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- p_properties->push_back(E->get());
+ for (const PropertyInfo &E : properties) {
+ p_properties->push_back(E);
}
} else {
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- PropertyInfo pinfo = E->get();
+ for (const PropertyInfo &E : properties) {
+ PropertyInfo pinfo = E;
if (!values.has(pinfo.name)) {
pinfo.usage |= PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE;
}
- p_properties->push_back(E->get());
+ p_properties->push_back(E);
}
}
}
@@ -489,11 +489,11 @@ bool PlaceHolderScriptInstance::has_method(const StringName &p_method) const {
void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, const Map<StringName, Variant> &p_values) {
Set<StringName> new_values;
- for (const List<PropertyInfo>::Element *E = p_properties.front(); E; E = E->next()) {
- StringName n = E->get().name;
+ for (const PropertyInfo &E : p_properties) {
+ StringName n = E.name;
new_values.insert(n);
- if (!values.has(n) || values[n].get_type() != E->get().type) {
+ if (!values.has(n) || values[n].get_type() != E.type) {
if (p_values.has(n)) {
values[n] = p_values[n];
}
@@ -511,7 +511,7 @@ void PlaceHolderScriptInstance::update(const List<PropertyInfo> &p_properties, c
Variant defval;
if (script->get_property_default_value(E->key(), defval)) {
//remove because it's the same as the default value
- if (defval == E->get()) {
+ if (defval == E) {
to_remove.push_back(E->key());
}
}
@@ -542,8 +542,8 @@ void PlaceHolderScriptInstance::property_set_fallback(const StringName &p_name,
}
bool found = false;
- for (const List<PropertyInfo>::Element *F = properties.front(); F; F = F->next()) {
- if (F->get().name == p_name) {
+ for (const PropertyInfo &F : properties) {
+ if (F.name == p_name) {
found = true;
break;
}
diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp
index 0532b2ae40..adf068eb2f 100644
--- a/core/object/undo_redo.cpp
+++ b/core/object/undo_redo.cpp
@@ -39,11 +39,15 @@ void UndoRedo::_discard_redo() {
}
for (int i = current_action + 1; i < actions.size(); i++) {
- for (List<Operation>::Element *E = actions.write[i].do_ops.front(); E; E = E->next()) {
- if (E->get().type == Operation::TYPE_REFERENCE) {
- Object *obj = ObjectDB::get_instance(E->get().object);
- if (obj) {
- memdelete(obj);
+ for (Operation &E : actions.write[i].do_ops) {
+ if (E.type == Operation::TYPE_REFERENCE) {
+ if (E.ref.is_valid()) {
+ E.ref.unref();
+ } else {
+ Object *obj = ObjectDB::get_instance(E.object);
+ if (obj) {
+ memdelete(obj);
+ }
}
}
}
@@ -240,11 +244,15 @@ void UndoRedo::_pop_history_tail() {
return;
}
- for (List<Operation>::Element *E = actions.write[0].undo_ops.front(); E; E = E->next()) {
- if (E->get().type == Operation::TYPE_REFERENCE) {
- Object *obj = ObjectDB::get_instance(E->get().object);
- if (obj) {
- memdelete(obj);
+ for (Operation &E : actions.write[0].undo_ops) {
+ if (E.type == Operation::TYPE_REFERENCE) {
+ if (E.ref.is_valid()) {
+ E.ref.unref();
+ } else {
+ Object *obj = ObjectDB::get_instance(E.object);
+ if (obj) {
+ memdelete(obj);
+ }
}
}
}
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 016d9d0a09..3c0e56f5a8 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -66,7 +66,7 @@ void MainLoop::initialize() {
}
}
-bool MainLoop::physics_process(float p_time) {
+bool MainLoop::physics_process(double p_time) {
if (get_script_instance()) {
return get_script_instance()->call("_physics_process", p_time);
}
@@ -74,7 +74,7 @@ bool MainLoop::physics_process(float p_time) {
return false;
}
-bool MainLoop::process(float p_time) {
+bool MainLoop::process(double p_time) {
if (get_script_instance()) {
return get_script_instance()->call("_process", p_time);
}
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 34e944709b..b42e9b18ff 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -60,8 +60,8 @@ public:
};
virtual void initialize();
- virtual bool physics_process(float p_time);
- virtual bool process(float p_time);
+ virtual bool physics_process(double p_time);
+ virtual bool process(double p_time);
virtual void finalize();
void set_initialize_script(const Ref<Script> &p_initialize_script);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 535eee4797..f7af74da3e 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -110,6 +110,10 @@ void OS::printerr(const char *p_format, ...) {
va_end(argp);
}
+void OS::alert(const String &p_alert, const String &p_title) {
+ fprintf(stderr, "%s: %s\n", p_title.utf8().get_data(), p_alert.utf8().get_data());
+}
+
void OS::set_low_processor_usage_mode(bool p_enabled) {
low_processor_usage_mode = p_enabled;
}
diff --git a/core/os/os.h b/core/os/os.h
index 301718a8b3..fcb195afe1 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -120,6 +120,8 @@ public:
virtual void open_midi_inputs();
virtual void close_midi_inputs();
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
+
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) { return ERR_UNAVAILABLE; }
virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; }
diff --git a/core/os/pool_allocator.h b/core/os/pool_allocator.h
index 15e50dac90..49f433ba97 100644
--- a/core/os/pool_allocator.h
+++ b/core/os/pool_allocator.h
@@ -37,7 +37,7 @@
@author Juan Linietsky <reduzio@gmail.com>
* Generic Pool Allocator.
* This is a generic memory pool allocator, with locking, compacting and alignment. (@TODO alignment)
- * It used as a standard way to manage alloction in a specific region of memory, such as texture memory,
+ * It used as a standard way to manage allocation in a specific region of memory, such as texture memory,
* audio sample memory, or just any kind of memory overall.
* (@TODO) abstraction should be greater, because in many platforms, you need to manage a nonreachable memory.
*/
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index eb37267546..3d1cb4a8e1 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -56,6 +56,7 @@
#include "core/io/pck_packer.h"
#include "core/io/resource_format_binary.h"
#include "core/io/resource_importer.h"
+#include "core/io/resource_uid.h"
#include "core/io/stream_peer_ssl.h"
#include "core/io/tcp_server.h"
#include "core/io/translation_loader_po.h"
@@ -102,6 +103,8 @@ static NativeExtensionManager *native_extension_manager = nullptr;
extern void register_global_constants();
extern void unregister_global_constants();
+static ResourceUID *resource_uid = nullptr;
+
void register_core_types() {
//consistency check
static_assert(sizeof(Callable) <= 16);
@@ -225,6 +228,10 @@ void register_core_types() {
GDREGISTER_VIRTUAL_CLASS(NativeExtensionManager);
+ GDREGISTER_VIRTUAL_CLASS(ResourceUID);
+
+ resource_uid = memnew(ResourceUID);
+
native_extension_manager = memnew(NativeExtensionManager);
ip = IP::create();
@@ -286,10 +293,11 @@ void register_core_singletons() {
Engine::get_singleton()->add_singleton(Engine::Singleton("EngineDebugger", _EngineDebugger::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
Engine::get_singleton()->add_singleton(Engine::Singleton("NativeExtensionManager", NativeExtensionManager::get_singleton()));
+ Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceUID", ResourceUID::get_singleton()));
}
void register_core_extensions() {
- //harcoded for now
+ // Hardcoded for now.
if (ProjectSettings::get_singleton()->has_setting("native_extensions/paths")) {
Vector<String> paths = ProjectSettings::get_singleton()->get("native_extensions/paths");
for (int i = 0; i < paths.size(); i++) {
@@ -304,6 +312,8 @@ void unregister_core_types() {
native_extension_manager->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_CORE);
memdelete(native_extension_manager);
+
+ memdelete(resource_uid);
memdelete(_resource_loader);
memdelete(_resource_saver);
memdelete(_os);
diff --git a/core/string/node_path.cpp b/core/string/node_path.cpp
index d3afa7b4dd..5fae13779e 100644
--- a/core/string/node_path.cpp
+++ b/core/string/node_path.cpp
@@ -240,19 +240,26 @@ NodePath NodePath::rel_path_to(const NodePath &p_np) const {
common_parent--;
Vector<StringName> relpath;
+ relpath.resize(src_dirs.size() + dst_dirs.size() + 1);
- for (int i = src_dirs.size() - 1; i > common_parent; i--) {
- relpath.push_back("..");
+ StringName *relpath_ptr = relpath.ptrw();
+
+ int path_size = 0;
+ StringName back_str("..");
+ for (int i = common_parent + 1; i < src_dirs.size(); i++) {
+ relpath_ptr[path_size++] = back_str;
}
for (int i = common_parent + 1; i < dst_dirs.size(); i++) {
- relpath.push_back(dst_dirs[i]);
+ relpath_ptr[path_size++] = dst_dirs[i];
}
- if (relpath.size() == 0) {
- relpath.push_back(".");
+ if (path_size == 0) {
+ relpath_ptr[path_size++] = ".";
}
+ relpath.resize(path_size);
+
return NodePath(relpath, p_np.get_subnames(), false);
}
diff --git a/core/string/optimized_translation.cpp b/core/string/optimized_translation.cpp
index 268562d971..5863bd1c46 100644
--- a/core/string/optimized_translation.cpp
+++ b/core/string/optimized_translation.cpp
@@ -66,9 +66,9 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
int total_compression_size = 0;
int total_string_size = 0;
- for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
+ for (const StringName &E : keys) {
//hash string
- CharString cs = E->get().operator String().utf8();
+ CharString cs = E.operator String().utf8();
uint32_t h = hash(0, cs.get_data());
Pair<int, CharString> p;
p.first = idx;
@@ -76,7 +76,7 @@ void OptimizedTranslation::generate(const Ref<Translation> &p_from) {
buckets.write[h % size].push_back(p);
//compress string
- CharString src_s = p_from->get_message(E->get()).operator String().utf8();
+ CharString src_s = p_from->get_message(E).operator String().utf8();
CompressedString ps;
ps.orig_len = src_s.size();
ps.offset = total_compression_size;
diff --git a/core/string/translation.cpp b/core/string/translation.cpp
index 678f8fb207..19d23fd375 100644
--- a/core/string/translation.cpp
+++ b/core/string/translation.cpp
@@ -841,8 +841,8 @@ Vector<String> Translation::_get_message_list() const {
void Translation::_set_messages(const Dictionary &p_messages) {
List<Variant> keys;
p_messages.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- translation_map[E->get()] = p_messages[E->get()];
+ for (const Variant &E : keys) {
+ translation_map[E] = p_messages[E];
}
}
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index f9b4e661e4..1da00aa54b 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -47,8 +47,7 @@ void TranslationPO::print_translation_map() {
List<StringName> context_l;
translation_map.get_key_list(&context_l);
- for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
- StringName ctx = E->get();
+ for (const StringName &ctx : context_l) {
file->store_line(" ===== Context: " + String::utf8(String(ctx).utf8()) + " ===== ");
const HashMap<StringName, Vector<StringName>> &inner_map = translation_map[ctx];
@@ -74,8 +73,7 @@ Dictionary TranslationPO::_get_messages() const {
List<StringName> context_l;
translation_map.get_key_list(&context_l);
- for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
- StringName ctx = E->get();
+ for (const StringName &ctx : context_l) {
const HashMap<StringName, Vector<StringName>> &id_str_map = translation_map[ctx];
Dictionary d2;
@@ -98,8 +96,7 @@ void TranslationPO::_set_messages(const Dictionary &p_messages) {
List<Variant> context_l;
p_messages.get_key_list(&context_l);
- for (List<Variant>::Element *E = context_l.front(); E; E = E->next()) {
- StringName ctx = E->get();
+ for (const Variant &ctx : context_l) {
const Dictionary &id_str_map = p_messages[ctx];
HashMap<StringName, Vector<StringName>> temp_map;
@@ -121,8 +118,8 @@ Vector<String> TranslationPO::_get_message_list() const {
get_message_list(&msgs);
Vector<String> v;
- for (List<StringName>::Element *E = msgs.front(); E; E = E->next()) {
- v.push_back(E->get());
+ for (const StringName &E : msgs) {
+ v.push_back(E);
}
return v;
@@ -281,13 +278,13 @@ void TranslationPO::get_message_list(List<StringName> *r_messages) const {
List<StringName> context_l;
translation_map.get_key_list(&context_l);
- for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
- if (String(E->get()) != "") {
+ for (const StringName &E : context_l) {
+ if (String(E) != "") {
continue;
}
List<StringName> msgid_l;
- translation_map[E->get()].get_key_list(&msgid_l);
+ translation_map[E].get_key_list(&msgid_l);
for (List<StringName>::Element *E2 = msgid_l.front(); E2; E2 = E2->next()) {
r_messages->push_back(E2->get());
@@ -300,8 +297,8 @@ int TranslationPO::get_message_count() const {
translation_map.get_key_list(&context_l);
int count = 0;
- for (List<StringName>::Element *E = context_l.front(); E; E = E->next()) {
- count += translation_map[E->get()].size();
+ for (const StringName &E : context_l) {
+ count += translation_map[E].size();
}
return count;
}
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 4cd2915ffa..7beecdb6b5 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -3421,11 +3421,8 @@ String String::format(const Variant &values, String placeholder) const {
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- String key = E->get();
- String val = d[E->get()];
-
- new_string = new_string.replace(placeholder.replace("_", key), val);
+ for (const Variant &key : keys) {
+ new_string = new_string.replace(placeholder.replace("_", key), d[key]);
}
} else {
ERR_PRINT(String("Invalid type: use Array or Dictionary.").ascii().get_data());
diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h
index acc46da0d5..519a896ffc 100644
--- a/core/templates/command_queue_mt.h
+++ b/core/templates/command_queue_mt.h
@@ -321,7 +321,7 @@ class CommandQueueMT {
DECL_CMD(0)
SPACE_SEP_LIST(DECL_CMD, 15)
- /* comands that return */
+ // Commands that return.
DECL_CMD_RET(0)
SPACE_SEP_LIST(DECL_CMD_RET, 15)
diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h
index 4572b269cf..2e932f9f26 100644
--- a/core/templates/hashfuncs.h
+++ b/core/templates/hashfuncs.h
@@ -95,7 +95,7 @@ static inline uint32_t hash_djb2_one_float(double p_in, uint32_t p_prev = 5381)
if (p_in == 0.0f) {
u.d = 0.0;
} else if (Math::is_nan(p_in)) {
- u.d = Math_NAN;
+ u.d = NAN;
} else {
u.d = p_in;
}
@@ -124,7 +124,7 @@ static inline uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 538
if (p_in == 0.0f) {
u.d = 0.0;
} else if (Math::is_nan(p_in)) {
- u.d = Math_NAN;
+ u.d = NAN;
} else {
u.d = p_in;
}
diff --git a/core/templates/rid_owner.h b/core/templates/rid_owner.h
index 4f5c74ca46..8d139551ef 100644
--- a/core/templates/rid_owner.h
+++ b/core/templates/rid_owner.h
@@ -101,7 +101,7 @@ class RID_Alloc : public RID_AllocBase {
//initialize
for (uint32_t i = 0; i < elements_in_chunk; i++) {
- //dont initialize chunk
+ // Don't initialize chunk.
validator_chunks[chunk_count][i] = 0xFFFFFFFF;
free_list_chunks[chunk_count][i] = alloc_count + i;
}
diff --git a/core/templates/set.h b/core/templates/set.h
index 245c174862..9261d2d3d2 100644
--- a/core/templates/set.h
+++ b/core/templates/set.h
@@ -71,6 +71,9 @@ public:
Element *prev() {
return _prev;
}
+ T &get() {
+ return value;
+ }
const T &get() const {
return value;
};
@@ -118,8 +121,8 @@ public:
return *this;
}
- _FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
- _FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
+ _FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
+ _FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
_FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; }
_FORCE_INLINE_ ConstIterator() {}
diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h
index ef5867c685..3cb2a6bfb5 100644
--- a/core/variant/binder_common.h
+++ b/core/variant/binder_common.h
@@ -69,17 +69,17 @@ struct VariantCaster<const T &> {
template <> \
struct VariantCaster<m_enum> { \
static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \
- return (m_enum)p_variant.operator int(); \
+ return (m_enum)p_variant.operator int64_t(); \
} \
}; \
template <> \
struct PtrToArg<m_enum> { \
_FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \
- return m_enum(*reinterpret_cast<const int *>(p_ptr)); \
+ return m_enum(*reinterpret_cast<const int64_t *>(p_ptr)); \
} \
typedef int64_t EncodeT; \
_FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \
- *(int *)p_ptr = p_val; \
+ *(int64_t *)p_ptr = p_val; \
} \
};
diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp
index ca6f3d615e..f487e718f4 100644
--- a/core/variant/callable.cpp
+++ b/core/variant/callable.cpp
@@ -407,8 +407,8 @@ Array Signal::get_connections() const {
object->get_signal_connection_list(name, &connections);
Array arr;
- for (List<Object::Connection>::Element *E = connections.front(); E; E = E->next()) {
- arr.push_back(E->get());
+ for (const Object::Connection &E : connections) {
+ arr.push_back(E);
}
return arr;
}
diff --git a/core/variant/method_ptrcall.h b/core/variant/method_ptrcall.h
index 7852187b77..8836e257a9 100644
--- a/core/variant/method_ptrcall.h
+++ b/core/variant/method_ptrcall.h
@@ -105,7 +105,7 @@ struct PtrToArg {};
} \
}
-MAKE_PTRARGCONV(bool, uint32_t);
+MAKE_PTRARGCONV(bool, uint8_t);
// Integer types.
MAKE_PTRARGCONV(uint8_t, int64_t);
MAKE_PTRARGCONV(int8_t, int64_t);
diff --git a/core/variant/variant.cpp b/core/variant/variant.cpp
index badb5ba103..97a1b4c02a 100644
--- a/core/variant/variant.cpp
+++ b/core/variant/variant.cpp
@@ -1681,10 +1681,10 @@ String Variant::stringify(List<const void *> &stack) const {
Vector<_VariantStrPair> pairs;
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ for (const Variant &E : keys) {
_VariantStrPair sp;
- sp.key = E->get().stringify(stack);
- sp.value = d[E->get()].stringify(stack);
+ sp.key = E.stringify(stack);
+ sp.value = d[E].stringify(stack);
pairs.push_back(sp);
}
diff --git a/core/variant/variant.h b/core/variant/variant.h
index 6d1b4da9e8..4dc706e853 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -253,7 +253,7 @@ private:
true, //PACKED_COLOR_ARRAY,
};
- if (unlikely(needs_deinit[type])) { //make it fast for types that dont need deinit
+ if (unlikely(needs_deinit[type])) { // Make it fast for types that don't need deinit.
_clear_internal();
}
type = NIL;
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index 733361fe58..f8538f71d3 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -750,6 +750,42 @@ struct _VariantCall {
return 0;
}
+ static PackedInt32Array func_PackedByteArray_decode_s32_array(PackedByteArray *p_instance) {
+ uint64_t size = p_instance->size();
+ const uint8_t *r = p_instance->ptr();
+ PackedInt32Array dest;
+ dest.resize(size / sizeof(int32_t));
+ memcpy(dest.ptrw(), r, size);
+ return dest;
+ }
+
+ static PackedInt64Array func_PackedByteArray_decode_s64_array(PackedByteArray *p_instance) {
+ uint64_t size = p_instance->size();
+ const uint8_t *r = p_instance->ptr();
+ PackedInt64Array dest;
+ dest.resize(size / sizeof(int64_t));
+ memcpy(dest.ptrw(), r, size);
+ return dest;
+ }
+
+ static PackedFloat32Array func_PackedByteArray_decode_float_array(PackedByteArray *p_instance) {
+ uint64_t size = p_instance->size();
+ const uint8_t *r = p_instance->ptr();
+ PackedFloat32Array dest;
+ dest.resize(size / sizeof(float));
+ memcpy(dest.ptrw(), r, size);
+ return dest;
+ }
+
+ static PackedFloat64Array func_PackedByteArray_decode_double_array(PackedByteArray *p_instance) {
+ uint64_t size = p_instance->size();
+ const uint8_t *r = p_instance->ptr();
+ PackedFloat64Array dest;
+ dest.resize(size / sizeof(double));
+ memcpy(dest.ptrw(), r, size);
+ return dest;
+ }
+
static void func_PackedByteArray_encode_u8(PackedByteArray *p_instance, int64_t p_offset, int64_t p_value) {
uint64_t size = p_instance->size();
ERR_FAIL_COND(p_offset < 0 || p_offset > int64_t(size) - 1);
@@ -1088,8 +1124,8 @@ bool Variant::has_builtin_method_return_value(Variant::Type p_type, const String
void Variant::get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list) {
ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX);
- for (List<StringName>::Element *E = builtin_method_names[p_type].front(); E; E = E->next()) {
- p_list->push_back(E->get());
+ for (const StringName &E : builtin_method_names[p_type]) {
+ p_list->push_back(E);
}
}
@@ -1152,12 +1188,12 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
obj->get_method_list(p_list);
}
} else {
- for (List<StringName>::Element *E = builtin_method_names[type].front(); E; E = E->next()) {
- const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E->get());
+ for (const StringName &E : builtin_method_names[type]) {
+ const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E);
ERR_CONTINUE(!method);
MethodInfo mi;
- mi.name = E->get();
+ mi.name = E;
//return type
if (method->has_return_type) {
@@ -1824,6 +1860,11 @@ static void _register_variant_builtin_methods() {
bind_function(PackedByteArray, decode_var, _VariantCall::func_PackedByteArray_decode_var, sarray("byte_offset", "allow_objects"), varray(false));
bind_function(PackedByteArray, decode_var_size, _VariantCall::func_PackedByteArray_decode_var_size, sarray("byte_offset", "allow_objects"), varray(false));
+ bind_function(PackedByteArray, to_int32_array, _VariantCall::func_PackedByteArray_decode_s32_array, sarray(), varray());
+ bind_function(PackedByteArray, to_int64_array, _VariantCall::func_PackedByteArray_decode_s64_array, sarray(), varray());
+ bind_function(PackedByteArray, to_float32_array, _VariantCall::func_PackedByteArray_decode_float_array, sarray(), varray());
+ bind_function(PackedByteArray, to_float64_array, _VariantCall::func_PackedByteArray_decode_double_array, sarray(), varray());
+
bind_functionnc(PackedByteArray, encode_u8, _VariantCall::func_PackedByteArray_encode_u8, sarray("byte_offset", "value"), varray());
bind_functionnc(PackedByteArray, encode_s8, _VariantCall::func_PackedByteArray_encode_s8, sarray("byte_offset", "value"), varray());
bind_functionnc(PackedByteArray, encode_u16, _VariantCall::func_PackedByteArray_encode_u16, sarray("byte_offset", "value"), varray());
@@ -2002,7 +2043,7 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR3, "ZERO", Vector3(0, 0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR3, "ONE", Vector3(1, 1, 1));
- _VariantCall::add_variant_constant(Variant::VECTOR3, "INF", Vector3(Math_INF, Math_INF, Math_INF));
+ _VariantCall::add_variant_constant(Variant::VECTOR3, "INF", Vector3(INFINITY, INFINITY, INFINITY));
_VariantCall::add_variant_constant(Variant::VECTOR3, "LEFT", Vector3(-1, 0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR3, "RIGHT", Vector3(1, 0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR3, "UP", Vector3(0, 1, 0));
@@ -2031,7 +2072,7 @@ static void _register_variant_builtin_methods() {
_VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0));
_VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1));
- _VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF));
+ _VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(INFINITY, INFINITY));
_VariantCall::add_variant_constant(Variant::VECTOR2, "LEFT", Vector2(-1, 0));
_VariantCall::add_variant_constant(Variant::VECTOR2, "RIGHT", Vector2(1, 0));
_VariantCall::add_variant_constant(Variant::VECTOR2, "UP", Vector2(0, -1));
diff --git a/core/variant/variant_parser.cpp b/core/variant/variant_parser.cpp
index 86d5ae7f38..50c48fd386 100644
--- a/core/variant/variant_parser.cpp
+++ b/core/variant/variant_parser.cpp
@@ -506,9 +506,9 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream,
} else if (id == "null" || id == "nil") {
value = Variant();
} else if (id == "inf") {
- value = Math_INF;
+ value = INFINITY;
} else if (id == "nan") {
- value = Math_NAN;
+ value = NAN;
} else if (id == "Vector2") {
Vector<real_t> args;
Error err = _parse_construct<real_t>(p_stream, args, line, r_err_str);
@@ -1586,8 +1586,8 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
List<PropertyInfo> props;
obj->get_property_list(&props);
bool first = true;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (E->get().usage & PROPERTY_USAGE_STORAGE || E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE) {
+ for (const PropertyInfo &E : props) {
+ if (E.usage & PROPERTY_USAGE_STORAGE || E.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) {
//must be serialized
if (first) {
@@ -1596,8 +1596,8 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, ",");
}
- p_store_string_func(p_store_string_ud, "\"" + E->get().name + "\":");
- write(obj->get(E->get().name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
+ p_store_string_func(p_store_string_ud, "\"" + E.name + "\":");
+ write(obj->get(E.name), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
}
}
@@ -1615,7 +1615,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
p_store_string_func(p_store_string_ud, "{\n");
for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
/*
- if (!_check_type(dict[E->get()]))
+ if (!_check_type(dict[E]))
continue;
*/
write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index de1deace63..ae3c7685fd 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -1093,9 +1093,9 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem);
List<Variant> keys;
dic->get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- if (E->get().get_type() == Variant::STRING) {
- p_list->push_back(PropertyInfo(Variant::STRING, E->get()));
+ for (const Variant &E : keys) {
+ if (E.get_type() == Variant::STRING) {
+ p_list->push_back(PropertyInfo(Variant::STRING, E));
}
}
} else if (type == OBJECT) {
@@ -1106,10 +1106,10 @@ void Variant::get_property_list(List<PropertyInfo> *p_list) const {
} else {
List<StringName> members;
get_member_list(type, &members);
- for (List<StringName>::Element *E = members.front(); E; E = E->next()) {
+ for (const StringName &E : members) {
PropertyInfo pi;
- pi.name = E->get();
- pi.type = get_member_type(type, E->get());
+ pi.name = E;
+ pi.type = get_member_type(type, E);
p_list->push_back(pi);
}
}
diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp
index 1f69e81d99..64f07e075e 100644
--- a/core/variant/variant_utility.cpp
+++ b/core/variant/variant_utility.cpp
@@ -1397,8 +1397,8 @@ uint32_t Variant::get_utility_function_hash(const StringName &p_name) {
}
void Variant::get_utility_function_list(List<StringName> *r_functions) {
- for (List<StringName>::Element *E = utility_function_name_table.front(); E; E = E->next()) {
- r_functions->push_back(E->get());
+ for (const StringName &E : utility_function_name_table) {
+ r_functions->push_back(E);
}
}
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index d0bd517050..c0e8b76969 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -1259,6 +1259,8 @@
<member name="ResourceSaver" type="ResourceSaver" setter="" getter="">
The [ResourceSaver] singleton.
</member>
+ <member name="ResourceUID" type="ResourceUID" setter="" getter="">
+ </member>
<member name="TextServerManager" type="TextServerManager" setter="" getter="">
The [TextServerManager] singleton.
</member>
diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml
index cc7f7072b9..327785a3b6 100644
--- a/doc/classes/AStar.xml
+++ b/doc/classes/AStar.xml
@@ -33,7 +33,7 @@
[/csharp]
[/codeblocks]
[method _estimate_cost] should return a lower bound of the distance, i.e. [code]_estimate_cost(u, v) &lt;= _compute_cost(u, v)[/code]. This serves as a hint to the algorithm because the custom [code]_compute_cost[/code] might be computation-heavy. If this is not the case, make [method _estimate_cost] return the same value as [method _compute_cost] to provide the algorithm with the most accurate information.
- If the default [method _estimate_cost] and [method _compute_cost] methods are used, or if the supplied [method _estimate_cost] method returns a lower bound of the cost, then the paths returned by A* will be the lowest cost paths. Here, the cost of a path equals to the sum of the [method _compute_cost] results of all segments in the path multiplied by the [code]weight_scale[/code]s of the end points of the respective segments. If the default methods are used and the [code]weight_scale[/code]s of all points are set to [code]1.0[/code], then this equals to the sum of Euclidean distances of all segments in the path.
+ If the default [method _estimate_cost] and [method _compute_cost] methods are used, or if the supplied [method _estimate_cost] method returns a lower bound of the cost, then the paths returned by A* will be the lowest-cost paths. Here, the cost of a path equals the sum of the [method _compute_cost] results of all segments in the path multiplied by the [code]weight_scale[/code]s of the endpoints of the respective segments. If the default methods are used and the [code]weight_scale[/code]s of all points are set to [code]1.0[/code], then this equals the sum of Euclidean distances of all segments in the path.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index 894e784397..4d192f8e97 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -616,7 +616,7 @@
<argument index="1" name="path" type="NodePath">
</argument>
<description>
- Sets the path of a track. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. Tracks that control properties or bones must append their name after the path, separated by [code]":"[/code].
+ Sets the path of a track. Paths must be valid scene-tree paths to a node and must be specified starting from the parent node of the node that will reproduce the animation. Tracks that control properties or bones must append their name after the path, separated by [code]":"[/code].
For example, [code]"character/skeleton:ankle"[/code] or [code]"character/mesh:transform/local"[/code].
</description>
</method>
diff --git a/doc/classes/AnimationTree.xml b/doc/classes/AnimationTree.xml
index af7d8d73e8..63460b70c5 100644
--- a/doc/classes/AnimationTree.xml
+++ b/doc/classes/AnimationTree.xml
@@ -7,7 +7,7 @@
Note: When linked with an [AnimationPlayer], several properties and methods of the corresponding [AnimationPlayer] will not function as expected. Playback and transitions should be handled using only the [AnimationTree] and its constituent [AnimationNode](s). The [AnimationPlayer] node should be used solely for adding, deleting, and editing animations.
</description>
<tutorials>
- <link title="AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link>
+ <link title="Using AnimationTree">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html</link>
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
@@ -24,7 +24,7 @@
<return type="Transform3D">
</return>
<description>
- Retrieve the motion of the [member root_motion_track] as a [Transform3D] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_TRANSFORM3D], returns an identity transformation.
+ Retrieve the motion of the [member root_motion_track] as a [Transform3D] that can be used elsewhere. If [member root_motion_track] is not a path to a track of type [constant Animation.TYPE_TRANSFORM3D], returns an identity transformation. See also [member root_motion_track] and [RootMotionView].
</description>
</method>
<method name="rename_parameter">
@@ -50,7 +50,7 @@
</member>
<member name="root_motion_track" type="NodePath" setter="set_root_motion_track" getter="get_root_motion_track" default="NodePath(&quot;&quot;)">
The path to the Animation track used for root motion. Paths must be valid scene-tree paths to a node, and must be specified starting from the parent node of the node that will reproduce the animation. To specify a track that controls properties or bones, append its name after the path, separated by [code]":"[/code]. For example, [code]"character/skeleton:ankle"[/code] or [code]"character/mesh:transform/local"[/code].
- If the track has type [constant Animation.TYPE_TRANSFORM3D], the transformation will be cancelled visually, and the animation will appear to stay in place.
+ If the track has type [constant Animation.TYPE_TRANSFORM3D], the transformation will be cancelled visually, and the animation will appear to stay in place. See also [method get_root_motion_transform] and [RootMotionView].
</member>
<member name="tree_root" type="AnimationNode" setter="set_tree_root" getter="get_tree_root">
The root animation node of this [AnimationTree]. See [AnimationNode].
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index f52c810ad2..cf2e7044af 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -34,7 +34,7 @@
</argument>
<description>
If [code]true[/code], the given area overlaps the Area2D.
- [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead.
+ [b]Note:[/b] The result of this test is not immediate after moving objects. For performance, the list of overlaps is updated once per frame and before the physics step. Consider using signals instead.
</description>
</method>
<method name="overlaps_body" qualifiers="const">
@@ -45,7 +45,7 @@
<description>
If [code]true[/code], the given physics body overlaps the Area2D.
[b]Note:[/b] The result of this test is not immediate after moving objects. For performance, list of overlaps is updated once per frame and before the physics step. Consider using signals instead.
- The [code]body[/code] argument can either be a [PhysicsBody2D] or a [TileMap] instance (while TileMaps are not physics body themselves, they register their tiles with collision shapes as a virtual physics body).
+ The [code]body[/code] argument can either be a [PhysicsBody2D] or a [TileMap] instance (while TileMaps are not physics bodies themselves, they register their tiles with collision shapes as a virtual physics body).
</description>
</method>
</methods>
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 543ec096c7..1ed7250adc 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Array" version="4.0">
<brief_description>
- Generic array datatype.
+ A generic array datatype.
</brief_description>
<description>
- Generic array which can contain several elements of any type, accessible by a numerical index starting at 0. Negative indices can be used to count from the back, like in Python (-1 is the last element, -2 the second to last, etc.).
+ A generic array that can contain several elements of any type, accessible by a numerical index starting at 0. Negative indices can be used to count from the back, like in Python (-1 is the last element, -2 is the second to last, etc.).
[b]Example:[/b]
[codeblocks]
[gdscript]
@@ -39,7 +39,7 @@
[/csharp]
[/codeblocks]
[b]Note:[/b] Concatenating with the [code]+=[/code] operator will create a new array, which has a cost. If you want to append another array to an existing array, [method append_array] is more efficient.
- [b]Note:[/b] Arrays are always passed by reference. To get a copy of an array which can be modified independently of the original array, use [method duplicate].
+ [b]Note:[/b] Arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate].
[b]Note:[/b] When declaring an array with [code]const[/code], the array itself can still be mutated by defining the values at individual indices or pushing/removing elements. Using [code]const[/code] will only prevent assigning the constant with another value after it was initialized.
</description>
<tutorials>
diff --git a/doc/classes/ArrayMesh.xml b/doc/classes/ArrayMesh.xml
index 7fbf53c7d1..e3d2eb74ff 100644
--- a/doc/classes/ArrayMesh.xml
+++ b/doc/classes/ArrayMesh.xml
@@ -75,7 +75,7 @@
</argument>
<description>
Creates a new surface.
- Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface.
+ Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines, or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface.
The [code]arrays[/code] argument is an array of arrays. See [enum Mesh.ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [constant Mesh.ARRAY_INDEX] if it is used.
</description>
</method>
diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml
index d7a89eef11..29e04dda7e 100644
--- a/doc/classes/CPUParticles3D.xml
+++ b/doc/classes/CPUParticles3D.xml
@@ -177,9 +177,21 @@
<member name="emission_normals" type="PackedVector3Array" setter="set_emission_normals" getter="get_emission_normals">
Sets the direction the particles will be emitted in when using [constant EMISSION_SHAPE_DIRECTED_POINTS].
</member>
- <member name="emission_points" type="PackedVector3Array" setter="set_emission_points" getter="get_emission_points" default="PackedVector3Array()">
+ <member name="emission_points" type="PackedVector3Array" setter="set_emission_points" getter="get_emission_points">
Sets the initial positions to spawn particles when using [constant EMISSION_SHAPE_POINTS] or [constant EMISSION_SHAPE_DIRECTED_POINTS].
</member>
+ <member name="emission_ring_axis" type="Vector3" setter="set_emission_ring_axis" getter="get_emission_ring_axis">
+ The axis of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
+ <member name="emission_ring_height" type="float" setter="set_emission_ring_height" getter="get_emission_ring_height">
+ The height of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
+ <member name="emission_ring_inner_radius" type="float" setter="set_emission_ring_inner_radius" getter="get_emission_ring_inner_radius">
+ The inner radius of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
+ <member name="emission_ring_radius" type="float" setter="set_emission_ring_radius" getter="get_emission_ring_radius">
+ The radius of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
<member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="CPUParticles3D.EmissionShape" default="0">
Particles will be emitted inside this region. See [enum EmissionShape] for possible values.
</member>
@@ -378,7 +390,10 @@
<constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="4" enum="EmissionShape">
Particles will be emitted at a position chosen randomly among [member emission_points]. Particle velocity and rotation will be set based on [member emission_normals]. Particle color will be modulated by [member emission_colors].
</constant>
- <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape">
+ <constant name="EMISSION_SHAPE_RING" value="5" enum="EmissionShape">
+ Particles will be emitted in a ring or cylinder.
+ </constant>
+ <constant name="EMISSION_SHAPE_MAX" value="6" enum="EmissionShape">
Represents the size of the [enum EmissionShape] enum.
</constant>
</constants>
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index e8f4cb49b6..ac90b6950b 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -5,7 +5,7 @@
</brief_description>
<description>
Camera node for 2D scenes. It forces the screen (current layer) to scroll following this node. This makes it easier (and faster) to program scrollable scenes than manually changing the position of [CanvasItem]-based nodes.
- This node is intended to be a simple helper to get things going quickly and it may happen that more functionality is desired to change how the camera works. To make your own custom camera node, inherit from [Node2D] and change the transform of the canvas by setting [member Viewport.canvas_transform] in [Viewport] (you can obtain the current [Viewport] by using [method Node.get_viewport]).
+ This node is intended to be a simple helper to get things going quickly, but more functionality may be desired to change how the camera works. To make your own custom camera node, inherit it from [Node2D] and change the transform of the canvas by setting [member Viewport.canvas_transform] in [Viewport] (you can obtain the current [Viewport] by using [method Node.get_viewport]).
Note that the [Camera2D] node's [code]position[/code] doesn't represent the actual position of the screen, which may differ due to applied smoothing or limits. You can use [method get_camera_screen_center] to get the real position.
</description>
<tutorials>
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml
index 0f0bfdc654..f74baa00a0 100644
--- a/doc/classes/Camera3D.xml
+++ b/doc/classes/Camera3D.xml
@@ -46,7 +46,7 @@
<return type="Array">
</return>
<description>
- Returns the camera's frustum planes in world-space units as an array of [Plane]s in the following order: near, far, left, top, right, bottom. Not to be confused with [member frustum_offset].
+ Returns the camera's frustum planes in world space units as an array of [Plane]s in the following order: near, far, left, top, right, bottom. Not to be confused with [member frustum_offset].
</description>
</method>
<method name="is_position_behind" qualifiers="const">
@@ -92,7 +92,7 @@
<argument index="1" name="z_depth" type="float">
</argument>
<description>
- Returns the 3D point in worldspace that maps to the given 2D coordinate in the [Viewport] rectangle on a plane that is the given [code]z_depth[/code] distance into the scene away from the camera.
+ Returns the 3D point in world space that maps to the given 2D coordinate in the [Viewport] rectangle on a plane that is the given [code]z_depth[/code] distance into the scene away from the camera.
</description>
</method>
<method name="project_ray_normal" qualifiers="const">
@@ -101,7 +101,7 @@
<argument index="0" name="screen_point" type="Vector2">
</argument>
<description>
- Returns a normal vector in worldspace, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
+ Returns a normal vector in world space, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
</description>
</method>
<method name="project_ray_origin" qualifiers="const">
@@ -110,7 +110,7 @@
<argument index="0" name="screen_point" type="Vector2">
</argument>
<description>
- Returns a 3D position in worldspace, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
+ Returns a 3D position in world space, that is the result of projecting a point on the [Viewport] rectangle by the camera projection. This is useful for casting rays in the form of (origin, normal) for object intersection or picking.
</description>
</method>
<method name="set_cull_mask_bit">
@@ -136,7 +136,7 @@
<argument index="3" name="z_far" type="float">
</argument>
<description>
- Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world-space units.
+ Sets the camera projection to frustum mode (see [constant PROJECTION_FRUSTUM]), by specifying a [code]size[/code], an [code]offset[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units.
</description>
</method>
<method name="set_orthogonal">
@@ -149,7 +149,7 @@
<argument index="2" name="z_far" type="float">
</argument>
<description>
- Sets the camera projection to orthogonal mode (see [constant PROJECTION_ORTHOGONAL]), by specifying a [code]size[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world-space units. (As a hint, 2D games often use this projection, with values specified in pixels.)
+ Sets the camera projection to orthogonal mode (see [constant PROJECTION_ORTHOGONAL]), by specifying a [code]size[/code], and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units. (As a hint, 2D games often use this projection, with values specified in pixels.)
</description>
</method>
<method name="set_perspective">
@@ -162,7 +162,7 @@
<argument index="2" name="z_far" type="float">
</argument>
<description>
- Sets the camera projection to perspective mode (see [constant PROJECTION_PERSPECTIVE]), by specifying a [code]fov[/code] (field of view) angle in degrees, and the [code]z_near[/code] and [code]z_far[/code] clip planes in world-space units.
+ Sets the camera projection to perspective mode (see [constant PROJECTION_PERSPECTIVE]), by specifying a [code]fov[/code] (field of view) angle in degrees, and the [code]z_near[/code] and [code]z_far[/code] clip planes in world space units.
</description>
</method>
<method name="unproject_position" qualifiers="const">
@@ -171,7 +171,7 @@
<argument index="0" name="world_point" type="Vector3">
</argument>
<description>
- Returns the 2D coordinate in the [Viewport] rectangle that maps to the given 3D point in worldspace.
+ Returns the 2D coordinate in the [Viewport] rectangle that maps to the given 3D point in world space.
[b]Note:[/b] When using this to position GUI elements over a 3D viewport, use [method is_position_behind] to prevent them from appearing if the 3D point is behind the camera:
[codeblock]
# This code block is part of a script that inherits from Node3D.
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index b0afbb201c..097bbc2de8 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -107,8 +107,8 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
- If [code]value[/value] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_layer].
- If [code]value[/value] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_layer].
+ If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_layer].
+ If [code]value[/code] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_layer].
</description>
</method>
<method name="set_collision_mask_bit">
@@ -119,8 +119,8 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
- If [code]value[/value] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_mask].
- If [code]value[/value] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_mask].
+ If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_mask].
+ If [code]value[/code] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_mask].
</description>
</method>
<method name="shape_find_owner" qualifiers="const">
diff --git a/doc/classes/CollisionObject3D.xml b/doc/classes/CollisionObject3D.xml
index dfd1e85e56..ac6a84dda6 100644
--- a/doc/classes/CollisionObject3D.xml
+++ b/doc/classes/CollisionObject3D.xml
@@ -93,8 +93,8 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
- If [code]value[/value] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_layer].
- If [code]value[/value] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_layer].
+ If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_layer].
+ If [code]value[/code] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_layer].
</description>
</method>
<method name="set_collision_mask_bit">
@@ -105,8 +105,8 @@
<argument index="1" name="value" type="bool">
</argument>
<description>
- If [code]value[/value] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_mask].
- If [code]value[/value] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_mask].
+ If [code]value[/code] is [code]true[/code], sets the specified [code]bit[/code] in the the [member collision_mask].
+ If [code]value[/code] is [code]false[/code], clears the specified [code]bit[/code] in the the [member collision_mask].
</description>
</method>
<method name="shape_find_owner" qualifiers="const">
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 23cbdd8cab..5c0856cb6a 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -9,7 +9,7 @@
[b]User Interface nodes and input[/b]
Godot sends input events to the scene's root node first, by calling [method Node._input]. [method Node._input] forwards the event down the node tree to the nodes under the mouse cursor, or on keyboard focus. To do so, it calls [code]MainLoop._input_event[/code].
[b]FIXME:[/b] No longer valid after DisplayServer split and Input refactoring.
- Call [method accept_event] so no other node receives the event. Once you accepted an input, it becomes handled so [method Node._unhandled_input] will not process it.
+ Call [method accept_event] so no other node receives the event. Once you accept an input, it becomes handled so [method Node._unhandled_input] will not process it.
Only one [Control] node can be in keyboard focus. Only the node in focus will receive keyboard events. To get the focus, call [method grab_focus]. [Control] nodes lose focus when another node grabs it, or if you hide the node in focus.
Sets [member mouse_filter] to [constant MOUSE_FILTER_IGNORE] to tell a [Control] node to ignore mouse or touch events. You'll need it if you place an icon on top of a button.
[Theme] resources change the Control's appearance. If you change the [Theme] on a [Control] node, it affects all of its children. To override some of the theme's parameters, call one of the [code]add_theme_*_override[/code] methods, like [method add_theme_font_override]. You can override the theme with the inspector.
@@ -147,7 +147,7 @@
* control has [member mouse_filter] set to [constant MOUSE_FILTER_IGNORE];
* control is obstructed by another [Control] on top of it, which doesn't have [member mouse_filter] set to [constant MOUSE_FILTER_IGNORE];
* control's parent has [member mouse_filter] set to [constant MOUSE_FILTER_STOP] or has accepted the event;
- * it happens outside parent's rectangle and the parent has either [member rect_clip_content] enabled.
+ * it happens outside the parent's rectangle and the parent has either [member rect_clip_content] enabled.
</description>
</method>
<method name="_has_point" qualifiers="virtual const">
@@ -168,10 +168,10 @@
</argument>
<description>
Virtual method to be implemented by the user. Returns a [Control] node that should be used as a tooltip instead of the default one. The [code]for_text[/code] includes the contents of the [member hint_tooltip] property.
- The returned node must be of type [Control] or Control-derived. It can have child nodes of any type. It is freed when the tooltip disappears, so make sure you always provide a new instance (if you want to use a pre-existing node from your scene tree, you can duplicate it and pass the duplicated instance).When [code]null[/code] or a non-Control node is returned, the default tooltip will be used instead.
+ The returned node must be of type [Control] or Control-derived. It can have child nodes of any type. It is freed when the tooltip disappears, so make sure you always provide a new instance (if you want to use a pre-existing node from your scene tree, you can duplicate it and pass the duplicated instance). When [code]null[/code] or a non-Control node is returned, the default tooltip will be used instead.
The returned node will be added as child to a [PopupPanel], so you should only provide the contents of that panel. That [PopupPanel] can be themed using [method Theme.set_stylebox] for the type [code]"TooltipPanel"[/code] (see [member hint_tooltip] for an example).
[b]Note:[/b] The tooltip is shrunk to minimal size. If you want to ensure it's fully visible, you might want to set its [member rect_min_size] to some non-zero value.
- [b]Note:[/b] The node (and any relevant children) should be [member CanvasItem.visible] when returned, otherwise the viewport that instantiates it will not be able to calculate its minimum size reliably.
+ [b]Note:[/b] The node (and any relevant children) should be [member CanvasItem.visible] when returned, otherwise, the viewport that instantiates it will not be able to calculate its minimum size reliably.
Example of usage with a custom-constructed node:
[codeblocks]
[gdscript]
@@ -860,7 +860,7 @@
<argument index="1" name="keep_offsets" type="bool" default="false">
</argument>
<description>
- Sets the anchors to a [code]preset[/code] from [enum Control.LayoutPreset] enum. This is code equivalent of using the Layout menu in 2D editor.
+ Sets the anchors to a [code]preset[/code] from [enum Control.LayoutPreset] enum. This is the code equivalent to using the Layout menu in the 2D editor.
If [code]keep_offsets[/code] is [code]true[/code], control's position will also be updated.
</description>
</method>
@@ -1029,7 +1029,7 @@
<argument index="2" name="margin" type="int" default="0">
</argument>
<description>
- Sets the offsets to a [code]preset[/code] from [enum Control.LayoutPreset] enum. This is code equivalent of using the Layout menu in 2D editor.
+ Sets the offsets to a [code]preset[/code] from [enum Control.LayoutPreset] enum. This is the code equivalent to using the Layout menu in the 2D editor.
Use parameter [code]resize_mode[/code] with constants from [enum Control.LayoutPresetMode] to better determine the resulting size of the [Control]. Constant size will be ignored if used with presets that change size, e.g. [code]PRESET_LEFT_WIDE[/code].
Use parameter [code]margin[/code] to determine the gap between the [Control] and the edges.
</description>
@@ -1229,11 +1229,13 @@
<signal name="mouse_entered">
<description>
Emitted when the mouse enters the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it.
+ [b]Note:[/b] [signal mouse_entered] will not be emitted if the mouse enters a child [Control] node before entering the parent's [code]Rect[/code] area, at least until the mouse is moved to reach the parent's [code]Rect[/code] area.
</description>
</signal>
<signal name="mouse_exited">
<description>
Emitted when the mouse leaves the control's [code]Rect[/code] area, provided its [member mouse_filter] lets the event reach it.
+ [b]Note:[/b] [signal mouse_exited] will be emitted if the mouse enters a child [Control] node, even if the mouse cursor is still inside the parent's [code]Rect[/code] area.
</description>
</signal>
<signal name="resized">
diff --git a/doc/classes/Directory.xml b/doc/classes/Directory.xml
index dae8d83f0c..ff92f6c5ef 100644
--- a/doc/classes/Directory.xml
+++ b/doc/classes/Directory.xml
@@ -159,7 +159,7 @@
<argument index="1" name="show_hidden" type="bool" default="false">
</argument>
<description>
- Initializes the stream used to list all files and directories using the [method get_next] function, closing the current opened stream if needed. Once the stream has been processed, it should typically be closed with [method list_dir_end].
+ Initializes the stream used to list all files and directories using the [method get_next] function, closing the currently opened stream if needed. Once the stream has been processed, it should typically be closed with [method list_dir_end].
If [code]show_navigational[/code] is [code]true[/code], [code].[/code] and [code]..[/code] are included too.
If [code]show_hidden[/code] is [code]true[/code], hidden files are included too.
</description>
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index 17b51d5cbe..5c9bcc5014 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -7,16 +7,6 @@
<tutorials>
</tutorials>
<methods>
- <method name="alert">
- <return type="void">
- </return>
- <argument index="0" name="text" type="String">
- </argument>
- <argument index="1" name="title" type="String" default="&quot;Alert!&quot;">
- </argument>
- <description>
- </description>
- </method>
<method name="clipboard_get" qualifiers="const">
<return type="String">
</return>
diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml
index a532e9bc2b..1722b278f8 100644
--- a/doc/classes/EditorImportPlugin.xml
+++ b/doc/classes/EditorImportPlugin.xml
@@ -126,7 +126,7 @@
<return type="int">
</return>
<description>
- Gets the order of this importer to be run when importing resources. Higher values will be called later. Use this to ensure the importer runs after the dependencies are already imported.
+ Gets the order of this importer to be run when importing resources. Importers with [i]lower[/i] import orders will be called first, and higher values will be called later. Use this to ensure the importer runs after the dependencies are already imported. The default import order is [code]0[/code] unless overridden by a specific importer. See [enum ResourceImporter.ImportOrder] for some predefined values.
</description>
</method>
<method name="_get_importer_name" qualifiers="virtual">
diff --git a/doc/classes/EditorNode3DGizmo.xml b/doc/classes/EditorNode3DGizmo.xml
index 221b5e44d6..d4d1e4a652 100644
--- a/doc/classes/EditorNode3DGizmo.xml
+++ b/doc/classes/EditorNode3DGizmo.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorNode3DGizmo" inherits="Node3DGizmo" version="4.0">
<brief_description>
- Custom gizmo for editing Node3D objects.
+ Gizmo for editing Node3D objects.
</brief_description>
<description>
- Custom gizmo that is used for providing custom visualization and editing (handles) for Node3D objects. See [EditorNode3DGizmoPlugin] for more information.
+ Gizmo that is used for providing custom visualization and editing (handles and subgizmos) for Node3D objects. Can be overridden to create custom gizmos, but for simple gizmos creating a [EditorNode3DGizmoPlugin] is usually recommended.
</description>
<tutorials>
</tutorials>
@@ -12,64 +12,119 @@
<method name="_commit_handle" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<argument index="1" name="restore" type="Variant">
</argument>
<argument index="2" name="cancel" type="bool" default="false">
</argument>
<description>
- Commit a handle being edited (handles must have been previously added by [method add_handles]).
- If the [code]cancel[/code] parameter is [code]true[/code], an option to restore the edited value to the original is provided.
+ Override this method to commit a handle being edited (handles must have been previously added by [method add_handles]). This usually means creating an [UndoRedo] action for the change, using the current handle value as "do" and the [code]restore[/code] argument as "undo".
+ If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] value should be directly set, without any [UndoRedo] action.
+ </description>
+ </method>
+ <method name="_commit_subgizmos" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="ids" type="PackedInt32Array">
+ </argument>
+ <argument index="1" name="restore" type="Array">
+ </argument>
+ <argument index="2" name="cancel" type="bool" default="false">
+ </argument>
+ <description>
+ Override this method to commit a group of subgizmos being edited (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). This usually means creating an [UndoRedo] action for the change, using the current transforms as "do" and the [code]restore[/code] transforms as "undo".
+ If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] transforms should be directly set, without any [UndoRedo] action.
</description>
</method>
<method name="_get_handle_name" qualifiers="virtual">
<return type="String">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<description>
- Gets the name of an edited handle (handles must have been previously added by [method add_handles]).
+ Override this method to return the name of an edited handle (handles must have been previously added by [method add_handles]).
Handles can be named for reference to the user when editing.
</description>
</method>
<method name="_get_handle_value" qualifiers="virtual">
<return type="Variant">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<description>
- Gets actual value of a handle. This value can be anything and used for eventually undoing the motion when calling [method _commit_handle].
+ Override this method to return the current value of a handle. This value will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_handle].
+ </description>
+ </method>
+ <method name="_get_subgizmo_transform" qualifiers="virtual">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ Override this method to return the current transform of a subgizmo. This transform will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_subgizmos].
</description>
</method>
<method name="_is_handle_highlighted" qualifiers="virtual">
<return type="bool">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<description>
- Returns [code]true[/code] if the handle at index [code]index[/code] is highlighted by being hovered with the mouse.
+ Override this method to return [code]true[/code] whenever the given handle should be highlighted in the editor.
</description>
</method>
<method name="_redraw" qualifiers="virtual">
<return type="void">
</return>
<description>
- This function is called when the [Node3D] this gizmo refers to changes (the [method Node3D.update_gizmo] is called).
+ Override this method to add all the gizmo elements whenever a gizmo update is requested. It's common to call [method clear] at the beginning of this method and then add visual elements depending on the node's properties.
</description>
</method>
<method name="_set_handle" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="index" type="int">
+ <argument index="0" name="id" type="int">
</argument>
<argument index="1" name="camera" type="Camera3D">
</argument>
<argument index="2" name="point" type="Vector2">
</argument>
<description>
- This function is used when the user drags a gizmo handle (previously added with [method add_handles]) in screen coordinates.
- The [Camera3D] is also provided so screen coordinates can be converted to raycasts.
+ Override this method to update the node properties when the user drags a gizmo handle (previously added with [method add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts.
+ </description>
+ </method>
+ <method name="_set_subgizmo_transform" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="transform" type="Transform3D">
+ </argument>
+ <description>
+ Override this method to update the node properties during subgizmo editing (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). The [code]transform[/code] is given in the Node3D's local coordinate system.
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_frustum" qualifiers="virtual">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="camera" type="Camera3D">
+ </argument>
+ <argument index="1" name="frustum" type="Array">
+ </argument>
+ <description>
+ Override this method to allow selecting subgizmos using mouse drag box selection. Given a [code]camera[/code] and a [code]frustum[/code], this method should return which subgizmos are contained within the frustum. The [code]frustum[/code] argument consists of an [code]Array[/code] with all the [code]Plane[/code]s that make up the selection frustum. The returned value should contain a list of unique subgizmo identifiers, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos].
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_ray" qualifiers="virtual">
+ <return type="int">
+ </return>
+ <argument index="0" name="camera" type="Camera3D">
+ </argument>
+ <argument index="1" name="point" type="Vector2">
+ </argument>
+ <description>
+ Override this method to allow selecting subgizmos using mouse clicks. Given a [code]camera[/code] and a [code]point[/code] in screen coordinates, this method should return which subgizmo should be selected. The returned value should be a unique subgizmo identifier, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos].
</description>
</method>
<method name="add_collision_segments">
@@ -78,7 +133,7 @@
<argument index="0" name="segments" type="PackedVector3Array">
</argument>
<description>
- Adds the specified [code]segments[/code] to the gizmo's collision shape for picking. Call this function during [method _redraw].
+ Adds the specified [code]segments[/code] to the gizmo's collision shape for picking. Call this method during [method _redraw].
</description>
</method>
<method name="add_collision_triangles">
@@ -87,7 +142,7 @@
<argument index="0" name="triangles" type="TriangleMesh">
</argument>
<description>
- Adds collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this function during [method _redraw].
+ Adds collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this method during [method _redraw].
</description>
</method>
<method name="add_handles">
@@ -97,13 +152,15 @@
</argument>
<argument index="1" name="material" type="Material">
</argument>
- <argument index="2" name="billboard" type="bool" default="false">
+ <argument index="2" name="ids" type="PackedInt32Array">
</argument>
- <argument index="3" name="secondary" type="bool" default="false">
+ <argument index="3" name="billboard" type="bool" default="false">
+ </argument>
+ <argument index="4" name="secondary" type="bool" default="false">
</argument>
<description>
- Adds a list of handles (points) which can be used to deform the object being edited.
- There are virtual functions which will be called upon editing of these handles. Call this function during [method _redraw].
+ Adds a list of handles (points) which can be used to edit the properties of the gizmo's Node3D. The [code]ids[/code] argument can be used to specify a custom identifier for each handle, if an empty [code]Array[/code] is passed, the ids will be assigned automatically from the [code]handles[/code] argument order.
+ There are virtual methods which will be called upon editing of these handles. Call this method during [method _redraw].
</description>
</method>
<method name="add_lines">
@@ -118,7 +175,7 @@
<argument index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
</argument>
<description>
- Adds lines to the gizmo (as sets of 2 points), with a given material. The lines are used for visualizing the gizmo. Call this function during [method _redraw].
+ Adds lines to the gizmo (as sets of 2 points), with a given material. The lines are used for visualizing the gizmo. Call this method during [method _redraw].
</description>
</method>
<method name="add_mesh">
@@ -126,14 +183,14 @@
</return>
<argument index="0" name="mesh" type="ArrayMesh">
</argument>
- <argument index="1" name="billboard" type="bool" default="false">
+ <argument index="1" name="material" type="Material" default="null">
</argument>
- <argument index="2" name="skeleton" type="SkinReference" default="null">
+ <argument index="2" name="transform" type="Transform3D" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
</argument>
- <argument index="3" name="material" type="Material" default="null">
+ <argument index="3" name="skeleton" type="SkinReference" default="null">
</argument>
<description>
- Adds a mesh to the gizmo with the specified [code]billboard[/code] state, [code]skeleton[/code] and [code]material[/code]. If [code]billboard[/code] is [code]true[/code], the mesh will rotate to always face the camera. Call this function during [method _redraw].
+ Adds a mesh to the gizmo with the specified [code]material[/code], local [code]transform[/code] and [code]skeleton[/code]. Call this method during [method _redraw].
</description>
</method>
<method name="add_unscaled_billboard">
@@ -146,7 +203,7 @@
<argument index="2" name="modulate" type="Color" default="Color(1, 1, 1, 1)">
</argument>
<description>
- Adds an unscaled billboard for visualization. Call this function during [method _redraw].
+ Adds an unscaled billboard for visualization and selection. Call this method during [method _redraw].
</description>
</method>
<method name="clear">
@@ -170,6 +227,22 @@
Returns the Node3D node associated with this gizmo.
</description>
</method>
+ <method name="get_subgizmo_selection" qualifiers="const">
+ <return type="PackedInt32Array">
+ </return>
+ <description>
+ Returns a list of the currently selected subgizmos. Can be used to highlight selected elements during [method _redraw].
+ </description>
+ </method>
+ <method name="is_subgizmo_selected" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="arg0" type="int">
+ </argument>
+ <description>
+ Returns [code]true[/code] if the given subgizmo is currently selected. Can be used to highlight selected elements during [method _redraw].
+ </description>
+ </method>
<method name="set_hidden">
<return type="void">
</return>
diff --git a/doc/classes/EditorNode3DGizmoPlugin.xml b/doc/classes/EditorNode3DGizmoPlugin.xml
index 41c94cbbc6..6152487eaf 100644
--- a/doc/classes/EditorNode3DGizmoPlugin.xml
+++ b/doc/classes/EditorNode3DGizmoPlugin.xml
@@ -14,7 +14,7 @@
<return type="bool">
</return>
<description>
- Override this method to define whether the gizmo can be hidden or not. Returns [code]true[/code] if not overridden.
+ Override this method to define whether the gizmos handled by this plugin can be hidden or not. Returns [code]true[/code] if not overridden.
</description>
</method>
<method name="_commit_handle" qualifiers="virtual">
@@ -22,14 +22,31 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<argument index="2" name="restore" type="Variant">
</argument>
<argument index="3" name="cancel" type="bool" default="false">
</argument>
<description>
- Override this method to commit gizmo handles. Called for this plugin's active gizmos.
+ Override this method to commit a handle being edited (handles must have been previously added by [method EditorNode3DGizmo.add_handles] during [method _redraw]). This usually means creating an [UndoRedo] action for the change, using the current handle value as "do" and the [code]restore[/code] argument as "undo".
+ If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] value should be directly set, without any [UndoRedo] action. Called for this plugin's active gizmos.
+ </description>
+ </method>
+ <method name="_commit_subgizmos" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="ids" type="PackedInt32Array">
+ </argument>
+ <argument index="2" name="restore" type="Array">
+ </argument>
+ <argument index="3" name="cancel" type="bool" default="false">
+ </argument>
+ <description>
+ Override this method to commit a group of subgizmos being edited (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). This usually means creating an [UndoRedo] action for the change, using the current transforms as "do" and the [code]restore[/code] transforms as "undo".
+ If the [code]cancel[/code] argument is [code]true[/code], the [code]restore[/code] transforms should be directly set, without any [UndoRedo] action. As with all subgizmo methods, transforms are given in local space respect to the gizmo's Node3D. Called for this plugin's active gizmos.
</description>
</method>
<method name="_create_gizmo" qualifiers="virtual">
@@ -53,7 +70,7 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<description>
Override this method to provide gizmo's handle names. Called for this plugin's active gizmos.
@@ -64,18 +81,29 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<description>
- Gets actual value of a handle from gizmo. Called for this plugin's active gizmos.
+ Override this method to return the current value of a handle. This value will be requested at the start of an edit and used as the [code]restore[/code] argument in [method _commit_handle]. Called for this plugin's active gizmos.
</description>
</method>
<method name="_get_priority" qualifiers="virtual">
<return type="int">
</return>
<description>
- Override this method to set the gizmo's priority. Higher values correspond to higher priority. If a gizmo with higher priority conflicts with another gizmo, only the gizmo with higher priority will be used.
- All built-in editor gizmos return a priority of [code]-1[/code]. If not overridden, this method will return [code]0[/code], which means custom gizmos will automatically override built-in gizmos.
+ Override this method to set the gizmo's priority. Gizmos with higher priority will have precedence when processing inputs like handles or subgizmos selection.
+ All built-in editor gizmos return a priority of [code]-1[/code]. If not overridden, this method will return [code]0[/code], which means custom gizmos will automatically get higher priority than built-in gizmos.
+ </description>
+ </method>
+ <method name="_get_subgizmo_transform" qualifiers="virtual">
+ <return type="Transform3D">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="id" type="int">
+ </argument>
+ <description>
+ Override this method to return the current transform of a subgizmo. As with all subgizmo methods, the transform should be in local space respect to the gizmo's Node3D. This transform will be requested at the start of an edit and used in the [code]restore[/code] argument in [method _commit_subgizmos]. Called for this plugin's active gizmos.
</description>
</method>
<method name="_has_gizmo" qualifiers="virtual">
@@ -92,10 +120,10 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<description>
- Gets whether a handle is highlighted or not. Called for this plugin's active gizmos.
+ Override this method to return [code]true[/code] whenever to given handle should be highlighted in the editor. Called for this plugin's active gizmos.
</description>
</method>
<method name="_is_selectable_when_hidden" qualifiers="virtual">
@@ -111,7 +139,7 @@
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
<description>
- Callback to redraw the provided gizmo. Called for this plugin's active gizmos.
+ Override this method to add all the gizmo elements whenever a gizmo update is requested. It's common to call [method EditorNode3DGizmo.clear] at the beginning of this method and then add visual elements depending on the node's properties.
</description>
</method>
<method name="_set_handle" qualifiers="virtual">
@@ -119,14 +147,53 @@
</return>
<argument index="0" name="gizmo" type="EditorNode3DGizmo">
</argument>
- <argument index="1" name="index" type="int">
+ <argument index="1" name="id" type="int">
</argument>
<argument index="2" name="camera" type="Camera3D">
</argument>
<argument index="3" name="point" type="Vector2">
</argument>
<description>
- Update the value of a handle after it has been updated. Called for this plugin's active gizmos.
+ Override this method to update the node's properties when the user drags a gizmo handle (previously added with [method EditorNode3DGizmo.add_handles]). The provided [code]point[/code] is the mouse position in screen coordinates and the [code]camera[/code] can be used to convert it to raycasts. Called for this plugin's active gizmos.
+ </description>
+ </method>
+ <method name="_set_subgizmo_transform" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="id" type="int">
+ </argument>
+ <argument index="2" name="transform" type="Transform3D">
+ </argument>
+ <description>
+ Override this method to update the node properties during subgizmo editing (see [method _subgizmos_intersect_ray] and [method _subgizmos_intersect_frustum]). The [code]transform[/code] is given in the Node3D's local coordinate system. Called for this plugin's active gizmos.
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_frustum" qualifiers="virtual">
+ <return type="PackedInt32Array">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="camera" type="Camera3D">
+ </argument>
+ <argument index="2" name="frustum" type="Array">
+ </argument>
+ <description>
+ Override this method to allow selecting subgizmos using mouse drag box selection. Given a [code]camera[/code] and a [code]frustum[/code], this method should return which subgizmos are contained within the frustum. The [code]frustum[/code] argument consists of an [code]Array[/code] with all the [code]Plane[/code]s that make up the selection frustum. The returned value should contain a list of unique subgizmo identifiers, these identifiers can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. Called for this plugin's active gizmos.
+ </description>
+ </method>
+ <method name="_subgizmos_intersect_ray" qualifiers="virtual">
+ <return type="int">
+ </return>
+ <argument index="0" name="gizmo" type="EditorNode3DGizmo">
+ </argument>
+ <argument index="1" name="camera" type="Camera3D">
+ </argument>
+ <argument index="2" name="point" type="Vector2">
+ </argument>
+ <description>
+ Override this method to allow selecting subgizmos using mouse clicks. Given a [code]camera[/code] and a [code]point[/code] in screen coordinates, this method should return which subgizmo should be selected. The returned value should be a unique subgizmo identifier, which can have any non-negative value and will be used in other virtual methods like [method _get_subgizmo_transform] or [method _commit_subgizmos]. Called for this plugin's active gizmos.
</description>
</method>
<method name="add_material">
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 753227513b..efd1d30565 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -404,7 +404,7 @@
</argument>
<description>
Adds a custom type, which will appear in the list of nodes or resources. An icon can be optionally passed.
- When given node or resource is selected, the base type will be instantiated (e.g. "Node3D", "Control", "Resource"), then the script will be loaded and set to this object.
+ When a given node or resource is selected, the base type will be instantiated (e.g. "Node3D", "Control", "Resource"), then the script will be loaded and set to this object.
You can use the virtual method [method _handles] to check if your custom object is being edited by checking the script or using the [code]is[/code] keyword.
During run-time, this will be a simple object with a script so this function does not need to be called then.
</description>
diff --git a/doc/classes/Engine.xml b/doc/classes/Engine.xml
index c0a8407ece..3fa7894fdc 100644
--- a/doc/classes/Engine.xml
+++ b/doc/classes/Engine.xml
@@ -170,7 +170,7 @@
The number of fixed iterations per second. This controls how often physics simulation and [method Node._physics_process] methods are run. This value should generally always be set to [code]60[/code] or above, as Godot doesn't interpolate the physics step. As a result, values lower than [code]60[/code] will look stuttery. This value can be increased to make input more reactive or work around tunneling issues, but keep in mind doing so will increase CPU usage.
</member>
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
- Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
+ Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of the in-game clock and real clock but smooth out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
[b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics_jitter_fix] to [code]0[/code].
</member>
<member name="print_error_messages" type="bool" setter="set_print_error_messages" getter="is_printing_error_messages" default="true">
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 5f468acc72..37a96fef3d 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -241,7 +241,7 @@
<argument index="0" name="renormalize" type="bool" default="false">
</argument>
<description>
- Generates mipmaps for the image. Mipmaps are precalculated and lower resolution copies of the image. Mipmaps are automatically used if the image needs to be scaled down when rendered. This improves image quality and the performance of the rendering. Returns an error if the image is compressed, in a custom format or if the image's width/height is 0.
+ Generates mipmaps for the image. Mipmaps are precalculated lower-resolution copies of the image that are automatically used if the image needs to be scaled down when rendered. They help improve image quality and performance when rendering. This method returns an error if the image is compressed, in a custom format, or if the image's width/height is [code]0[/code].
</description>
</method>
<method name="get_data" qualifiers="const">
@@ -711,7 +711,7 @@
</constant>
<constant name="INTERPOLATE_TRILINEAR" value="3" enum="Interpolation">
Performs bilinear separately on the two most-suited mipmap levels, then linearly interpolates between them.
- It's slower than [constant INTERPOLATE_BILINEAR], but produces higher-quality results with much less aliasing artifacts.
+ It's slower than [constant INTERPOLATE_BILINEAR], but produces higher-quality results with far fewer aliasing artifacts.
If the image does not have mipmaps, they will be generated and used internally, but no mipmaps will be generated on the resulting image.
[b]Note:[/b] If you intend to scale multiple copies of the original image, it's better to call [method generate_mipmaps]] on it in advance, to avoid wasting processing power in generating them again and again.
On the other hand, if the image already has mipmaps, they will be used, and a new set will be generated for the resulting image.
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index b970070659..c340895130 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -208,7 +208,7 @@
<argument index="4" name="deadzone" type="float" default="-1.0">
</argument>
<description>
- Get vector input by specifying four actions, two for the X axis and two for the Y axis, negative and positive.
+ Gets an input vector by specifying four actions for the positive and negative X and Y axes.
This method is useful when getting vector input, such as from a joystick, directional pad, arrows, or WASD. The vector has its length limited to 1 and has a circular deadzone, which is useful for using vector input as movement.
By default, the deadzone is automatically calculated from the average of the action deadzones. However, you can override the deadzone to be whatever you want (on the range of 0 to 1).
</description>
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index ca22567ad5..9e96f11ccc 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -4,7 +4,7 @@
Displays plain text in a line or wrapped inside a rectangle. For formatted text, use [RichTextLabel].
</brief_description>
<description>
- Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment, and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics or other formatting. For that, use [RichTextLabel] instead.
+ Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics, or other formatting. For that, use [RichTextLabel] instead.
[b]Note:[/b] Contrarily to most other [Control]s, Label's [member Control.mouse_filter] defaults to [constant Control.MOUSE_FILTER_IGNORE] (i.e. it doesn't react to mouse input events). This implies that a label won't display any configured [member Control.hint_tooltip], unless you change its mouse filter.
</description>
<tutorials>
diff --git a/doc/classes/MethodTweener.xml b/doc/classes/MethodTweener.xml
index 42b91abf93..3badeb164b 100644
--- a/doc/classes/MethodTweener.xml
+++ b/doc/classes/MethodTweener.xml
@@ -4,7 +4,7 @@
Interpolates an abstract value and supplies it to a method called over time.
</brief_description>
<description>
- [MethodTweener] is similar to a combination of [CallbackTweener] and [PropertyTweener]. It calls a method providing an interpolated value as a paramater. See [method Tween.tween_method] for more usage information.
+ [MethodTweener] is similar to a combination of [CallbackTweener] and [PropertyTweener]. It calls a method providing an interpolated value as a parameter. See [method Tween.tween_method] for more usage information.
[b]Note:[/b] [method Tween.tween_method] is the only correct way to create [MethodTweener]. Any [MethodTweener] created manually will not function correctly.
</description>
<tutorials>
diff --git a/doc/classes/MultiMesh.xml b/doc/classes/MultiMesh.xml
index 7151e58c5f..45326f12e9 100644
--- a/doc/classes/MultiMesh.xml
+++ b/doc/classes/MultiMesh.xml
@@ -6,7 +6,7 @@
<description>
MultiMesh provides low-level mesh instancing. Drawing thousands of [MeshInstance3D] nodes can be slow, since each object is submitted to the GPU then drawn individually.
MultiMesh is much faster as it can draw thousands of instances with a single draw call, resulting in less API overhead.
- As a drawback, if the instances are too far away of each other, performance may be reduced as every single instance will always render (they are spatially indexed as one, for the whole object).
+ As a drawback, if the instances are too far away from each other, performance may be reduced as every single instance will always render (they are spatially indexed as one, for the whole object).
Since instances may have any behavior, the AABB used for visibility must be provided by the user.
</description>
<tutorials>
diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml
index 14e03a2186..8cb331a578 100644
--- a/doc/classes/Node3D.xml
+++ b/doc/classes/Node3D.xml
@@ -13,6 +13,29 @@
<link title="All 3D Demos">https://github.com/godotengine/godot-demo-projects/tree/master/3d</link>
</tutorials>
<methods>
+ <method name="add_gizmo">
+ <return type="void">
+ </return>
+ <argument index="0" name="gizmo" type="Node3DGizmo">
+ </argument>
+ <description>
+ Attach a gizmo to this [code]Node3D[/code].
+ </description>
+ </method>
+ <method name="clear_gizmos">
+ <return type="void">
+ </return>
+ <description>
+ Clear all gizmos attached to this [code]Node3D[/code].
+ </description>
+ </method>
+ <method name="clear_subgizmo_selection">
+ <return type="void">
+ </return>
+ <description>
+ Clears subgizmo selection for this node in the editor. Useful when subgizmo IDs become invalid after a property change.
+ </description>
+ </method>
<method name="force_update_transform">
<return type="void">
</return>
@@ -20,6 +43,13 @@
Forces the transform to update. Transform changes in physics are not instant for performance reasons. Transforms are accumulated and then set. Use this if you need an up-to-date transform when doing physics operations.
</description>
</method>
+ <method name="get_gizmos" qualifiers="const">
+ <return type="Array">
+ </return>
+ <description>
+ Returns all the gizmos attached to this [code]Node3D[/code].
+ </description>
+ </method>
<method name="get_parent_node_3d" qualifiers="const">
<return type="Node3D">
</return>
@@ -276,18 +306,15 @@
Changes the node's position by the given offset [Vector3] in local space.
</description>
</method>
- <method name="update_gizmo">
+ <method name="update_gizmos">
<return type="void">
</return>
<description>
- Updates the [Node3DGizmo] of this node.
+ Updates all the [Node3DGizmo]s attached to this node.
</description>
</method>
</methods>
<members>
- <member name="gizmo" type="Node3DGizmo" setter="set_gizmo" getter="get_gizmo">
- The [Node3DGizmo] for this node. Used for example in [EditorNode3DGizmo] as custom visualization and editing handles in Editor.
- </member>
<member name="global_transform" type="Transform3D" setter="set_global_transform" getter="get_global_transform">
World3D space (global) [Transform3D] of this node.
</member>
@@ -308,7 +335,7 @@
Local space [Transform3D] of this node, with respect to the parent node.
</member>
<member name="visibility_parent" type="NodePath" setter="set_visibility_parent" getter="get_visibility_parent" default="NodePath(&quot;&quot;)">
- Defines the visibility range parent for this node and its subtree. The visibility parent must be a GeometryInstance3D. Any visual instance will only be visible if the visibility parent (and all of its visibility ancestors) is hidden by being closer to the camera than its own [member GeometryInstance3D.visibility_range_begin]. Nodes hidden via the [member Node3D.visible] property are essentially removed from the visibility dependency tree, so dependant instances will not take the hidden node or its ancestors into account.
+ Defines the visibility range parent for this node and its subtree. The visibility parent must be a GeometryInstance3D. Any visual instance will only be visible if the visibility parent (and all of its visibility ancestors) is hidden by being closer to the camera than its own [member GeometryInstance3D.visibility_range_begin]. Nodes hidden via the [member Node3D.visible] property are essentially removed from the visibility dependency tree, so dependent instances will not take the hidden node or its ancestors into account.
</member>
<member name="visible" type="bool" setter="set_visible" getter="is_visible" default="true">
If [code]true[/code], this node is drawn. The node is only visible if all of its antecedents are visible as well (in other words, [method is_visible_in_tree] must return [code]true[/code]).
@@ -324,7 +351,7 @@
<constants>
<constant name="NOTIFICATION_TRANSFORM_CHANGED" value="2000">
Node3D nodes receives this notification when their global transform changes. This means that either the current or a parent node changed its transform.
- In order for [constant NOTIFICATION_TRANSFORM_CHANGED] to work, users first need to ask for it, with [method set_notify_transform]. The notification is also sent if the node is in the editor context and it has a valid gizmo.
+ In order for [constant NOTIFICATION_TRANSFORM_CHANGED] to work, users first need to ask for it, with [method set_notify_transform]. The notification is also sent if the node is in the editor context and it has at least one valid gizmo.
</constant>
<constant name="NOTIFICATION_ENTER_WORLD" value="41">
Node3D nodes receives this notification when they are registered to new [World3D] resource.
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index a9396306f4..679a51935d 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -10,6 +10,17 @@
<link title="OS Test Demo">https://godotengine.org/asset-library/asset/677</link>
</tutorials>
<methods>
+ <method name="alert">
+ <return type="void">
+ </return>
+ <argument index="0" name="text" type="String">
+ </argument>
+ <argument index="1" name="title" type="String" default="&quot;Alert!&quot;">
+ </argument>
+ <description>
+ Displays a modal dialog box using the host OS' facilities. Execution is blocked until the dialog is closed.
+ </description>
+ </method>
<method name="can_use_threads" qualifiers="const">
<return type="bool">
</return>
@@ -54,7 +65,7 @@
<argument index="0" name="msec" type="int">
</argument>
<description>
- Delay execution of the current thread by [code]msec[/code] milliseconds. [code]usec[/code] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_msec] will do nothing and will print an error message.
+ Delay execution of the current thread by [code]msec[/code] milliseconds. [code]msec[/code] must be greater than or equal to [code]0[/code]. Otherwise, [method delay_msec] will do nothing and will print an error message.
</description>
</method>
<method name="delay_usec" qualifiers="const">
@@ -228,7 +239,7 @@
<return type="PackedStringArray">
</return>
<description>
- With this function you can get the list of dangerous permissions that have been granted to the Android application.
+ With this function, you can get the list of dangerous permissions that have been granted to the Android application.
[b]Note:[/b] This method is implemented on Android.
</description>
</method>
@@ -250,7 +261,7 @@
[code]language[/code] - 2 or 3-letter [url=https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes]language code[/url], in lower case.
[code]Script[/code] - optional, 4-letter [url=https://en.wikipedia.org/wiki/ISO_15924]script code[/url], in title case.
[code]COUNTRY[/code] - optional, 2 or 3-letter [url=https://en.wikipedia.org/wiki/ISO_3166-1]country code[/url], in upper case.
- [code]VARIANT[/code] - optional, language variant, region and sort order. Variant can have any number of underscored key words.
+ [code]VARIANT[/code] - optional, language variant, region and sort order. Variant can have any number of underscored keywords.
[code]extra[/code] - optional, semicolon separated list of additional key words. Currency, calendar, sort order and numbering system information.
</description>
</method>
@@ -321,7 +332,7 @@
</return>
<description>
Returns a string that is unique to the device.
- [b]Note:[/b] This string may change without notice if the user reinstalls/upgrades their operating system or changes their hardware. This means it should generally not be used to encrypt persistent data as the data saved prior to an unexpected ID change would become inaccessible. The returned string may also be falsified using external programs, so do not rely on the string returned by [method get_unique_id] for security purposes.
+ [b]Note:[/b] This string may change without notice if the user reinstalls/upgrades their operating system or changes their hardware. This means it should generally not be used to encrypt persistent data as the data saved before an unexpected ID change would become inaccessible. The returned string may also be falsified using external programs, so do not rely on the string returned by [method get_unique_id] for security purposes.
[b]Note:[/b] Returns an empty string on HTML5 and UWP, as this method isn't implemented on those platforms yet.
</description>
</method>
@@ -353,7 +364,7 @@
<argument index="0" name="tag_name" type="String">
</argument>
<description>
- Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on platform, build etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=https://docs.godotengine.org/en/latest/getting_started/workflow/export/feature_tags.html]Feature Tags[/url] documentation for more details.
+ Returns [code]true[/code] if the feature for the given feature tag is supported in the currently running instance, depending on the platform, build, etc. Can be used to check whether you're currently running a debug build, on a certain platform or arch, etc. Refer to the [url=https://docs.godotengine.org/en/latest/getting_started/workflow/export/feature_tags.html]Feature Tags[/url] documentation for more details.
[b]Note:[/b] Tag names are case-sensitive.
</description>
</method>
@@ -455,7 +466,7 @@
<return type="bool">
</return>
<description>
- With this function you can request dangerous permissions since normal permissions are automatically granted at install time in Android application.
+ With this function, you can request dangerous permissions since normal permissions are automatically granted at install time in Android applications.
[b]Note:[/b] This method is implemented on Android.
</description>
</method>
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index cdf76a3a59..fe7529bceb 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -400,7 +400,7 @@
<method name="get_meta" qualifiers="const">
<return type="Variant">
</return>
- <argument index="0" name="name" type="String">
+ <argument index="0" name="name" type="StringName">
</argument>
<description>
Returns the object's metadata entry for the given [code]name[/code].
@@ -454,7 +454,7 @@
<method name="has_meta" qualifiers="const">
<return type="bool">
</return>
- <argument index="0" name="name" type="String">
+ <argument index="0" name="name" type="StringName">
</argument>
<description>
Returns [code]true[/code] if a metadata entry is found with the given [code]name[/code].
@@ -543,7 +543,7 @@
<method name="remove_meta">
<return type="void">
</return>
- <argument index="0" name="name" type="String">
+ <argument index="0" name="name" type="StringName">
</argument>
<description>
Removes a given entry from the object's metadata. See also [method set_meta].
@@ -619,7 +619,7 @@
<method name="set_meta">
<return type="void">
</return>
- <argument index="0" name="name" type="String">
+ <argument index="0" name="name" type="StringName">
</argument>
<argument index="1" name="value" type="Variant">
</argument>
diff --git a/doc/classes/PackedByteArray.xml b/doc/classes/PackedByteArray.xml
index 0652cf0aa1..82bfa14ded 100644
--- a/doc/classes/PackedByteArray.xml
+++ b/doc/classes/PackedByteArray.xml
@@ -515,6 +515,42 @@
Returns the slice of the [PackedByteArray] between indices (inclusive) as a new [PackedByteArray]. Any negative index is considered to be from the end of the array.
</description>
</method>
+ <method name="to_float32_array" qualifiers="const">
+ <return type="PackedFloat32Array">
+ </return>
+ <description>
+ Returns a copy of the data converted to a [PackedFloat32Array], where each block of 4 bytes has been converted to a 32-bit float (C++ [code]float[/code]).
+ The size of the new array will be [code]byte_array.size() / 4[/code].
+ If the original data can't be converted to 32-bit floats, the resulting data is undefined.
+ </description>
+ </method>
+ <method name="to_float64_array" qualifiers="const">
+ <return type="PackedFloat64Array">
+ </return>
+ <description>
+ Returns a copy of the data converted to a [PackedFloat64Array], where each block of 8 bytes has been converted to a 64-bit float (C++ [code]double[/code], Godot [float]).
+ The size of the new array will be [code]byte_array.size() / 8[/code].
+ If the original data can't be converted to 64-bit floats, the resulting data is undefined.
+ </description>
+ </method>
+ <method name="to_int32_array" qualifiers="const">
+ <return type="PackedInt32Array">
+ </return>
+ <description>
+ Returns a copy of the data converted to a [PackedInt32Array], where each block of 4 bytes has been converted to a signed 32-bit integer (C++ [code]int32_t[/code]).
+ The size of the new array will be [code]byte_array.size() / 4[/code].
+ If the original data can't be converted to signed 32-bit integers, the resulting data is undefined.
+ </description>
+ </method>
+ <method name="to_int64_array" qualifiers="const">
+ <return type="PackedInt64Array">
+ </return>
+ <description>
+ Returns a copy of the data converted to a [PackedInt64Array], where each block of 4 bytes has been converted to a signed 64-bit integer (C++ [code]int64_t[/code], Godot [int]).
+ The size of the new array will be [code]byte_array.size() / 8[/code].
+ If the original data can't be converted to signed 64-bit integers, the resulting data is undefined.
+ </description>
+ </method>
</methods>
<constants>
</constants>
diff --git a/doc/classes/PackedFloat32Array.xml b/doc/classes/PackedFloat32Array.xml
index ab97c9a695..663aeeb21d 100644
--- a/doc/classes/PackedFloat32Array.xml
+++ b/doc/classes/PackedFloat32Array.xml
@@ -201,6 +201,8 @@
<return type="PackedByteArray">
</return>
<description>
+ Returns a copy of the data converted to a [PackedByteArray], where each element have been encoded as 4 bytes.
+ The size of the new array will be [code]float32_array.size() * 4[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/PackedFloat64Array.xml b/doc/classes/PackedFloat64Array.xml
index ad20801b01..bf2200f5bb 100644
--- a/doc/classes/PackedFloat64Array.xml
+++ b/doc/classes/PackedFloat64Array.xml
@@ -201,6 +201,8 @@
<return type="PackedByteArray">
</return>
<description>
+ Returns a copy of the data converted to a [PackedByteArray], where each element have been encoded as 8 bytes.
+ The size of the new array will be [code]float64_array.size() * 8[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/PackedInt32Array.xml b/doc/classes/PackedInt32Array.xml
index ff4729082e..c587126d50 100644
--- a/doc/classes/PackedInt32Array.xml
+++ b/doc/classes/PackedInt32Array.xml
@@ -201,6 +201,8 @@
<return type="PackedByteArray">
</return>
<description>
+ Returns a copy of the data converted to a [PackedByteArray], where each element have been encoded as 4 bytes.
+ The size of the new array will be [code]int32_array.size() * 4[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/PackedInt64Array.xml b/doc/classes/PackedInt64Array.xml
index 195b12b129..a9ebc80601 100644
--- a/doc/classes/PackedInt64Array.xml
+++ b/doc/classes/PackedInt64Array.xml
@@ -201,6 +201,8 @@
<return type="PackedByteArray">
</return>
<description>
+ Returns a copy of the data converted to a [PackedByteArray], where each element have been encoded as 8 bytes.
+ The size of the new array will be [code]int64_array.size() * 8[/code].
</description>
</method>
</methods>
diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticlesMaterial.xml
index 52430b3f45..640a26b8cb 100644
--- a/doc/classes/ParticlesMaterial.xml
+++ b/doc/classes/ParticlesMaterial.xml
@@ -174,6 +174,18 @@
<member name="emission_point_texture" type="Texture2D" setter="set_emission_point_texture" getter="get_emission_point_texture">
Particles will be emitted at positions determined by sampling this texture at a random position. Used with [constant EMISSION_SHAPE_POINTS] and [constant EMISSION_SHAPE_DIRECTED_POINTS]. Can be created automatically from mesh or node by selecting "Create Emission Points from Mesh/Node" under the "Particles" tool in the toolbar.
</member>
+ <member name="emission_ring_axis" type="Vector3" setter="set_emission_ring_axis" getter="get_emission_ring_axis">
+ The axis of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
+ <member name="emission_ring_height" type="float" setter="set_emission_ring_height" getter="get_emission_ring_height">
+ The height of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
+ <member name="emission_ring_inner_radius" type="float" setter="set_emission_ring_inner_radius" getter="get_emission_ring_inner_radius">
+ The inner radius of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
+ <member name="emission_ring_radius" type="float" setter="set_emission_ring_radius" getter="get_emission_ring_radius">
+ The radius of the ring when using the emitter [constant EMISSION_SHAPE_RING].
+ </member>
<member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticlesMaterial.EmissionShape" default="0">
Particles will be emitted inside this region. Use [enum EmissionShape] constants for values.
</member>
@@ -338,7 +350,10 @@
<constant name="EMISSION_SHAPE_DIRECTED_POINTS" value="4" enum="EmissionShape">
Particles will be emitted at a position determined by sampling a random point on the [member emission_point_texture]. Particle velocity and rotation will be set based on [member emission_normal_texture]. Particle color will be modulated by [member emission_color_texture].
</constant>
- <constant name="EMISSION_SHAPE_MAX" value="5" enum="EmissionShape">
+ <constant name="EMISSION_SHAPE_RING" value="5" enum="EmissionShape">
+ Particles will be emitted in a ring or cylinder.
+ </constant>
+ <constant name="EMISSION_SHAPE_MAX" value="6" enum="EmissionShape">
Represents the size of the [enum EmissionShape] enum.
</constant>
<constant name="SUB_EMITTER_DISABLED" value="0" enum="SubEmitterMode">
diff --git a/doc/classes/RDShaderFile.xml b/doc/classes/RDShaderFile.xml
index 346a97a1c0..dab2b9822f 100644
--- a/doc/classes/RDShaderFile.xml
+++ b/doc/classes/RDShaderFile.xml
@@ -7,8 +7,8 @@
<tutorials>
</tutorials>
<methods>
- <method name="get_bytecode" qualifiers="const">
- <return type="RDShaderBytecode">
+ <method name="get_spirv" qualifiers="const">
+ <return type="RDShaderSPIRV">
</return>
<argument index="0" name="version" type="StringName" default="&amp;&quot;&quot;">
</argument>
@@ -24,7 +24,7 @@
<method name="set_bytecode">
<return type="void">
</return>
- <argument index="0" name="bytecode" type="RDShaderBytecode">
+ <argument index="0" name="bytecode" type="RDShaderSPIRV">
</argument>
<argument index="1" name="version" type="StringName" default="&amp;&quot;&quot;">
</argument>
diff --git a/doc/classes/RDShaderBytecode.xml b/doc/classes/RDShaderSPIRV.xml
index 20bf9bdd72..c9aefe31dc 100644
--- a/doc/classes/RDShaderBytecode.xml
+++ b/doc/classes/RDShaderSPIRV.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="RDShaderBytecode" inherits="Resource" version="4.0">
+<class name="RDShaderSPIRV" inherits="Resource" version="4.0">
<brief_description>
</brief_description>
<description>
diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml
index 901a985961..c73c2ddfd7 100644
--- a/doc/classes/RenderingDevice.xml
+++ b/doc/classes/RenderingDevice.xml
@@ -635,8 +635,16 @@
<description>
</description>
</method>
- <method name="shader_compile_from_source">
- <return type="RDShaderBytecode">
+ <method name="shader_compile_binary_from_spirv">
+ <return type="PackedByteArray">
+ </return>
+ <argument index="0" name="spirv_data" type="RDShaderSPIRV">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="shader_compile_spirv_from_source">
+ <return type="RDShaderSPIRV">
</return>
<argument index="0" name="shader_source" type="RDShaderSource">
</argument>
@@ -645,10 +653,18 @@
<description>
</description>
</method>
- <method name="shader_create">
+ <method name="shader_create_from_bytecode">
<return type="RID">
</return>
- <argument index="0" name="shader_data" type="RDShaderBytecode">
+ <argument index="0" name="binary_data" type="PackedByteArray">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="shader_create_from_spirv">
+ <return type="PackedByteArray">
+ </return>
+ <argument index="0" name="spirv_data" type="RDShaderSPIRV">
</argument>
<description>
</description>
diff --git a/doc/classes/ResourceImporter.xml b/doc/classes/ResourceImporter.xml
index 59900b1b73..03d47ee518 100644
--- a/doc/classes/ResourceImporter.xml
+++ b/doc/classes/ResourceImporter.xml
@@ -1,13 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ResourceImporter" inherits="RefCounted" version="4.0">
<brief_description>
+ Base class for the implementation of core resource importers.
</brief_description>
<description>
+ This is the base class for the resource importers implemented in core. To implement your own resource importers using editor plugins, see [EditorImportPlugin].
</description>
<tutorials>
+ <link title="Import plugins">https://docs.godotengine.org/en/latest/tutorials/plugins/editor/import_plugins.html</link>
</tutorials>
<methods>
</methods>
<constants>
+ <constant name="IMPORT_ORDER_DEFAULT" value="0" enum="ImportOrder">
+ The default import order.
+ </constant>
+ <constant name="IMPORT_ORDER_SCENE" value="100" enum="ImportOrder">
+ The import order for scenes, which ensures scenes are imported [i]after[/i] all other core resources such as textures. Custom importers should generally have an import order lower than [code]100[/code] to avoid issues when importing scenes that rely on custom resources.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/ResourceUID.xml b/doc/classes/ResourceUID.xml
new file mode 100644
index 0000000000..9fe61d8008
--- /dev/null
+++ b/doc/classes/ResourceUID.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="ResourceUID" inherits="Object" version="4.0">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_id">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="create_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_id_path" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="has_id" qualifiers="const">
+ <return type="bool">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="id_to_text" qualifiers="const">
+ <return type="String">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="remove_id">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_id">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="int">
+ </argument>
+ <argument index="1" name="path" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="text_to_id" qualifiers="const">
+ <return type="int">
+ </return>
+ <argument index="0" name="text_id" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ <constant name="INVALID_ID" value="-1">
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/RootMotionView.xml b/doc/classes/RootMotionView.xml
index be8d8d0078..e31ea9265e 100644
--- a/doc/classes/RootMotionView.xml
+++ b/doc/classes/RootMotionView.xml
@@ -1,23 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RootMotionView" inherits="VisualInstance3D" version="4.0">
<brief_description>
+ Editor-only helper for setting up root motion in [AnimationTree].
</brief_description>
<description>
+ [i]Root motion[/i] refers to an animation technique where a mesh's skeleton is used to give impulse to a character. When working with 3D animations, a popular technique is for animators to use the root skeleton bone to give motion to the rest of the skeleton. This allows animating characters in a way where steps actually match the floor below. It also allows precise interaction with objects during cinematics. See also [AnimationTree].
+ [b]Note:[/b] [RootMotionView] is only visible in the editor. It will be hidden automatically in the running project, and will also be converted to a plain [Node] in the running project. This means a script attached to a [RootMotionView] node [i]must[/i] have [code]extends Node[/code] instead of [code]extends RootMotionView[/code]. Additionally, it must not be a [code]@tool[/code] script.
</description>
<tutorials>
+ <link title="Using AnimationTree - Root motion">https://docs.godotengine.org/en/latest/tutorials/animation/animation_tree.html#root-motion</link>
</tutorials>
<methods>
</methods>
<members>
<member name="animation_path" type="NodePath" setter="set_animation_path" getter="get_animation_path">
+ Path to an [AnimationTree] node to use as a basis for root motion.
</member>
<member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size">
+ The grid's cell size in 3D units.
</member>
<member name="color" type="Color" setter="set_color" getter="get_color">
+ The grid's color.
</member>
<member name="radius" type="float" setter="set_radius" getter="get_radius">
+ The grid's radius in 3D units. The grid's opacity will fade gradually as the distance from the origin increases until this [member radius] is reached.
</member>
<member name="zero_y" type="bool" setter="set_zero_y" getter="get_zero_y">
+ If [code]true[/code], the grid's points will all be on the same Y coordinate ([i]local[/i] Y = 0). If [code]false[/code], the points' original Y coordinate is preserved.
</member>
</members>
<constants>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index bf51b4dfa7..9930665d26 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -132,7 +132,7 @@
<return type="Array">
</return>
<description>
- Returns an array of currently exising [Tween]s in the [SceneTree] (both running and paused).
+ Returns an array of currently existing [Tween]s in the [SceneTree] (both running and paused).
</description>
</method>
<method name="has_group" qualifiers="const">
diff --git a/doc/classes/Skeleton2D.xml b/doc/classes/Skeleton2D.xml
index 6665a4a9f6..1ae39dfc07 100644
--- a/doc/classes/Skeleton2D.xml
+++ b/doc/classes/Skeleton2D.xml
@@ -73,7 +73,7 @@
</argument>
<description>
Sets the local pose transform, [code]pose[/code], for the bone at [code]bone_idx[/code].
- [code]amount[/code] is the interpolation strengh that will be used when applying the pose, and [code]persistent[/code] determines if the applied pose will remain.
+ [code]amount[/code] is the interpolation strength that will be used when applying the pose, and [code]persistent[/code] determines if the applied pose will remain.
[b]Note:[/b] The pose transform needs to be a local transform relative to the [Bone2D] node at [code]bone_idx[/code]!
</description>
</method>
diff --git a/doc/classes/SkeletonModification2D.xml b/doc/classes/SkeletonModification2D.xml
index 8596dac76e..dfd0256d9b 100644
--- a/doc/classes/SkeletonModification2D.xml
+++ b/doc/classes/SkeletonModification2D.xml
@@ -14,7 +14,7 @@
<return type="void">
</return>
<description>
- Used for drawing [b]editor-only[/b] modification gizmos. This function will only be called in the Godot editor and can be overriden to draw custom gizmos.
+ Used for drawing [b]editor-only[/b] modification gizmos. This function will only be called in the Godot editor and can be overridden to draw custom gizmos.
[b]Note:[/b] You will need to use the Skeleton2D from [method SkeletonModificationStack2D.get_skeleton] and it's draw functions, as the [SkeletonModification2D] resource cannot draw on its own.
</description>
</method>
@@ -96,7 +96,7 @@
If [code]true[/code], the modification's [method _execute] function will be called by the [SkeletonModificationStack2D].
</member>
<member name="execution_mode" type="int" setter="set_execution_mode" getter="get_execution_mode" default="0">
- The execution mode for the modification. This tells the modification stack when to execute the modification. Some modifications have settings that are only availible in certain execution modes.
+ The execution mode for the modification. This tells the modification stack when to execute the modification. Some modifications have settings that are only available in certain execution modes.
</member>
</members>
<constants>
diff --git a/doc/classes/SkeletonModification2DCCDIK.xml b/doc/classes/SkeletonModification2DCCDIK.xml
index 014d366a42..1a74905df2 100644
--- a/doc/classes/SkeletonModification2DCCDIK.xml
+++ b/doc/classes/SkeletonModification2DCCDIK.xml
@@ -4,7 +4,7 @@
A modification that uses CCDIK to manipulate a series of bones to reach a target in 2D.
</brief_description>
<description>
- This [SkeletonModification2D] uses an algorithm called [b]C[/b]yclic [b]C[/b]oordinate [b]D[/b]escent [b]I[/b]nverse [b]K[/b]inematics, or CCDIK, to maniuplate a chain of bones in a [Skeleton2D] so it reaches a defined target.
+ This [SkeletonModification2D] uses an algorithm called [b]C[/b]yclic [b]C[/b]oordinate [b]D[/b]escent [b]I[/b]nverse [b]K[/b]inematics, or CCDIK, to manipulate a chain of bones in a [Skeleton2D] so it reaches a defined target.
CCDIK works by rotating a set of bones, typically called a "bone chain", on a single axis. Each bone is rotated to face the target from the tip (by default), which over a chain of bones allow it to rotate properly to reach the target. Because the bones only rotate on a single axis, CCDIK [i]can[/i] look more robotic than other IK solvers.
[b]Note:[/b] The CCDIK modifier has [code]ccdik_joints[/code], which are the data objects that hold the data for each joint in the CCDIK chain. This is different from a bone! CCDIK joints hold the data needed for each bone in the bone chain used by CCDIK.
CCDIK also fully supports angle constraints, allowing for more control over how a solution is met.
diff --git a/doc/classes/SkeletonModification2DJiggle.xml b/doc/classes/SkeletonModification2DJiggle.xml
index ae46acd0d0..da25191dc0 100644
--- a/doc/classes/SkeletonModification2DJiggle.xml
+++ b/doc/classes/SkeletonModification2DJiggle.xml
@@ -69,7 +69,7 @@
<argument index="0" name="joint_idx" type="int">
</argument>
<description>
- Returns a boolean that indiciates whether the joint at [code]joint_idx[/code] is overriding the default Jiggle joint data defined in the modification.
+ Returns a boolean that indicates whether the joint at [code]joint_idx[/code] is overriding the default Jiggle joint data defined in the modification.
</description>
</method>
<method name="get_jiggle_joint_stiffness" qualifiers="const">
@@ -87,7 +87,7 @@
<argument index="0" name="joint_idx" type="int">
</argument>
<description>
- Returns a boolean that indiciates whether the joint at [code]joint_idx[/code] is using gravity or not.
+ Returns a boolean that indicates whether the joint at [code]joint_idx[/code] is using gravity or not.
</description>
</method>
<method name="get_use_colliders" qualifiers="const">
@@ -206,19 +206,19 @@
</methods>
<members>
<member name="damping" type="float" setter="set_damping" getter="get_damping" default="0.75">
- The default amount of dampening applied to the Jiggle joints, if they are not overriden. Higher values lead to more of the calculated velocity being applied.
+ The default amount of dampening applied to the Jiggle joints, if they are not overridden. Higher values lead to more of the calculated velocity being applied.
</member>
<member name="gravity" type="Vector2" setter="set_gravity" getter="get_gravity" default="Vector2(0, 6)">
- The default amount of gravity applied to the Jiggle joints, if they are not overriden.
+ The default amount of gravity applied to the Jiggle joints, if they are not overridden.
</member>
<member name="jiggle_data_chain_length" type="int" setter="set_jiggle_data_chain_length" getter="get_jiggle_data_chain_length" default="0">
The amount of Jiggle joints in the Jiggle modification.
</member>
<member name="mass" type="float" setter="set_mass" getter="get_mass" default="0.75">
- The default amount of mass assigned to the Jiggle joints, if they are not overriden. Higher values lead to faster movements and more overshooting.
+ The default amount of mass assigned to the Jiggle joints, if they are not overridden. Higher values lead to faster movements and more overshooting.
</member>
<member name="stiffness" type="float" setter="set_stiffness" getter="get_stiffness" default="3.0">
- The default amount of stiffness assigned to the Jiggle joints, if they are not overriden. Higher values act more like springs, quickly moving into the correct position.
+ The default amount of stiffness assigned to the Jiggle joints, if they are not overridden. Higher values act more like springs, quickly moving into the correct position.
</member>
<member name="target_nodepath" type="NodePath" setter="set_target_node" getter="get_target_node" default="NodePath(&quot;&quot;)">
The NodePath to the node that is the target for the Jiggle modification. This node is what the Jiggle chain will attempt to rotate the bone chain to.
diff --git a/doc/classes/SkeletonModification2DTwoBoneIK.xml b/doc/classes/SkeletonModification2DTwoBoneIK.xml
index 554515556b..0eecfa635c 100644
--- a/doc/classes/SkeletonModification2DTwoBoneIK.xml
+++ b/doc/classes/SkeletonModification2DTwoBoneIK.xml
@@ -4,7 +4,7 @@
A modification that rotates two bones using the law of cosigns to reach the target.
</brief_description>
<description>
- This [SkeletonModification2D] uses an algorithm typically called TwoBoneIK. This algorithm works by leveraging the law of cosigns and the lengths of the bones to figure out what rotation the bones currently have, and what rotation they need to make a complete triangle, where the first bone, the second bone, and the target form the three verticies of the triangle. Because the algorithm works by making a triangle, it can only opperate on two bones.
+ This [SkeletonModification2D] uses an algorithm typically called TwoBoneIK. This algorithm works by leveraging the law of cosigns and the lengths of the bones to figure out what rotation the bones currently have, and what rotation they need to make a complete triangle, where the first bone, the second bone, and the target form the three vertices of the triangle. Because the algorithm works by making a triangle, it can only operate on two bones.
TwoBoneIK is great for arms, legs, and really any joints that can be represented by just two bones that bend to reach a target. This solver is more lightweight than [SkeletonModification2DFABRIK], but gives similar, natural looking results.
</description>
<tutorials>
diff --git a/doc/classes/SkeletonModificationStack2D.xml b/doc/classes/SkeletonModificationStack2D.xml
index 35b899fe08..4ffd2c33fb 100644
--- a/doc/classes/SkeletonModificationStack2D.xml
+++ b/doc/classes/SkeletonModificationStack2D.xml
@@ -54,7 +54,7 @@
<return type="bool">
</return>
<description>
- Returns a boolean that indiciates whether the modification stack is setup and can execute.
+ Returns a boolean that indicates whether the modification stack is setup and can execute.
</description>
</method>
<method name="get_modification" qualifiers="const">
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index e51bf42bdb..8d5f8f951c 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -127,7 +127,7 @@
<return type="Vector2">
</return>
<description>
- Gets the caret pixel draw poistion.
+ Gets the caret pixel draw position.
</description>
</method>
<method name="get_first_non_whitespace_column" qualifiers="const">
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index 5a4068ec86..e6f696d27c 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -36,6 +36,8 @@
</return>
<argument index="0" name="coords" type="Vector2i">
</argument>
+ <argument index="1" name="use_proxies" type="bool">
+ </argument>
<description>
</description>
</method>
@@ -44,6 +46,8 @@
</return>
<argument index="0" name="coords" type="Vector2i">
</argument>
+ <argument index="1" name="use_proxies" type="bool">
+ </argument>
<description>
</description>
</method>
@@ -52,6 +56,8 @@
</return>
<argument index="0" name="coords" type="Vector2i">
</argument>
+ <argument index="1" name="use_proxies" type="bool">
+ </argument>
<description>
</description>
</method>
diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml
index 436e15387d..8185b09a30 100644
--- a/doc/classes/TileSet.xml
+++ b/doc/classes/TileSet.xml
@@ -27,6 +27,40 @@
<description>
</description>
</method>
+ <method name="cleanup_invalid_tile_proxies">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="clear_tile_proxies">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_alternative_level_tile_proxy">
+ <return type="Array">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <argument index="2" name="alternative_from" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="get_coords_level_tile_proxy">
+ <return type="Array">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_navigation_layer_layers" qualifiers="const">
<return type="int">
</return>
@@ -103,6 +137,14 @@
<description>
</description>
</method>
+ <method name="get_source_level_tile_proxy">
+ <return type="int">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="get_terrain_color" qualifiers="const">
<return type="Color">
</return>
@@ -139,6 +181,28 @@
<description>
</description>
</method>
+ <method name="has_alternative_level_tile_proxy">
+ <return type="bool">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <argument index="2" name="alternative_from" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="has_coords_level_tile_proxy">
+ <return type="bool">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="has_source" qualifiers="const">
<return type="bool">
</return>
@@ -147,6 +211,48 @@
<description>
</description>
</method>
+ <method name="has_source_level_tile_proxy">
+ <return type="bool">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="map_tile_proxy" qualifiers="const">
+ <return type="Array">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <argument index="2" name="alternative_from" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="remove_alternative_level_tile_proxy">
+ <return type="void">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <argument index="2" name="alternative_from" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="remove_coords_level_tile_proxy">
+ <return type="void">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="remove_source">
<return type="void">
</return>
@@ -155,6 +261,46 @@
<description>
</description>
</method>
+ <method name="remove_source_level_tile_proxy">
+ <return type="void">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_alternative_level_tile_proxy">
+ <return type="void">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <argument index="2" name="alternative_from" type="int">
+ </argument>
+ <argument index="3" name="source_to" type="int">
+ </argument>
+ <argument index="4" name="coords_to" type="Vector2i">
+ </argument>
+ <argument index="5" name="alternative_to" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_coords_level_tile_proxy">
+ <return type="void">
+ </return>
+ <argument index="0" name="p_source_from" type="int">
+ </argument>
+ <argument index="1" name="coords_from" type="Vector2i">
+ </argument>
+ <argument index="2" name="source_to" type="int">
+ </argument>
+ <argument index="3" name="coords_to" type="Vector2i">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_navigation_layer_layers">
<return type="void">
</return>
@@ -225,6 +371,16 @@
<description>
</description>
</method>
+ <method name="set_source_level_tile_proxy">
+ <return type="void">
+ </return>
+ <argument index="0" name="source_from" type="int">
+ </argument>
+ <argument index="1" name="source_to" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_terrain_color">
<return type="void">
</return>
diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index 253822cf32..4efb0a3309 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -125,7 +125,7 @@
<return type="Tween">
</return>
<description>
- Makes the next [Tweener] run parallely to the previous one. Example:
+ Makes the next [Tweener] run parallelly to the previous one. Example:
[codeblock]
var tween = create_tween()
tween.tween_property(...)
@@ -175,7 +175,7 @@
<argument index="0" name="parallel" type="bool" default="true">
</argument>
<description>
- If [code]parallel[/code] is [code]true[/code], the [Tweener]s appended after this method will by default run simultanously, as opposed to sequentially.
+ If [code]parallel[/code] is [code]true[/code], the [Tweener]s appended after this method will by default run simultaneously, as opposed to sequentially.
</description>
</method>
<method name="set_pause_mode">
diff --git a/doc/classes/Tweener.xml b/doc/classes/Tweener.xml
index 5cd502ced9..a3279502e0 100644
--- a/doc/classes/Tweener.xml
+++ b/doc/classes/Tweener.xml
@@ -13,7 +13,7 @@
<signals>
<signal name="finished">
<description>
- Emited when the [Tweener] has just finished its job.
+ Emitted when the [Tweener] has just finished its job.
</description>
</signal>
</signals>
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 6ea55219bb..f07c654bd6 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -111,7 +111,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
}
}
- if (is_backup_save_enabled() && (p_mode_flags & WRITE) && !(p_mode_flags & READ)) {
+ if (is_backup_save_enabled() && (p_mode_flags == WRITE)) {
save_path = path;
path = path + ".tmp";
}
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index efeaf32ff7..e01c6a0e0f 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -269,11 +269,11 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, Str
break; // IPv6 uses index.
}
- for (List<IPAddress>::Element *F = c.ip_addresses.front(); F; F = F->next()) {
- if (!F->get().is_ipv4()) {
+ for (const IPAddress &F : c.ip_addresses) {
+ if (!F.is_ipv4()) {
continue; // Wrong IP type
}
- if_ip = F->get();
+ if_ip = F;
break;
}
break;
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index a5c61bbea5..f6a3e93b55 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -139,10 +139,6 @@ void OS_Unix::finalize_core() {
NetSocketPosix::cleanup();
}
-void OS_Unix::alert(const String &p_alert, const String &p_title) {
- fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data());
-}
-
String OS_Unix::get_stdin_string(bool p_block) {
if (p_block) {
char buff[1024];
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 6c79d984e9..bf82019d38 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -52,7 +52,6 @@ protected:
public:
OS_Unix();
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual String get_stdin_string(bool p_block) override;
//virtual void set_mouse_show(bool p_show);
diff --git a/drivers/vulkan/SCsub b/drivers/vulkan/SCsub
index 14b9d63204..6a2a57d18c 100644
--- a/drivers/vulkan/SCsub
+++ b/drivers/vulkan/SCsub
@@ -105,7 +105,7 @@ elif env["builtin_vulkan"]:
else: # Always build VMA.
thirdparty_dir = "#thirdparty/vulkan"
- env.Prepend(CPPPATH=[thirdparty_dir])
+ env.Prepend(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"])
# Build Vulkan loader library
env_thirdparty = env.Clone()
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 5bf3bbf8a4..9ee2a28240 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -31,11 +31,14 @@
#include "rendering_device_vulkan.h"
#include "core/config/project_settings.h"
+#include "core/io/compression.h"
#include "core/io/file_access.h"
+#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/templates/hashfuncs.h"
#include "drivers/vulkan/vulkan_context.h"
+#include "thirdparty/misc/smolv.h"
#include "thirdparty/spirv-reflect/spirv_reflect.h"
//#define FORCE_FULL_BARRIER
@@ -4360,53 +4363,87 @@ bool RenderingDeviceVulkan::_uniform_add_binding(Vector<Vector<VkDescriptorSetLa
}
#endif
-RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages) {
- //descriptor layouts
- Vector<Vector<VkDescriptorSetLayoutBinding>> set_bindings;
- Vector<Vector<UniformInfo>> uniform_info;
- Shader::PushConstant push_constant;
- push_constant.push_constant_size = 0;
- push_constant.push_constants_vk_stage = 0;
+#define SHADER_BINARY_VERSION 1
- uint32_t vertex_input_mask = 0;
+String RenderingDeviceVulkan::shader_get_binary_cache_key() const {
+ return "Vulkan-SV" + itos(SHADER_BINARY_VERSION);
+}
- uint32_t fragment_outputs = 0;
+struct RenderingDeviceVulkanShaderBinaryDataBinding {
+ uint32_t type;
+ uint32_t binding;
+ uint32_t stages;
+ uint32_t length; //size of arrays (in total elements), or ubos (in bytes * total elements)
+};
- uint32_t stages_processed = 0;
+struct RenderingDeviceVulkanShaderBinarySpecializationConstant {
+ uint32_t type;
+ uint32_t constant_id;
+ union {
+ uint32_t int_value;
+ float float_value;
+ bool bool_value;
+ };
+ uint32_t stage_flags;
+};
- Vector<Shader::SpecializationConstant> specialization_constants;
+struct RenderingDeviceVulkanShaderBinaryData {
+ uint32_t vertex_input_mask;
+ uint32_t fragment_outputs;
+ uint32_t specialization_constant_count;
+ uint32_t is_compute;
+ uint32_t compute_local_size[3];
+ uint32_t set_count;
+ uint32_t push_constant_size;
+ uint32_t push_constants_vk_stage;
+ uint32_t stage_count;
+};
- bool is_compute = false;
+Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv) {
+ RenderingDeviceVulkanShaderBinaryData binary_data;
+ binary_data.vertex_input_mask = 0;
+ binary_data.fragment_outputs = 0;
+ binary_data.specialization_constant_count = 0;
+ binary_data.is_compute = 0;
+ binary_data.compute_local_size[0] = 0;
+ binary_data.compute_local_size[1] = 0;
+ binary_data.compute_local_size[2] = 0;
+ binary_data.set_count = 0;
+ binary_data.push_constant_size = 0;
+ binary_data.push_constants_vk_stage = 0;
+
+ Vector<Vector<RenderingDeviceVulkanShaderBinaryDataBinding>> uniform_info; //set bindings
+ Vector<RenderingDeviceVulkanShaderBinarySpecializationConstant> specialization_constants;
- uint32_t compute_local_size[3] = { 0, 0, 0 };
+ uint32_t stages_processed = 0;
- for (int i = 0; i < p_stages.size(); i++) {
- if (p_stages[i].shader_stage == SHADER_STAGE_COMPUTE) {
- is_compute = true;
- ERR_FAIL_COND_V_MSG(p_stages.size() != 1, RID(),
+ for (int i = 0; i < p_spirv.size(); i++) {
+ if (p_spirv[i].shader_stage == SHADER_STAGE_COMPUTE) {
+ binary_data.is_compute = true;
+ ERR_FAIL_COND_V_MSG(p_spirv.size() != 1, Vector<uint8_t>(),
"Compute shaders can only receive one stage, dedicated to compute.");
}
- ERR_FAIL_COND_V_MSG(stages_processed & (1 << p_stages[i].shader_stage), RID(),
- "Stage " + String(shader_stage_names[p_stages[i].shader_stage]) + " submitted more than once.");
+ ERR_FAIL_COND_V_MSG(stages_processed & (1 << p_spirv[i].shader_stage), Vector<uint8_t>(),
+ "Stage " + String(shader_stage_names[p_spirv[i].shader_stage]) + " submitted more than once.");
{
SpvReflectShaderModule module;
- const uint8_t *spirv = p_stages[i].spir_v.ptr();
- SpvReflectResult result = spvReflectCreateShaderModule(p_stages[i].spir_v.size(), spirv, &module);
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed parsing shader.");
-
- if (is_compute) {
- compute_local_size[0] = module.entry_points->local_size.x;
- compute_local_size[1] = module.entry_points->local_size.y;
- compute_local_size[2] = module.entry_points->local_size.z;
+ const uint8_t *spirv = p_spirv[i].spir_v.ptr();
+ SpvReflectResult result = spvReflectCreateShaderModule(p_spirv[i].spir_v.size(), spirv, &module);
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed parsing shader.");
+
+ if (binary_data.is_compute) {
+ binary_data.compute_local_size[0] = module.entry_points->local_size.x;
+ binary_data.compute_local_size[1] = module.entry_points->local_size.y;
+ binary_data.compute_local_size[2] = module.entry_points->local_size.z;
}
uint32_t binding_count = 0;
result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, nullptr);
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating descriptor bindings.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating descriptor bindings.");
- uint32_t stage = p_stages[i].shader_stage;
+ uint32_t stage = p_spirv[i].shader_stage;
if (binding_count > 0) {
//Parse bindings
@@ -4415,56 +4452,47 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
bindings.resize(binding_count);
result = spvReflectEnumerateDescriptorBindings(&module, &binding_count, bindings.ptrw());
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed getting descriptor bindings.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed getting descriptor bindings.");
for (uint32_t j = 0; j < binding_count; j++) {
const SpvReflectDescriptorBinding &binding = *bindings[j];
- VkDescriptorSetLayoutBinding layout_binding;
- UniformInfo info;
+ RenderingDeviceVulkanShaderBinaryDataBinding info;
bool need_array_dimensions = false;
bool need_block_size = false;
switch (binding.descriptor_type) {
case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
info.type = UNIFORM_TYPE_SAMPLER;
need_array_dimensions = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
info.type = UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
need_array_dimensions = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
info.type = UNIFORM_TYPE_TEXTURE;
need_array_dimensions = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
info.type = UNIFORM_TYPE_IMAGE;
need_array_dimensions = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
info.type = UNIFORM_TYPE_TEXTURE_BUFFER;
need_array_dimensions = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
info.type = UNIFORM_TYPE_IMAGE_BUFFER;
need_array_dimensions = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
info.type = UNIFORM_TYPE_UNIFORM_BUFFER;
need_block_size = true;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
info.type = UNIFORM_TYPE_STORAGE_BUFFER;
need_block_size = true;
} break;
@@ -4477,7 +4505,6 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
continue;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
- layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
info.type = UNIFORM_TYPE_INPUT_ATTACHMENT;
} break;
case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: {
@@ -4499,42 +4526,35 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
}
}
- layout_binding.descriptorCount = info.length;
-
} else if (need_block_size) {
info.length = binding.block.size;
- layout_binding.descriptorCount = 1;
} else {
info.length = 0;
- layout_binding.descriptorCount = 1;
}
info.binding = binding.binding;
uint32_t set = binding.set;
- //print_line("Stage: " + String(shader_stage_names[stage]) + " set=" + itos(set) + " binding=" + itos(info.binding) + " type=" + shader_uniform_names[info.type] + " length=" + itos(info.length));
-
- ERR_FAIL_COND_V_MSG(set >= MAX_UNIFORM_SETS, RID(),
+ ERR_FAIL_COND_V_MSG(set >= MAX_UNIFORM_SETS, Vector<uint8_t>(),
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported (" + itos(MAX_UNIFORM_SETS) + ").");
- ERR_FAIL_COND_V_MSG(set >= limits.maxBoundDescriptorSets, RID(),
+ ERR_FAIL_COND_V_MSG(set >= limits.maxBoundDescriptorSets, Vector<uint8_t>(),
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' uses a set (" + itos(set) + ") index larger than what is supported by the hardware (" + itos(limits.maxBoundDescriptorSets) + ").");
- if (set < (uint32_t)set_bindings.size()) {
+ if (set < (uint32_t)uniform_info.size()) {
//check if this already exists
bool exists = false;
- for (int k = 0; k < set_bindings[set].size(); k++) {
- if (set_bindings[set][k].binding == (uint32_t)info.binding) {
+ for (int k = 0; k < uniform_info[set].size(); k++) {
+ if (uniform_info[set][k].binding == (uint32_t)info.binding) {
//already exists, verify that it's the same type
- ERR_FAIL_COND_V_MSG(set_bindings[set][k].descriptorType != layout_binding.descriptorType, RID(),
+ ERR_FAIL_COND_V_MSG(uniform_info[set][k].type != info.type, Vector<uint8_t>(),
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform type.");
//also, verify that it's the same size
- ERR_FAIL_COND_V_MSG(set_bindings[set][k].descriptorCount != layout_binding.descriptorCount || uniform_info[set][k].length != info.length, RID(),
+ ERR_FAIL_COND_V_MSG(uniform_info[set][k].length != info.length, Vector<uint8_t>(),
"On shader stage '" + String(shader_stage_names[stage]) + "', uniform '" + binding.name + "' trying to re-use location for set=" + itos(set) + ", binding=" + itos(info.binding) + " with different uniform size.");
//just append stage mask and return
- set_bindings.write[set].write[k].stageFlags |= shader_stage_masks[stage];
uniform_info.write[set].write[k].stages |= 1 << stage;
exists = true;
}
@@ -4545,19 +4565,12 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
}
}
- layout_binding.binding = info.binding;
- layout_binding.stageFlags = shader_stage_masks[stage];
- layout_binding.pImmutableSamplers = nullptr; //no support for this yet
-
info.stages = 1 << stage;
- info.binding = info.binding;
- if (set >= (uint32_t)set_bindings.size()) {
- set_bindings.resize(set + 1);
+ if (set >= (uint32_t)uniform_info.size()) {
uniform_info.resize(set + 1);
}
- set_bindings.write[set].push_back(layout_binding);
uniform_info.write[set].push_back(info);
}
}
@@ -4567,41 +4580,41 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
uint32_t sc_count = 0;
result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, nullptr);
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating specialization constants.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating specialization constants.");
if (sc_count) {
Vector<SpvReflectSpecializationConstant *> spec_constants;
spec_constants.resize(sc_count);
result = spvReflectEnumerateSpecializationConstants(&module, &sc_count, spec_constants.ptrw());
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed obtaining specialization constants.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining specialization constants.");
for (uint32_t j = 0; j < sc_count; j++) {
int32_t existing = -1;
- Shader::SpecializationConstant sconst;
- sconst.constant.constant_id = spec_constants[j]->constant_id;
+ RenderingDeviceVulkanShaderBinarySpecializationConstant sconst;
+ sconst.constant_id = spec_constants[j]->constant_id;
switch (spec_constants[j]->constant_type) {
case SPV_REFLECT_SPECIALIZATION_CONSTANT_BOOL: {
- sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
- sconst.constant.bool_value = spec_constants[j]->default_value.int_bool_value != 0;
+ sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sconst.bool_value = spec_constants[j]->default_value.int_bool_value != 0;
} break;
case SPV_REFLECT_SPECIALIZATION_CONSTANT_INT: {
- sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
- sconst.constant.int_value = spec_constants[j]->default_value.int_bool_value;
+ sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
+ sconst.int_value = spec_constants[j]->default_value.int_bool_value;
} break;
case SPV_REFLECT_SPECIALIZATION_CONSTANT_FLOAT: {
- sconst.constant.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
- sconst.constant.float_value = spec_constants[j]->default_value.float_value;
+ sconst.type = PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
+ sconst.float_value = spec_constants[j]->default_value.float_value;
} break;
}
- sconst.stage_flags = 1 << p_stages[i].shader_stage;
+ sconst.stage_flags = 1 << p_spirv[i].shader_stage;
for (int k = 0; k < specialization_constants.size(); k++) {
- if (specialization_constants[k].constant.constant_id == sconst.constant.constant_id) {
- ERR_FAIL_COND_V_MSG(specialization_constants[k].constant.type != sconst.constant.type, RID(), "More than one specialization constant used for id (" + itos(sconst.constant.constant_id) + "), but their types differ.");
- ERR_FAIL_COND_V_MSG(specialization_constants[k].constant.int_value != sconst.constant.int_value, RID(), "More than one specialization constant used for id (" + itos(sconst.constant.constant_id) + "), but their default values differ.");
+ if (specialization_constants[k].constant_id == sconst.constant_id) {
+ ERR_FAIL_COND_V_MSG(specialization_constants[k].type != sconst.type, Vector<uint8_t>(), "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their types differ.");
+ ERR_FAIL_COND_V_MSG(specialization_constants[k].int_value != sconst.int_value, Vector<uint8_t>(), "More than one specialization constant used for id (" + itos(sconst.constant_id) + "), but their default values differ.");
existing = k;
break;
}
@@ -4619,20 +4632,20 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
if (stage == SHADER_STAGE_VERTEX) {
uint32_t iv_count = 0;
result = spvReflectEnumerateInputVariables(&module, &iv_count, nullptr);
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating input variables.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating input variables.");
if (iv_count) {
Vector<SpvReflectInterfaceVariable *> input_vars;
input_vars.resize(iv_count);
result = spvReflectEnumerateInputVariables(&module, &iv_count, input_vars.ptrw());
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed obtaining input variables.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining input variables.");
for (uint32_t j = 0; j < iv_count; j++) {
if (input_vars[j] && input_vars[j]->decoration_flags == 0) { //regular input
- vertex_input_mask |= (1 << uint32_t(input_vars[j]->location));
+ binary_data.vertex_input_mask |= (1 << uint32_t(input_vars[j]->location));
}
}
}
@@ -4641,21 +4654,21 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
if (stage == SHADER_STAGE_FRAGMENT) {
uint32_t ov_count = 0;
result = spvReflectEnumerateOutputVariables(&module, &ov_count, nullptr);
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating output variables.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating output variables.");
if (ov_count) {
Vector<SpvReflectInterfaceVariable *> output_vars;
output_vars.resize(ov_count);
result = spvReflectEnumerateOutputVariables(&module, &ov_count, output_vars.ptrw());
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed obtaining output variables.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining output variables.");
for (uint32_t j = 0; j < ov_count; j++) {
const SpvReflectInterfaceVariable *refvar = output_vars[j];
if (refvar != nullptr && refvar->built_in != SpvBuiltInFragDepth) {
- fragment_outputs |= 1 << refvar->location;
+ binary_data.fragment_outputs |= 1 << refvar->location;
}
}
}
@@ -4663,18 +4676,18 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
uint32_t pc_count = 0;
result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, nullptr);
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed enumerating push constants.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed enumerating push constants.");
if (pc_count) {
- ERR_FAIL_COND_V_MSG(pc_count > 1, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "': Only one push constant is supported, which should be the same across shader stages.");
+ ERR_FAIL_COND_V_MSG(pc_count > 1, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Only one push constant is supported, which should be the same across shader stages.");
Vector<SpvReflectBlockVariable *> pconstants;
pconstants.resize(pc_count);
result = spvReflectEnumeratePushConstantBlocks(&module, &pc_count, pconstants.ptrw());
- ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "' failed obtaining push constants.");
+ ERR_FAIL_COND_V_MSG(result != SPV_REFLECT_RESULT_SUCCESS, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining push constants.");
#if 0
if (pconstants[0] == nullptr) {
FileAccess *f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
@@ -4683,11 +4696,11 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
}
#endif
- ERR_FAIL_COND_V_MSG(push_constant.push_constant_size && push_constant.push_constant_size != pconstants[0]->size, RID(),
- "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_stages[i].shader_stage]) + "': Push constant block must be the same across shader stages.");
+ ERR_FAIL_COND_V_MSG(binary_data.push_constant_size && binary_data.push_constant_size != pconstants[0]->size, Vector<uint8_t>(),
+ "Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "': Push constant block must be the same across shader stages.");
- push_constant.push_constant_size = pconstants[0]->size;
- push_constant.push_constants_vk_stage |= shader_stage_masks[stage];
+ binary_data.push_constant_size = pconstants[0]->size;
+ binary_data.push_constants_vk_stage |= shader_stage_masks[stage];
//print_line("Stage: " + String(shader_stage_names[stage]) + " push constant of size=" + itos(push_constant.push_constant_size));
}
@@ -4696,9 +4709,291 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
spvReflectDestroyShaderModule(&module);
}
- stages_processed |= (1 << p_stages[i].shader_stage);
+ stages_processed |= (1 << p_spirv[i].shader_stage);
+ }
+
+ Vector<Vector<uint8_t>> compressed_stages;
+ Vector<uint32_t> smolv_size;
+ Vector<uint32_t> zstd_size; //if 0, stdno t used
+
+ uint32_t stages_binary_size = 0;
+
+ bool strip_debug = false;
+
+ for (int i = 0; i < p_spirv.size(); i++) {
+ smolv::ByteArray smolv;
+ if (!smolv::Encode(p_spirv[i].spir_v.ptr(), p_spirv[i].spir_v.size(), smolv, strip_debug ? smolv::kEncodeFlagStripDebugInfo : 0)) {
+ ERR_FAIL_V_MSG(Vector<uint8_t>(), "Error compressing shader stage :" + String(shader_stage_names[p_spirv[i].shader_stage]));
+ } else {
+ smolv_size.push_back(smolv.size());
+ { //zstd
+ Vector<uint8_t> zstd;
+ zstd.resize(Compression::get_max_compressed_buffer_size(smolv.size(), Compression::MODE_ZSTD));
+ int dst_size = Compression::compress(zstd.ptrw(), &smolv[0], smolv.size(), Compression::MODE_ZSTD);
+
+ if (dst_size > 0 && (uint32_t)dst_size < smolv.size()) {
+ zstd_size.push_back(dst_size);
+ zstd.resize(dst_size);
+ compressed_stages.push_back(zstd);
+ } else {
+ Vector<uint8_t> smv;
+ smv.resize(smolv.size());
+ memcpy(smv.ptrw(), &smolv[0], smolv.size());
+ zstd_size.push_back(0); //not using zstd
+ compressed_stages.push_back(smv);
+ }
+ }
+ }
+ uint32_t s = compressed_stages[i].size();
+ if (s % 4 != 0) {
+ s += 4 - (s % 4);
+ }
+ stages_binary_size += s;
+ }
+
+ binary_data.specialization_constant_count = specialization_constants.size();
+ binary_data.set_count = uniform_info.size();
+ binary_data.stage_count = p_spirv.size();
+
+ uint32_t total_size = sizeof(uint32_t) * 3; //header + version + main datasize;
+ total_size += sizeof(RenderingDeviceVulkanShaderBinaryData);
+
+ for (int i = 0; i < uniform_info.size(); i++) {
+ total_size += sizeof(uint32_t);
+ total_size += uniform_info[i].size() * sizeof(RenderingDeviceVulkanShaderBinaryDataBinding);
+ }
+
+ total_size += sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant) * specialization_constants.size();
+
+ total_size += compressed_stages.size() * sizeof(uint32_t) * 3; //sizes
+ total_size += stages_binary_size;
+
+ Vector<uint8_t> ret;
+ ret.resize(total_size);
+ uint32_t offset = 0;
+ {
+ uint8_t *binptr = ret.ptrw();
+ binptr[0] = 'G';
+ binptr[1] = 'V';
+ binptr[2] = 'B';
+ binptr[3] = 'D'; //godot vulkan binary data
+ offset += 4;
+ encode_uint32(SHADER_BINARY_VERSION, binptr + offset);
+ offset += sizeof(uint32_t);
+ encode_uint32(sizeof(RenderingDeviceVulkanShaderBinaryData), binptr + offset);
+ offset += sizeof(uint32_t);
+ memcpy(binptr + offset, &binary_data, sizeof(RenderingDeviceVulkanShaderBinaryData));
+ offset += sizeof(RenderingDeviceVulkanShaderBinaryData);
+
+ for (int i = 0; i < uniform_info.size(); i++) {
+ int count = uniform_info[i].size();
+ encode_uint32(count, binptr + offset);
+ offset += sizeof(uint32_t);
+ if (count > 0) {
+ memcpy(binptr + offset, uniform_info[i].ptr(), sizeof(RenderingDeviceVulkanShaderBinaryDataBinding) * count);
+ offset += sizeof(RenderingDeviceVulkanShaderBinaryDataBinding) * count;
+ }
+ }
+
+ if (specialization_constants.size()) {
+ memcpy(binptr + offset, specialization_constants.ptr(), sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant) * specialization_constants.size());
+ offset += sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant) * specialization_constants.size();
+ }
+
+ for (int i = 0; i < compressed_stages.size(); i++) {
+ encode_uint32(p_spirv[i].shader_stage, binptr + offset);
+ offset += sizeof(uint32_t);
+ encode_uint32(smolv_size[i], binptr + offset);
+ offset += sizeof(uint32_t);
+ encode_uint32(zstd_size[i], binptr + offset);
+ offset += sizeof(uint32_t);
+ memcpy(binptr + offset, compressed_stages[i].ptr(), compressed_stages[i].size());
+
+ uint32_t s = compressed_stages[i].size();
+
+ if (s % 4 != 0) {
+ s += 4 - (s % 4);
+ }
+
+ offset += s;
+ }
+
+ ERR_FAIL_COND_V(offset != (uint32_t)ret.size(), Vector<uint8_t>());
}
+ return ret;
+}
+
+RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary) {
+ const uint8_t *binptr = p_shader_binary.ptr();
+ uint32_t binsize = p_shader_binary.size();
+
+ uint32_t read_offset = 0;
+ //consistency check
+ ERR_FAIL_COND_V(binsize < sizeof(uint32_t) * 3 + sizeof(RenderingDeviceVulkanShaderBinaryData), RID());
+ ERR_FAIL_COND_V(binptr[0] != 'G' || binptr[1] != 'V' || binptr[2] != 'B' || binptr[3] != 'D', RID());
+
+ uint32_t bin_version = decode_uint32(binptr + 4);
+ ERR_FAIL_COND_V(bin_version > SHADER_BINARY_VERSION, RID());
+
+ uint32_t bin_data_size = decode_uint32(binptr + 8);
+
+ const RenderingDeviceVulkanShaderBinaryData &binary_data = *(const RenderingDeviceVulkanShaderBinaryData *)(binptr + 12);
+
+ Shader::PushConstant push_constant;
+ push_constant.push_constant_size = binary_data.push_constant_size;
+ push_constant.push_constants_vk_stage = binary_data.push_constants_vk_stage;
+
+ uint32_t vertex_input_mask = binary_data.vertex_input_mask;
+
+ uint32_t fragment_outputs = binary_data.fragment_outputs;
+
+ bool is_compute = binary_data.is_compute;
+
+ uint32_t compute_local_size[3] = { binary_data.compute_local_size[0], binary_data.compute_local_size[1], binary_data.compute_local_size[2] };
+
+ read_offset += sizeof(uint32_t) * 3 + bin_data_size;
+
+ Vector<Vector<VkDescriptorSetLayoutBinding>> set_bindings;
+ Vector<Vector<UniformInfo>> uniform_info;
+
+ set_bindings.resize(binary_data.set_count);
+ uniform_info.resize(binary_data.set_count);
+
+ for (uint32_t i = 0; i < binary_data.set_count; i++) {
+ ERR_FAIL_COND_V(read_offset + sizeof(uint32_t) >= binsize, RID());
+ uint32_t set_count = decode_uint32(binptr + read_offset);
+ read_offset += sizeof(uint32_t);
+ const RenderingDeviceVulkanShaderBinaryDataBinding *set_ptr = (const RenderingDeviceVulkanShaderBinaryDataBinding *)(binptr + read_offset);
+ uint32_t set_size = set_count * sizeof(RenderingDeviceVulkanShaderBinaryDataBinding);
+ ERR_FAIL_COND_V(read_offset + set_size >= binsize, RID());
+
+ for (uint32_t j = 0; j < set_count; j++) {
+ UniformInfo info;
+ info.type = UniformType(set_ptr[j].type);
+ info.length = set_ptr[j].length;
+ info.binding = set_ptr[j].binding;
+ info.stages = set_ptr[j].stages;
+
+ VkDescriptorSetLayoutBinding layout_binding;
+ layout_binding.pImmutableSamplers = nullptr;
+ layout_binding.binding = set_ptr[j].binding;
+ layout_binding.descriptorCount = 1;
+ layout_binding.stageFlags = 0;
+ for (uint32_t k = 0; k < SHADER_STAGE_MAX; k++) {
+ if (set_ptr[j].stages & (1 << k)) {
+ layout_binding.stageFlags |= shader_stage_masks[k];
+ }
+ }
+
+ switch (info.type) {
+ case UNIFORM_TYPE_SAMPLER: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+ layout_binding.descriptorCount = set_ptr[j].length;
+ } break;
+ case UNIFORM_TYPE_SAMPLER_WITH_TEXTURE: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ layout_binding.descriptorCount = set_ptr[j].length;
+ } break;
+ case UNIFORM_TYPE_TEXTURE: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ layout_binding.descriptorCount = set_ptr[j].length;
+ } break;
+ case UNIFORM_TYPE_IMAGE: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ layout_binding.descriptorCount = set_ptr[j].length;
+ } break;
+ case UNIFORM_TYPE_TEXTURE_BUFFER: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ layout_binding.descriptorCount = set_ptr[j].length;
+ } break;
+ case UNIFORM_TYPE_IMAGE_BUFFER: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ } break;
+ case UNIFORM_TYPE_UNIFORM_BUFFER: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ } break;
+ case UNIFORM_TYPE_STORAGE_BUFFER: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ } break;
+ case UNIFORM_TYPE_INPUT_ATTACHMENT: {
+ layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+ } break;
+ default: {
+ ERR_FAIL_V(RID());
+ }
+ }
+
+ set_bindings.write[i].push_back(layout_binding);
+ uniform_info.write[i].push_back(info);
+ }
+
+ read_offset += set_size;
+ }
+
+ ERR_FAIL_COND_V(read_offset + binary_data.specialization_constant_count * sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant) >= binsize, RID());
+
+ Vector<Shader::SpecializationConstant> specialization_constants;
+
+ for (uint32_t i = 0; i < binary_data.specialization_constant_count; i++) {
+ const RenderingDeviceVulkanShaderBinarySpecializationConstant &src_sc = *(const RenderingDeviceVulkanShaderBinarySpecializationConstant *)(binptr + read_offset);
+ Shader::SpecializationConstant sc;
+ sc.constant.int_value = src_sc.int_value;
+ sc.constant.type = PipelineSpecializationConstantType(src_sc.type);
+ sc.constant.constant_id = src_sc.constant_id;
+ sc.stage_flags = src_sc.stage_flags;
+ specialization_constants.push_back(sc);
+
+ read_offset += sizeof(RenderingDeviceVulkanShaderBinarySpecializationConstant);
+ }
+
+ Vector<Vector<uint8_t>> stage_spirv_data;
+ Vector<ShaderStage> stage_type;
+
+ for (uint32_t i = 0; i < binary_data.stage_count; i++) {
+ ERR_FAIL_COND_V(read_offset + sizeof(uint32_t) * 3 >= binsize, RID());
+ uint32_t stage = decode_uint32(binptr + read_offset);
+ read_offset += sizeof(uint32_t);
+ uint32_t smolv_size = decode_uint32(binptr + read_offset);
+ read_offset += sizeof(uint32_t);
+ uint32_t zstd_size = decode_uint32(binptr + read_offset);
+ read_offset += sizeof(uint32_t);
+
+ uint32_t buf_size = (zstd_size > 0) ? zstd_size : smolv_size;
+
+ Vector<uint8_t> smolv;
+ const uint8_t *src_smolv = nullptr;
+
+ if (zstd_size > 0) {
+ //decompress to smolv
+ smolv.resize(smolv_size);
+ int dec_smolv_size = Compression::decompress(smolv.ptrw(), smolv.size(), binptr + read_offset, zstd_size, Compression::MODE_ZSTD);
+ ERR_FAIL_COND_V(dec_smolv_size != (int32_t)smolv_size, RID());
+ src_smolv = smolv.ptr();
+ } else {
+ src_smolv = binptr + read_offset;
+ }
+
+ Vector<uint8_t> spirv;
+ uint32_t spirv_size = smolv::GetDecodedBufferSize(src_smolv, smolv_size);
+ spirv.resize(spirv_size);
+ if (!smolv::Decode(src_smolv, smolv_size, spirv.ptrw(), spirv_size)) {
+ ERR_FAIL_V_MSG(RID(), "Malformed smolv input uncompressing shader stage:" + String(shader_stage_names[stage]));
+ }
+ stage_spirv_data.push_back(spirv);
+ stage_type.push_back(ShaderStage(stage));
+
+ if (buf_size % 4 != 0) {
+ buf_size += 4 - (buf_size % 4);
+ }
+
+ ERR_FAIL_COND_V(read_offset + buf_size > binsize, RID());
+
+ read_offset += buf_size;
+ }
+
+ ERR_FAIL_COND_V(read_offset != binsize, RID());
+
//all good, let's create modules
_THREAD_SAFE_METHOD_
@@ -4717,13 +5012,13 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
String error_text;
bool success = true;
- for (int i = 0; i < p_stages.size(); i++) {
+ for (int i = 0; i < stage_spirv_data.size(); i++) {
VkShaderModuleCreateInfo shader_module_create_info;
shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shader_module_create_info.pNext = nullptr;
shader_module_create_info.flags = 0;
- shader_module_create_info.codeSize = p_stages[i].spir_v.size();
- const uint8_t *r = p_stages[i].spir_v.ptr();
+ shader_module_create_info.codeSize = stage_spirv_data[i].size();
+ const uint8_t *r = stage_spirv_data[i].ptr();
shader_module_create_info.pCode = (const uint32_t *)r;
@@ -4731,7 +5026,7 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
VkResult res = vkCreateShaderModule(device, &shader_module_create_info, nullptr, &module);
if (res) {
success = false;
- error_text = "Error (" + itos(res) + ") creating shader module for stage: " + String(shader_stage_names[p_stages[i].shader_stage]);
+ error_text = "Error (" + itos(res) + ") creating shader module for stage: " + String(shader_stage_names[stage_type[i]]);
break;
}
@@ -4747,7 +5042,7 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
shader_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shader_stage.pNext = nullptr;
shader_stage.flags = 0;
- shader_stage.stage = shader_stage_bits[p_stages[i].shader_stage];
+ shader_stage.stage = shader_stage_bits[stage_type[i]];
shader_stage.module = module;
shader_stage.pName = "main";
shader_stage.pSpecializationInfo = nullptr;
@@ -6037,7 +6332,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
specialization_info.resize(pipeline_stages.size());
specialization_map_entries.resize(pipeline_stages.size());
for (int i = 0; i < shader->specialization_constants.size(); i++) {
- //see if overriden
+ //see if overridden
const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
@@ -6181,7 +6476,7 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
specialization_constant_data.resize(shader->specialization_constants.size());
uint32_t *data_ptr = specialization_constant_data.ptrw();
for (int i = 0; i < shader->specialization_constants.size(); i++) {
- //see if overriden
+ //see if overridden
const Shader::SpecializationConstant &sc = shader->specialization_constants[i];
data_ptr[i] = sc.constant.int_value; //just copy the 32 bits
@@ -8542,8 +8837,8 @@ void RenderingDeviceVulkan::_free_rids(T &p_owner, const char *p_type) {
} else {
WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type));
}
- for (List<RID>::Element *E = owned.front(); E; E = E->next()) {
- free(E->get());
+ for (const RID &E : owned) {
+ free(E);
}
}
}
@@ -8764,13 +9059,13 @@ void RenderingDeviceVulkan::finalize() {
List<RID>::Element *N = E->next();
if (texture_is_shared(E->get())) {
free(E->get());
- owned.erase(E->get());
+ owned.erase(E);
}
E = N;
}
//free non shared second, this will avoid an error trying to free unexisting textures due to dependencies.
- for (List<RID>::Element *E = owned.front(); E; E = E->next()) {
- free(E->get());
+ for (const RID &E : owned) {
+ free(E);
}
}
}
diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h
index 8b95ff43b8..f9ff61310a 100644
--- a/drivers/vulkan/rendering_device_vulkan.h
+++ b/drivers/vulkan/rendering_device_vulkan.h
@@ -652,8 +652,8 @@ class RenderingDeviceVulkan : public RenderingDevice {
// Basically, you can mix and match pools as you
// like, but you'll run into fragmentation issues.
// Because of this, the recommended approach is to
- // create a a pool for every descriptor set type,
- // as this prevents fragmentation.
+ // create a pool for every descriptor set type, as
+ // this prevents fragmentation.
//
// This is implemented here as a having a list of
// pools (each can contain up to 64 sets) for each
@@ -1083,7 +1083,11 @@ public:
/**** SHADER ****/
/****************/
- virtual RID shader_create(const Vector<ShaderStageData> &p_stages);
+ virtual String shader_get_binary_cache_key() const;
+ virtual Vector<uint8_t> shader_compile_binary_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv);
+
+ virtual RID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary);
+
virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader);
/*****************/
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index d6deda7b5d..f504bad60d 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -108,7 +108,7 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
}
#endif
- if (is_backup_save_enabled() && p_mode_flags & WRITE && !(p_mode_flags & READ)) {
+ if (is_backup_save_enabled() && p_mode_flags == WRITE) {
save_path = path;
path = path + ".tmp";
}
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 05db9045bd..1e3140e202 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -898,8 +898,7 @@ void AnimationBezierTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
}
// 6-(undo) reinsert overlapped keys
- for (List<AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) {
- AnimMoveRestore &amr = E->get();
+ for (const AnimMoveRestore &amr : to_restore) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, 1);
}
@@ -1091,9 +1090,9 @@ void AnimationBezierTrackEdit::duplicate_selection() {
//reselect duplicated
selection.clear();
- for (List<Pair<int, float>>::Element *E = new_selection_values.front(); E; E = E->next()) {
- int track = E->get().first;
- float time = E->get().second;
+ for (const Pair<int, float> &E : new_selection_values) {
+ int track = E.first;
+ float time = E.second;
int existing_idx = animation->track_find_key(track, time, true);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 174f19280a..91835c1866 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -598,12 +598,12 @@ public:
if (ap) {
List<StringName> anims;
ap->get_animation_list(&anims);
- for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
+ for (const StringName &E : anims) {
if (animations != String()) {
animations += ",";
}
- animations += String(E->get());
+ animations += String(E);
}
}
}
@@ -702,8 +702,8 @@ public:
for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) {
int key = 0;
- for (List<float>::Element *F = E->value().front(); F; F = F->next()) {
- float key_ofs = F->get();
+ for (float &F : E->value()) {
+ float key_ofs = F;
if (from != key_ofs) {
key++;
continue;
@@ -728,8 +728,8 @@ public:
bool change_notify_deserved = false;
for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) {
int track = E->key();
- for (List<float>::Element *F = E->value().front(); F; F = F->next()) {
- float key_ofs = F->get();
+ for (float &F : E->value()) {
+ float key_ofs = F;
int key = animation->track_find_key(track, key_ofs, true);
ERR_FAIL_COND_V(key == -1, false);
@@ -986,8 +986,8 @@ public:
bool _get(const StringName &p_name, Variant &r_ret) const {
for (Map<int, List<float>>::Element *E = key_ofs_map.front(); E; E = E->next()) {
int track = E->key();
- for (List<float>::Element *F = E->value().front(); F; F = F->next()) {
- float key_ofs = F->get();
+ for (float &F : E->value()) {
+ float key_ofs = F;
int key = animation->track_find_key(track, key_ofs, true);
ERR_CONTINUE(key == -1);
@@ -1137,8 +1137,8 @@ public:
same_key_type = false;
}
- for (List<float>::Element *F = E->value().front(); F; F = F->next()) {
- int key = animation->track_find_key(track, F->get(), true);
+ for (float &F : E->value()) {
+ int key = animation->track_find_key(track, F, true);
ERR_FAIL_COND(key == -1);
if (first_key < 0) {
first_key = key;
@@ -3356,9 +3356,9 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
}
insert_frame = Engine::get_singleton()->get_frames_drawn();
- for (List<InsertData>::Element *E = insert_data.front(); E; E = E->next()) {
+ for (const InsertData &E : insert_data) {
//prevent insertion of multiple tracks
- if (E->get().path == p_id.path) {
+ if (E.path == p_id.path) {
return; //already inserted a track for this on this frame
}
}
@@ -3843,9 +3843,9 @@ PropertyInfo AnimationTrackEditor::_find_hint_for_track(int p_idx, NodePath &r_b
List<PropertyInfo> pinfo;
property_info_base.get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().name == leftover_path[leftover_path.size() - 1]) {
- return E->get();
+ for (const PropertyInfo &E : pinfo) {
+ if (E.name == leftover_path[leftover_path.size() - 1]) {
+ return E;
}
}
@@ -4675,21 +4675,21 @@ void AnimationTrackEditor::_add_method_key(const String &p_method) {
List<MethodInfo> minfo;
base->get_method_list(&minfo);
- for (List<MethodInfo>::Element *E = minfo.front(); E; E = E->next()) {
- if (E->get().name == p_method) {
+ for (const MethodInfo &E : minfo) {
+ if (E.name == p_method) {
Dictionary d;
d["method"] = p_method;
Array params;
- int first_defarg = E->get().arguments.size() - E->get().default_arguments.size();
+ int first_defarg = E.arguments.size() - E.default_arguments.size();
- for (int i = 0; i < E->get().arguments.size(); i++) {
+ for (int i = 0; i < E.arguments.size(); i++) {
if (i >= first_defarg) {
- Variant arg = E->get().default_arguments[i - first_defarg];
+ Variant arg = E.default_arguments[i - first_defarg];
params.push_back(arg);
} else {
Callable::CallError ce;
Variant arg;
- Variant::construct(E->get().arguments[i].type, arg, nullptr, 0, ce);
+ Variant::construct(E.arguments[i].type, arg, nullptr, 0, ce);
params.push_back(arg);
}
}
@@ -4936,8 +4936,7 @@ void AnimationTrackEditor::_move_selection_commit() {
}
// 6 - (undo) reinsert overlapped keys
- for (List<_AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) {
- _AnimMoveRestore &amr = E->get();
+ for (_AnimMoveRestore &amr : to_restore) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
}
@@ -5151,9 +5150,9 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
//reselect duplicated
Map<SelectedKey, KeyInfo> new_selection;
- for (List<Pair<int, float>>::Element *E = new_selection_values.front(); E; E = E->next()) {
- int track = E->get().first;
- float time = E->get().second;
+ for (const Pair<int, float> &E : new_selection_values) {
+ int track = E.first;
+ float time = E.second;
int existing_idx = animation->track_find_key(track, time, true);
@@ -5462,8 +5461,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
}
// 6-(undo) reinsert overlapped keys
- for (List<_AnimMoveRestore>::Element *E = to_restore.front(); E; E = E->next()) {
- _AnimMoveRestore &amr = E->get();
+ for (_AnimMoveRestore &amr : to_restore) {
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
}
@@ -5543,8 +5541,8 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
if (cleanup_all->is_pressed()) {
List<StringName> names;
AnimationPlayerEditor::singleton->get_player()->get_animation_list(&names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- _cleanup_animation(AnimationPlayerEditor::singleton->get_player()->get_animation(E->get()));
+ for (const StringName &E : names) {
+ _cleanup_animation(AnimationPlayerEditor::singleton->get_player()->get_animation(E));
}
} else {
_cleanup_animation(animation);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index b0ec346afe..03695419cb 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -854,9 +854,7 @@ void CodeTextEditor::_complete_request() {
return;
}
- for (List<ScriptCodeCompletionOption>::Element *E = entries.front(); E; E = E->next()) {
- ScriptCodeCompletionOption &e = E->get();
-
+ for (const ScriptCodeCompletionOption &e : entries) {
Color font_color = completion_font_color;
if (e.insert_text.begins_with("\"") || e.insert_text.begins_with("\'")) {
font_color = completion_string_color;
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index c439d6a1d4..c773f51342 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -944,9 +944,7 @@ void ConnectionsDock::update_tree() {
node_signals2.sort();
}
- for (List<MethodInfo>::Element *E = node_signals2.front(); E; E = E->next()) {
- MethodInfo &mi = E->get();
-
+ for (MethodInfo &mi : node_signals2) {
StringName signal_name = mi.name;
String signaldesc = "(";
PackedStringArray argnames;
@@ -1025,8 +1023,8 @@ void ConnectionsDock::update_tree() {
List<Object::Connection> connections;
selectedNode->get_signal_connection_list(signal_name, &connections);
- for (List<Object::Connection>::Element *F = connections.front(); F; F = F->next()) {
- Connection cn = F->get();
+ for (const Object::Connection &F : connections) {
+ Connection cn = F;
if (!(cn.flags & CONNECT_PERSIST)) {
continue;
}
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index bfbd697409..3389b53317 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -447,8 +447,7 @@ Variant CreateDialog::instance_selected() {
List<PropertyInfo> pinfo;
((Object *)obj)->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- PropertyInfo pi = E->get();
+ for (const PropertyInfo &pi : pinfo) {
if (pi.type == Variant::OBJECT && pi.usage & PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT) {
Object *prop = ClassDB::instantiate(pi.class_name);
((Object *)obj)->set(pi.name, prop);
diff --git a/editor/debugger/editor_debugger_inspector.cpp b/editor/debugger/editor_debugger_inspector.cpp
index a629bf6159..a1eb71235c 100644
--- a/editor/debugger/editor_debugger_inspector.cpp
+++ b/editor/debugger/editor_debugger_inspector.cpp
@@ -56,8 +56,8 @@ bool EditorDebuggerRemoteObject::_get(const StringName &p_name, Variant &r_ret)
void EditorDebuggerRemoteObject::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->clear(); //sorry, no want category
- for (const List<PropertyInfo>::Element *E = prop_list.front(); E; E = E->next()) {
- p_list->push_back(E->get());
+ for (const PropertyInfo &E : prop_list) {
+ p_list->push_back(E);
}
}
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index 6b015e1fda..fa9c9f61f5 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -588,8 +588,8 @@ EditorProfiler::EditorProfiler() {
hb->add_child(memnew(Label(TTR("Measure:"))));
display_mode = memnew(OptionButton);
- display_mode->add_item(TTR("Frame Time (sec)"));
- display_mode->add_item(TTR("Average Time (sec)"));
+ display_mode->add_item(TTR("Frame Time (ms)"));
+ display_mode->add_item(TTR("Average Time (ms)"));
display_mode->add_item(TTR("Frame %"));
display_mode->add_item(TTR("Physics Frame %"));
display_mode->connect("item_selected", callable_mp(this, &EditorProfiler::_combo_changed));
@@ -601,6 +601,7 @@ EditorProfiler::EditorProfiler() {
display_time = memnew(OptionButton);
display_time->add_item(TTR("Inclusive"));
display_time->add_item(TTR("Self"));
+ display_time->set_tooltip(TTR("Inclusive: Includes time from other functions called by this function.\nUse this to spot bottlenecks.\n\nSelf: Only count the time spent in the function itself, not in other functions called by that function.\nUse this to find individual functions to optimize."));
display_time->connect("item_selected", callable_mp(this, &EditorProfiler::_combo_changed));
hb->add_child(display_time);
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index a61e9bd73e..f17ad0d36c 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -365,13 +365,13 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) {
}
TreeItem *category = variables->create_item(parent);
- for (List<TreeItem *>::Element *E = stack.front(); E; E = E->next()) {
- float total_cpu = E->get()->get_metadata(1);
- float total_gpu = E->get()->get_metadata(2);
+ for (TreeItem *E : stack) {
+ float total_cpu = E->get_metadata(1);
+ float total_gpu = E->get_metadata(2);
total_cpu += cpu_time;
total_gpu += gpu_time;
- E->get()->set_metadata(1, cpu_time);
- E->get()->set_metadata(2, gpu_time);
+ E->set_metadata(1, cpu_time);
+ E->set_metadata(2, gpu_time);
}
category->set_icon(0, track_icon);
@@ -392,11 +392,11 @@ void EditorVisualProfiler::_update_frame(bool p_focus_selected) {
}
}
- for (List<TreeItem *>::Element *E = categories.front(); E; E = E->next()) {
- float total_cpu = E->get()->get_metadata(1);
- float total_gpu = E->get()->get_metadata(2);
- E->get()->set_text(1, _get_time_as_text(total_cpu));
- E->get()->set_text(2, _get_time_as_text(total_gpu));
+ for (TreeItem *E : categories) {
+ float total_cpu = E->get_metadata(1);
+ float total_gpu = E->get_metadata(2);
+ E->set_text(1, _get_time_as_text(total_cpu));
+ E->set_text(2, _get_time_as_text(total_gpu));
}
if (ensure_selected) {
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 06b02cceb4..9856fbec74 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -347,13 +347,13 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
uint64_t total = 0;
- for (List<DebuggerMarshalls::ResourceInfo>::Element *E = usage.infos.front(); E; E = E->next()) {
+ for (const DebuggerMarshalls::ResourceInfo &E : usage.infos) {
TreeItem *it = vmem_tree->create_item(root);
- String type = E->get().type;
- int bytes = E->get().vram;
- it->set_text(0, E->get().path);
+ String type = E.type;
+ int bytes = E.vram;
+ it->set_text(0, E.path);
it->set_text(1, type);
- it->set_text(2, E->get().format);
+ it->set_text(2, E.format);
it->set_text(3, String::humanize_size(bytes));
total += bytes;
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index c18b8743cd..069ae2c7f2 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -55,8 +55,8 @@ void DependencyEditor::_load_pressed(Object *p_item, int p_cell, int p_button) {
search->clear_filters();
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type(ti->get_metadata(0), &ext);
- for (List<String>::Element *E = ext.front(); E; E = E->next()) {
- search->add_filter("*" + E->get());
+ for (const String &E : ext) {
+ search->add_filter("*" + E);
}
search->popup_file_dialog();
}
@@ -120,13 +120,13 @@ void DependencyEditor::_fix_all() {
Map<String, Map<String, String>> candidates;
- for (List<String>::Element *E = missing.front(); E; E = E->next()) {
- String base = E->get().get_file();
+ for (const String &E : missing) {
+ String base = E.get_file();
if (!candidates.has(base)) {
candidates[base] = Map<String, String>();
}
- candidates[base][E->get()] = "";
+ candidates[base][E] = "";
}
_fix_and_find(EditorFileSystem::get_singleton()->get_filesystem(), candidates);
@@ -166,10 +166,8 @@ void DependencyEditor::_update_list() {
bool broken = false;
- for (List<String>::Element *E = deps.front(); E; E = E->next()) {
+ for (const String &n : deps) {
TreeItem *item = tree->create_item(root);
-
- String n = E->get();
String path;
String type;
@@ -180,6 +178,15 @@ void DependencyEditor::_update_list() {
path = n;
type = "Resource";
}
+
+ ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(path);
+ if (uid != ResourceUID::INVALID_ID) {
+ // dependency is in uid format, obtain proper path
+ ERR_CONTINUE(!ResourceUID::get_singleton()->has_id(uid));
+
+ path = ResourceUID::get_singleton()->get_id_path(uid);
+ }
+
String name = path.get_file();
Ref<Texture2D> icon = EditorNode::get_singleton()->get_class_icon(type);
@@ -741,9 +748,9 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path
void OrphanResourcesDialog::_delete_confirm() {
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- for (List<String>::Element *E = paths.front(); E; E = E->next()) {
- da->remove(E->get());
- EditorFileSystem::get_singleton()->update_file(E->get());
+ for (const String &E : paths) {
+ da->remove(E);
+ EditorFileSystem::get_singleton()->update_file(E);
}
memdelete(da);
refresh();
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index befafec6cb..cbd4a1b916 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -266,20 +266,20 @@ void DocTools::generate(bool p_basic_types) {
}
List<PropertyInfo>::Element *EO = own_properties.front();
- for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ for (const PropertyInfo &E : properties) {
bool inherited = EO == nullptr;
- if (EO && EO->get() == E->get()) {
+ if (EO && EO->get() == E) {
inherited = false;
EO = EO->next();
}
- if (E->get().usage & PROPERTY_USAGE_GROUP || E->get().usage & PROPERTY_USAGE_SUBGROUP || E->get().usage & PROPERTY_USAGE_CATEGORY || E->get().usage & PROPERTY_USAGE_INTERNAL) {
+ if (E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP || E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_INTERNAL) {
continue;
}
DocData::PropertyDoc prop;
- prop.name = E->get().name;
+ prop.name = E.name;
prop.overridden = inherited;
@@ -288,20 +288,20 @@ void DocTools::generate(bool p_basic_types) {
if (name == "ProjectSettings") {
// Special case for project settings, so that settings are not taken from the current project's settings
- if (E->get().name == "script" || !ProjectSettings::get_singleton()->is_builtin_setting(E->get().name)) {
+ if (E.name == "script" || !ProjectSettings::get_singleton()->is_builtin_setting(E.name)) {
continue;
}
- if (E->get().usage & PROPERTY_USAGE_EDITOR) {
- if (!ProjectSettings::get_singleton()->get_ignore_value_in_docs(E->get().name)) {
- default_value = ProjectSettings::get_singleton()->property_get_revert(E->get().name);
+ if (E.usage & PROPERTY_USAGE_EDITOR) {
+ if (!ProjectSettings::get_singleton()->get_ignore_value_in_docs(E.name)) {
+ default_value = ProjectSettings::get_singleton()->property_get_revert(E.name);
default_value_valid = true;
}
}
} else {
- default_value = get_documentation_default_value(name, E->get().name, default_value_valid);
+ default_value = get_documentation_default_value(name, E.name, default_value_valid);
if (inherited) {
bool base_default_value_valid = false;
- Variant base_default_value = get_documentation_default_value(ClassDB::get_parent_class(name), E->get().name, base_default_value_valid);
+ Variant base_default_value = get_documentation_default_value(ClassDB::get_parent_class(name), E.name, base_default_value_valid);
if (!default_value_valid || !base_default_value_valid || default_value == base_default_value) {
continue;
}
@@ -309,13 +309,13 @@ void DocTools::generate(bool p_basic_types) {
}
//used to track uninitialized values using valgrind
- //print_line("getting default value for " + String(name) + "." + String(E->get().name));
+ //print_line("getting default value for " + String(name) + "." + String(E.name));
if (default_value_valid && default_value.get_type() != Variant::OBJECT) {
prop.default_value = default_value.get_construct_string().replace("\n", "");
}
- StringName setter = ClassDB::get_property_setter(name, E->get().name);
- StringName getter = ClassDB::get_property_getter(name, E->get().name);
+ StringName setter = ClassDB::get_property_setter(name, E.name);
+ StringName getter = ClassDB::get_property_getter(name, E.name);
prop.setter = setter;
prop.getter = getter;
@@ -353,10 +353,10 @@ void DocTools::generate(bool p_basic_types) {
}
if (!found_type) {
- if (E->get().type == Variant::OBJECT && E->get().hint == PROPERTY_HINT_RESOURCE_TYPE) {
- prop.type = E->get().hint_string;
+ if (E.type == Variant::OBJECT && E.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ prop.type = E.hint_string;
} else {
- prop.type = Variant::get_type_name(E->get().type);
+ prop.type = Variant::get_type_name(E.type);
}
}
@@ -367,62 +367,62 @@ void DocTools::generate(bool p_basic_types) {
ClassDB::get_method_list(name, &method_list, true);
method_list.sort();
- for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
- if (E->get().name == "" || (E->get().name[0] == '_' && !(E->get().flags & METHOD_FLAG_VIRTUAL))) {
+ for (const MethodInfo &E : method_list) {
+ if (E.name == "" || (E.name[0] == '_' && !(E.flags & METHOD_FLAG_VIRTUAL))) {
continue; //hidden, don't count
}
- if (skip_setter_getter_methods && setters_getters.has(E->get().name)) {
+ if (skip_setter_getter_methods && setters_getters.has(E.name)) {
// Don't skip parametric setters and getters, i.e. method which require
// one or more parameters to define what property should be set or retrieved.
// E.g. CPUParticles3D::set_param(Parameter param, float value).
- if (E->get().arguments.size() == 0 /* getter */ || (E->get().arguments.size() == 1 && E->get().return_val.type == Variant::NIL /* setter */)) {
+ if (E.arguments.size() == 0 /* getter */ || (E.arguments.size() == 1 && E.return_val.type == Variant::NIL /* setter */)) {
continue;
}
}
DocData::MethodDoc method;
- method.name = E->get().name;
+ method.name = E.name;
- if (E->get().flags & METHOD_FLAG_VIRTUAL) {
+ if (E.flags & METHOD_FLAG_VIRTUAL) {
method.qualifiers = "virtual";
}
- if (E->get().flags & METHOD_FLAG_CONST) {
+ if (E.flags & METHOD_FLAG_CONST) {
if (method.qualifiers != "") {
method.qualifiers += " ";
}
method.qualifiers += "const";
}
- if (E->get().flags & METHOD_FLAG_VARARG) {
+ if (E.flags & METHOD_FLAG_VARARG) {
if (method.qualifiers != "") {
method.qualifiers += " ";
}
method.qualifiers += "vararg";
}
- if (E->get().flags & METHOD_FLAG_STATIC) {
+ if (E.flags & METHOD_FLAG_STATIC) {
if (method.qualifiers != "") {
method.qualifiers += " ";
}
method.qualifiers += "static";
}
- for (int i = -1; i < E->get().arguments.size(); i++) {
+ for (int i = -1; i < E.arguments.size(); i++) {
if (i == -1) {
#ifdef DEBUG_METHODS_ENABLED
- DocData::return_doc_from_retinfo(method, E->get().return_val);
+ DocData::return_doc_from_retinfo(method, E.return_val);
#endif
} else {
- const PropertyInfo &arginfo = E->get().arguments[i];
+ const PropertyInfo &arginfo = E.arguments[i];
DocData::ArgumentDoc argument;
DocData::argument_doc_from_arginfo(argument, arginfo);
- int darg_idx = i - (E->get().arguments.size() - E->get().default_arguments.size());
+ int darg_idx = i - (E.arguments.size() - E.default_arguments.size());
if (darg_idx >= 0) {
- Variant default_arg = E->get().default_arguments[darg_idx];
+ Variant default_arg = E.default_arguments[darg_idx];
argument.default_value = default_arg.get_construct_string();
}
@@ -455,12 +455,12 @@ void DocTools::generate(bool p_basic_types) {
List<String> constant_list;
ClassDB::get_integer_constant_list(name, &constant_list, true);
- for (List<String>::Element *E = constant_list.front(); E; E = E->next()) {
+ for (const String &E : constant_list) {
DocData::ConstantDoc constant;
- constant.name = E->get();
- constant.value = itos(ClassDB::get_integer_constant(name, E->get()));
+ constant.name = E;
+ constant.value = itos(ClassDB::get_integer_constant(name, E));
constant.is_value_valid = true;
- constant.enumeration = ClassDB::get_integer_constant_enum(name, E->get());
+ constant.enumeration = ClassDB::get_integer_constant_enum(name, E);
c.constants.push_back(constant);
}
@@ -469,53 +469,53 @@ void DocTools::generate(bool p_basic_types) {
{
List<StringName> l;
Theme::get_default()->get_constant_list(cname, &l);
- for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
+ for (const StringName &E : l) {
DocData::PropertyDoc pd;
- pd.name = E->get();
+ pd.name = E;
pd.type = "int";
- pd.default_value = itos(Theme::get_default()->get_constant(E->get(), cname));
+ pd.default_value = itos(Theme::get_default()->get_constant(E, cname));
c.theme_properties.push_back(pd);
}
l.clear();
Theme::get_default()->get_color_list(cname, &l);
- for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
+ for (const StringName &E : l) {
DocData::PropertyDoc pd;
- pd.name = E->get();
+ pd.name = E;
pd.type = "Color";
- pd.default_value = Variant(Theme::get_default()->get_color(E->get(), cname)).get_construct_string();
+ pd.default_value = Variant(Theme::get_default()->get_color(E, cname)).get_construct_string();
c.theme_properties.push_back(pd);
}
l.clear();
Theme::get_default()->get_icon_list(cname, &l);
- for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
+ for (const StringName &E : l) {
DocData::PropertyDoc pd;
- pd.name = E->get();
+ pd.name = E;
pd.type = "Texture2D";
c.theme_properties.push_back(pd);
}
l.clear();
Theme::get_default()->get_font_list(cname, &l);
- for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
+ for (const StringName &E : l) {
DocData::PropertyDoc pd;
- pd.name = E->get();
+ pd.name = E;
pd.type = "Font";
c.theme_properties.push_back(pd);
}
l.clear();
Theme::get_default()->get_font_size_list(cname, &l);
- for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
+ for (const StringName &E : l) {
DocData::PropertyDoc pd;
- pd.name = E->get();
+ pd.name = E;
pd.type = "int";
c.theme_properties.push_back(pd);
}
l.clear();
Theme::get_default()->get_stylebox_list(cname, &l);
- for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
+ for (const StringName &E : l) {
DocData::PropertyDoc pd;
- pd.name = E->get();
+ pd.name = E;
pd.type = "StyleBox";
c.theme_properties.push_back(pd);
}
@@ -621,8 +621,7 @@ void DocTools::generate(bool p_basic_types) {
method_list.push_back(mi);
}
- for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
- MethodInfo &mi = E->get();
+ for (const MethodInfo &mi : method_list) {
DocData::MethodDoc method;
method.name = mi.name;
@@ -675,8 +674,7 @@ void DocTools::generate(bool p_basic_types) {
List<PropertyInfo> properties;
v.get_property_list(&properties);
- for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- PropertyInfo pi = E->get();
+ for (const PropertyInfo &pi : properties) {
DocData::PropertyDoc property;
property.name = pi.name;
property.type = Variant::get_type_name(pi.type);
@@ -688,10 +686,10 @@ void DocTools::generate(bool p_basic_types) {
List<StringName> constants;
Variant::get_constants_for_type(Variant::Type(i), &constants);
- for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
+ for (const StringName &E : constants) {
DocData::ConstantDoc constant;
- constant.name = E->get();
- Variant value = Variant::get_constant_value(Variant::Type(i), E->get());
+ constant.name = E;
+ Variant value = Variant::get_constant_value(Variant::Type(i), E);
constant.value = value.get_type() == Variant::INT ? itos(value) : value.get_construct_string();
constant.is_value_valid = true;
c.constants.push_back(constant);
@@ -723,9 +721,8 @@ void DocTools::generate(bool p_basic_types) {
Engine::get_singleton()->get_singletons(&singletons);
//servers (this is kind of hackish)
- for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
+ for (const Engine::Singleton &s : singletons) {
DocData::PropertyDoc pd;
- Engine::Singleton &s = E->get();
if (!s.ptr) {
continue;
}
@@ -743,13 +740,13 @@ void DocTools::generate(bool p_basic_types) {
List<StringName> utility_functions;
Variant::get_utility_function_list(&utility_functions);
utility_functions.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = utility_functions.front(); E; E = E->next()) {
+ for (const StringName &E : utility_functions) {
DocData::MethodDoc md;
- md.name = E->get();
+ md.name = E;
//return
- if (Variant::has_utility_function_return_value(E->get())) {
+ if (Variant::has_utility_function_return_value(E)) {
PropertyInfo pi;
- pi.type = Variant::get_utility_function_return_type(E->get());
+ pi.type = Variant::get_utility_function_return_type(E);
if (pi.type == Variant::NIL) {
pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
}
@@ -758,13 +755,13 @@ void DocTools::generate(bool p_basic_types) {
md.return_type = ad.type;
}
- if (Variant::is_utility_function_vararg(E->get())) {
+ if (Variant::is_utility_function_vararg(E)) {
md.qualifiers = "vararg";
} else {
- for (int i = 0; i < Variant::get_utility_function_argument_count(E->get()); i++) {
+ for (int i = 0; i < Variant::get_utility_function_argument_count(E); i++) {
PropertyInfo pi;
- pi.type = Variant::get_utility_function_argument_type(E->get(), i);
- pi.name = Variant::get_utility_function_argument_name(E->get(), i);
+ pi.type = Variant::get_utility_function_argument_type(E, i);
+ pi.name = Variant::get_utility_function_argument_name(E, i);
if (pi.type == Variant::NIL) {
pi.usage = PROPERTY_USAGE_NIL_IS_VARIANT;
}
@@ -793,8 +790,7 @@ void DocTools::generate(bool p_basic_types) {
List<MethodInfo> minfo;
lang->get_public_functions(&minfo);
- for (List<MethodInfo>::Element *E = minfo.front(); E; E = E->next()) {
- MethodInfo &mi = E->get();
+ for (const MethodInfo &mi : minfo) {
DocData::MethodDoc md;
md.name = mi.name;
@@ -813,7 +809,7 @@ void DocTools::generate(bool p_basic_types) {
int darg_idx = j - (mi.arguments.size() - mi.default_arguments.size());
if (darg_idx >= 0) {
- Variant default_arg = E->get().default_arguments[darg_idx];
+ Variant default_arg = mi.default_arguments[darg_idx];
ad.default_value = default_arg.get_construct_string();
}
@@ -827,10 +823,10 @@ void DocTools::generate(bool p_basic_types) {
List<Pair<String, Variant>> cinfo;
lang->get_public_constants(&cinfo);
- for (List<Pair<String, Variant>>::Element *E = cinfo.front(); E; E = E->next()) {
+ for (const Pair<String, Variant> &E : cinfo) {
DocData::ConstantDoc cd;
- cd.name = E->get().first;
- cd.value = E->get().second;
+ cd.name = E.first;
+ cd.value = E.second;
cd.is_value_valid = true;
c.constants.push_back(cd);
}
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index d94ac21837..4a19f007d4 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -920,15 +920,15 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
List<StringName> effects;
ClassDB::get_inheriters_from_class("AudioEffect", &effects);
effects.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = effects.front(); E; E = E->next()) {
- if (!ClassDB::can_instantiate(E->get())) {
+ for (const StringName &E : effects) {
+ if (!ClassDB::can_instantiate(E)) {
continue;
}
- Ref<Texture2D> icon = EditorNode::get_singleton()->get_class_icon(E->get());
- String name = E->get().operator String().replace("AudioEffect", "");
+ Ref<Texture2D> icon = EditorNode::get_singleton()->get_class_icon(E);
+ String name = E.operator String().replace("AudioEffect", "");
effect_options->add_item(name);
- effect_options->set_item_metadata(effect_options->get_item_count() - 1, E->get());
+ effect_options->set_item_metadata(effect_options->get_item_count() - 1, E);
effect_options->set_item_icon(effect_options->get_item_count() - 1, icon);
}
@@ -1331,8 +1331,8 @@ EditorAudioBuses::EditorAudioBuses() {
file_dialog = memnew(EditorFileDialog);
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("AudioBusLayout", &ext);
- for (List<String>::Element *E = ext.front(); E; E = E->next()) {
- file_dialog->add_filter("*." + E->get() + "; Audio Bus Layout");
+ for (const String &E : ext) {
+ file_dialog->add_filter("*." + E + "; Audio Bus Layout");
}
add_child(file_dialog);
file_dialog->connect("file_selected", callable_mp(this, &EditorAudioBuses::_file_dialog_callback));
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index c6d52107cd..fad76682b5 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -46,12 +46,11 @@ void EditorAutoloadSettings::_notification(int p_what) {
ResourceLoader::get_recognized_extensions_for_type("Script", &afn);
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &afn);
- for (List<String>::Element *E = afn.front(); E; E = E->next()) {
- file_dialog->add_filter("*." + E->get());
+ for (const String &E : afn) {
+ file_dialog->add_filter("*." + E);
}
- for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
- AutoLoadInfo &info = E->get();
+ for (const AutoLoadInfo &info : autoload_cache) {
if (info.node && info.in_editor) {
get_tree()->get_root()->call_deferred(SNAME("add_child"), info.node);
}
@@ -102,8 +101,8 @@ bool EditorAutoloadSettings::_autoload_name_is_valid(const String &p_name, Strin
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
List<String> keywords;
ScriptServer::get_language(i)->get_reserved_words(&keywords);
- for (List<String>::Element *E = keywords.front(); E; E = E->next()) {
- if (E->get() == p_name) {
+ for (const String &E : keywords) {
+ if (E == p_name) {
if (r_error) {
*r_error = TTR("Invalid name.") + "\n" + TTR("Keyword cannot be used as an autoload name.");
}
@@ -379,8 +378,7 @@ void EditorAutoloadSettings::update_autoload() {
Map<String, AutoLoadInfo> to_remove;
List<AutoLoadInfo *> to_add;
- for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
- AutoLoadInfo &info = E->get();
+ for (const AutoLoadInfo &info : autoload_cache) {
to_remove.insert(info.name, info);
}
@@ -392,9 +390,7 @@ void EditorAutoloadSettings::update_autoload() {
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- const PropertyInfo &pi = E->get();
-
+ for (const PropertyInfo &pi : props) {
if (!pi.name.begins_with("autoload/")) {
continue;
}
@@ -483,9 +479,7 @@ void EditorAutoloadSettings::update_autoload() {
// Load new/changed autoloads
List<Node *> nodes_to_add;
- for (List<AutoLoadInfo *>::Element *E = to_add.front(); E; E = E->next()) {
- AutoLoadInfo *info = E->get();
-
+ for (AutoLoadInfo *info : to_add) {
info->node = _create_autoload(info->path);
ERR_CONTINUE(!info->node);
@@ -518,8 +512,8 @@ void EditorAutoloadSettings::update_autoload() {
}
}
- for (List<Node *>::Element *E = nodes_to_add.front(); E; E = E->next()) {
- get_tree()->get_root()->add_child(E->get());
+ for (Node *E : nodes_to_add) {
+ get_tree()->get_root()->add_child(E);
}
updating_autoload = false;
@@ -649,8 +643,8 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant &
int i = 0;
- for (List<AutoLoadInfo>::Element *F = autoload_cache.front(); F; F = F->next()) {
- orders.write[i++] = F->get().order;
+ for (const AutoLoadInfo &F : autoload_cache) {
+ orders.write[i++] = F.order;
}
orders.sort();
@@ -661,9 +655,9 @@ void EditorAutoloadSettings::drop_data_fw(const Point2 &p_point, const Variant &
i = 0;
- for (List<AutoLoadInfo>::Element *F = autoload_cache.front(); F; F = F->next()) {
- undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + F->get().name, orders[i++]);
- undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + F->get().name, F->get().order);
+ for (const AutoLoadInfo &F : autoload_cache) {
+ undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + F.name, orders[i++]);
+ undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", "autoload/" + F.name, F.order);
}
orders.clear();
@@ -764,9 +758,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
// Make first cache
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- const PropertyInfo &pi = E->get();
-
+ for (const PropertyInfo &pi : props) {
if (!pi.name.begins_with("autoload/")) {
continue;
}
@@ -799,9 +791,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
autoload_cache.push_back(info);
}
- for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
- AutoLoadInfo &info = E->get();
-
+ for (AutoLoadInfo &info : autoload_cache) {
info.node = _create_autoload(info.path);
if (info.node) {
@@ -904,8 +894,7 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
}
EditorAutoloadSettings::~EditorAutoloadSettings() {
- for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) {
- AutoLoadInfo &info = E->get();
+ for (const AutoLoadInfo &info : autoload_cache) {
if (info.node && !info.in_editor) {
memdelete(info.node);
}
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 3529a4fbdc..c62e5b75b2 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -299,13 +299,13 @@ void EditorData::copy_object_params(Object *p_object) {
List<PropertyInfo> pinfo;
p_object->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_EDITOR) || E->get().name == "script" || E->get().name == "scripts") {
+ for (const PropertyInfo &E : pinfo) {
+ if (!(E.usage & PROPERTY_USAGE_EDITOR) || E.name == "script" || E.name == "scripts") {
continue;
}
PropertyData pd;
- pd.name = E->get().name;
+ pd.name = E.name;
pd.value = p_object->get(pd.name);
clipboard.push_back(pd);
}
@@ -404,9 +404,9 @@ void EditorData::restore_editor_global_states() {
void EditorData::paste_object_params(Object *p_object) {
ERR_FAIL_NULL(p_object);
undo_redo.create_action(TTR("Paste Params"));
- for (List<PropertyData>::Element *E = clipboard.front(); E; E = E->next()) {
- String name = E->get().name;
- undo_redo.add_do_property(p_object, name, E->get().value);
+ for (const PropertyData &E : clipboard) {
+ String name = E.name;
+ undo_redo.add_do_property(p_object, name, E.value);
undo_redo.add_undo_property(p_object, name, p_object->get(name));
}
undo_redo.commit_action();
@@ -616,8 +616,8 @@ bool EditorData::check_and_update_scene(int p_idx) {
//transfer selection
List<Node *> new_selection;
- for (List<Node *>::Element *E = edited_scene.write[p_idx].selection.front(); E; E = E->next()) {
- NodePath p = edited_scene[p_idx].root->get_path_to(E->get());
+ for (const Node *E : edited_scene.write[p_idx].selection) {
+ NodePath p = edited_scene[p_idx].root->get_path_to(E);
Node *new_node = new_scene->get_node(p);
if (new_node) {
new_selection.push_back(new_node);
@@ -841,8 +841,8 @@ Dictionary EditorData::restore_edited_scene_state(EditorSelection *p_selection,
p_history->history = es.history_stored;
p_selection->clear();
- for (List<Node *>::Element *E = es.selection.front(); E; E = E->next()) {
- p_selection->add_node(E->get());
+ for (Node *E : es.selection) {
+ p_selection->add_node(E);
}
set_editor_states(es.editor_states);
@@ -964,9 +964,9 @@ void EditorData::script_class_save_icon_paths() {
_script_class_icon_paths.get_key_list(&keys);
Dictionary d;
- for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
- if (ScriptServer::is_global_class(E->get())) {
- d[E->get()] = _script_class_icon_paths[E->get()];
+ for (const StringName &E : keys) {
+ if (ScriptServer::is_global_class(E)) {
+ d[E] = _script_class_icon_paths[E];
}
}
@@ -996,8 +996,8 @@ void EditorData::script_class_load_icon_paths() {
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- String name = E->get().operator String();
+ for (const Variant &E : keys) {
+ String name = E.operator String();
_script_class_icon_paths[name] = d[name];
String path = ScriptServer::get_global_class_path(name);
@@ -1038,8 +1038,8 @@ void EditorSelection::add_node(Node *p_node) {
changed = true;
nl_changed = true;
Object *meta = nullptr;
- for (List<Object *>::Element *E = editor_plugins.front(); E; E = E->next()) {
- meta = E->get()->call("_get_editor_data", p_node);
+ for (Object *E : editor_plugins) {
+ meta = E->call("_get_editor_data", p_node);
if (meta) {
break;
}
@@ -1076,8 +1076,8 @@ bool EditorSelection::is_selected(Node *p_node) const {
Array EditorSelection::_get_transformable_selected_nodes() {
Array ret;
- for (List<Node *>::Element *E = selected_node_list.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const Node *E : selected_node_list) {
+ ret.push_back(E);
}
return ret;
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index fc483b46b7..b374f56f6d 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -80,9 +80,9 @@ bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const {
}
void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (platform->get_option_visibility(E->get().name, values)) {
- p_list->push_back(E->get());
+ for (const PropertyInfo &E : properties) {
+ if (platform->get_option_visibility(E.name, values)) {
+ p_list->push_back(E);
}
}
}
@@ -436,9 +436,9 @@ Ref<EditorExportPreset> EditorExportPlatform::create_preset() {
List<ExportOption> options;
get_export_options(&options);
- for (List<ExportOption>::Element *E = options.front(); E; E = E->next()) {
- preset->properties.push_back(E->get().option);
- preset->values[E->get().option.name] = E->get().default_value;
+ for (const ExportOption &E : options) {
+ preset->properties.push_back(E.option);
+ preset->values[E.option.name] = E.default_value;
}
return preset;
@@ -679,9 +679,9 @@ EditorExportPlatform::FeatureContainers EditorExportPlatform::get_feature_contai
platform->get_preset_features(p_preset, &feature_list);
FeatureContainers result;
- for (List<String>::Element *E = feature_list.front(); E; E = E->next()) {
- result.features.insert(E->get());
- result.features_pv.push_back(E->get());
+ for (const String &E : feature_list) {
+ result.features.insert(E);
+ result.features_pv.push_back(E);
}
if (p_preset->get_custom_features() != String()) {
@@ -752,9 +752,7 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- const PropertyInfo &pi = E->get();
-
+ for (const PropertyInfo &pi : props) {
if (!pi.name.begins_with("autoload/")) {
continue;
}
@@ -899,8 +897,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
Set<String> remap_features;
- for (List<String>::Element *F = remaps.front(); F; F = F->next()) {
- String remap = F->get();
+ for (const String &F : remaps) {
+ String remap = F;
String feature = remap.get_slice(".", 1);
if (features.has(feature)) {
remap_features.insert(feature);
@@ -913,8 +911,8 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
err = OK;
- for (List<String>::Element *F = remaps.front(); F; F = F->next()) {
- String remap = F->get();
+ for (const String &F : remaps) {
+ String remap = F;
if (remap == "path") {
String remapped_path = config->get_value("remap", remap);
Vector<uint8_t> array = FileAccess::get_file_as_array(remapped_path);
@@ -1050,6 +1048,13 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
return err;
}
}
+ if (FileAccess::exists(ResourceUID::CACHE_FILE)) {
+ Vector<uint8_t> array = FileAccess::get_file_as_array(ResourceUID::CACHE_FILE);
+ err = p_func(p_udata, ResourceUID::CACHE_FILE, array, idx, total, enc_in_filters, enc_ex_filters, key);
+ if (err != OK) {
+ return err;
+ }
+ }
// Store text server data if it is supported.
if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
@@ -1362,7 +1367,7 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags
if (breakpoints.size()) {
r_flags.push_back("--breakpoints");
String bpoints;
- for (const List<String>::Element *E = breakpoints.front(); E; E = E->next()) {
+ for (List<String>::Element *E = breakpoints.front(); E; E = E->next()) {
bpoints += E->get().replace(" ", "%20");
if (E->next()) {
bpoints += ",";
@@ -1436,8 +1441,8 @@ void EditorExport::_save() {
String option_section = "preset." + itos(i) + ".options";
- for (const List<PropertyInfo>::Element *E = preset->get_properties().front(); E; E = E->next()) {
- config->set_value(option_section, E->get().name, preset->get(E->get().name));
+ for (const PropertyInfo &E : preset->get_properties()) {
+ config->set_value(option_section, E.name, preset->get(E.name));
}
}
@@ -1642,10 +1647,10 @@ void EditorExport::load_config() {
config->get_section_keys(option_section, &options);
- for (List<String>::Element *E = options.front(); E; E = E->next()) {
- Variant value = config->get_value(option_section, E->get());
+ for (const String &E : options) {
+ Variant value = config->get_value(option_section, E);
- preset->set(E->get(), value);
+ preset->set(E, value);
}
add_export_preset(preset);
@@ -1684,11 +1689,11 @@ void EditorExport::update_export_presets() {
preset->properties.clear();
preset->values.clear();
- for (List<EditorExportPlatform::ExportOption>::Element *E = options.front(); E; E = E->next()) {
- preset->properties.push_back(E->get().option);
+ for (const EditorExportPlatform::ExportOption &E : options) {
+ preset->properties.push_back(E.option);
- StringName option_name = E->get().option.name;
- preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E->get().default_value;
+ StringName option_name = E.option.name;
+ preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value;
}
}
}
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index e36cc7bc2e..22f44a54bb 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -527,9 +527,8 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S
ClassDB::get_direct_inheriters_from_class(p_class, &child_classes);
child_classes.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = child_classes.front(); E; E = E->next()) {
- String name = E->get();
- if (name.begins_with("Editor") || ClassDB::get_api_type(name) != ClassDB::API_CORE) {
+ for (const StringName &name : child_classes) {
+ if (String(name).begins_with("Editor") || ClassDB::get_api_type(name) != ClassDB::API_CORE) {
continue;
}
_fill_classes_from(class_item, name, p_selected);
@@ -597,9 +596,9 @@ void EditorFeatureProfileManager::_class_list_item_selected() {
TreeItem *properties = property_list->create_item(root);
properties->set_text(0, TTR("Class Properties:"));
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- String name = E->get().name;
- if (!(E->get().usage & PROPERTY_USAGE_EDITOR)) {
+ for (const PropertyInfo &E : props) {
+ String name = E.name;
+ if (!(E.usage & PROPERTY_USAGE_EDITOR)) {
continue;
}
TreeItem *property = property_list->create_item(properties);
@@ -609,7 +608,7 @@ void EditorFeatureProfileManager::_class_list_item_selected() {
property->set_checked(0, !edited->is_class_property_disabled(class_name, name));
property->set_text(0, name.capitalize());
property->set_metadata(0, name);
- String icon_type = Variant::get_type_name(E->get().type);
+ String icon_type = Variant::get_type_name(E.type);
property->set_icon(0, EditorNode::get_singleton()->get_class_icon(icon_type));
}
}
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index ed2edb5a5d..5ccbed1b49 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -830,8 +830,8 @@ void EditorFileDialog::update_file_list() {
while (!files.is_empty()) {
bool match = patterns.is_empty();
- for (List<String>::Element *E = patterns.front(); E; E = E->next()) {
- if (files.front()->get().matchn(E->get())) {
+ for (const String &E : patterns) {
+ if (files.front()->get().matchn(E)) {
match = true;
break;
}
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 82a71c0e0c..78861eff9d 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -43,7 +43,7 @@
EditorFileSystem *EditorFileSystem::singleton = nullptr;
//the name is the version, to keep compatibility with different versions of Godot
-#define CACHE_FILE_NAME "filesystem_cache6"
+#define CACHE_FILE_NAME "filesystem_cache7"
void EditorFileSystemDirectory::sort_files() {
files.sort_custom<FileInfoSort>();
@@ -116,7 +116,26 @@ String EditorFileSystemDirectory::get_file_path(int p_idx) const {
Vector<String> EditorFileSystemDirectory::get_file_deps(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, files.size(), Vector<String>());
- return files[p_idx]->deps;
+ Vector<String> deps;
+
+ for (int i = 0; i < files[p_idx]->deps.size(); i++) {
+ String dep = files[p_idx]->deps[i];
+ int sep_idx = dep.find("::"); //may contain type information, unwanted
+ if (sep_idx != -1) {
+ dep = dep.substr(0, sep_idx);
+ }
+ ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(dep);
+ if (uid != ResourceUID::INVALID_ID) {
+ //return proper dependency resource from uid
+ if (ResourceUID::get_singleton()->has_id(uid)) {
+ dep = ResourceUID::get_singleton()->get_id_path(uid);
+ } else {
+ continue;
+ }
+ }
+ deps.push_back(dep);
+ }
+ return deps;
}
bool EditorFileSystemDirectory::get_file_import_is_valid(int p_idx) const {
@@ -234,7 +253,7 @@ void EditorFileSystem::_scan_filesystem() {
} else {
Vector<String> split = l.split("::");
- ERR_CONTINUE(split.size() != 8);
+ ERR_CONTINUE(split.size() != 9);
String name = split[0];
String file;
@@ -243,15 +262,16 @@ void EditorFileSystem::_scan_filesystem() {
FileCache fc;
fc.type = split[1];
- fc.modification_time = split[2].to_int();
- fc.import_modification_time = split[3].to_int();
- fc.import_valid = split[4].to_int() != 0;
- fc.import_group_file = split[5].strip_edges();
- fc.script_class_name = split[6].get_slice("<>", 0);
- fc.script_class_extends = split[6].get_slice("<>", 1);
- fc.script_class_icon_path = split[6].get_slice("<>", 2);
-
- String deps = split[7].strip_edges();
+ fc.uid = split[2].to_int();
+ fc.modification_time = split[3].to_int();
+ fc.import_modification_time = split[4].to_int();
+ fc.import_valid = split[5].to_int() != 0;
+ fc.import_group_file = split[6].strip_edges();
+ fc.script_class_name = split[7].get_slice("<>", 0);
+ fc.script_class_extends = split[7].get_slice("<>", 1);
+ fc.script_class_icon_path = split[7].get_slice("<>", 2);
+
+ String deps = split[8].strip_edges();
if (deps.length()) {
Vector<String> dp = deps.split("<>");
for (int i = 0; i < dp.size(); i++) {
@@ -368,6 +388,7 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
Vector<String> dest_files;
String dest_md5 = "";
int version = 0;
+ bool found_uid = false;
while (true) {
assign = Variant();
@@ -395,6 +416,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
version = value;
} else if (assign == "importer") {
importer_name = value;
+ } else if (assign == "uid") {
+ found_uid = true;
} else if (!p_only_imported_files) {
if (assign == "source_file") {
source_file = value;
@@ -414,6 +437,10 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
return false; //keep mode, do not reimport
}
+ if (!found_uid) {
+ return true; //UUID not found, old format, reimport.
+ }
+
Ref<ResourceImporter> importer = ResourceFormatImporter::get_singleton()->get_importer_by_name(importer_name);
if (importer->get_format_version() > version) {
@@ -457,8 +484,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
memdelete(md5s);
//imported files are gone, reimport
- for (List<String>::Element *E = to_check.front(); E; E = E->next()) {
- if (!FileAccess::exists(E->get())) {
+ for (const String &E : to_check) {
+ if (!FileAccess::exists(E)) {
return true;
}
}
@@ -497,9 +524,7 @@ bool EditorFileSystem::_update_scan_actions() {
Vector<String> reimports;
Vector<String> reloads;
- for (List<ItemAction>::Element *E = scan_actions.front(); E; E = E->next()) {
- ItemAction &ia = E->get();
-
+ for (const ItemAction &ia : scan_actions) {
switch (ia.action) {
case ItemAction::ACTION_NONE: {
} break;
@@ -582,6 +607,9 @@ bool EditorFileSystem::_update_scan_actions() {
if (reimports.size()) {
reimport_files(reimports);
+ } else {
+ //reimport files will update the uid cache file so if nothing was reimported, update it manually
+ ResourceUID::get_singleton()->update_cache();
}
if (first_scan) {
@@ -756,6 +784,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
if (fc && fc->modification_time == mt && fc->import_modification_time == import_mt && !_test_for_reimport(path, true)) {
fi->type = fc->type;
+ fi->uid = fc->uid;
fi->deps = fc->deps;
fi->modified_time = fc->modification_time;
fi->import_modified_time = fc->import_modification_time;
@@ -781,8 +810,14 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
//note: I think this should not happen any longer..
}
+ if (fc->uid == ResourceUID::INVALID_ID) {
+ // imported files should always have a UUID, so attempt to fetch it.
+ fi->uid = ResourceLoader::get_resource_uid(path);
+ }
+
} else {
fi->type = ResourceFormatImporter::get_singleton()->get_resource_type(path);
+ fi->uid = ResourceFormatImporter::get_singleton()->get_resource_uid(path);
fi->import_group_file = ResourceFormatImporter::get_singleton()->get_import_group_file(path);
fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path);
fi->modified_time = 0;
@@ -799,6 +834,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
if (fc && fc->modification_time == mt) {
//not imported, so just update type if changed
fi->type = fc->type;
+ fi->uid = fc->uid;
fi->modified_time = fc->modification_time;
fi->deps = fc->deps;
fi->import_modified_time = 0;
@@ -809,6 +845,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
} else {
//new or modified time
fi->type = ResourceLoader::get_resource_type(path);
+ fi->uid = ResourceLoader::get_resource_uid(path);
fi->script_class_name = _get_global_script_class(fi->type, path, &fi->script_class_extends, &fi->script_class_icon_path);
fi->deps = _get_dependencies(path);
fi->modified_time = mt;
@@ -817,6 +854,14 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess
}
}
+ if (fi->uid != ResourceUID::INVALID_ID) {
+ if (ResourceUID::get_singleton()->has_id(fi->uid)) {
+ ResourceUID::get_singleton()->set_id(fi->uid, path);
+ } else {
+ ResourceUID::get_singleton()->add_id(fi->uid, path);
+ }
+ }
+
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
ScriptLanguage *lang = ScriptServer::get_language(i);
if (lang->supports_documentation() && fi->type == lang->get_type()) {
@@ -1027,8 +1072,8 @@ void EditorFileSystem::_delete_internal_files(String p_file) {
List<String> paths;
ResourceFormatImporter::get_singleton()->get_internal_resource_path_list(p_file, &paths);
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- for (List<String>::Element *E = paths.front(); E; E = E->next()) {
- da->remove(E->get());
+ for (const String &E : paths) {
+ da->remove(E);
}
da->remove(p_file + ".import");
memdelete(da);
@@ -1181,7 +1226,7 @@ void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir,
if (p_dir->files[i]->import_group_file != String()) {
group_file_cache.insert(p_dir->files[i]->import_group_file);
}
- String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->import_group_file + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path;
+ String s = p_dir->files[i]->file + "::" + p_dir->files[i]->type + "::" + itos(p_dir->files[i]->uid) + "::" + itos(p_dir->files[i]->modified_time) + "::" + itos(p_dir->files[i]->import_modified_time) + "::" + itos(p_dir->files[i]->import_valid) + "::" + p_dir->files[i]->import_group_file + "::" + p_dir->files[i]->script_class_name + "<>" + p_dir->files[i]->script_class_extends + "<>" + p_dir->files[i]->script_class_icon_path;
s += "::";
for (int j = 0; j < p_dir->files[i]->deps.size(); j++) {
if (j > 0) {
@@ -1368,8 +1413,8 @@ Vector<String> EditorFileSystem::_get_dependencies(const String &p_path) {
ResourceLoader::get_dependencies(p_path, &deps);
Vector<String> ret;
- for (List<String>::Element *E = deps.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const String &E : deps) {
+ ret.push_back(E);
}
return ret;
@@ -1462,6 +1507,11 @@ void EditorFileSystem::update_file(const String &p_file) {
//was removed
_delete_internal_files(p_file);
if (cpos != -1) { // Might've never been part of the editor file system (*.* files deleted in Open dialog).
+ if (fs->files[cpos]->uid != ResourceUID::INVALID_ID) {
+ if (ResourceUID::get_singleton()->has_id(fs->files[cpos]->uid)) {
+ ResourceUID::get_singleton()->remove_id(fs->files[cpos]->uid);
+ }
+ }
memdelete(fs->files[cpos]);
fs->files.remove(cpos);
}
@@ -1472,6 +1522,7 @@ void EditorFileSystem::update_file(const String &p_file) {
}
String type = ResourceLoader::get_resource_type(p_file);
+ ResourceUID::ID uid = ResourceLoader::get_resource_uid(p_file);
if (cpos == -1) {
// The file did not exist, it was added.
@@ -1504,12 +1555,22 @@ void EditorFileSystem::update_file(const String &p_file) {
}
fs->files[cpos]->type = type;
+ fs->files[cpos]->uid = uid;
fs->files[cpos]->script_class_name = _get_global_script_class(type, p_file, &fs->files[cpos]->script_class_extends, &fs->files[cpos]->script_class_icon_path);
fs->files[cpos]->import_group_file = ResourceLoader::get_import_group_file(p_file);
fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
fs->files[cpos]->deps = _get_dependencies(p_file);
fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file);
+ if (uid != ResourceUID::INVALID_ID) {
+ if (ResourceUID::get_singleton()->has_id(uid)) {
+ ResourceUID::get_singleton()->set_id(uid, p_file);
+ } else {
+ ResourceUID::get_singleton()->add_id(uid, p_file);
+ }
+
+ ResourceUID::get_singleton()->update_cache();
+ }
// Update preview
EditorResourcePreview::get_singleton()->check_for_invalidation(p_file);
@@ -1532,7 +1593,6 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
ERR_CONTINUE(file_importer_name == String());
if (importer_name != String() && importer_name != file_importer_name) {
- print_line("one importer '" + importer_name + "' the other '" + file_importer_name + "'.");
EditorNode::get_singleton()->show_warning(vformat(TTR("There are multiple importers for different types pointing to file %s, import aborted"), p_group_file));
ERR_FAIL_V(ERR_FILE_CORRUPT);
}
@@ -1549,15 +1609,14 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
List<ResourceImporter::ImportOption> options;
importer->get_import_options(&options);
//set default values
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- source_file_options[p_files[i]][E->get().option.name] = E->get().default_value;
+ for (const ResourceImporter::ImportOption &E : options) {
+ source_file_options[p_files[i]][E.option.name] = E.default_value;
}
if (config->has_section("params")) {
List<String> sk;
config->get_section_keys("params", &sk);
- for (List<String>::Element *E = sk.front(); E; E = E->next()) {
- String param = E->get();
+ for (const String &param : sk) {
Variant value = config->get_value("params", param);
//override with whathever is in file
source_file_options[p_files[i]][param] = value;
@@ -1631,9 +1690,9 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
List<ResourceImporter::ImportOption> options;
importer->get_import_options(&options);
//set default values
- for (List<ResourceImporter::ImportOption>::Element *F = options.front(); F; F = F->next()) {
- String base = F->get().option.name;
- Variant v = F->get().default_value;
+ for (const ResourceImporter::ImportOption &F : options) {
+ String base = F.option.name;
+ Variant v = F.default_value;
if (source_file_options[file].has(base)) {
v = source_file_options[file][base];
}
@@ -1702,6 +1761,8 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
params = *p_custom_options;
}
+ ResourceUID::ID uid = ResourceUID::INVALID_ID;
+
if (FileAccess::exists(p_file + ".import")) {
//use existing
if (p_custom_options == nullptr) {
@@ -1712,12 +1773,20 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
if (cf->has_section("params")) {
List<String> sk;
cf->get_section_keys("params", &sk);
- for (List<String>::Element *E = sk.front(); E; E = E->next()) {
- params[E->get()] = cf->get_value("params", E->get());
+ for (const String &E : sk) {
+ params[E] = cf->get_value("params", E);
}
}
- if (p_custom_importer == String() && cf->has_section("remap")) {
- importer_name = cf->get_value("remap", "importer");
+
+ if (cf->has_section("remap")) {
+ if (p_custom_importer == String()) {
+ importer_name = cf->get_value("remap", "importer");
+ }
+
+ if (cf->has_section_key("remap", "uid")) {
+ String uidt = cf->get_value("remap", "uid");
+ uid = ResourceUID::get_singleton()->text_to_id(uidt);
+ }
}
}
}
@@ -1754,9 +1823,9 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
List<ResourceImporter::ImportOption> opts;
importer->get_import_options(&opts);
- for (List<ResourceImporter::ImportOption>::Element *E = opts.front(); E; E = E->next()) {
- if (!params.has(E->get().option.name)) { //this one is not present
- params[E->get().option.name] = E->get().default_value;
+ for (const ResourceImporter::ImportOption &E : opts) {
+ if (!params.has(E.option.name)) { //this one is not present
+ params[E.option.name] = E.default_value;
}
}
@@ -1766,8 +1835,8 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
List<Variant> v;
d.get_key_list(&v);
- for (List<Variant>::Element *E = v.front(); E; E = E->next()) {
- params[E->get()] = d[E->get()];
+ for (const Variant &E : v) {
+ params[E] = d[E];
}
}
@@ -1800,6 +1869,12 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
f->store_line("type=\"" + importer->get_resource_type() + "\"");
}
+ if (uid == ResourceUID::INVALID_ID) {
+ uid = ResourceUID::get_singleton()->create_id();
+ }
+
+ f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
+
Vector<String> dest_paths;
if (err == OK) {
@@ -1807,10 +1882,10 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
//no path
} else if (import_variants.size()) {
//import with variants
- for (List<String>::Element *E = import_variants.front(); E; E = E->next()) {
- String path = base_path.c_escape() + "." + E->get() + "." + importer->get_save_extension();
+ for (const String &E : import_variants) {
+ String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension();
- f->store_line("path." + E->get() + "=\"" + path + "\"");
+ f->store_line("path." + E + "=\"" + path + "\"");
dest_paths.push_back(path);
}
} else {
@@ -1833,9 +1908,9 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
if (gen_files.size()) {
Array genf;
- for (List<String>::Element *E = gen_files.front(); E; E = E->next()) {
- genf.push_back(E->get());
- dest_paths.push_back(E->get());
+ for (const String &E : gen_files) {
+ genf.push_back(E);
+ dest_paths.push_back(E);
}
String value;
@@ -1859,8 +1934,8 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
//store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
- for (List<ResourceImporter::ImportOption>::Element *E = opts.front(); E; E = E->next()) {
- String base = E->get().option.name;
+ for (const ResourceImporter::ImportOption &E : opts) {
+ String base = E.option.name;
String value;
VariantWriter::write_to_string(params[base], value);
f->store_line(base + "=" + value);
@@ -1885,8 +1960,15 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
fs->files[cpos]->import_modified_time = FileAccess::get_modified_time(p_file + ".import");
fs->files[cpos]->deps = _get_dependencies(p_file);
fs->files[cpos]->type = importer->get_resource_type();
+ fs->files[cpos]->uid = uid;
fs->files[cpos]->import_valid = ResourceLoader::is_import_valid(p_file);
+ if (ResourceUID::get_singleton()->has_id(uid)) {
+ ResourceUID::get_singleton()->set_id(uid, p_file);
+ } else {
+ ResourceUID::get_singleton()->add_id(uid, p_file);
+ }
+
//if file is currently up, maybe the source it was loaded from changed, so import math must be updated for it
//to reload properly
if (ResourceCache::has(p_file)) {
@@ -1937,11 +2019,18 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
Set<String> groups_to_reimport;
for (int i = 0; i < p_files.size(); i++) {
- String group_file = ResourceFormatImporter::get_singleton()->get_import_group_file(p_files[i]);
+ String file = p_files[i];
+
+ ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(file);
+ if (uid != ResourceUID::INVALID_ID && ResourceUID::get_singleton()->has_id(uid)) {
+ file = ResourceUID::get_singleton()->get_id_path(uid);
+ }
+
+ String group_file = ResourceFormatImporter::get_singleton()->get_import_group_file(file);
- if (group_file_cache.has(p_files[i])) {
+ if (group_file_cache.has(file)) {
//maybe the file itself is a group!
- groups_to_reimport.insert(p_files[i]);
+ groups_to_reimport.insert(file);
//groups do not belong to grups
group_file = String();
} else if (group_file != String()) {
@@ -1950,15 +2039,15 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
} else {
//it's a regular file
ImportFile ifile;
- ifile.path = p_files[i];
- ResourceFormatImporter::get_singleton()->get_import_order_threads_and_importer(p_files[i], ifile.order, ifile.threaded, ifile.importer);
+ ifile.path = file;
+ ResourceFormatImporter::get_singleton()->get_import_order_threads_and_importer(file, ifile.order, ifile.threaded, ifile.importer);
reimport_files.push_back(ifile);
}
//group may have changed, so also update group reference
EditorFileSystemDirectory *fs = nullptr;
int cpos = -1;
- if (_find_file(p_files[i], &fs, cpos)) {
+ if (_find_file(file, &fs, cpos)) {
fs->files.write[cpos]->import_group_file = group_file;
}
}
@@ -2023,6 +2112,8 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
}
}
+ ResourceUID::get_singleton()->update_cache(); //after reimporting, update the cache
+
_save_filesystem_cache();
importing = false;
if (!is_scanning()) {
@@ -2080,9 +2171,8 @@ void EditorFileSystem::_move_group_files(EditorFileSystemDirectory *efd, const S
List<String> sk;
config->get_section_keys("params", &sk);
- for (List<String>::Element *E = sk.front(); E; E = E->next()) {
+ for (const String &param : sk) {
//not very clean, but should work
- String param = E->get();
String value = config->get_value("params", param);
if (value == p_group_file) {
config->set_value("params", param, p_new_location);
@@ -2108,6 +2198,30 @@ void EditorFileSystem::move_group_file(const String &p_path, const String &p_new
}
}
+ResourceUID::ID EditorFileSystem::_resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate) {
+ if (!p_path.is_resource_file() || p_path.begins_with("res://.godot")) {
+ //saved externally (configuration file) or internal file, do not assign an ID.
+ return ResourceUID::INVALID_ID;
+ }
+
+ EditorFileSystemDirectory *fs = nullptr;
+ int cpos = -1;
+
+ if (!singleton->_find_file(p_path, &fs, cpos)) {
+ if (p_generate) {
+ return ResourceUID::get_singleton()->create_id(); //just create a new one, we will be notified of save anyway and fetch the right UUID at that time, to keep things simple.
+ } else {
+ return ResourceUID::INVALID_ID;
+ }
+ } else if (fs->files[cpos]->uid != ResourceUID::INVALID_ID) {
+ return fs->files[cpos]->uid;
+ } else if (p_generate) {
+ return ResourceUID::get_singleton()->create_id(); //just create a new one, we will be notified of save anyway and fetch the right UUID at that time, to keep things simple.
+ } else {
+ return ResourceUID::INVALID_ID;
+ }
+}
+
void EditorFileSystem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_filesystem"), &EditorFileSystem::get_filesystem);
ClassDB::bind_method(D_METHOD("is_scanning"), &EditorFileSystem::is_scanning);
@@ -2131,14 +2245,14 @@ void EditorFileSystem::_update_extensions() {
List<String> extensionsl;
ResourceLoader::get_recognized_extensions_for_type("", &extensionsl);
- for (List<String>::Element *E = extensionsl.front(); E; E = E->next()) {
- valid_extensions.insert(E->get());
+ for (const String &E : extensionsl) {
+ valid_extensions.insert(E);
}
extensionsl.clear();
ResourceFormatImporter::get_singleton()->get_recognized_extensions(&extensionsl);
- for (List<String>::Element *E = extensionsl.front(); E; E = E->next()) {
- import_extensions.insert(E->get());
+ for (const String &E : extensionsl) {
+ import_extensions.insert(E);
}
}
@@ -2169,8 +2283,11 @@ EditorFileSystem::EditorFileSystem() {
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);
}
EditorFileSystem::~EditorFileSystem() {
import_threads.finish();
+ ResourceSaver::set_get_resource_id_for_path(nullptr);
}
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index 37eee13c16..9dce29d09c 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -55,6 +55,7 @@ class EditorFileSystemDirectory : public Object {
struct FileInfo {
String file;
StringName type;
+ ResourceUID::ID uid = ResourceUID::INVALID_ID;
uint64_t modified_time = 0;
uint64_t import_modified_time = 0;
bool import_valid = false;
@@ -159,6 +160,7 @@ class EditorFileSystem : public Node {
/* Used for reading the filesystem cache file */
struct FileCache {
String type;
+ ResourceUID::ID uid = ResourceUID::INVALID_ID;
uint64_t modification_time = 0;
uint64_t import_modification_time = 0;
Vector<String> deps;
@@ -251,6 +253,8 @@ class EditorFileSystem : public Node {
void _reimport_thread(uint32_t p_index, ImportThreadData *p_import_data);
+ static ResourceUID::ID _resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index 5d6c415d39..29e3236ac2 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -109,10 +109,10 @@ void EditorFolding::_fill_folds(const Node *p_root, const Node *p_node, Array &p
List<PropertyInfo> plist;
p_node->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (E->get().usage & PROPERTY_USAGE_EDITOR) {
- if (E->get().type == Variant::OBJECT) {
- RES res = p_node->get(E->get().name);
+ for (const PropertyInfo &E : plist) {
+ if (E.usage & PROPERTY_USAGE_EDITOR) {
+ if (E.type == Variant::OBJECT) {
+ RES res = p_node->get(E.name);
if (res.is_valid() && !resources.has(res) && res->get_path() != String() && !res->get_path().is_resource_file()) {
Vector<String> res_unfolds = _get_unfolds(res.ptr());
resource_folds.push_back(res->get_path());
@@ -228,41 +228,41 @@ void EditorFolding::_do_object_unfolds(Object *p_object, Set<RES> &resources) {
Set<String> unfold_group;
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (E->get().usage & PROPERTY_USAGE_CATEGORY) {
+ for (const PropertyInfo &E : plist) {
+ if (E.usage & PROPERTY_USAGE_CATEGORY) {
group = "";
group_base = "";
}
- if (E->get().usage & PROPERTY_USAGE_GROUP) {
- group = E->get().name;
- group_base = E->get().hint_string;
+ if (E.usage & PROPERTY_USAGE_GROUP) {
+ group = E.name;
+ group_base = E.hint_string;
if (group_base.ends_with("_")) {
group_base = group_base.substr(0, group_base.length() - 1);
}
}
//can unfold
- if (E->get().usage & PROPERTY_USAGE_EDITOR) {
+ if (E.usage & PROPERTY_USAGE_EDITOR) {
if (group != "") { //group
- if (group_base == String() || E->get().name.begins_with(group_base)) {
- bool can_revert = EditorPropertyRevert::can_property_revert(p_object, E->get().name);
+ if (group_base == String() || E.name.begins_with(group_base)) {
+ bool can_revert = EditorPropertyRevert::can_property_revert(p_object, E.name);
if (can_revert) {
unfold_group.insert(group);
}
}
} else { //path
- int last = E->get().name.rfind("/");
+ int last = E.name.rfind("/");
if (last != -1) {
- bool can_revert = EditorPropertyRevert::can_property_revert(p_object, E->get().name);
+ bool can_revert = EditorPropertyRevert::can_property_revert(p_object, E.name);
if (can_revert) {
- unfold_group.insert(E->get().name.substr(0, last));
+ unfold_group.insert(E.name.substr(0, last));
}
}
}
- if (E->get().type == Variant::OBJECT) {
- RES res = p_object->get(E->get().name);
- print_line("res: " + String(E->get().name) + " valid " + itos(res.is_valid()));
+ if (E.type == Variant::OBJECT) {
+ RES res = p_object->get(E.name);
+ print_line("res: " + String(E.name) + " valid " + itos(res.is_valid()));
if (res.is_valid()) {
print_line("path " + res->get_path());
}
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 9fa2007597..3db03c0276 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -1508,9 +1508,9 @@ String EditorInspector::get_selected_path() const {
}
void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped) {
- for (List<EditorInspectorPlugin::AddedEditor>::Element *F = ped->added_editors.front(); F; F = F->next()) {
- EditorProperty *ep = Object::cast_to<EditorProperty>(F->get().property_editor);
- current_vbox->add_child(F->get().property_editor);
+ for (const EditorInspectorPlugin::AddedEditor &F : ped->added_editors) {
+ EditorProperty *ep = Object::cast_to<EditorProperty>(F.property_editor);
+ current_vbox->add_child(F.property_editor);
if (ep) {
ep->object = object;
@@ -1524,19 +1524,19 @@ void EditorInspector::_parse_added_editors(VBoxContainer *current_vbox, Ref<Edit
ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), varray(), CONNECT_DEFERRED);
ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), varray(), CONNECT_DEFERRED);
- if (F->get().properties.size()) {
- if (F->get().properties.size() == 1) {
+ if (F.properties.size()) {
+ if (F.properties.size() == 1) {
//since it's one, associate:
- ep->property = F->get().properties[0];
+ ep->property = F.properties[0];
ep->property_usage = 0;
}
- if (F->get().label != String()) {
- ep->set_label(F->get().label);
+ if (F.label != String()) {
+ ep->set_label(F.label);
}
- for (int i = 0; i < F->get().properties.size(); i++) {
- String prop = F->get().properties[i];
+ for (int i = 0; i < F.properties.size(); i++) {
+ String prop = F.properties[i];
if (!editor_property_map.has(prop)) {
editor_property_map[prop] = List<EditorProperty *>();
@@ -1648,8 +1648,7 @@ void EditorInspector::update_tree() {
Color sscolor = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
- for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
- Ref<EditorInspectorPlugin> ped = E->get();
+ for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_begin(object);
_parse_added_editors(main_vbox, ped);
}
@@ -1746,8 +1745,7 @@ void EditorInspector::update_tree() {
category->set_tooltip(p.name + "::" + (class_descr_cache[type2] == "" ? "" : class_descr_cache[type2]));
}
- for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
- Ref<EditorInspectorPlugin> ped = E->get();
+ for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_category(object, p.name);
_parse_added_editors(main_vbox, ped);
}
@@ -1948,36 +1946,35 @@ void EditorInspector::update_tree() {
doc_hint = descr;
}
- for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
- Ref<EditorInspectorPlugin> ped = E->get();
+ for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
bool exclusive = ped->parse_property(object, p.type, p.name, p.hint, p.hint_string, p.usage, wide_editors);
List<EditorInspectorPlugin::AddedEditor> editors = ped->added_editors; //make a copy, since plugins may be used again in a sub-inspector
ped->added_editors.clear();
- for (List<EditorInspectorPlugin::AddedEditor>::Element *F = editors.front(); F; F = F->next()) {
- EditorProperty *ep = Object::cast_to<EditorProperty>(F->get().property_editor);
+ for (const EditorInspectorPlugin::AddedEditor &F : editors) {
+ EditorProperty *ep = Object::cast_to<EditorProperty>(F.property_editor);
if (ep) {
//set all this before the control gets the ENTER_TREE notification
ep->object = object;
- if (F->get().properties.size()) {
- if (F->get().properties.size() == 1) {
+ if (F.properties.size()) {
+ if (F.properties.size() == 1) {
//since it's one, associate:
- ep->property = F->get().properties[0];
+ ep->property = F.properties[0];
ep->property_usage = p.usage;
//and set label?
}
- if (F->get().label != String()) {
- ep->set_label(F->get().label);
+ if (F.label != String()) {
+ ep->set_label(F.label);
} else {
- //use existin one
+ // Use the existing one.
ep->set_label(name);
}
- for (int i = 0; i < F->get().properties.size(); i++) {
- String prop = F->get().properties[i];
+ for (int i = 0; i < F.properties.size(); i++) {
+ String prop = F.properties[i];
if (!editor_property_map.has(prop)) {
editor_property_map[prop] = List<EditorProperty *>();
@@ -1995,7 +1992,7 @@ void EditorInspector::update_tree() {
ep->set_deletable(deletable_properties);
}
- current_vbox->add_child(F->get().property_editor);
+ current_vbox->add_child(F.property_editor);
if (ep) {
ep->connect("property_changed", callable_mp(this, &EditorInspector::_property_changed));
@@ -2031,8 +2028,7 @@ void EditorInspector::update_tree() {
}
}
- for (List<Ref<EditorInspectorPlugin>>::Element *E = valid_plugins.front(); E; E = E->next()) {
- Ref<EditorInspectorPlugin> ped = E->get();
+ for (Ref<EditorInspectorPlugin> &ped : valid_plugins) {
ped->parse_end();
_parse_added_editors(main_vbox, ped);
}
@@ -2045,10 +2041,10 @@ void EditorInspector::update_property(const String &p_prop) {
return;
}
- for (List<EditorProperty *>::Element *E = editor_property_map[p_prop].front(); E; E = E->next()) {
- E->get()->update_property();
- E->get()->update_reload_status();
- E->get()->update_cache();
+ for (EditorProperty *E : editor_property_map[p_prop]) {
+ E->update_property();
+ E->update_reload_status();
+ E->update_cache();
}
}
@@ -2157,24 +2153,24 @@ bool EditorInspector::is_using_folding() {
}
void EditorInspector::collapse_all_folding() {
- for (List<EditorInspectorSection *>::Element *E = sections.front(); E; E = E->next()) {
- E->get()->fold();
+ for (EditorInspectorSection *E : sections) {
+ E->fold();
}
for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) {
- for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
- E->get()->collapse_all_folding();
+ for (EditorProperty *E : F->get()) {
+ E->collapse_all_folding();
}
}
}
void EditorInspector::expand_all_folding() {
- for (List<EditorInspectorSection *>::Element *E = sections.front(); E; E = E->next()) {
- E->get()->unfold();
+ for (EditorInspectorSection *E : sections) {
+ E->unfold();
}
for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) {
- for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
- E->get()->expand_all_folding();
+ for (EditorProperty *E : F->get()) {
+ E->expand_all_folding();
}
}
}
@@ -2239,9 +2235,9 @@ void EditorInspector::_edit_request_change(Object *p_object, const String &p_pro
void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bool p_refresh_all, const String &p_changed_field) {
if (autoclear && editor_property_map.has(p_name)) {
- for (List<EditorProperty *>::Element *E = editor_property_map[p_name].front(); E; E = E->next()) {
- if (E->get()->is_checkable()) {
- E->get()->set_checked(true);
+ for (EditorProperty *E : editor_property_map[p_name]) {
+ if (E->is_checkable()) {
+ E->set_checked(true);
}
}
}
@@ -2308,8 +2304,8 @@ void EditorInspector::_edit_set(const String &p_name, const Variant &p_value, bo
}
if (editor_property_map.has(p_name)) {
- for (List<EditorProperty *>::Element *E = editor_property_map[p_name].front(); E; E = E->next()) {
- E->get()->update_reload_status();
+ for (EditorProperty *E : editor_property_map[p_name]) {
+ E->update_reload_status();
}
}
}
@@ -2395,10 +2391,10 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
Variant to_create;
List<PropertyInfo> pinfo;
object->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().name == p_path) {
+ for (const PropertyInfo &E : pinfo) {
+ if (E.name == p_path) {
Callable::CallError ce;
- Variant::construct(E->get().type, to_create, nullptr, 0, ce);
+ Variant::construct(E.type, to_create, nullptr, 0, ce);
break;
}
}
@@ -2406,10 +2402,10 @@ void EditorInspector::_property_checked(const String &p_path, bool p_checked) {
}
if (editor_property_map.has(p_path)) {
- for (List<EditorProperty *>::Element *E = editor_property_map[p_path].front(); E; E = E->next()) {
- E->get()->update_property();
- E->get()->update_reload_status();
- E->get()->update_cache();
+ for (EditorProperty *E : editor_property_map[p_path]) {
+ E->update_property();
+ E->update_reload_status();
+ E->update_cache();
}
}
@@ -2426,9 +2422,9 @@ void EditorInspector::_property_selected(const String &p_path, int p_focusable)
if (F->key() == property_selected) {
continue;
}
- for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
- if (E->get()->is_selected()) {
- E->get()->deselect();
+ for (EditorProperty *E : F->get()) {
+ if (E->is_selected()) {
+ E->deselect();
}
}
}
@@ -2485,11 +2481,11 @@ void EditorInspector::_notification(int p_what) {
refresh_countdown -= get_process_delta_time();
if (refresh_countdown <= 0) {
for (Map<StringName, List<EditorProperty *>>::Element *F = editor_property_map.front(); F; F = F->next()) {
- for (List<EditorProperty *>::Element *E = F->get().front(); E; E = E->next()) {
- if (!E->get()->is_cache_valid()) {
- E->get()->update_property();
- E->get()->update_reload_status();
- E->get()->update_cache();
+ for (EditorProperty *E : F->get()) {
+ if (!E->is_cache_valid()) {
+ E->update_property();
+ E->update_reload_status();
+ E->update_cache();
}
}
}
@@ -2508,10 +2504,10 @@ void EditorInspector::_notification(int p_what) {
while (pending.size()) {
StringName prop = pending.front()->get();
if (editor_property_map.has(prop)) {
- for (List<EditorProperty *>::Element *E = editor_property_map[prop].front(); E; E = E->next()) {
- E->get()->update_property();
- E->get()->update_reload_status();
- E->get()->update_cache();
+ for (EditorProperty *E : editor_property_map[prop]) {
+ E->update_property();
+ E->update_reload_status();
+ E->update_cache();
}
}
pending.erase(pending.front());
@@ -2599,8 +2595,7 @@ void EditorInspector::_update_script_class_properties(const Object &p_object, Li
}
Set<StringName> added;
- for (List<Ref<Script>>::Element *E = classes.front(); E; E = E->next()) {
- Ref<Script> s = E->get();
+ for (const Ref<Script> &s : classes) {
String path = s->get_path();
String name = EditorNode::get_editor_data().script_class_get_name(path);
if (name.is_empty()) {
diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp
index 16538a2376..0c8660c216 100644
--- a/editor/editor_layouts_dialog.cpp
+++ b/editor/editor_layouts_dialog.cpp
@@ -92,8 +92,8 @@ void EditorLayoutsDialog::_post_popup() {
List<String> layouts;
config.ptr()->get_sections(&layouts);
- for (List<String>::Element *E = layouts.front(); E; E = E->next()) {
- layout_names->add_item(**E);
+ for (const String &E : layouts) {
+ layout_names->add_item(E);
}
}
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 6de7f6c425..2cb73664f5 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -57,35 +57,43 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f
}
}
+void EditorLog::_update_theme() {
+ Ref<Font> normal_font = get_theme_font(SNAME("output_source"), SNAME("EditorFonts"));
+ if (normal_font.is_valid()) {
+ log->add_theme_font_override("normal_font", normal_font);
+ }
+
+ log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts")));
+ log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
+
+ Ref<Font> bold_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts"));
+ if (bold_font.is_valid()) {
+ log->add_theme_font_override("bold_font", bold_font);
+ }
+
+ type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_theme_icon(SNAME("Popup"), SNAME("EditorIcons")));
+ type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons")));
+ type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
+ type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+
+ clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
+ copy_button->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
+ collapse_button->set_icon(get_theme_icon(SNAME("CombineLines"), SNAME("EditorIcons")));
+ show_search_button->set_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
+}
+
void EditorLog::_notification(int p_what) {
- if (p_what == NOTIFICATION_ENTER_TREE) {
- //button->set_icon(get_icon("Console","EditorIcons"));
- log->add_theme_font_override("normal_font", get_theme_font(SNAME("output_source"), SNAME("EditorFonts")));
- log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts")));
- log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
- log->add_theme_font_override("bold_font", get_theme_font(SNAME("bold"), SNAME("EditorFonts")));
-
- type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_theme_icon(SNAME("Popup"), SNAME("EditorIcons")));
- type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons")));
- type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")));
- type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
-
- clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")));
- copy_button->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")));
- collapse_button->set_icon(get_theme_icon(SNAME("CombineLines"), SNAME("EditorIcons")));
- show_search_button->set_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons")));
-
- _load_state();
-
- } else if (p_what == NOTIFICATION_THEME_CHANGED) {
- Ref<Font> df_output_code = get_theme_font(SNAME("output_source"), SNAME("EditorFonts"));
- if (df_output_code.is_valid()) {
- if (log != nullptr) {
- log->add_theme_font_override("normal_font", get_theme_font(SNAME("output_source"), SNAME("EditorFonts")));
- log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts")));
- log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4));
- }
- }
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ _update_theme();
+ _load_state();
+ } break;
+ case NOTIFICATION_THEME_CHANGED: {
+ _update_theme();
+ _rebuild_log();
+ } break;
+ default:
+ break;
}
}
diff --git a/editor/editor_log.h b/editor/editor_log.h
index 3b6476634a..6cbf4bedee 100644
--- a/editor/editor_log.h
+++ b/editor/editor_log.h
@@ -163,6 +163,8 @@ private:
void _save_state();
void _load_state();
+ void _update_theme();
+
protected:
static void _bind_methods();
void _notification(int p_what);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6bdf428f81..46d76a946f 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -797,8 +797,8 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) {
}
if (changed.size()) {
- for (List<Ref<Resource>>::Element *E = changed.front(); E; E = E->next()) {
- E->get()->reload_from_file();
+ for (Ref<Resource> &res : changed) {
+ res->reload_from_file();
}
}
}
@@ -914,8 +914,8 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
}
}
- for (List<String>::Element *E = scenes.front(); E; E = E->next()) {
- reload_scene(E->get());
+ for (const String &E : scenes) {
+ reload_scene(E);
}
scene_tabs->set_current_tab(current_tab);
@@ -926,7 +926,7 @@ void EditorNode::_sources_changed(bool p_exist) {
waiting_for_first_scan = false;
// Reload the global shader variables, but this time
- // loading texures, as they are now properly imported.
+ // loading textures, as they are now properly imported.
RenderingServer::get_singleton()->global_variables_load_settings(true);
// Start preview thread now that it's safe.
@@ -1143,13 +1143,13 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String
file->clear_filters();
List<String> preferred;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (p_resource->is_class("Script") && (E->get() == "tres" || E->get() == "res")) {
+ for (const String &E : extensions) {
+ if (p_resource->is_class("Script") && (E == "tres" || E == "res")) {
//this serves no purpose and confused people
continue;
}
- file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
- preferred.push_back(E->get());
+ file->add_filter("*." + E + " ; " + E.to_upper());
+ preferred.push_back(E);
}
// Lowest priority extension
List<String>::Element *res_element = preferred.find("res");
@@ -1259,10 +1259,10 @@ void EditorNode::_get_scene_metadata(const String &p_file) {
cf->get_section_keys("editor_states", &esl);
Dictionary md;
- for (List<String>::Element *E = esl.front(); E; E = E->next()) {
- Variant st = cf->get_value("editor_states", E->get());
+ for (const String &E : esl) {
+ Variant st = cf->get_value("editor_states", E);
if (st.get_type() != Variant::NIL) {
- md[E->get()] = st;
+ md[E] = st;
}
}
@@ -1295,8 +1295,8 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) {
List<Variant> keys;
md.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- cf->set_value("editor_states", E->get(), md[E->get()]);
+ for (const Variant &E : keys) {
+ cf->set_value("editor_states", E, md[E]);
}
Error err = cf->save(path);
@@ -1334,14 +1334,14 @@ bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<RES, bool>
bool ret_changed = false;
List<PropertyInfo> pi;
obj->get_property_list(&pi);
- for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : pi) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- switch (E->get().type) {
+ switch (E.type) {
case Variant::OBJECT: {
- RES res = obj->get(E->get().name);
+ RES res = obj->get(E.name);
if (_find_and_save_resource(res, processed, flags)) {
ret_changed = true;
@@ -1349,7 +1349,7 @@ bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<RES, bool>
} break;
case Variant::ARRAY: {
- Array varray = obj->get(E->get().name);
+ Array varray = obj->get(E.name);
int len = varray.size();
for (int i = 0; i < len; i++) {
const Variant &v = varray.get(i);
@@ -1361,11 +1361,11 @@ bool EditorNode::_find_and_save_edited_subresources(Object *obj, Map<RES, bool>
} break;
case Variant::DICTIONARY: {
- Dictionary d = obj->get(E->get().name);
+ Dictionary d = obj->get(E.name);
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *F = keys.front(); F; F = F->next()) {
- Variant v = d[F->get()];
+ for (const Variant &F : keys) {
+ Variant v = d[F];
RES res = v;
if (_find_and_save_resource(res, processed, flags)) {
ret_changed = true;
@@ -1520,9 +1520,9 @@ static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Reso
p_resource->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (E->get().type == Variant::OBJECT && E->get().usage & PROPERTY_USAGE_STORAGE && !(E->get().usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT)) {
- RES res = p_resource->get(E->get().name);
+ for (const PropertyInfo &E : plist) {
+ if (E.type == Variant::OBJECT && E.usage & PROPERTY_USAGE_STORAGE && !(E.usage & PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT)) {
+ RES res = p_resource->get(E.name);
if (res.is_null()) {
continue;
}
@@ -1551,12 +1551,11 @@ int EditorNode::_save_external_resources() {
int saved = 0;
List<Ref<Resource>> cached;
ResourceCache::get_cached_resources(&cached);
- for (List<Ref<Resource>>::Element *E = cached.front(); E; E = E->next()) {
- Ref<Resource> res = E->get();
+ for (const Ref<Resource> &res : cached) {
if (!res->get_path().is_resource_file()) {
continue;
}
- //not only check if this resourec is edited, check contained subresources too
+ //not only check if this resource is edited, check contained subresources too
if (_find_edited_resources(res, edited_subresources)) {
ResourceSaver::save(res->get_path(), res, flg);
saved++;
@@ -1642,8 +1641,8 @@ void EditorNode::_save_scene(String p_file, int idx) {
editor_data.save_editor_external_data();
- for (List<Ref<AnimatedValuesBackup>>::Element *E = anim_backups.front(); E; E = E->next()) {
- E->get()->restore();
+ for (Ref<AnimatedValuesBackup> &E : anim_backups) {
+ E->restore();
}
if (err == OK) {
@@ -1884,8 +1883,8 @@ void EditorNode::_dialog_action(String p_file) {
// erase
List<String> keys;
config->get_section_keys(p_file, &keys);
- for (List<String>::Element *E = keys.front(); E; E = E->next()) {
- config->set_value(p_file, E->get(), Variant());
+ for (const String &E : keys) {
+ config->set_value(p_file, E, Variant());
}
config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
@@ -2533,8 +2532,8 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
Ref<MeshLibrary> ml(memnew(MeshLibrary));
ResourceSaver::get_recognized_extensions(ml, &extensions);
file_export_lib->clear_filters();
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- file_export_lib->add_filter("*." + E->get());
+ for (const String &E : extensions) {
+ file_export_lib->add_filter("*." + E);
}
file_export_lib->popup_file_dialog();
@@ -4055,11 +4054,11 @@ void EditorNode::_build_icon_type_cache() {
List<StringName> tl;
StringName ei = "EditorIcons";
theme_base->get_theme()->get_icon_list(ei, &tl);
- for (List<StringName>::Element *E = tl.front(); E; E = E->next()) {
- if (!ClassDB::class_exists(E->get())) {
+ for (const StringName &E : tl) {
+ if (!ClassDB::class_exists(E)) {
continue;
}
- icon_type_cache[E->get()] = theme_base->get_theme()->get_icon(E->get(), ei);
+ icon_type_cache[E] = theme_base->get_theme()->get_icon(E, ei);
}
}
@@ -4784,9 +4783,7 @@ void EditorNode::_update_layouts_menu() {
List<String> layouts;
config.ptr()->get_sections(&layouts);
- for (List<String>::Element *E = layouts.front(); E; E = E->next()) {
- String layout = E->get();
-
+ for (const String &layout : layouts) {
if (layout == TTR("Default")) {
editor_layouts->remove_item(editor_layouts->get_item_index(SETTINGS_LAYOUT_DEFAULT));
overridden_default_layout = editor_layouts->get_item_count();
@@ -5336,27 +5333,6 @@ void EditorNode::_file_access_close_error_notify(const String &p_str) {
}
void EditorNode::reload_scene(const String &p_path) {
- /*
- * No longer necessary since scenes now reset and reload their internal resource if needed.
- //first of all, reload internal textures, materials, meshes, etc. as they might have changed on disk
-
- List<Ref<Resource>> cached;
- ResourceCache::get_cached_resources(&cached);
- List<Ref<Resource>> to_clear; //clear internal resources from previous scene from being used
- for (List<Ref<Resource>>::Element *E = cached.front(); E; E = E->next()) {
- if (E->get()->get_path().begins_with(p_path + "::")) { //subresources of existing scene
- to_clear.push_back(E->get());
- }
- }
-
- //so reload reloads everything, clear subresources of previous scene
- while (to_clear.front()) {
- to_clear.front()->get()->set_path("");
- to_clear.pop_front();
- }
-
- */
-
int scene_idx = -1;
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == p_path) {
@@ -6741,8 +6717,8 @@ EditorNode::EditorNode() {
file_script->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
List<String> sexts;
ResourceLoader::get_recognized_extensions_for_type("Script", &sexts);
- for (List<String>::Element *E = sexts.front(); E; E = E->next()) {
- file_script->add_filter("*." + E->get());
+ for (const String &E : sexts) {
+ file_script->add_filter("*." + E);
}
gui_base->add_child(file_script);
file_script->connect("file_selected", callable_mp(this, &EditorNode::_dialog_action));
diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp
index a31b9fd0c7..f3b3eedccc 100644
--- a/editor/editor_path.cpp
+++ b/editor/editor_path.cpp
@@ -40,15 +40,15 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) {
List<PropertyInfo> pinfo;
p_obj->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_EDITOR)) {
+ for (const PropertyInfo &E : pinfo) {
+ if (!(E.usage & PROPERTY_USAGE_EDITOR)) {
continue;
}
- if (E->get().hint != PROPERTY_HINT_RESOURCE_TYPE) {
+ if (E.hint != PROPERTY_HINT_RESOURCE_TYPE) {
continue;
}
- Variant value = p_obj->get(E->get().name);
+ Variant value = p_obj->get(E.name);
if (value.get_type() != Variant::OBJECT) {
continue;
}
@@ -60,7 +60,7 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) {
Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(obj);
String proper_name = "";
- Vector<String> name_parts = E->get().name.split("/");
+ Vector<String> name_parts = E.name.split("/");
for (int i = 0; i < name_parts.size(); i++) {
if (i > 0) {
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 8bb6c590dc..7d809ea656 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -221,8 +221,8 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
}
Set<String> valid_extensions;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- valid_extensions.insert(E->get());
+ for (const String &E : extensions) {
+ valid_extensions.insert(E);
}
if (!file_dialog) {
@@ -260,9 +260,8 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
List<PropertyInfo> property_list;
edited_resource->get_property_list(&property_list);
List<Pair<String, Variant>> propvalues;
- for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+ for (const PropertyInfo &pi : property_list) {
Pair<String, Variant> p;
- PropertyInfo &pi = E->get();
if (pi.usage & PROPERTY_USAGE_STORAGE) {
p.first = pi.name;
p.second = edited_resource->get(pi.name);
@@ -276,8 +275,7 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
Ref<Resource> unique_resource = Ref<Resource>(Object::cast_to<Resource>(inst));
ERR_FAIL_COND(unique_resource.is_null());
- for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) {
- Pair<String, Variant> &p = E->get();
+ for (const Pair<String, Variant> &p : propvalues) {
unique_resource->set(p.first, p.second);
}
@@ -467,13 +465,13 @@ void EditorResourcePicker::_get_allowed_types(bool p_with_convert, Set<String> *
List<StringName> inheriters;
ClassDB::get_inheriters_from_class(base, &inheriters);
- for (List<StringName>::Element *E = inheriters.front(); E; E = E->next()) {
- p_vector->insert(E->get());
+ for (const StringName &E : inheriters) {
+ p_vector->insert(E);
}
- for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
- if (EditorNode::get_editor_data().script_class_is_parent(E->get(), base)) {
- p_vector->insert(E->get());
+ for (const StringName &E : global_classes) {
+ if (EditorNode::get_editor_data().script_class_is_parent(E, base)) {
+ p_vector->insert(E);
}
}
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 5e6d2ab69c..4fadbf5922 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -228,8 +228,8 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L
}
printf("Running: %s", exec.utf8().get_data());
- for (List<String>::Element *E = args.front(); E; E = E->next()) {
- printf(" %s", E->get().utf8().get_data());
+ for (const String &E : args) {
+ printf(" %s", E.utf8().get_data());
};
printf("\n");
@@ -250,8 +250,8 @@ Error EditorRun::run(const String &p_scene, const String &p_custom_args, const L
}
bool EditorRun::has_child_process(OS::ProcessID p_pid) const {
- for (const List<OS::ProcessID>::Element *E = pids.front(); E; E = E->next()) {
- if (E->get() == p_pid) {
+ for (const OS::ProcessID &E : pids) {
+ if (E == p_pid) {
return true;
}
}
@@ -267,8 +267,8 @@ void EditorRun::stop_child_process(OS::ProcessID p_pid) {
void EditorRun::stop() {
if (status != STATUS_STOP && pids.size() > 0) {
- for (List<OS::ProcessID>::Element *E = pids.front(); E; E = E->next()) {
- OS::get_singleton()->kill(E->get());
+ for (const OS::ProcessID &E : pids) {
+ OS::get_singleton()->kill(E);
}
}
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index 1209df50ed..751cc7a574 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -76,8 +76,7 @@ class SectionedInspectorFilter : public Object {
List<PropertyInfo> pinfo;
edited->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- PropertyInfo pi = E->get();
+ for (PropertyInfo &pi : pinfo) {
int sp = pi.name.find("/");
if (pi.name == "resource_path" || pi.name == "resource_name" || pi.name == "resource_local_to_scene" || pi.name.begins_with("script/") || pi.name.begins_with("_global_script")) { //skip resource stuff
@@ -221,9 +220,7 @@ void SectionedInspector::update_category_list() {
filter = search_box->get_text();
}
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- PropertyInfo pi = E->get();
-
+ for (PropertyInfo &pi : pinfo) {
if (pi.usage & PROPERTY_USAGE_CATEGORY) {
continue;
} else if (!(pi.usage & PROPERTY_USAGE_EDITOR) || (restrict_to_basic && !(pi.usage & PROPERTY_USAGE_EDITOR_BASIC_SETTING))) {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 0667d7116f..df4469b6fe 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -759,8 +759,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
List<String> keys;
p_extra_config->get_section_keys("presets", &keys);
- for (List<String>::Element *E = keys.front(); E; E = E->next()) {
- String key = E->get();
+ for (const String &key : keys) {
Variant val = p_extra_config->get_value("presets", key);
set(key, val);
}
@@ -815,8 +814,7 @@ bool EditorSettings::_save_text_editor_theme(String p_file) {
props.get_key_list(&keys);
keys.sort();
- for (const List<String>::Element *E = keys.front(); E; E = E->next()) {
- const String &key = E->get();
+ for (const String &key : keys) {
if (key.begins_with("text_editor/highlighting/") && key.find("color") >= 0) {
cf->set_value(theme_section, key.replace("text_editor/highlighting/", ""), ((Color)props[key].variant).to_html());
}
@@ -1015,15 +1013,13 @@ void EditorSettings::setup_network() {
String selected = "127.0.0.1";
// Check that current remote_host is a valid interface address and populate hints.
- for (List<IPAddress>::Element *E = local_ip.front(); E; E = E->next()) {
- String ip = E->get();
-
+ for (const IPAddress &ip : local_ip) {
// link-local IPv6 addresses don't work, skipping them
- if (ip.begins_with("fe80:0:0:0:")) { // fe80::/64
+ if (String(ip).begins_with("fe80:0:0:0:")) { // fe80::/64
continue;
}
// Same goes for IPv4 link-local (APIPA) addresses.
- if (ip.begins_with("169.254.")) { // 169.254.0.0/16
+ if (String(ip).begins_with("169.254.")) { // 169.254.0.0/16
continue;
}
// Select current IP (found)
@@ -1303,8 +1299,8 @@ void EditorSettings::list_text_editor_themes() {
memdelete(d);
custom_themes.sort();
- for (List<String>::Element *E = custom_themes.front(); E; E = E->next()) {
- themes += "," + E->get();
+ for (const String &E : custom_themes) {
+ themes += "," + E;
}
}
add_property_hint(PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, themes));
@@ -1332,8 +1328,7 @@ void EditorSettings::load_text_editor_theme() {
List<String> keys;
cf->get_section_keys("color_theme", &keys);
- for (List<String>::Element *E = keys.front(); E; E = E->next()) {
- String key = E->get();
+ for (const String &key : keys) {
String val = cf->get_value("color_theme", key);
// don't load if it's not already there!
@@ -1434,7 +1429,7 @@ float EditorSettings::get_auto_display_scale() const {
return DisplayServer::get_singleton()->screen_get_max_scale();
#else
const int screen = DisplayServer::get_singleton()->window_get_current_screen();
- // Use the smallest dimension to use a correct display scale on portait displays.
+ // Use the smallest dimension to use a correct display scale on portrait displays.
const int smallest_dimension = MIN(DisplayServer::get_singleton()->screen_get_size(screen).x, DisplayServer::get_singleton()->screen_get_size(screen).y);
if (DisplayServer::get_singleton()->screen_get_dpi(screen) >= 192 && smallest_dimension >= 1400) {
// hiDPI display.
@@ -1585,8 +1580,8 @@ void EditorSettings::set_builtin_action_override(const String &p_name, const Arr
int event_idx = 0;
// Check equality of each event.
- for (List<Ref<InputEvent>>::Element *E = builtin_events.front(); E; E = E->next()) {
- if (!E->get()->is_match(p_events[event_idx])) {
+ for (const Ref<InputEvent> &E : builtin_events) {
+ if (!E->is_match(p_events[event_idx])) {
same_as_builtin = false;
break;
}
@@ -1615,8 +1610,8 @@ const Array EditorSettings::get_builtin_action_overrides(const String &p_name) c
Array event_array;
List<Ref<InputEvent>> events_list = AO->get();
- for (List<Ref<InputEvent>>::Element *E = events_list.front(); E; E = E->next()) {
- event_array.push_back(E->get());
+ for (const Ref<InputEvent> &E : events_list) {
+ event_array.push_back(E);
}
return event_array;
}
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 49c2a84e18..daee61c2dd 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -135,9 +135,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
_sort_file_info_list(file_list);
// Build the tree.
- for (List<FileInfo>::Element *E = file_list.front(); E; E = E->next()) {
- FileInfo fi = E->get();
-
+ for (const FileInfo &fi : file_list) {
TreeItem *file_item = tree->create_item(subdirectory_item);
file_item->set_text(0, fi.name);
file_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE);
@@ -869,8 +867,8 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
// Fills the ItemList control node from the FileInfos.
String main_scene = ProjectSettings::get_singleton()->get("application/run/main_scene");
String oi = "Object";
- for (List<FileInfo>::Element *E = file_list.front(); E; E = E->next()) {
- FileInfo *finfo = &(E->get());
+ for (FileInfo &E : file_list) {
+ FileInfo *finfo = &(E);
String fname = finfo->name;
String fpath = finfo->path;
String ftype = finfo->type;
@@ -966,8 +964,8 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
List<String> importer_exts;
ResourceImporterScene::get_singleton()->get_recognized_extensions(&importer_exts);
String extension = fpath.get_extension();
- for (List<String>::Element *E = importer_exts.front(); E; E = E->next()) {
- if (extension.nocasecmp_to(E->get()) == 0) {
+ for (const String &E : importer_exts) {
+ if (extension.nocasecmp_to(E) == 0) {
is_imported = true;
break;
}
@@ -1239,9 +1237,7 @@ void FileSystemDock::_update_resource_paths_after_move(const Map<String, String>
List<Ref<Resource>> cached;
ResourceCache::get_cached_resources(&cached);
- for (List<Ref<Resource>>::Element *E = cached.front(); E; E = E->next()) {
- Ref<Resource> r = E->get();
-
+ for (Ref<Resource> &r : cached) {
String base_path = r->get_path();
String extra_path;
int sep_pos = r->get_path().find("::");
@@ -1317,16 +1313,16 @@ void FileSystemDock::_update_project_settings_after_move(const Map<String, Strin
// Also search for the file in autoload, as they are stored differently from normal files.
List<PropertyInfo> property_list;
ProjectSettings::get_singleton()->get_property_list(&property_list);
- for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- if (E->get().name.begins_with("autoload/")) {
+ for (const PropertyInfo &E : property_list) {
+ if (E.name.begins_with("autoload/")) {
// If the autoload resource paths has a leading "*", it indicates that it is a Singleton,
// so we have to handle both cases when updating.
- String autoload = GLOBAL_GET(E->get().name);
+ String autoload = GLOBAL_GET(E.name);
String autoload_singleton = autoload.substr(1, autoload.length());
if (p_renames.has(autoload)) {
- ProjectSettings::get_singleton()->set_setting(E->get().name, p_renames[autoload]);
+ ProjectSettings::get_singleton()->set_setting(E.name, p_renames[autoload]);
} else if (autoload.begins_with("*") && p_renames.has(autoload_singleton)) {
- ProjectSettings::get_singleton()->set_setting(E->get().name, "*" + p_renames[autoload_singleton]);
+ ProjectSettings::get_singleton()->set_setting(E.name, "*" + p_renames[autoload_singleton]);
}
}
}
@@ -1417,8 +1413,8 @@ void FileSystemDock::_make_scene_confirm() {
ResourceSaver::get_recognized_extensions(sd, &extensions);
bool extension_correct = false;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get() == extension) {
+ for (const String &E : extensions) {
+ if (E == extension) {
extension_correct = true;
break;
}
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 0a39768b9a..113306fc8a 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -240,8 +240,7 @@ void GroupDialog::_group_renamed() {
List<Node *> nodes;
scene_tree->get_nodes_in_group(selected_group, &nodes);
bool removed_all = true;
- for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) {
- Node *node = E->get();
+ for (Node *node : nodes) {
if (_can_edit(node, selected_group)) {
undo_redo->add_do_method(node, "remove_from_group", selected_group);
undo_redo->add_undo_method(node, "remove_from_group", name);
@@ -286,11 +285,11 @@ void GroupDialog::_load_groups(Node *p_current) {
List<Node::GroupInfo> gi;
p_current->get_groups(&gi);
- for (List<Node::GroupInfo>::Element *E = gi.front(); E; E = E->next()) {
- if (!E->get().persistent) {
+ for (const Node::GroupInfo &E : gi) {
+ if (!E.persistent) {
continue;
}
- _add_group(E->get().name);
+ _add_group(E.name);
}
for (int i = 0; i < p_current->get_child_count(); i++) {
@@ -311,10 +310,10 @@ void GroupDialog::_delete_group_pressed(Object *p_item, int p_column, int p_id)
List<Node *> nodes;
scene_tree->get_nodes_in_group(name, &nodes);
bool removed_all = true;
- for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) {
- if (_can_edit(E->get(), name)) {
- undo_redo->add_do_method(E->get(), "remove_from_group", name);
- undo_redo->add_undo_method(E->get(), "add_to_group", name, true);
+ for (Node *E : nodes) {
+ if (_can_edit(E, name)) {
+ undo_redo->add_do_method(E, "remove_from_group", name);
+ undo_redo->add_undo_method(E, "add_to_group", name, true);
} else {
removed_all = false;
}
@@ -628,8 +627,7 @@ void GroupsEditor::update_tree() {
TreeItem *root = tree->create_item();
- for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next()) {
- Node::GroupInfo gi = E->get();
+ for (const GroupInfo &gi : groups) {
if (!gi.persistent) {
continue;
}
diff --git a/editor/icons/ImmediateGeometry3D.svg b/editor/icons/ImmediateGeometry3D.svg
deleted file mode 100644
index ec5a392a68..0000000000
--- a/editor/icons/ImmediateGeometry3D.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m2.9208 1046.4c-.26373.3-.4204.7296-.4204 1.2383 0 1.6277-3.1381-.1781-.33757 2.6703.88382.899 2.6544.6701 3.5382-.2288.88384-.899.88382-2.3565 0-3.2554-1.1002-1.1191-2.2001-1.0845-2.7803-.4244zm2.3802-1.6103 2.4005 2.4416 6.8014-6.9177c.66286-.6742.66286-1.7673 0-2.4415-.66288-.6741-1.7376-.6741-2.4005 0z" fill="#fc7f7f" transform="translate(0 -1036.4)"/></svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index ddf89f077b..b615c73422 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -894,8 +894,8 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref<EditorSceneImpor
surftool->add_vertex(vertex_array[k].vertex);
}
- for (List<int>::Element *E = indices_list.front(); E; E = E->next()) {
- surftool->add_index(E->get());
+ for (int &E : indices_list) {
+ surftool->add_index(E);
}
if (!normal_src) {
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 01603c0a6a..34bc0a7d8d 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -438,17 +438,16 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
Node3D *scene = memnew(Node3D);
- for (List<Ref<Mesh>>::Element *E = meshes.front(); E; E = E->next()) {
+ for (const Ref<Mesh> &m : meshes) {
Ref<EditorSceneImporterMesh> mesh;
mesh.instantiate();
- Ref<Mesh> m = E->get();
for (int i = 0; i < m->get_surface_count(); i++) {
mesh->add_surface(m->surface_get_primitive_type(i), m->surface_get_arrays(i), Array(), Dictionary(), m->surface_get_material(i));
}
EditorSceneImporterMeshNode3D *mi = memnew(EditorSceneImporterMeshNode3D);
mi->set_mesh(mesh);
- mi->set_name(E->get()->get_name());
+ mi->set_name(m->get_name());
scene->add_child(mi);
mi->set_owner(scene);
}
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index c14b948dae..e9160f0414 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -312,8 +312,8 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
List<StringName> anims;
ap->get_animation_list(&anims);
- for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
- Ref<Animation> anim = ap->get_animation(E->get());
+ for (const StringName &E : anims) {
+ Ref<Animation> anim = ap->get_animation(E);
ERR_CONTINUE(anim.is_null());
for (int i = 0; i < anim->get_track_count(); i++) {
NodePath path = anim->track_get_path(i);
@@ -328,14 +328,14 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<E
}
}
- String animname = E->get();
+ String animname = E;
const int loop_string_count = 3;
static const char *loop_strings[loop_string_count] = { "loops", "loop", "cycle" };
for (int i = 0; i < loop_string_count; i++) {
if (_teststr(animname, loop_strings[i])) {
anim->set_loop(true);
animname = _fixstr(animname, loop_strings[i]);
- ap->rename_animation(E->get(), animname);
+ ap->rename_animation(E, animname);
}
}
}
@@ -659,9 +659,9 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
}
int idx = 0;
- for (List<Ref<Shape3D>>::Element *E = shapes.front(); E; E = E->next()) {
+ for (const Ref<Shape3D> &E : shapes) {
CollisionShape3D *cshape = memnew(CollisionShape3D);
- cshape->set_shape(E->get());
+ cshape->set_shape(E);
base->add_child(cshape);
cshape->set_owner(base->get_owner());
@@ -712,9 +712,9 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
//fill node settings for this node with default values
List<ImportOption> iopts;
get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE, &iopts);
- for (List<ImportOption>::Element *E = iopts.front(); E; E = E->next()) {
- if (!node_settings.has(E->get().option.name)) {
- node_settings[E->get().option.name] = E->get().default_value;
+ for (const ImportOption &E : iopts) {
+ if (!node_settings.has(E.option.name)) {
+ node_settings[E.option.name] = E.default_value;
}
}
}
@@ -756,8 +756,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
} else {
List<StringName> anims;
ap->get_animation_list(&anims);
- for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
- String name = E->get();
+ for (const StringName &name : anims) {
Ref<Animation> anim = ap->get_animation(name);
if (p_animation_data.has(name)) {
Dictionary anim_settings = p_animation_data[name];
@@ -765,9 +764,9 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
//fill with default values
List<ImportOption> iopts;
get_internal_import_options(INTERNAL_IMPORT_CATEGORY_ANIMATION, &iopts);
- for (List<ImportOption>::Element *F = iopts.front(); F; F = F->next()) {
- if (!anim_settings.has(F->get().option.name)) {
- anim_settings[F->get().option.name] = F->get().default_value;
+ for (const ImportOption &F : iopts) {
+ if (!anim_settings.has(F.option.name)) {
+ anim_settings[F.option.name] = F.default_value;
}
}
}
@@ -936,8 +935,8 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle) {
List<StringName> anim_names;
anim->get_animation_list(&anim_names);
- for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) {
- Ref<Animation> a = anim->get_animation(E->get());
+ for (const StringName &E : anim_names) {
+ Ref<Animation> a = anim->get_animation(E);
a->optimize(p_max_lin_error, p_max_ang_error, Math::deg2rad(p_max_angle));
}
}
@@ -1046,11 +1045,11 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
String script_ext_hint;
- for (List<String>::Element *E = script_extentions.front(); E; E = E->next()) {
+ for (const String &E : script_extentions) {
if (script_ext_hint != "") {
script_ext_hint += ",";
}
- script_ext_hint += "*." + E->get();
+ script_ext_hint += "*." + E;
}
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "nodes/root_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001"), 1.0));
@@ -1089,9 +1088,9 @@ Node *ResourceImporterScene::import_scene_from_other_importer(EditorSceneImporte
List<String> extensions;
E->get()->get_extensions(&extensions);
- for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
- if (F->get().to_lower() == ext) {
- importer = E->get();
+ for (const String &F : extensions) {
+ if (F.to_lower() == ext) {
+ importer = E;
break;
}
}
@@ -1119,9 +1118,9 @@ Ref<Animation> ResourceImporterScene::import_animation_from_other_importer(Edito
List<String> extensions;
E->get()->get_extensions(&extensions);
- for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
- if (F->get().to_lower() == ext) {
- importer = E->get();
+ for (const String &F : extensions) {
+ if (F.to_lower() == ext) {
+ importer = E;
break;
}
}
@@ -1291,9 +1290,9 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m
}
void ResourceImporterScene::_add_shapes(Node *p_node, const List<Ref<Shape3D>> &p_shapes) {
- for (const List<Ref<Shape3D>>::Element *E = p_shapes.front(); E; E = E->next()) {
+ for (const Ref<Shape3D> &E : p_shapes) {
CollisionShape3D *cshape = memnew(CollisionShape3D);
- cshape->set_shape(E->get());
+ cshape->set_shape(E);
p_node->add_child(cshape);
cshape->set_owner(p_node->get_owner());
@@ -1311,8 +1310,8 @@ Node *ResourceImporterScene::pre_import(const String &p_source_file) {
List<String> extensions;
E->get()->get_extensions(&extensions);
- for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
- if (F->get().to_lower() == ext) {
+ for (const String &F : extensions) {
+ if (F.to_lower() == ext) {
importer = E->get();
break;
}
@@ -1351,8 +1350,8 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
List<String> extensions;
E->get()->get_extensions(&extensions);
- for (List<String>::Element *F = extensions.front(); F; F = F->next()) {
- if (F->get().to_lower() == ext) {
+ for (const String &F : extensions) {
+ if (F.to_lower() == ext) {
importer = E->get();
break;
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index c6e5836a23..781beff689 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -155,7 +155,8 @@ public:
virtual void get_import_options(List<ImportOption> *r_options, int p_preset = 0) const override;
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override;
- virtual int get_import_order() const override { return 100; } //after everything
+ // Import scenes *after* everything else (such as textures).
+ virtual int get_import_order() const override { return ResourceImporter::IMPORT_ORDER_SCENE; }
Node *_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map);
Node *_post_fix_node(Node *p_node, Node *p_root, Map<Ref<EditorSceneImporterMesh>, List<Ref<Shape3D>>> &collision_map, Set<Ref<EditorSceneImporterMesh>> &r_scanned_meshes, const Dictionary &p_node_data, const Dictionary &p_material_data, const Dictionary &p_animation_data, float p_animation_fps);
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 5dc494d6df..19a8f209bb 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -71,9 +71,9 @@ class SceneImportSettingsData : public Object {
return false;
}
void _get_property_list(List<PropertyInfo> *p_list) const {
- for (const List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E->get().option.name, current)) {
- p_list->push_back(E->get().option);
+ for (const ResourceImporter::ImportOption &E : options) {
+ if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E.option.name, current)) {
+ p_list->push_back(E.option);
}
}
}
@@ -305,8 +305,8 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
if (anim_node) {
List<StringName> animations;
anim_node->get_animation_list(&animations);
- for (List<StringName>::Element *E = animations.front(); E; E = E->next()) {
- _fill_animation(scene_tree, anim_node->get_animation(E->get()), E->get(), item);
+ for (const StringName &E : animations) {
+ _fill_animation(scene_tree, anim_node->get_animation(E), E, item);
}
}
@@ -394,8 +394,8 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var
d = d[p_import_id];
List<ResourceImporterScene::ImportOption> options;
ResourceImporterScene::get_singleton()->get_internal_import_options(p_category, &options);
- for (List<ResourceImporterScene::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- String key = E->get().option.name;
+ for (const ResourceImporterScene::ImportOption &E : options) {
+ String key = E.option.name;
if (d.has(key)) {
settings[key] = d[key];
}
@@ -440,12 +440,12 @@ void SceneImportSettings::open_settings(const String &p_path) {
if (err == OK) {
List<String> keys;
config->get_section_keys("params", &keys);
- for (List<String>::Element *E = keys.front(); E; E = E->next()) {
- Variant value = config->get_value("params", E->get());
- if (E->get() == "_subresources") {
+ for (const String &E : keys) {
+ Variant value = config->get_value("params", E);
+ if (E == "_subresources") {
base_subresource_settings = value;
} else {
- defaults[E->get()] = value;
+ defaults[E] = value;
}
}
}
@@ -605,13 +605,13 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
scene_import_settings_data->defaults.clear();
scene_import_settings_data->current.clear();
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- scene_import_settings_data->defaults[E->get().option.name] = E->get().default_value;
+ for (const ResourceImporter::ImportOption &E : options) {
+ scene_import_settings_data->defaults[E.option.name] = E.default_value;
//needed for visibility toggling (fails if something is missing)
- if (scene_import_settings_data->settings->has(E->get().option.name)) {
- scene_import_settings_data->current[E->get().option.name] = (*scene_import_settings_data->settings)[E->get().option.name];
+ if (scene_import_settings_data->settings->has(E.option.name)) {
+ scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name];
} else {
- scene_import_settings_data->current[E->get().option.name] = E->get().default_value;
+ scene_import_settings_data->current[E.option.name] = E.default_value;
}
}
scene_import_settings_data->options = options;
diff --git a/editor/import/scene_importer_mesh.cpp b/editor/import/scene_importer_mesh.cpp
index f8e93df382..0d14347225 100644
--- a/editor/import/scene_importer_mesh.cpp
+++ b/editor/import/scene_importer_mesh.cpp
@@ -79,11 +79,11 @@ void EditorSceneImporterMesh::add_surface(Mesh::PrimitiveType p_primitive, const
List<Variant> lods;
p_lods.get_key_list(&lods);
- for (List<Variant>::Element *E = lods.front(); E; E = E->next()) {
- ERR_CONTINUE(!E->get().is_num());
+ for (const Variant &E : lods) {
+ ERR_CONTINUE(!E.is_num());
Surface::LOD lod;
- lod.distance = E->get();
- lod.indices = p_lods[E->get()];
+ lod.distance = E;
+ lod.indices = p_lods[E];
ERR_CONTINUE(lod.indices.size() == 0);
s.lods.push_back(lod);
}
diff --git a/editor/import_defaults_editor.cpp b/editor/import_defaults_editor.cpp
index 8c506e938d..25bca1d4f4 100644
--- a/editor/import_defaults_editor.cpp
+++ b/editor/import_defaults_editor.cpp
@@ -61,9 +61,9 @@ protected:
if (importer.is_null()) {
return;
}
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (importer->get_option_visibility(E->get().name, values)) {
- p_list->push_back(E->get());
+ for (const PropertyInfo &E : properties) {
+ if (importer->get_option_visibility(E.name, values)) {
+ p_list->push_back(E);
}
}
}
@@ -106,9 +106,9 @@ void ImportDefaultsEditor::_update_importer() {
List<Ref<ResourceImporter>> importer_list;
ResourceFormatImporter::get_singleton()->get_importers(&importer_list);
Ref<ResourceImporter> importer;
- for (List<Ref<ResourceImporter>>::Element *E = importer_list.front(); E; E = E->next()) {
- if (E->get()->get_visible_name() == importers->get_item_text(importers->get_selected())) {
- importer = E->get();
+ for (const Ref<ResourceImporter> &E : importer_list) {
+ if (E->get_visible_name() == importers->get_item_text(importers->get_selected())) {
+ importer = E;
break;
}
}
@@ -125,14 +125,14 @@ void ImportDefaultsEditor::_update_importer() {
d = ProjectSettings::get_singleton()->get("importer_defaults/" + importer->get_importer_name());
}
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- settings->properties.push_back(E->get().option);
- if (d.has(E->get().option.name)) {
- settings->values[E->get().option.name] = d[E->get().option.name];
+ for (const ResourceImporter::ImportOption &E : options) {
+ settings->properties.push_back(E.option);
+ if (d.has(E.option.name)) {
+ settings->values[E.option.name] = d[E.option.name];
} else {
- settings->values[E->get().option.name] = E->get().default_value;
+ settings->values[E.option.name] = E.default_value;
}
- settings->default_values[E->get().option.name] = E->get().default_value;
+ settings->default_values[E.option.name] = E.default_value;
}
save_defaults->set_disabled(false);
@@ -166,8 +166,8 @@ void ImportDefaultsEditor::clear() {
List<Ref<ResourceImporter>> importer_list;
ResourceFormatImporter::get_singleton()->get_importers(&importer_list);
Vector<String> names;
- for (List<Ref<ResourceImporter>>::Element *E = importer_list.front(); E; E = E->next()) {
- String vn = E->get()->get_visible_name();
+ for (const Ref<ResourceImporter> &E : importer_list) {
+ String vn = E->get_visible_name();
names.push_back(vn);
}
names.sort();
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 4110912ff3..648e60a554 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -65,14 +65,14 @@ public:
return false;
}
void _get_property_list(List<PropertyInfo> *p_list) const {
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (!importer->get_option_visibility(E->get().name, values)) {
+ for (const PropertyInfo &E : properties) {
+ if (!importer->get_option_visibility(E.name, values)) {
continue;
}
- PropertyInfo pi = E->get();
+ PropertyInfo pi = E;
if (checking) {
pi.usage |= PROPERTY_USAGE_CHECKABLE;
- if (checked.has(E->get().name)) {
+ if (checked.has(E.name)) {
pi.usage |= PROPERTY_USAGE_CHECKED;
}
}
@@ -111,18 +111,18 @@ void ImportDock::set_edit_path(const String &p_path) {
ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_path.get_extension(), &importers);
List<Pair<String, String>> importer_names;
- for (List<Ref<ResourceImporter>>::Element *E = importers.front(); E; E = E->next()) {
- importer_names.push_back(Pair<String, String>(E->get()->get_visible_name(), E->get()->get_importer_name()));
+ for (const Ref<ResourceImporter> &E : importers) {
+ importer_names.push_back(Pair<String, String>(E->get_visible_name(), E->get_importer_name()));
}
importer_names.sort_custom<PairSort<String, String>>();
import_as->clear();
- for (List<Pair<String, String>>::Element *E = importer_names.front(); E; E = E->next()) {
- import_as->add_item(E->get().first);
- import_as->set_item_metadata(import_as->get_item_count() - 1, E->get().second);
- if (E->get().second == importer_name) {
+ 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);
+ if (E.second == importer_name) {
import_as->select(import_as->get_item_count() - 1);
}
}
@@ -153,12 +153,12 @@ void ImportDock::_update_options(const Ref<ConfigFile> &p_config) {
params->checking = params->paths.size() > 1;
params->checked.clear();
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- params->properties.push_back(E->get().option);
- if (p_config.is_valid() && p_config->has_section_key("params", E->get().option.name)) {
- params->values[E->get().option.name] = p_config->get_value("params", E->get().option.name);
+ for (const ResourceImporter::ImportOption &E : options) {
+ params->properties.push_back(E.option);
+ if (p_config.is_valid() && p_config->has_section_key("params", E.option.name)) {
+ params->values[E.option.name] = p_config->get_value("params", E.option.name);
} else {
- params->values[E->get().option.name] = E->get().default_value;
+ params->values[E.option.name] = E.default_value;
}
}
@@ -201,17 +201,17 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
List<String> keys;
config->get_section_keys("params", &keys);
- for (List<String>::Element *E = keys.front(); E; E = E->next()) {
- if (!value_frequency.has(E->get())) {
- value_frequency[E->get()] = Dictionary();
+ for (const String &E : keys) {
+ if (!value_frequency.has(E)) {
+ value_frequency[E] = Dictionary();
}
- Variant value = config->get_value("params", E->get());
+ Variant value = config->get_value("params", E);
- if (value_frequency[E->get()].has(value)) {
- value_frequency[E->get()][value] = int(value_frequency[E->get()][value]) + 1;
+ if (value_frequency[E].has(value)) {
+ value_frequency[E][value] = int(value_frequency[E][value]) + 1;
} else {
- value_frequency[E->get()][value] = 1;
+ value_frequency[E][value] = 1;
}
}
}
@@ -226,25 +226,25 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
params->checking = true;
params->checked.clear();
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- params->properties.push_back(E->get().option);
+ for (const ResourceImporter::ImportOption &E : options) {
+ params->properties.push_back(E.option);
- if (value_frequency.has(E->get().option.name)) {
- Dictionary d = value_frequency[E->get().option.name];
+ if (value_frequency.has(E.option.name)) {
+ Dictionary d = value_frequency[E.option.name];
int freq = 0;
List<Variant> v;
d.get_key_list(&v);
Variant value;
- for (List<Variant>::Element *F = v.front(); F; F = F->next()) {
- int f = d[F->get()];
+ for (const Variant &F : v) {
+ int f = d[F];
if (f > freq) {
- value = F->get();
+ value = F;
}
}
- params->values[E->get().option.name] = value;
+ params->values[E.option.name] = value;
} else {
- params->values[E->get().option.name] = E->get().default_value;
+ params->values[E.option.name] = E.default_value;
}
}
@@ -254,18 +254,18 @@ void ImportDock::set_edit_multiple_paths(const Vector<String> &p_paths) {
ResourceFormatImporter::get_singleton()->get_importers_for_extension(p_paths[0].get_extension(), &importers);
List<Pair<String, String>> importer_names;
- for (List<Ref<ResourceImporter>>::Element *E = importers.front(); E; E = E->next()) {
- importer_names.push_back(Pair<String, String>(E->get()->get_visible_name(), E->get()->get_importer_name()));
+ for (const Ref<ResourceImporter> &E : importers) {
+ importer_names.push_back(Pair<String, String>(E->get_visible_name(), E->get_importer_name()));
}
importer_names.sort_custom<PairSort<String, String>>();
import_as->clear();
- for (List<Pair<String, String>>::Element *E = importer_names.front(); E; E = E->next()) {
- import_as->add_item(E->get().first);
- import_as->set_item_metadata(import_as->get_item_count() - 1, E->get().second);
- if (E->get().second == params->importer->get_importer_name()) {
+ 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);
+ if (E.second == params->importer->get_importer_name()) {
import_as->select(import_as->get_item_count() - 1);
}
}
@@ -345,8 +345,8 @@ void ImportDock::_preset_selected(int p_idx) {
case ITEM_SET_AS_DEFAULT: {
Dictionary d;
- for (const List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
- d[E->get().name] = params->values[E->get().name];
+ for (const PropertyInfo &E : params->properties) {
+ d[E.name] = params->values[E.name];
}
ProjectSettings::get_singleton()->set("importer_defaults/" + params->importer->get_importer_name(), d);
@@ -363,10 +363,10 @@ void ImportDock::_preset_selected(int p_idx) {
if (params->checking) {
params->checked.clear();
}
- for (List<Variant>::Element *E = v.front(); E; E = E->next()) {
- params->values[E->get()] = d[E->get()];
+ for (const Variant &E : v) {
+ params->values[E] = d[E];
if (params->checking) {
- params->checked.insert(E->get());
+ params->checked.insert(E);
}
}
params->update();
@@ -384,10 +384,10 @@ void ImportDock::_preset_selected(int p_idx) {
if (params->checking) {
params->checked.clear();
}
- for (List<ResourceImporter::ImportOption>::Element *E = options.front(); E; E = E->next()) {
- params->values[E->get().option.name] = E->get().default_value;
+ for (const ResourceImporter::ImportOption &E : options) {
+ params->values[E.option.name] = E.default_value;
if (params->checking) {
- params->checked.insert(E->get().option.name);
+ params->checked.insert(E.option.name);
}
}
params->update();
@@ -486,9 +486,9 @@ void ImportDock::_reimport() {
if (params->checking && config->get_value("remap", "importer") == params->importer->get_importer_name()) {
//update only what is edited (checkboxes) if the importer is the same
- for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
- if (params->checked.has(E->get().name)) {
- config->set_value("params", E->get().name, params->values[E->get().name]);
+ for (const PropertyInfo &E : params->properties) {
+ if (params->checked.has(E.name)) {
+ config->set_value("params", E.name, params->values[E.name]);
}
}
} else {
@@ -498,8 +498,8 @@ void ImportDock::_reimport() {
config->erase_section("params");
}
- for (List<PropertyInfo>::Element *E = params->properties.front(); E; E = E->next()) {
- config->set_value("params", E->get().name, params->values[E->get().name]);
+ for (const PropertyInfo &E : params->properties) {
+ config->set_value("params", E.name, params->values[E.name]);
}
}
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index ab307500e7..1973494a2a 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -87,12 +87,12 @@ void InspectorDock::_menu_option(int p_option) {
List<PropertyInfo> props;
current->get_property_list(&props);
Map<RES, RES> duplicates;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant v = current->get(E->get().name);
+ Variant v = current->get(E.name);
if (v.is_ref()) {
REF ref = v;
if (ref.is_valid()) {
@@ -103,8 +103,8 @@ void InspectorDock::_menu_option(int p_option) {
}
res = duplicates[res];
- current->set(E->get().name, res);
- editor->get_inspector()->update_property(E->get().name);
+ current->set(E.name, res);
+ editor->get_inspector()->update_property(E.name);
}
}
}
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index f51decd9dc..b32ea67d4d 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -43,15 +43,15 @@ void LocalizationEditor::_notification(int p_what) {
List<String> tfn;
ResourceLoader::get_recognized_extensions_for_type("Translation", &tfn);
- for (List<String>::Element *E = tfn.front(); E; E = E->next()) {
- translation_file_open->add_filter("*." + E->get());
+ for (const String &E : tfn) {
+ translation_file_open->add_filter("*." + E);
}
List<String> rfn;
ResourceLoader::get_recognized_extensions_for_type("Resource", &rfn);
- for (List<String>::Element *E = rfn.front(); E; E = E->next()) {
- translation_res_file_open_dialog->add_filter("*." + E->get());
- translation_res_option_file_open_dialog->add_filter("*." + E->get());
+ for (const String &E : rfn) {
+ translation_res_file_open_dialog->add_filter("*." + E);
+ translation_res_option_file_open_dialog->add_filter("*." + E);
}
_update_pot_file_extensions();
@@ -430,8 +430,8 @@ void LocalizationEditor::_update_pot_file_extensions() {
pot_file_open_dialog->clear_filters();
List<String> translation_parse_file_extensions;
EditorTranslationParser::get_singleton()->get_recognized_extensions(&translation_parse_file_extensions);
- for (List<String>::Element *E = translation_parse_file_extensions.front(); E; E = E->next()) {
- pot_file_open_dialog->add_filter("*." + E->get());
+ for (const String &E : translation_parse_file_extensions) {
+ pot_file_open_dialog->add_filter("*." + E);
}
}
@@ -560,8 +560,8 @@ void LocalizationEditor::update_translations() {
List<Variant> rk;
remaps.get_key_list(&rk);
Vector<String> keys;
- for (List<Variant>::Element *E = rk.front(); E; E = E->next()) {
- keys.push_back(E->get());
+ for (const Variant &E : rk) {
+ keys.push_back(E);
}
keys.sort();
diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp
index b714109af7..fd4a4334fc 100644
--- a/editor/multi_node_edit.cpp
+++ b/editor/multi_node_edit.cpp
@@ -52,12 +52,12 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value,
UndoRedo *ur = EditorNode::get_undo_redo();
ur->create_action(TTR("MultiNode Set") + " " + String(name), UndoRedo::MERGE_ENDS);
- for (const List<NodePath>::Element *E = nodes.front(); E; E = E->next()) {
- if (!es->has_node(E->get())) {
+ for (const NodePath &E : nodes) {
+ if (!es->has_node(E)) {
continue;
}
- Node *n = es->get_node(E->get());
+ Node *n = es->get_node(E);
if (!n) {
continue;
}
@@ -98,12 +98,12 @@ bool MultiNodeEdit::_get(const StringName &p_name, Variant &r_ret) const {
name = "script";
}
- for (const List<NodePath>::Element *E = nodes.front(); E; E = E->next()) {
- if (!es->has_node(E->get())) {
+ for (const NodePath &E : nodes) {
+ if (!es->has_node(E)) {
continue;
}
- const Node *n = es->get_node(E->get());
+ const Node *n = es->get_node(E);
if (!n) {
continue;
}
@@ -130,12 +130,12 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const {
List<PLData *> data_list;
- for (const List<NodePath>::Element *E = nodes.front(); E; E = E->next()) {
- if (!es->has_node(E->get())) {
+ for (const NodePath &E : nodes) {
+ if (!es->has_node(E)) {
continue;
}
- Node *n = es->get_node(E->get());
+ Node *n = es->get_node(E);
if (!n) {
continue;
}
@@ -143,30 +143,30 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const {
List<PropertyInfo> plist;
n->get_property_list(&plist, true);
- for (List<PropertyInfo>::Element *F = plist.front(); F; F = F->next()) {
- if (F->get().name == "script") {
+ for (const PropertyInfo &F : plist) {
+ if (F.name == "script") {
continue; //added later manually, since this is intercepted before being set (check Variant Object::get() )
}
- if (!usage.has(F->get().name)) {
+ if (!usage.has(F.name)) {
PLData pld;
pld.uses = 0;
- pld.info = F->get();
- usage[F->get().name] = pld;
- data_list.push_back(usage.getptr(F->get().name));
+ pld.info = F;
+ usage[F.name] = pld;
+ data_list.push_back(usage.getptr(F.name));
}
// Make sure only properties with the same exact PropertyInfo data will appear
- if (usage[F->get().name].info == F->get()) {
- usage[F->get().name].uses++;
+ if (usage[F.name].info == F) {
+ usage[F.name].uses++;
}
}
nc++;
}
- for (List<PLData *>::Element *E = data_list.front(); E; E = E->next()) {
- if (nc == E->get()->uses) {
- p_list->push_back(E->get()->info);
+ for (const PLData *E : data_list) {
+ if (nc == E->uses) {
+ p_list->push_back(E->info);
}
}
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index 35b27b25aa..5fe466140b 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -150,7 +150,7 @@ void PluginConfigDialog::_on_required_text_changed(const String &) {
if (script_edit->get_text().get_extension() != ext) {
is_valid = false;
script_validation->set_texture(invalid_icon);
- script_validation->set_tooltip(vformat(TTR("Script extension must match chosen langauge extension (.%s)."), ext));
+ script_validation->set_tooltip(vformat(TTR("Script extension must match chosen language extension (.%s)."), ext));
}
if (script_edit->get_text().get_basename().is_empty()) {
is_valid = false;
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index 9e58332e41..ad2d9866fa 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -72,22 +72,22 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven
List<StringName> names;
ap->get_animation_list(&names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E->get());
- animations_to_add.push_back(E->get());
+ for (const StringName &E : names) {
+ animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E);
+ animations_to_add.push_back(E);
}
}
}
- for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
- String name = String(E->get()).replace_first("AnimationNode", "");
+ for (const StringName &E : classes) {
+ String name = String(E).replace_first("AnimationNode", "");
if (name == "Animation") {
continue;
}
int idx = menu->get_item_count();
menu->add_item(vformat("Add %s", name), idx);
- menu->set_item_metadata(idx, E->get());
+ menu->set_item_metadata(idx, E);
}
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
@@ -373,8 +373,8 @@ void AnimationNodeBlendSpace1DEditor::_add_menu_type(int p_index) {
open_file->clear_filters();
List<String> filters;
ResourceLoader::get_recognized_extensions_for_type("AnimationRootNode", &filters);
- for (List<String>::Element *E = filters.front(); E; E = E->next()) {
- open_file->add_filter("*." + E->get());
+ for (const String &E : filters) {
+ open_file->add_filter("*." + E);
}
open_file->popup_file_dialog();
return;
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index bbf88bbd8f..49fcac512b 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -96,21 +96,21 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven
if (ap) {
List<StringName> names;
ap->get_animation_list(&names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E->get());
- animations_to_add.push_back(E->get());
+ for (const StringName &E : names) {
+ animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E);
+ animations_to_add.push_back(E);
}
}
}
- for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
- String name = String(E->get()).replace_first("AnimationNode", "");
+ for (const StringName &E : classes) {
+ String name = String(E).replace_first("AnimationNode", "");
if (name == "Animation") {
continue; // nope
}
int idx = menu->get_item_count();
menu->add_item(vformat("Add %s", name), idx);
- menu->set_item_metadata(idx, E->get());
+ menu->set_item_metadata(idx, E);
}
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
@@ -295,8 +295,8 @@ void AnimationNodeBlendSpace2DEditor::_add_menu_type(int p_index) {
open_file->clear_filters();
List<String> filters;
ResourceLoader::get_recognized_extensions_for_type("AnimationRootNode", &filters);
- for (List<String>::Element *E = filters.front(); E; E = E->next()) {
- open_file->add_filter("*." + E->get());
+ for (const String &E : filters) {
+ open_file->add_filter("*." + E);
}
open_file->popup_file_dialog();
return;
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index 7930bc1e1c..c94014944c 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -121,21 +121,21 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
List<StringName> nodes;
blend_tree->get_node_list(&nodes);
- for (List<StringName>::Element *E = nodes.front(); E; E = E->next()) {
+ for (const StringName &E : nodes) {
GraphNode *node = memnew(GraphNode);
graph->add_child(node);
- Ref<AnimationNode> agnode = blend_tree->get_node(E->get());
+ Ref<AnimationNode> agnode = blend_tree->get_node(E);
- node->set_position_offset(blend_tree->get_node_position(E->get()) * EDSCALE);
+ node->set_position_offset(blend_tree->get_node_position(E) * EDSCALE);
node->set_title(agnode->get_caption());
- node->set_name(E->get());
+ node->set_name(E);
int base = 0;
- if (String(E->get()) != "output") {
+ if (String(E) != "output") {
LineEdit *name = memnew(LineEdit);
- name->set_text(E->get());
+ name->set_text(E);
name->set_expand_to_text_length_enabled(true);
node->add_child(name);
node->set_slot(0, false, 0, Color(), true, 0, get_theme_color(SNAME("font_color"), SNAME("Label")));
@@ -143,7 +143,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out), varray(name, agnode), CONNECT_DEFERRED);
base = 1;
node->set_show_close_button(true);
- node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_request), varray(E->get()), CONNECT_DEFERRED);
+ node->connect("close_request", callable_mp(this, &AnimationNodeBlendTreeEditor::_delete_request), varray(E), CONNECT_DEFERRED);
}
for (int i = 0; i < agnode->get_input_count(); i++) {
@@ -155,12 +155,12 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
List<PropertyInfo> pinfo;
agnode->get_parameter_list(&pinfo);
- for (List<PropertyInfo>::Element *F = pinfo.front(); F; F = F->next()) {
- if (!(F->get().usage & PROPERTY_USAGE_EDITOR)) {
+ for (const PropertyInfo &F : pinfo) {
+ if (!(F.usage & PROPERTY_USAGE_EDITOR)) {
continue;
}
- String base_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E->get()) + "/" + F->get().name;
- EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_tree(), F->get().type, base_path, F->get().hint, F->get().hint_string, F->get().usage);
+ String base_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E) + "/" + F.name;
+ EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_tree(), F.type, base_path, F.hint, F.hint_string, F.usage);
if (prop) {
prop->set_object_and_property(AnimationTreeEditor::get_singleton()->get_tree(), base_path);
prop->update_property();
@@ -171,7 +171,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
}
}
- node->connect("dragged", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_dragged), varray(E->get()));
+ node->connect("dragged", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_dragged), varray(E));
if (AnimationTreeEditor::get_singleton()->can_edit(agnode)) {
node->add_child(memnew(HSeparator));
@@ -179,7 +179,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
open_in_editor->set_text(TTR("Open Editor"));
open_in_editor->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
node->add_child(open_in_editor);
- open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor), varray(E->get()), CONNECT_DEFERRED);
+ open_in_editor->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_open_in_editor), varray(E), CONNECT_DEFERRED);
open_in_editor->set_h_size_flags(SIZE_SHRINK_CENTER);
}
@@ -189,7 +189,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
edit_filters->set_text(TTR("Edit Filters"));
edit_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons")));
node->add_child(edit_filters);
- edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters), varray(E->get()), CONNECT_DEFERRED);
+ edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters), varray(E), CONNECT_DEFERRED);
edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER);
}
@@ -212,9 +212,9 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
List<StringName> anims;
ap->get_animation_list(&anims);
- for (List<StringName>::Element *F = anims.front(); F; F = F->next()) {
- mb->get_popup()->add_item(F->get());
- options.push_back(F->get());
+ for (const StringName &F : anims) {
+ mb->get_popup()->add_item(F);
+ options.push_back(F);
}
if (ap->has_animation(anim->get_animation())) {
@@ -225,10 +225,10 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
pb->set_percent_visible(false);
pb->set_custom_minimum_size(Vector2(0, 14) * EDSCALE);
- animations[E->get()] = pb;
+ animations[E] = pb;
node->add_child(pb);
- mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected), varray(options, E->get()), CONNECT_DEFERRED);
+ mb->get_popup()->connect("index_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_anim_selected), varray(options, E), CONNECT_DEFERRED);
}
Ref<StyleBoxFlat> sb = node->get_theme_stylebox(SNAME("frame"), SNAME("GraphNode"));
@@ -246,10 +246,10 @@ void AnimationNodeBlendTreeEditor::_update_graph() {
List<AnimationNodeBlendTree::NodeConnection> connections;
blend_tree->get_node_connections(&connections);
- for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = connections.front(); E; E = E->next()) {
- StringName from = E->get().output_node;
- StringName to = E->get().input_node;
- int to_idx = E->get().input_index;
+ for (const AnimationNodeBlendTree::NodeConnection &E : connections) {
+ StringName from = E.output_node;
+ StringName to = E.input_node;
+ int to_idx = E.input_index;
graph->connect_node(from, 0, to, to_idx);
}
@@ -274,8 +274,8 @@ void AnimationNodeBlendTreeEditor::_add_node(int p_idx) {
open_file->clear_filters();
List<String> filters;
ResourceLoader::get_recognized_extensions_for_type("AnimationNode", &filters);
- for (List<String>::Element *E = filters.front(); E; E = E->next()) {
- open_file->add_filter("*." + E->get());
+ for (const String &E : filters) {
+ open_file->add_filter("*." + E);
}
open_file->popup_file_dialog();
return;
@@ -394,9 +394,9 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) {
List<AnimationNodeBlendTree::NodeConnection> conns;
blend_tree->get_node_connections(&conns);
- for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().output_node == p_which || E->get().input_node == p_which) {
- undo_redo->add_undo_method(blend_tree.ptr(), "connect_node", E->get().input_node, E->get().input_index, E->get().output_node);
+ for (const AnimationNodeBlendTree::NodeConnection &E : conns) {
+ if (E.output_node == p_which || E.input_node == p_which) {
+ undo_redo->add_undo_method(blend_tree.ptr(), "connect_node", E.input_node, E.input_index, E.output_node);
}
}
@@ -423,8 +423,8 @@ void AnimationNodeBlendTreeEditor::_delete_nodes_request() {
undo_redo->create_action(TTR("Delete Node(s)"));
- for (List<StringName>::Element *F = to_erase.front(); F; F = F->next()) {
- _delete_request(F->get());
+ for (const StringName &F : to_erase) {
+ _delete_request(F);
}
undo_redo->commit_action();
@@ -517,8 +517,8 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano
List<StringName> animations;
player->get_animation_list(&animations);
- for (List<StringName>::Element *E = animations.front(); E; E = E->next()) {
- Ref<Animation> anim = player->get_animation(E->get());
+ for (const StringName &E : animations) {
+ Ref<Animation> anim = player->get_animation(E);
for (int i = 0; i < anim->get_track_count(); i++) {
String track_path = anim->track_get_path(i);
paths.insert(track_path);
@@ -718,13 +718,13 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
List<AnimationNodeBlendTree::NodeConnection> conns;
blend_tree->get_node_connections(&conns);
- for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = conns.front(); E; E = E->next()) {
+ for (const AnimationNodeBlendTree::NodeConnection &E : conns) {
float activity = 0;
- StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E->get().input_node;
+ StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E.input_node;
if (AnimationTreeEditor::get_singleton()->get_tree() && !AnimationTreeEditor::get_singleton()->get_tree()->is_state_invalid()) {
- activity = AnimationTreeEditor::get_singleton()->get_tree()->get_connection_activity(path, E->get().input_index);
+ activity = AnimationTreeEditor::get_singleton()->get_tree()->get_connection_activity(path, E.input_index);
}
- graph->set_connection_activity(E->get().output_node, 0, E->get().input_node, E->get().input_index, activity);
+ graph->set_connection_activity(E.output_node, 0, E.input_node, E.input_index, activity);
}
AnimationTree *graph_player = AnimationTreeEditor::get_singleton()->get_tree();
@@ -741,7 +741,7 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) {
Ref<Animation> anim = player->get_animation(an->get_animation());
if (anim.is_valid()) {
E->get()->set_max(anim->get_length());
- //StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E->get().input_node;
+ //StringName path = AnimationTreeEditor::get_singleton()->get_base_path() + E.input_node;
StringName time_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E->key()) + "/time";
E->get()->set_value(AnimationTreeEditor::get_singleton()->get_tree()->get(time_path));
}
@@ -828,10 +828,10 @@ void AnimationNodeBlendTreeEditor::_node_renamed(const String &p_text, Ref<Anima
List<AnimationNodeBlendTree::NodeConnection> connections;
blend_tree->get_node_connections(&connections);
- for (List<AnimationNodeBlendTree::NodeConnection>::Element *E = connections.front(); E; E = E->next()) {
- StringName from = E->get().output_node;
- StringName to = E->get().input_node;
- int to_idx = E->get().input_index;
+ for (const AnimationNodeBlendTree::NodeConnection &E : connections) {
+ StringName from = E.output_node;
+ StringName to = E.input_node;
+ int to_idx = E.input_index;
graph->connect_node(from, 0, to, to_idx);
}
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index cbce5bb3f5..4ba9147955 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -350,8 +350,8 @@ void AnimationPlayerEditor::_animation_load() {
List<String> extensions;
ResourceLoader::get_recognized_extensions_for_type("Animation", &extensions);
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
+ for (const String &E : extensions) {
+ file->add_filter("*." + E + " ; " + E.to_upper());
}
file->popup_file_dialog();
@@ -584,8 +584,7 @@ void AnimationPlayerEditor::_animation_blend() {
blend_editor.next->clear();
blend_editor.next->add_item("", i);
- for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
- String to = E->get();
+ for (const StringName &to : anims) {
TreeItem *blend = blend_editor.tree->create_item(root);
blend->set_editable(0, false);
blend->set_editable(1, true);
@@ -830,20 +829,20 @@ void AnimationPlayerEditor::_update_player() {
}
int active_idx = -1;
- for (List<StringName>::Element *E = animlist.front(); E; E = E->next()) {
+ for (const StringName &E : animlist) {
Ref<Texture2D> icon;
- if (E->get() == player->get_autoplay()) {
- if (E->get() == "RESET") {
+ if (E == player->get_autoplay()) {
+ if (E == "RESET") {
icon = autoplay_reset_icon;
} else {
icon = autoplay_icon;
}
- } else if (E->get() == "RESET") {
+ } else if (E == "RESET") {
icon = reset_icon;
}
- animation->add_icon_item(icon, E->get());
+ animation->add_icon_item(icon, E);
- if (player->get_assigned_animation() == E->get()) {
+ if (player->get_assigned_animation() == E) {
active_idx = animation->get_item_count() - 1;
}
}
@@ -966,9 +965,9 @@ void AnimationPlayerEditor::_animation_duplicate() {
Ref<Animation> new_anim = memnew(Animation);
List<PropertyInfo> plist;
anim->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (E->get().usage & PROPERTY_USAGE_STORAGE) {
- new_anim->set(E->get().name, anim->get(E->get().name));
+ for (const PropertyInfo &E : plist) {
+ if (E.usage & PROPERTY_USAGE_STORAGE) {
+ new_anim->set(E.name, anim->get(E.name));
}
}
new_anim->set_path("");
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 8abe20c3c9..a1f96f21bf 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -93,21 +93,21 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
if (ap) {
List<StringName> names;
ap->get_animation_list(&names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E->get());
- animations_to_add.push_back(E->get());
+ for (const StringName &E : names) {
+ animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E);
+ animations_to_add.push_back(E);
}
}
}
- for (List<StringName>::Element *E = classes.front(); E; E = E->next()) {
- String name = String(E->get()).replace_first("AnimationNode", "");
+ for (const StringName &E : classes) {
+ String name = String(E).replace_first("AnimationNode", "");
if (name == "Animation") {
continue; // nope
}
int idx = menu->get_item_count();
menu->add_item(vformat("Add %s", name), idx);
- menu->set_item_metadata(idx, E->get());
+ menu->set_item_metadata(idx, E);
}
Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard();
@@ -318,24 +318,24 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
float best_d_x = 1e20;
float best_d_y = 1e20;
- for (List<StringName>::Element *E = nodes.front(); E; E = E->next()) {
- if (E->get() == selected_node) {
+ for (const StringName &E : nodes) {
+ if (E == selected_node) {
continue;
}
- Vector2 npos = state_machine->get_node_position(E->get());
+ Vector2 npos = state_machine->get_node_position(E);
float d_x = ABS(npos.x - cpos.x);
if (d_x < MIN(5, best_d_x)) {
drag_ofs.x -= cpos.x - npos.x;
best_d_x = d_x;
- snap_x = E->get();
+ snap_x = E;
}
float d_y = ABS(npos.y - cpos.y);
if (d_y < MIN(5, best_d_y)) {
drag_ofs.y -= cpos.y - npos.y;
best_d_y = d_y;
- snap_y = E->get();
+ snap_y = E;
}
}
}
@@ -409,8 +409,8 @@ void AnimationNodeStateMachineEditor::_add_menu_type(int p_index) {
open_file->clear_filters();
List<String> filters;
ResourceLoader::get_recognized_extensions_for_type("AnimationRootNode", &filters);
- for (List<String>::Element *E = filters.front(); E; E = E->next()) {
- open_file->add_filter("*." + E->get());
+ for (const String &E : filters) {
+ open_file->add_filter("*." + E);
}
open_file->popup_file_dialog();
return;
@@ -606,11 +606,11 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
//pre pass nodes so we know the rectangles
- for (List<StringName>::Element *E = nodes.front(); E; E = E->next()) {
- Ref<AnimationNode> anode = state_machine->get_node(E->get());
- String name = E->get();
+ for (const StringName &E : nodes) {
+ Ref<AnimationNode> anode = state_machine->get_node(E);
+ String name = E;
bool needs_editor = EditorNode::get_singleton()->item_has_editor(anode.ptr());
- Ref<StyleBox> sb = E->get() == selected_node ? style_selected : style;
+ Ref<StyleBox> sb = E == selected_node ? style_selected : style;
Size2 s = sb->get_minimum_size();
int strsize = font->get_string_size(name, font_size).width;
@@ -622,8 +622,8 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
Vector2 offset;
- offset += state_machine->get_node_position(E->get()) * EDSCALE;
- if (selected_node == E->get() && dragging_selected) {
+ offset += state_machine->get_node_position(E) * EDSCALE;
+ if (selected_node == E && dragging_selected) {
offset += drag_ofs;
}
offset -= s / 2;
@@ -633,7 +633,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
NodeRect nr;
nr.node = Rect2(offset, s);
- nr.node_name = E->get();
+ nr.node_name = E;
scroll_range = scroll_range.merge(nr.node); //merge with range
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 9c28e023dd..cd84be0c25 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -215,8 +215,8 @@ Vector<String> AnimationTreeEditor::get_animation_list() {
List<StringName> anims;
ap->get_animation_list(&anims);
Vector<String> ret;
- for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const StringName &E : anims) {
+ ret.push_back(E);
}
return ret;
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index bbc8107cf6..785bab42cf 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -603,12 +603,11 @@ void EditorAssetLibrary::_notification(int p_what) {
void EditorAssetLibrary::_update_repository_options() {
Dictionary default_urls;
- default_urls["godotengine.org"] = "https://godotengine.org/asset-library/api";
- default_urls["localhost"] = "http://127.0.0.1/asset-library/api";
+ default_urls["godotengine.org (Official)"] = "https://godotengine.org/asset-library/api";
Dictionary available_urls = _EDITOR_DEF("asset_library/available_urls", default_urls, true);
repository->clear();
Array keys = available_urls.keys();
- for (int i = 0; i < available_urls.size(); i++) {
+ for (int i = 0; i < keys.size(); i++) {
String key = keys[i];
repository->add_item(key);
repository->set_item_metadata(i, available_urls[key]);
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index d5ef13e426..869a582d96 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -301,8 +301,8 @@ void CanvasItemEditor::_snap_other_nodes(
// Check if the element is in the exception
bool exception = false;
- for (List<const CanvasItem *>::Element *E = p_exceptions.front(); E; E = E->next()) {
- if (E->get() == p_current) {
+ for (const CanvasItem *&E : p_exceptions) {
+ if (E == p_current) {
exception = true;
break;
}
@@ -399,8 +399,8 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, unsig
if ((is_snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
Transform2D to_snap_transform = Transform2D();
List<const CanvasItem *> exceptions = List<const CanvasItem *>();
- for (List<CanvasItem *>::Element *E = p_other_nodes_exceptions.front(); E; E = E->next()) {
- exceptions.push_back(E->get());
+ for (const CanvasItem *E : p_other_nodes_exceptions) {
+ exceptions.push_back(E);
}
if (p_self_canvas_item) {
exceptions.push_back(p_self_canvas_item);
@@ -527,8 +527,7 @@ Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_li
Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2());
// Expand with the other ones
- for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) {
- CanvasItem *canvas_item2 = E->get();
+ for (CanvasItem *canvas_item2 : p_list) {
Transform2D xform = canvas_item2->get_global_transform_with_canvas();
Rect2 current_rect = canvas_item2->_edit_get_rect();
@@ -760,9 +759,9 @@ List<CanvasItem *> CanvasItemEditor::_get_edited_canvas_items(bool retreive_lock
if (remove_canvas_item_if_parent_in_selection) {
List<CanvasItem *> filtered_selection;
- for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
- if (!selection.find(E->get()->get_parent())) {
- filtered_selection.push_back(E->get());
+ for (CanvasItem *E : selection) {
+ if (!selection.find(E->get_parent())) {
+ filtered_selection.push_back(E);
}
}
return filtered_selection;
@@ -800,8 +799,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
}
void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones) {
- for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : p_canvas_items) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (se) {
se->undo_state = canvas_item->_edit_get_state();
@@ -816,8 +814,7 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items
}
void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones) {
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : drag_selection) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
canvas_item->_edit_set_state(se->undo_state);
}
@@ -825,8 +822,7 @@ void CanvasItemEditor::_restore_canvas_item_state(List<CanvasItem *> p_canvas_it
void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones) {
List<CanvasItem *> modified_canvas_items;
- for (List<CanvasItem *>::Element *E = p_canvas_items.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : p_canvas_items) {
Dictionary old_state = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item)->undo_state;
Dictionary new_state = canvas_item->_edit_get_state();
@@ -840,17 +836,16 @@ void CanvasItemEditor::_commit_canvas_item_state(List<CanvasItem *> p_canvas_ite
}
undo_redo->create_action(action_name);
- for (List<CanvasItem *>::Element *E = modified_canvas_items.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : modified_canvas_items) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (se) {
undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
undo_redo->add_undo_method(canvas_item, "_edit_set_state", se->undo_state);
if (commit_bones) {
- for (List<Dictionary>::Element *F = se->pre_drag_bones_undo_state.front(); F; F = F->next()) {
+ for (const Dictionary &F : se->pre_drag_bones_undo_state) {
canvas_item = Object::cast_to<CanvasItem>(canvas_item->get_parent());
undo_redo->add_do_method(canvas_item, "_edit_set_state", canvas_item->_edit_get_state());
- undo_redo->add_undo_method(canvas_item, "_edit_set_state", F->get());
+ undo_redo->add_undo_method(canvas_item, "_edit_set_state", F);
}
}
}
@@ -1304,8 +1299,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
// Filters the selection with nodes that allow setting the pivot
drag_selection = List<CanvasItem *>();
- for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : selection) {
if (canvas_item->_edit_use_pivot()) {
drag_selection.push_back(canvas_item);
}
@@ -1321,8 +1315,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
} else {
new_pos = snap_point(drag_from, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, 0, nullptr, drag_selection);
}
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : drag_selection) {
canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
}
@@ -1343,8 +1336,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) {
} else {
new_pos = snap_point(drag_to, SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL);
}
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : drag_selection) {
canvas_item->_edit_set_pivot(canvas_item->get_global_transform_with_canvas().affine_inverse().xform(new_pos));
}
return true;
@@ -1387,8 +1379,8 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
List<CanvasItem *> selection = _get_edited_canvas_items();
// Remove not movable nodes
- for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
- if (!_is_node_movable(E->get(), true)) {
+ for (CanvasItem *E : selection) {
+ if (!_is_node_movable(E, true)) {
selection.erase(E);
}
}
@@ -1414,8 +1406,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) {
// Rotate the node
if (m.is_valid()) {
_restore_canvas_item_state(drag_selection);
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : drag_selection) {
drag_to = transform.affine_inverse().xform(m->get_position());
//Rotate the opposite way if the canvas item's compounded scale has an uneven number of negative elements
bool opposite = (canvas_item->get_global_transform().get_scale().sign().dot(canvas_item->get_transform().get_scale().sign()) == 0);
@@ -2046,8 +2037,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
}
int index = 0;
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : drag_selection) {
Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
@@ -2162,8 +2152,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
}
int index = 0;
- for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : drag_selection) {
Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
@@ -2375,8 +2364,8 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
if (selitems.size() == 1 && editor_selection->get_selected_node_list().is_empty()) {
editor->push_item(selitems[0]);
}
- for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) {
- editor_selection->add_node(E->get());
+ for (CanvasItem *E : selitems) {
+ editor_selection->add_node(E);
}
}
@@ -3248,8 +3237,8 @@ void CanvasItemEditor::_draw_selection() {
List<CanvasItem *> selection = _get_edited_canvas_items(true, false);
bool single = selection.size() == 1;
- for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
+ for (CanvasItem *E : selection) {
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E);
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
bool item_locked = canvas_item->has_meta("_edit_lock_");
@@ -3566,9 +3555,9 @@ void CanvasItemEditor::_draw_hover() {
Point2 pos = transform.xform(hovering_results[i].position) - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4);
// Rectify the position to avoid overlapping items
- for (List<Rect2>::Element *E = previous_rects.front(); E; E = E->next()) {
- if (E->get().intersects(Rect2(pos, item_size))) {
- pos.y = E->get().get_position().y - item_size.y;
+ for (const Rect2 &E : previous_rects) {
+ if (E.intersects(Rect2(pos, item_size))) {
+ pos.y = E.get_position().y - item_size.y;
}
}
@@ -3642,14 +3631,14 @@ void CanvasItemEditor::_draw_viewport() {
all_locked = false;
all_group = false;
} else {
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_lock_")) {
+ for (Node *E : selection) {
+ if (Object::cast_to<CanvasItem>(E) && !Object::cast_to<CanvasItem>(E)->has_meta("_edit_lock_")) {
all_locked = false;
break;
}
}
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_group_")) {
+ for (Node *E : selection) {
+ if (Object::cast_to<CanvasItem>(E) && !Object::cast_to<CanvasItem>(E)->has_meta("_edit_group_")) {
all_group = false;
break;
}
@@ -3716,8 +3705,7 @@ void CanvasItemEditor::_notification(int p_what) {
// Update the viewport if the canvas_item changes
List<CanvasItem *> selection = _get_edited_canvas_items(true);
- for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = E->get();
+ for (CanvasItem *canvas_item : selection) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
Rect2 rect;
@@ -3932,8 +3920,8 @@ void CanvasItemEditor::_selection_changed() {
int nbValidControls = 0;
int nbAnchorsMode = 0;
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Control *control = Object::cast_to<Control>(E->get());
+ for (Node *E : selection) {
+ Control *control = Object::cast_to<Control>(E);
if (!control) {
continue;
}
@@ -4101,8 +4089,8 @@ void CanvasItemEditor::_set_anchors_and_offsets_preset(Control::LayoutPreset p_p
undo_redo->create_action(TTR("Change Anchors and Offsets"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Control *control = Object::cast_to<Control>(E->get());
+ for (Node *E : selection) {
+ Control *control = Object::cast_to<Control>(E);
if (control) {
undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
switch (p_preset) {
@@ -4142,8 +4130,8 @@ void CanvasItemEditor::_set_anchors_and_offsets_to_keep_ratio() {
undo_redo->create_action(TTR("Change Anchors and Offsets"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Control *control = Object::cast_to<Control>(E->get());
+ for (Node *E : selection) {
+ Control *control = Object::cast_to<Control>(E);
if (control) {
Point2 top_left_anchor = _position_to_anchor(control, Point2());
Point2 bottom_right_anchor = _position_to_anchor(control, control->get_size());
@@ -4169,8 +4157,8 @@ void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
List<Node *> selection = editor_selection->get_selected_node_list();
undo_redo->create_action(TTR("Change Anchors"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Control *control = Object::cast_to<Control>(E->get());
+ for (Node *E : selection) {
+ Control *control = Object::cast_to<Control>(E);
if (control) {
undo_redo->add_do_method(control, "set_anchors_preset", p_preset);
undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
@@ -4295,15 +4283,15 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
}
if (has_chain && ik_chain.size()) {
- for (List<Node2D *>::Element *F = ik_chain.front(); F; F = F->next()) {
+ for (Node2D *&F : ik_chain) {
if (key_pos) {
- AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "position", F->get()->get_position(), p_on_existing);
+ AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F, "position", F->get_position(), p_on_existing);
}
if (key_rot) {
- AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "rotation", F->get()->get_rotation(), p_on_existing);
+ AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F, "rotation", F->get_rotation(), p_on_existing);
}
if (key_scale) {
- AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F->get(), "scale", F->get()->get_scale(), p_on_existing);
+ AnimationPlayerEditor::singleton->get_track_editor()->insert_node_value_key(F, "scale", F->get_scale(), p_on_existing);
}
}
}
@@ -4327,8 +4315,8 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
void CanvasItemEditor::_button_toggle_anchor_mode(bool p_status) {
List<CanvasItem *> selection = _get_edited_canvas_items(false, false);
- for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
- Control *control = Object::cast_to<Control>(E->get());
+ for (CanvasItem *E : selection) {
+ Control *control = Object::cast_to<Control>(E);
if (!control || Object::cast_to<Container>(control->get_parent())) {
continue;
}
@@ -4441,13 +4429,13 @@ void CanvasItemEditor::_popup_callback(int p_op) {
} break;
case SKELETON_SHOW_BONES: {
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ for (Node *E : selection) {
// Add children nodes so they are processed
- for (int child = 0; child < E->get()->get_child_count(); child++) {
- selection.push_back(E->get()->get_child(child));
+ for (int child = 0; child < E->get_child_count(); child++) {
+ selection.push_back(E->get_child(child));
}
- Bone2D *bone_2d = Object::cast_to<Bone2D>(E->get());
+ Bone2D *bone_2d = Object::cast_to<Bone2D>(E);
if (!bone_2d || !bone_2d->is_inside_tree()) {
continue;
}
@@ -4477,8 +4465,8 @@ void CanvasItemEditor::_popup_callback(int p_op) {
undo_redo->create_action(TTR("Lock Selected"));
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
+ for (Node *E : selection) {
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E);
if (!canvas_item || !canvas_item->is_inside_tree()) {
continue;
}
@@ -4499,8 +4487,8 @@ void CanvasItemEditor::_popup_callback(int p_op) {
undo_redo->create_action(TTR("Unlock Selected"));
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
+ for (Node *E : selection) {
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E);
if (!canvas_item || !canvas_item->is_inside_tree()) {
continue;
}
@@ -4521,8 +4509,8 @@ void CanvasItemEditor::_popup_callback(int p_op) {
undo_redo->create_action(TTR("Group Selected"));
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
+ for (Node *E : selection) {
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E);
if (!canvas_item || !canvas_item->is_inside_tree()) {
continue;
}
@@ -4543,8 +4531,8 @@ void CanvasItemEditor::_popup_callback(int p_op) {
undo_redo->create_action(TTR("Ungroup Selected"));
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
+ for (Node *E : selection) {
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E);
if (!canvas_item || !canvas_item->is_inside_tree()) {
continue;
}
@@ -4711,14 +4699,14 @@ void CanvasItemEditor::_popup_callback(int p_op) {
}
undo_redo->create_action(TTR("Paste Pose"));
- for (List<PoseClipboard>::Element *E = pose_clipboard.front(); E; E = E->next()) {
- Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->get().id));
+ for (const PoseClipboard &E : pose_clipboard) {
+ Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E.id));
if (!n2d) {
continue;
}
- undo_redo->add_do_method(n2d, "set_position", E->get().pos);
- undo_redo->add_do_method(n2d, "set_rotation", E->get().rot);
- undo_redo->add_do_method(n2d, "set_scale", E->get().scale);
+ undo_redo->add_do_method(n2d, "set_position", E.pos);
+ undo_redo->add_do_method(n2d, "set_rotation", E.rot);
+ undo_redo->add_do_method(n2d, "set_scale", E.scale);
undo_redo->add_undo_method(n2d, "set_position", n2d->get_position());
undo_redo->add_undo_method(n2d, "set_rotation", n2d->get_rotation());
undo_redo->add_undo_method(n2d, "set_scale", n2d->get_scale());
@@ -5325,7 +5313,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
select_button->set_pressed(true);
select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), KEY_Q));
select_button->set_shortcut_context(this);
- select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate") + "\n" + TTR("Alt+Drag: Move") + "\n" + TTR("Press 'v' to Change Pivot, 'Shift+v' to Drag Pivot (while moving).") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
+ select_button->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("RMB: Add node at position clicked."));
hb->add_child(memnew(VSeparator));
@@ -5819,14 +5807,14 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
String property = "texture";
List<PropertyInfo> props;
child->get_property_list(&props);
- for (const List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (E->get().name == "config/texture") { // Particles2D
+ for (const PropertyInfo &E : props) {
+ if (E.name == "config/texture") { // Particles2D
property = "config/texture";
break;
- } else if (E->get().name == "texture/texture") { // Polygon2D
+ } else if (E.name == "texture/texture") { // Polygon2D
property = "texture/texture";
break;
- } else if (E->get().name == "normal") { // TouchScreenButton
+ } else if (E.name == "normal") { // TouchScreenButton
property = "normal";
break;
}
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp
index 45adbe29de..2c2adc2672 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp
@@ -31,6 +31,7 @@
#include "collision_shape_2d_editor_plugin.h"
#include "canvas_item_editor_plugin.h"
+#include "core/os/keyboard.h"
#include "scene/resources/capsule_shape_2d.h"
#include "scene/resources/circle_shape_2d.h"
#include "scene/resources/concave_polygon_shape_2d.h"
@@ -97,7 +98,7 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const {
case RECTANGLE_SHAPE: {
Ref<RectangleShape2D> rect = node->get_shape();
- if (idx < 3) {
+ if (idx < 8) {
return rect->get_size().abs();
}
@@ -176,16 +177,26 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) {
} break;
case RECTANGLE_SHAPE: {
- if (idx < 3) {
+ if (idx < 8) {
Ref<RectangleShape2D> rect = node->get_shape();
+ Vector2 size = (Point2)original;
- Vector2 size = rect->get_size();
- if (idx == 2) {
- size = p_point * 2;
+ if (RECT_HANDLES[idx].x != 0) {
+ size.x = p_point.x * RECT_HANDLES[idx].x * 2;
+ }
+ if (RECT_HANDLES[idx].y != 0) {
+ size.y = p_point.y * RECT_HANDLES[idx].y * 2;
+ }
+
+ if (Input::get_singleton()->is_key_pressed(KEY_ALT)) {
+ rect->set_size(size.abs());
+ node->set_global_position(original_transform.get_origin());
} else {
- size[idx] = p_point[idx] * 2;
+ rect->set_size(((Point2)original + (size - (Point2)original) * 0.5).abs());
+ Point2 pos = original_transform.affine_inverse().xform(original_transform.get_origin());
+ pos += (size - (Point2)original) * 0.5 * RECT_HANDLES[idx] * 0.5;
+ node->set_global_position(original_transform.xform(pos));
}
- rect->set_size(size.abs());
canvas_item_editor->update_viewport();
}
@@ -280,8 +291,10 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) {
Ref<RectangleShape2D> rect = node->get_shape();
undo_redo->add_do_method(rect.ptr(), "set_size", rect->get_size());
+ undo_redo->add_do_method(node, "set_global_transform", node->get_global_transform());
undo_redo->add_do_method(canvas_item_editor, "update_viewport");
undo_redo->add_undo_method(rect.ptr(), "set_size", p_org);
+ undo_redo->add_undo_method(node, "set_global_transform", original_transform);
undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
} break;
@@ -342,6 +355,8 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
}
original = get_handle_value(edit_handle);
+ original_transform = node->get_global_transform();
+ last_point = original;
pressed = true;
return true;
@@ -369,13 +384,26 @@ bool CollisionShape2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_e
}
Vector2 cpoint = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()));
- cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
+ cpoint = original_transform.affine_inverse().xform(cpoint);
+ last_point = cpoint;
set_handle(edit_handle, cpoint);
return true;
}
+ Ref<InputEventKey> k = p_event;
+
+ if (k.is_valid()) {
+ if (edit_handle == -1 || !pressed || k->is_echo()) {
+ return false;
+ }
+
+ if (shape_type == RECTANGLE_SHAPE && k->get_keycode() == KEY_ALT) {
+ set_handle(edit_handle, last_point); // Update handle when Alt key is toggled.
+ }
+ }
+
return false;
}
@@ -492,15 +520,12 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla
case RECTANGLE_SHAPE: {
Ref<RectangleShape2D> shape = node->get_shape();
- handles.resize(3);
+ handles.resize(8);
Vector2 ext = shape->get_size() / 2;
- handles.write[0] = Point2(ext.x, 0);
- handles.write[1] = Point2(0, ext.y);
- handles.write[2] = Point2(ext.x, ext.y);
-
- p_overlay->draw_texture(h, gt.xform(handles[0]) - size);
- p_overlay->draw_texture(h, gt.xform(handles[1]) - size);
- p_overlay->draw_texture(h, gt.xform(handles[2]) - size);
+ for (int i = 0; i < handles.size(); i++) {
+ handles.write[i] = RECT_HANDLES[i] * ext;
+ p_overlay->draw_texture(h, gt.xform(handles[i]) - size);
+ }
} break;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index 054db1a61b..7db6bd22aa 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -52,6 +52,17 @@ class CollisionShape2DEditor : public Control {
SEGMENT_SHAPE
};
+ const Point2 RECT_HANDLES[8] = {
+ Point2(1, 0),
+ Point2(1, 1),
+ Point2(0, 1),
+ Point2(-1, 1),
+ Point2(-1, 0),
+ Point2(-1, -1),
+ Point2(0, -1),
+ Point2(1, -1),
+ };
+
EditorNode *editor;
UndoRedo *undo_redo;
CanvasItemEditor *canvas_item_editor;
@@ -63,6 +74,8 @@ class CollisionShape2DEditor : public Control {
int edit_handle;
bool pressed;
Variant original;
+ Transform2D original_transform;
+ Point2 last_point;
Variant get_handle_value(int idx) const;
void set_handle(int idx, Point2 &p_point);
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
index c4deb296fb..6f246c1661 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp
@@ -253,8 +253,8 @@ CPUParticles2DEditorPlugin::CPUParticles2DEditorPlugin(EditorNode *p_node) {
file = memnew(EditorFileDialog);
List<String> ext;
ImageLoader::get_recognized_extensions(&ext);
- for (List<String>::Element *E = ext.front(); E; E = E->next()) {
- file->add_filter("*." + E->get() + "; " + E->get().to_upper());
+ for (const String &E : ext) {
+ file->add_filter("*." + E + "; " + E.to_upper());
}
file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
toolbar->add_child(file);
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index a233d66d82..81c340e9a4 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -490,11 +490,11 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size
Set<String> control_flow_keywords;
Set<String> keywords;
- for (List<String>::Element *E = kwors.front(); E; E = E->next()) {
- if (scr->get_language()->is_control_flow_keyword(E->get())) {
- control_flow_keywords.insert(E->get());
+ for (const String &E : kwors) {
+ if (scr->get_language()->is_control_flow_keyword(E)) {
+ control_flow_keywords.insert(E);
} else {
- keywords.insert(E->get());
+ keywords.insert(E);
}
}
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
index cc5793a1f9..5184e837ce 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp
@@ -361,8 +361,8 @@ GPUParticles2DEditorPlugin::GPUParticles2DEditorPlugin(EditorNode *p_node) {
file = memnew(EditorFileDialog);
List<String> ext;
ImageLoader::get_recognized_extensions(&ext);
- for (List<String>::Element *E = ext.front(); E; E = E->next()) {
- file->add_filter("*." + E->get() + "; " + E->get().to_upper());
+ for (const String &E : ext) {
+ file->add_filter("*." + E + "; " + E.to_upper());
}
file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
toolbar->add_child(file);
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 7105d351b0..94966d4fe6 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -265,15 +265,15 @@ Ref<Resource> StandardMaterial3DConversionPlugin::convert(const Ref<Resource> &p
List<PropertyInfo> params;
RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
- for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
+ for (const PropertyInfo &E : params) {
// Texture parameter has to be treated specially since StandardMaterial3D saved it
// as RID but ShaderMaterial needs Texture itself
- Ref<Texture2D> texture = mat->get_texture_by_name(E->get().name);
+ Ref<Texture2D> texture = mat->get_texture_by_name(E.name);
if (texture.is_valid()) {
- smat->set_shader_param(E->get().name, texture);
+ smat->set_shader_param(E.name, texture);
} else {
- Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
- smat->set_shader_param(E->get().name, value);
+ Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
+ smat->set_shader_param(E.name, value);
}
}
@@ -309,9 +309,9 @@ Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_
List<PropertyInfo> params;
RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
- for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
- Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
- smat->set_shader_param(E->get().name, value);
+ for (const PropertyInfo &E : params) {
+ Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
+ smat->set_shader_param(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -346,9 +346,9 @@ Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p
List<PropertyInfo> params;
RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
- for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
- Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
- smat->set_shader_param(E->get().name, value);
+ for (const PropertyInfo &E : params) {
+ Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
+ smat->set_shader_param(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -383,9 +383,9 @@ Ref<Resource> ProceduralSkyMaterialConversionPlugin::convert(const Ref<Resource>
List<PropertyInfo> params;
RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
- for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
- Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
- smat->set_shader_param(E->get().name, value);
+ for (const PropertyInfo &E : params) {
+ Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
+ smat->set_shader_param(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -420,9 +420,9 @@ Ref<Resource> PanoramaSkyMaterialConversionPlugin::convert(const Ref<Resource> &
List<PropertyInfo> params;
RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
- for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
- Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
- smat->set_shader_param(E->get().name, value);
+ for (const PropertyInfo &E : params) {
+ Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
+ smat->set_shader_param(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
@@ -457,9 +457,9 @@ Ref<Resource> PhysicalSkyMaterialConversionPlugin::convert(const Ref<Resource> &
List<PropertyInfo> params;
RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
- for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
- Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
- smat->set_shader_param(E->get().name, value);
+ for (const PropertyInfo &E : params) {
+ Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
+ smat->set_shader_param(E.name, value);
}
smat->set_render_priority(mat->get_render_priority());
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 91415f4883..9ee1fcb325 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -90,8 +90,8 @@ void MeshInstance3DEditor::_menu_option(int p_option) {
ur->create_action(TTR("Create Static Trimesh Body"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- MeshInstance3D *instance = Object::cast_to<MeshInstance3D>(E->get());
+ for (Node *E : selection) {
+ MeshInstance3D *instance = Object::cast_to<MeshInstance3D>(E);
if (!instance) {
continue;
}
diff --git a/editor/plugins/mesh_library_editor_plugin.cpp b/editor/plugins/mesh_library_editor_plugin.cpp
index 15b6a0f3a0..b3f92c9d95 100644
--- a/editor/plugins/mesh_library_editor_plugin.cpp
+++ b/editor/plugins/mesh_library_editor_plugin.cpp
@@ -122,23 +122,23 @@ void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library,
List<uint32_t> shapes;
sb->get_shape_owners(&shapes);
- for (List<uint32_t>::Element *E = shapes.front(); E; E = E->next()) {
- if (sb->is_shape_owner_disabled(E->get())) {
+ for (uint32_t &E : shapes) {
+ if (sb->is_shape_owner_disabled(E)) {
continue;
}
- //Transform3D shape_transform = sb->shape_owner_get_transform(E->get());
+ //Transform3D shape_transform = sb->shape_owner_get_transform(E);
//shape_transform.set_origin(shape_transform.get_origin() - phys_offset);
- for (int k = 0; k < sb->shape_owner_get_shape_count(E->get()); k++) {
- Ref<Shape3D> collision = sb->shape_owner_get_shape(E->get(), k);
+ for (int k = 0; k < sb->shape_owner_get_shape_count(E); k++) {
+ Ref<Shape3D> collision = sb->shape_owner_get_shape(E, k);
if (!collision.is_valid()) {
continue;
}
MeshLibrary::ShapeData shape_data;
shape_data.shape = collision;
- shape_data.local_transform = sb->get_transform() * sb->shape_owner_get_transform(E->get());
+ shape_data.local_transform = sb->get_transform() * sb->shape_owner_get_transform(E);
collisions.push_back(shape_data);
}
}
diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 2e85e19732..2138f943da 100644
--- a/editor/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -33,7 +33,9 @@
#include "core/math/convex_hull.h"
#include "core/math/geometry_2d.h"
#include "core/math/geometry_3d.h"
+#include "editor/plugins/node_3d_editor_plugin.h"
#include "scene/3d/audio_stream_player_3d.h"
+#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_polygon_3d.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/cpu_particles_3d.h"
@@ -106,58 +108,122 @@ void EditorNode3DGizmo::clear() {
void EditorNode3DGizmo::redraw() {
if (get_script_instance() && get_script_instance()->has_method("_redraw")) {
get_script_instance()->call("_redraw");
- return;
+ } else {
+ ERR_FAIL_COND(!gizmo_plugin);
+ gizmo_plugin->redraw(this);
}
- ERR_FAIL_COND(!gizmo_plugin);
- gizmo_plugin->redraw(this);
+ if (Node3DEditor::get_singleton()->is_current_selected_gizmo(this)) {
+ Node3DEditor::get_singleton()->update_transform_gizmo();
+ }
}
-String EditorNode3DGizmo::get_handle_name(int p_idx) const {
+String EditorNode3DGizmo::get_handle_name(int p_id) const {
if (get_script_instance() && get_script_instance()->has_method("_get_handle_name")) {
- return get_script_instance()->call("_get_handle_name", p_idx);
+ return get_script_instance()->call("_get_handle_name", p_id);
}
ERR_FAIL_COND_V(!gizmo_plugin, "");
- return gizmo_plugin->get_handle_name(this, p_idx);
+ return gizmo_plugin->get_handle_name(this, p_id);
}
-bool EditorNode3DGizmo::is_handle_highlighted(int p_idx) const {
+bool EditorNode3DGizmo::is_handle_highlighted(int p_id) const {
if (get_script_instance() && get_script_instance()->has_method("_is_handle_highlighted")) {
- return get_script_instance()->call("_is_handle_highlighted", p_idx);
+ return get_script_instance()->call("_is_handle_highlighted", p_id);
}
ERR_FAIL_COND_V(!gizmo_plugin, false);
- return gizmo_plugin->is_handle_highlighted(this, p_idx);
+ return gizmo_plugin->is_handle_highlighted(this, p_id);
}
-Variant EditorNode3DGizmo::get_handle_value(int p_idx) {
+Variant EditorNode3DGizmo::get_handle_value(int p_id) const {
if (get_script_instance() && get_script_instance()->has_method("_get_handle_value")) {
- return get_script_instance()->call("_get_handle_value", p_idx);
+ return get_script_instance()->call("_get_handle_value", p_id);
}
ERR_FAIL_COND_V(!gizmo_plugin, Variant());
- return gizmo_plugin->get_handle_value(this, p_idx);
+ return gizmo_plugin->get_handle_value(this, p_id);
}
-void EditorNode3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void EditorNode3DGizmo::set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const {
if (get_script_instance() && get_script_instance()->has_method("_set_handle")) {
- get_script_instance()->call("_set_handle", p_idx, p_camera, p_point);
+ get_script_instance()->call("_set_handle", p_id, p_camera, p_point);
return;
}
ERR_FAIL_COND(!gizmo_plugin);
- gizmo_plugin->set_handle(this, p_idx, p_camera, p_point);
+ gizmo_plugin->set_handle(this, p_id, p_camera, p_point);
}
-void EditorNode3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
+void EditorNode3DGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) const {
if (get_script_instance() && get_script_instance()->has_method("_commit_handle")) {
- get_script_instance()->call("_commit_handle", p_idx, p_restore, p_cancel);
+ get_script_instance()->call("_commit_handle", p_id, p_restore, p_cancel);
+ return;
+ }
+
+ ERR_FAIL_COND(!gizmo_plugin);
+ gizmo_plugin->commit_handle(this, p_id, p_restore, p_cancel);
+}
+
+int EditorNode3DGizmo::subgizmos_intersect_ray(Camera3D *p_camera, const Vector2 &p_point) const {
+ if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_ray")) {
+ return get_script_instance()->call("_subgizmos_intersect_ray", p_camera, p_point);
+ }
+
+ ERR_FAIL_COND_V(!gizmo_plugin, -1);
+ return gizmo_plugin->subgizmos_intersect_ray(this, p_camera, p_point);
+}
+
+Vector<int> EditorNode3DGizmo::subgizmos_intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum) const {
+ if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_frustum")) {
+ Array frustum;
+ for (int i = 0; i < p_frustum.size(); i++) {
+ frustum[i] = p_frustum[i];
+ }
+ return get_script_instance()->call("_subgizmos_intersect_frustum", p_camera, frustum);
+ }
+
+ ERR_FAIL_COND_V(!gizmo_plugin, Vector<int>());
+ return gizmo_plugin->subgizmos_intersect_frustum(this, p_camera, p_frustum);
+}
+
+Transform3D EditorNode3DGizmo::get_subgizmo_transform(int p_id) const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_subgizmo_transform")) {
+ return get_script_instance()->call("_get_subgizmo_transform", p_id);
+ }
+
+ ERR_FAIL_COND_V(!gizmo_plugin, Transform3D());
+ return gizmo_plugin->get_subgizmo_transform(this, p_id);
+}
+
+void EditorNode3DGizmo::set_subgizmo_transform(int p_id, Transform3D p_transform) const {
+ if (get_script_instance() && get_script_instance()->has_method("_set_subgizmo_transform")) {
+ get_script_instance()->call("_set_subgizmo_transform", p_id, p_transform);
return;
}
ERR_FAIL_COND(!gizmo_plugin);
- gizmo_plugin->commit_handle(this, p_idx, p_restore, p_cancel);
+ gizmo_plugin->set_subgizmo_transform(this, p_id, p_transform);
+}
+
+void EditorNode3DGizmo::commit_subgizmos(const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) const {
+ if (get_script_instance() && get_script_instance()->has_method("_commit_subgizmos")) {
+ Array ids;
+ for (int i = 0; i < p_ids.size(); i++) {
+ ids[i] = p_ids[i];
+ }
+
+ Array restore;
+ for (int i = 0; i < p_restore.size(); i++) {
+ restore[i] = p_restore[i];
+ }
+
+ get_script_instance()->call("_commit_subgizmos", ids, restore, p_cancel);
+ return;
+ }
+
+ ERR_FAIL_COND(!gizmo_plugin);
+ gizmo_plugin->commit_subgizmos(this, p_ids, p_restore, p_cancel);
}
void EditorNode3DGizmo::set_spatial_node(Node3D *p_node) {
@@ -180,17 +246,17 @@ void EditorNode3DGizmo::Instance::create_instance(Node3D *p_base, bool p_hidden)
RS::get_singleton()->instance_geometry_set_flag(instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
}
-void EditorNode3DGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard, const Ref<SkinReference> &p_skin_reference, const Ref<Material> &p_material) {
+void EditorNode3DGizmo::add_mesh(const Ref<ArrayMesh> &p_mesh, const Ref<Material> &p_material, const Transform3D &p_xform, const Ref<SkinReference> &p_skin_reference) {
ERR_FAIL_COND(!spatial_node);
Instance ins;
- ins.billboard = p_billboard;
ins.mesh = p_mesh;
ins.skin_reference = p_skin_reference;
ins.material = p_material;
+ ins.xform = p_xform;
if (valid) {
ins.create_instance(spatial_node, hidden);
- RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
+ RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform() * ins.xform);
if (ins.material.is_valid()) {
RS::get_singleton()->instance_geometry_set_material_override(ins.instance, p_material->get_rid());
}
@@ -245,7 +311,6 @@ void EditorNode3DGizmo::add_vertices(const Vector<Vector3> &p_vertices, const Re
}
}
- ins.billboard = p_billboard;
ins.mesh = mesh;
if (valid) {
ins.create_instance(spatial_node, hidden);
@@ -307,8 +372,6 @@ void EditorNode3DGizmo::add_unscaled_billboard(const Ref<Material> &p_material,
mesh->set_custom_aabb(AABB(Vector3(-selectable_icon_size, -selectable_icon_size, -selectable_icon_size) * 100.0f, Vector3(selectable_icon_size, selectable_icon_size, selectable_icon_size) * 200.0f));
ins.mesh = mesh;
- ins.unscaled = true;
- ins.billboard = true;
if (valid) {
ins.create_instance(spatial_node, hidden);
RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
@@ -331,7 +394,7 @@ void EditorNode3DGizmo::add_collision_segments(const Vector<Vector3> &p_lines) {
}
}
-void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard, bool p_secondary) {
+void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, const Vector<int> &p_ids, bool p_billboard, bool p_secondary) {
billboard_handle = p_billboard;
if (!is_selected() || !is_editable()) {
@@ -340,8 +403,16 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<
ERR_FAIL_COND(!spatial_node);
- Instance ins;
+ if (p_ids.is_empty()) {
+ ERR_FAIL_COND_MSG((!handles.is_empty() && !handle_ids.is_empty()) || (!secondary_handles.is_empty() && !secondary_handle_ids.is_empty()), "Fail");
+ } else {
+ ERR_FAIL_COND_MSG(handles.size() != handle_ids.size() || secondary_handles.size() != secondary_handle_ids.size(), "Fail");
+ }
+ bool is_current_hover_gizmo = Node3DEditor::get_singleton()->get_current_hover_gizmo() == this;
+ int current_hover_handle = Node3DEditor::get_singleton()->get_current_hover_gizmo_handle();
+
+ Instance ins;
Ref<ArrayMesh> mesh = memnew(ArrayMesh);
Array a;
@@ -357,7 +428,8 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<
col = Color(0, 0, 1, 0.9);
}
- if (Node3DEditor::get_singleton()->get_over_gizmo_handle() != i) {
+ int id = p_ids.is_empty() ? i : p_ids[i];
+ if (!is_current_hover_gizmo || current_hover_handle != id) {
col.a = 0.8;
}
@@ -379,29 +451,31 @@ void EditorNode3DGizmo::add_handles(const Vector<Vector3> &p_handles, const Ref<
}
ins.mesh = mesh;
- ins.billboard = p_billboard;
ins.extra_margin = true;
if (valid) {
ins.create_instance(spatial_node, hidden);
RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform());
}
instances.push_back(ins);
- if (!p_secondary) {
- int chs = handles.size();
- handles.resize(chs + p_handles.size());
- for (int i = 0; i < p_handles.size(); i++) {
- handles.write[i + chs] = p_handles[i];
- }
- } else {
- int chs = secondary_handles.size();
- secondary_handles.resize(chs + p_handles.size());
- for (int i = 0; i < p_handles.size(); i++) {
- secondary_handles.write[i + chs] = p_handles[i];
+
+ Vector<Vector3> &h = p_secondary ? secondary_handles : handles;
+ int current_size = h.size();
+ h.resize(current_size + p_handles.size());
+ for (int i = 0; i < p_handles.size(); i++) {
+ h.write[current_size + i] = p_handles[i];
+ }
+
+ if (!p_ids.is_empty()) {
+ Vector<int> &ids = p_secondary ? secondary_handle_ids : handle_ids;
+ current_size = ids.size();
+ ids.resize(current_size + p_ids.size());
+ for (int i = 0; i < p_ids.size(); i++) {
+ ids.write[current_size + i] = p_ids[i];
}
}
}
-void EditorNode3DGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position) {
+void EditorNode3DGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position, const Transform3D &p_xform) {
ERR_FAIL_COND(!spatial_node);
BoxMesh box_mesh;
@@ -419,8 +493,7 @@ void EditorNode3DGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size,
Ref<ArrayMesh> m = memnew(ArrayMesh);
m->add_surface_from_arrays(box_mesh.surface_get_primitive_type(0), arrays);
- m->surface_set_material(0, p_material);
- add_mesh(m);
+ add_mesh(m, p_material, p_xform);
}
bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum) {
@@ -485,13 +558,15 @@ bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector
Transform3D it = t.affine_inverse();
Vector<Plane> transformed_frustum;
+ int plane_count = p_frustum.size();
+ transformed_frustum.resize(plane_count);
- for (int i = 0; i < p_frustum.size(); i++) {
- transformed_frustum.push_back(it.xform(p_frustum[i]));
+ for (int i = 0; i < plane_count; i++) {
+ transformed_frustum.write[i] = it.xform(p_frustum[i]);
}
- Vector<Vector3> convex_points = Geometry3D::compute_convex_mesh_points(p_frustum.ptr(), p_frustum.size());
- if (collision_mesh->inside_convex_shape(transformed_frustum.ptr(), transformed_frustum.size(), convex_points.ptr(), convex_points.size(), mesh_scale)) {
+ Vector<Vector3> convex_points = Geometry3D::compute_convex_mesh_points(transformed_frustum.ptr(), plane_count);
+ if (collision_mesh->inside_convex_shape(transformed_frustum.ptr(), plane_count, convex_points.ptr(), convex_points.size(), mesh_scale)) {
return true;
}
}
@@ -499,70 +574,77 @@ bool EditorNode3DGizmo::intersect_frustum(const Camera3D *p_camera, const Vector
return false;
}
-bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle, bool p_sec_first) {
- ERR_FAIL_COND_V(!spatial_node, false);
- ERR_FAIL_COND_V(!valid, false);
+void EditorNode3DGizmo::handles_intersect_ray(Camera3D *p_camera, const Vector2 &p_point, bool p_shift_pressed, int &r_id) {
+ r_id = -1;
- if (hidden && !gizmo_plugin->is_selectable_when_hidden()) {
- return false;
+ ERR_FAIL_COND(!spatial_node);
+ ERR_FAIL_COND(!valid);
+
+ if (hidden) {
+ return;
}
- if (r_gizmo_handle && !hidden) {
- Transform3D t = spatial_node->get_global_transform();
- if (billboard_handle) {
- t.set_look_at(t.origin, t.origin - p_camera->get_transform().basis.get_axis(2), p_camera->get_transform().basis.get_axis(1));
- }
+ Transform3D camera_xform = p_camera->get_global_transform();
+ Transform3D t = spatial_node->get_global_transform();
+ if (billboard_handle) {
+ t.set_look_at(t.origin, t.origin - camera_xform.basis.get_axis(2), camera_xform.basis.get_axis(1));
+ }
- float min_d = 1e20;
- int idx = -1;
+ float min_d = 1e20;
- for (int i = 0; i < secondary_handles.size(); i++) {
- Vector3 hpos = t.xform(secondary_handles[i]);
- Vector2 p = p_camera->unproject_position(hpos);
+ for (int i = 0; i < secondary_handles.size(); i++) {
+ Vector3 hpos = t.xform(secondary_handles[i]);
+ Vector2 p = p_camera->unproject_position(hpos);
- if (p.distance_to(p_point) < HANDLE_HALF_SIZE) {
- real_t dp = p_camera->get_transform().origin.distance_to(hpos);
- if (dp < min_d) {
- r_pos = t.xform(hpos);
- r_normal = p_camera->get_transform().basis.get_axis(2);
- min_d = dp;
- idx = i + handles.size();
+ if (p.distance_to(p_point) < HANDLE_HALF_SIZE) {
+ real_t dp = p_camera->get_transform().origin.distance_to(hpos);
+ if (dp < min_d) {
+ min_d = dp;
+ if (secondary_handle_ids.is_empty()) {
+ r_id = i;
+ } else {
+ r_id = secondary_handle_ids[i];
}
}
}
+ }
- if (p_sec_first && idx != -1) {
- *r_gizmo_handle = idx;
- return true;
- }
+ if (r_id != -1 && p_shift_pressed) {
+ return;
+ }
- min_d = 1e20;
+ min_d = 1e20;
- for (int i = 0; i < handles.size(); i++) {
- Vector3 hpos = t.xform(handles[i]);
- Vector2 p = p_camera->unproject_position(hpos);
+ for (int i = 0; i < handles.size(); i++) {
+ Vector3 hpos = t.xform(handles[i]);
+ Vector2 p = p_camera->unproject_position(hpos);
- if (p.distance_to(p_point) < HANDLE_HALF_SIZE) {
- real_t dp = p_camera->get_transform().origin.distance_to(hpos);
- if (dp < min_d) {
- r_pos = t.xform(hpos);
- r_normal = p_camera->get_transform().basis.get_axis(2);
- min_d = dp;
- idx = i;
+ if (p.distance_to(p_point) < HANDLE_HALF_SIZE) {
+ real_t dp = p_camera->get_transform().origin.distance_to(hpos);
+ if (dp < min_d) {
+ min_d = dp;
+ if (handle_ids.is_empty()) {
+ r_id = i;
+ } else {
+ r_id = handle_ids[i];
}
}
}
+ }
+}
- if (idx >= 0) {
- *r_gizmo_handle = idx;
- return true;
- }
+bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal) {
+ ERR_FAIL_COND_V(!spatial_node, false);
+ ERR_FAIL_COND_V(!valid, false);
+
+ if (hidden && !gizmo_plugin->is_selectable_when_hidden()) {
+ return false;
}
if (selectable_icon_size > 0.0f) {
Transform3D t = spatial_node->get_global_transform();
Vector3 camera_position = p_camera->get_camera_transform().origin;
- if (camera_position.distance_squared_to(t.origin) > 0.01) {
+ if (!camera_position.is_equal_approx(t.origin)) {
t.set_look_at(t.origin, camera_position);
}
@@ -578,7 +660,7 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
Transform3D orig_camera_transform = p_camera->get_camera_transform();
- if (orig_camera_transform.origin.distance_squared_to(t.origin) > 0.01 &&
+ if (!orig_camera_transform.origin.is_equal_approx(t.origin) &&
ABS(orig_camera_transform.basis.get_axis(Vector3::AXIS_Z).dot(Vector3(0, 1, 0))) < 0.99) {
p_camera->look_at(t.origin);
}
@@ -674,6 +756,25 @@ bool EditorNode3DGizmo::intersect_ray(Camera3D *p_camera, const Point2 &p_point,
return false;
}
+bool EditorNode3DGizmo::is_subgizmo_selected(int p_id) const {
+ Node3DEditor *ed = Node3DEditor::get_singleton();
+ ERR_FAIL_COND_V(!ed, false);
+ return ed->is_current_selected_gizmo(this) && ed->is_subgizmo_selected(p_id);
+}
+
+Vector<int> EditorNode3DGizmo::get_subgizmo_selection() const {
+ Vector<int> ret;
+
+ Node3DEditor *ed = Node3DEditor::get_singleton();
+ ERR_FAIL_COND_V(!ed, ret);
+
+ if (ed->is_current_selected_gizmo(this)) {
+ ret = ed->get_subgizmo_selection();
+ }
+
+ return ret;
+}
+
void EditorNode3DGizmo::create() {
ERR_FAIL_COND(!spatial_node);
ERR_FAIL_COND(valid);
@@ -690,7 +791,7 @@ void EditorNode3DGizmo::transform() {
ERR_FAIL_COND(!spatial_node);
ERR_FAIL_COND(!valid);
for (int i = 0; i < instances.size(); i++) {
- RS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform());
+ RS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform() * instances[i].xform);
}
}
@@ -724,38 +825,46 @@ void EditorNode3DGizmo::set_plugin(EditorNode3DGizmoPlugin *p_plugin) {
void EditorNode3DGizmo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard", "modulate"), &EditorNode3DGizmo::add_lines, DEFVAL(false), DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "billboard", "skeleton", "material"), &EditorNode3DGizmo::add_mesh, DEFVAL(false), DEFVAL(Ref<SkinReference>()), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("add_mesh", "mesh", "material", "transform", "skeleton"), &EditorNode3DGizmo::add_mesh, DEFVAL(Variant()), DEFVAL(Transform3D()), DEFVAL(Ref<SkinReference>()));
ClassDB::bind_method(D_METHOD("add_collision_segments", "segments"), &EditorNode3DGizmo::add_collision_segments);
ClassDB::bind_method(D_METHOD("add_collision_triangles", "triangles"), &EditorNode3DGizmo::add_collision_triangles);
ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "material", "default_scale", "modulate"), &EditorNode3DGizmo::add_unscaled_billboard, DEFVAL(1), DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "billboard", "secondary"), &EditorNode3DGizmo::add_handles, DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_handles", "handles", "material", "ids", "billboard", "secondary"), &EditorNode3DGizmo::add_handles, DEFVAL(false), DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_spatial_node", "node"), &EditorNode3DGizmo::_set_spatial_node);
ClassDB::bind_method(D_METHOD("get_spatial_node"), &EditorNode3DGizmo::get_spatial_node);
ClassDB::bind_method(D_METHOD("get_plugin"), &EditorNode3DGizmo::get_plugin);
ClassDB::bind_method(D_METHOD("clear"), &EditorNode3DGizmo::clear);
ClassDB::bind_method(D_METHOD("set_hidden", "hidden"), &EditorNode3DGizmo::set_hidden);
+ ClassDB::bind_method(D_METHOD("is_subgizmo_selected"), &EditorNode3DGizmo::is_subgizmo_selected);
+ ClassDB::bind_method(D_METHOD("get_subgizmo_selection"), &EditorNode3DGizmo::get_subgizmo_selection);
BIND_VMETHOD(MethodInfo("_redraw"));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", PropertyInfo(Variant::INT, "index")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", PropertyInfo(Variant::INT, "index")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", PropertyInfo(Variant::INT, "id")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", PropertyInfo(Variant::INT, "id")));
- MethodInfo hvget(Variant::NIL, "_get_handle_value", PropertyInfo(Variant::INT, "index"));
+ MethodInfo hvget(Variant::NIL, "_get_handle_value", PropertyInfo(Variant::INT, "id"));
hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
BIND_VMETHOD(hvget);
- BIND_VMETHOD(MethodInfo("_set_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
- MethodInfo cm = MethodInfo("_commit_handle", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ BIND_VMETHOD(MethodInfo("_set_handle", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ MethodInfo cm = MethodInfo("_commit_handle", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
cm.default_arguments.push_back(false);
BIND_VMETHOD(cm);
+
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_subgizmos_intersect_ray", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_INT32_ARRAY, "_subgizmos_intersect_frustum", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::ARRAY, "frustum")));
+ BIND_VMETHOD(MethodInfo(Variant::TRANSFORM3D, "_get_subgizmo_transform", PropertyInfo(Variant::INT, "id")));
+ BIND_VMETHOD(MethodInfo("_set_subgizmo_transform", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM3D, "transform")));
+ MethodInfo cs = MethodInfo("_commit_subgizmos", PropertyInfo(Variant::PACKED_INT32_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ cs.default_arguments.push_back(false);
+ BIND_VMETHOD(cs);
}
EditorNode3DGizmo::EditorNode3DGizmo() {
valid = false;
billboard_handle = false;
hidden = false;
- base = nullptr;
selected = false;
- instantiated = false;
spatial_node = nullptr;
gizmo_plugin = nullptr;
selectable_icon_size = -1.0f;
@@ -768,10 +877,362 @@ EditorNode3DGizmo::~EditorNode3DGizmo() {
clear();
}
-Vector3 EditorNode3DGizmo::get_handle_pos(int p_idx) const {
- ERR_FAIL_INDEX_V(p_idx, handles.size(), Vector3());
+/////
+
+void EditorNode3DGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) {
+ Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
+
+ Vector<Ref<StandardMaterial3D>> mats;
+
+ for (int i = 0; i < 4; i++) {
+ bool selected = i % 2 == 1;
+ bool instantiated = i < 2;
+
+ Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
- return handles[p_idx];
+ Color color = instantiated ? instantiated_color : p_color;
+
+ if (!selected) {
+ color.a *= 0.3;
+ }
+
+ material->set_albedo(color);
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN + 1);
+ material->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
+
+ if (p_use_vertex_color) {
+ material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ }
+
+ if (p_billboard) {
+ material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
+ }
+
+ if (p_on_top && selected) {
+ material->set_on_top_of_alpha();
+ }
+
+ mats.push_back(material);
+ }
+
+ materials[p_name] = mats;
+}
+
+void EditorNode3DGizmoPlugin::create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top, const Color &p_albedo) {
+ Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
+
+ Vector<Ref<StandardMaterial3D>> icons;
+
+ for (int i = 0; i < 4; i++) {
+ bool selected = i % 2 == 1;
+ bool instantiated = i < 2;
+
+ Ref<StandardMaterial3D> icon = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+
+ Color color = instantiated ? instantiated_color : p_albedo;
+
+ if (!selected) {
+ color.a *= 0.85;
+ }
+
+ icon->set_albedo(color);
+
+ icon->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ icon->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ icon->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ icon->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
+ icon->set_depth_draw_mode(StandardMaterial3D::DEPTH_DRAW_DISABLED);
+ icon->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ icon->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, p_texture);
+ icon->set_flag(StandardMaterial3D::FLAG_FIXED_SIZE, true);
+ icon->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
+ icon->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN);
+
+ if (p_on_top && selected) {
+ icon->set_on_top_of_alpha();
+ }
+
+ icons.push_back(icon);
+ }
+
+ materials[p_name] = icons;
+}
+
+void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard, const Ref<Texture2D> &p_icon) {
+ Ref<StandardMaterial3D> handle_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+
+ handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true);
+ Ref<Texture2D> handle_t = p_icon != nullptr ? p_icon : Node3DEditor::get_singleton()->get_theme_icon(SNAME("Editor3DHandle"), SNAME("EditorIcons"));
+ handle_material->set_point_size(handle_t->get_width());
+ handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t);
+ handle_material->set_albedo(Color(1, 1, 1));
+ handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ handle_material->set_on_top_of_alpha();
+ if (p_billboard) {
+ handle_material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
+ handle_material->set_on_top_of_alpha();
+ }
+ handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+
+ materials[p_name] = Vector<Ref<StandardMaterial3D>>();
+ materials[p_name].push_back(handle_material);
+}
+
+void EditorNode3DGizmoPlugin::add_material(const String &p_name, Ref<StandardMaterial3D> p_material) {
+ materials[p_name] = Vector<Ref<StandardMaterial3D>>();
+ materials[p_name].push_back(p_material);
+}
+
+Ref<StandardMaterial3D> EditorNode3DGizmoPlugin::get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo) {
+ ERR_FAIL_COND_V(!materials.has(p_name), Ref<StandardMaterial3D>());
+ ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref<StandardMaterial3D>());
+
+ if (p_gizmo.is_null() || materials[p_name].size() == 1) {
+ return materials[p_name][0];
+ }
+
+ int index = (p_gizmo->is_selected() ? 1 : 0) + (p_gizmo->is_editable() ? 2 : 0);
+
+ Ref<StandardMaterial3D> mat = materials[p_name][index];
+
+ if (current_state == ON_TOP && p_gizmo->is_selected()) {
+ mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ } else {
+ mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, false);
+ }
+
+ return mat;
+}
+
+String EditorNode3DGizmoPlugin::get_gizmo_name() const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_gizmo_name")) {
+ return get_script_instance()->call("_get_gizmo_name");
+ }
+ return TTR("Nameless gizmo");
+}
+
+int EditorNode3DGizmoPlugin::get_priority() const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_priority")) {
+ return get_script_instance()->call("_get_priority");
+ }
+ return 0;
+}
+
+Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) {
+ if (get_script_instance() && get_script_instance()->has_method("_get_gizmo")) {
+ return get_script_instance()->call("_get_gizmo", p_spatial);
+ }
+
+ Ref<EditorNode3DGizmo> ref = create_gizmo(p_spatial);
+
+ if (ref.is_null()) {
+ return ref;
+ }
+
+ ref->set_plugin(this);
+ ref->set_spatial_node(p_spatial);
+ ref->set_hidden(current_state == HIDDEN);
+
+ current_gizmos.push_back(ref.ptr());
+ return ref;
+}
+
+void EditorNode3DGizmoPlugin::_bind_methods() {
+#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo")
+
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
+ BIND_VMETHOD(MethodInfo(GIZMO_REF, "_create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
+
+ ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorNode3DGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorNode3DGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1)));
+ ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorNode3DGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorNode3DGizmoPlugin::add_material);
+
+ ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>()));
+
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_gizmo_name"));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_get_priority"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_can_be_hidden"));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_selectable_when_hidden"));
+
+ BIND_VMETHOD(MethodInfo("_redraw", GIZMO_REF));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", GIZMO_REF, PropertyInfo(Variant::INT, "id")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", GIZMO_REF, PropertyInfo(Variant::INT, "id")));
+
+ MethodInfo hvget(Variant::NIL, "_get_handle_value", GIZMO_REF, PropertyInfo(Variant::INT, "id"));
+ hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ BIND_VMETHOD(hvget);
+
+ BIND_VMETHOD(MethodInfo("_set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ MethodInfo cm = MethodInfo("_commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ cm.default_arguments.push_back(false);
+ BIND_VMETHOD(cm);
+
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_subgizmos_intersect_ray", GIZMO_REF, PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
+ BIND_VMETHOD(MethodInfo(Variant::PACKED_INT32_ARRAY, "_subgizmos_intersect_frustum", GIZMO_REF, PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::ARRAY, "frustum")));
+ BIND_VMETHOD(MethodInfo(Variant::TRANSFORM3D, "_get_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id")));
+ BIND_VMETHOD(MethodInfo("_set_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM3D, "transform")));
+ MethodInfo cs = MethodInfo("_commit_subgizmos", GIZMO_REF, PropertyInfo(Variant::PACKED_INT32_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
+ cs.default_arguments.push_back(false);
+ BIND_VMETHOD(cs);
+
+#undef GIZMO_REF
+}
+
+bool EditorNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+ if (get_script_instance() && get_script_instance()->has_method("_has_gizmo")) {
+ return get_script_instance()->call("_has_gizmo", p_spatial);
+ }
+ return false;
+}
+
+Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) {
+ if (get_script_instance() && get_script_instance()->has_method("_create_gizmo")) {
+ return get_script_instance()->call("_create_gizmo", p_spatial);
+ }
+
+ Ref<EditorNode3DGizmo> ref;
+ if (has_gizmo(p_spatial)) {
+ ref.instantiate();
+ }
+ return ref;
+}
+
+bool EditorNode3DGizmoPlugin::can_be_hidden() const {
+ if (get_script_instance() && get_script_instance()->has_method("_can_be_hidden")) {
+ return get_script_instance()->call("_can_be_hidden");
+ }
+ return true;
+}
+
+bool EditorNode3DGizmoPlugin::is_selectable_when_hidden() const {
+ if (get_script_instance() && get_script_instance()->has_method("_is_selectable_when_hidden")) {
+ return get_script_instance()->call("_is_selectable_when_hidden");
+ }
+ return false;
+}
+
+void EditorNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+ if (get_script_instance() && get_script_instance()->has_method("_redraw")) {
+ Ref<EditorNode3DGizmo> ref(p_gizmo);
+ get_script_instance()->call("_redraw", ref);
+ }
+}
+
+bool EditorNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ if (get_script_instance() && get_script_instance()->has_method("_is_handle_highlighted")) {
+ return get_script_instance()->call("_is_handle_highlighted", p_gizmo, p_id);
+ }
+ return false;
+}
+
+String EditorNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_handle_name")) {
+ return get_script_instance()->call("_get_handle_name", p_gizmo, p_id);
+ }
+ return "";
+}
+
+Variant EditorNode3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_handle_value")) {
+ return get_script_instance()->call("_get_handle_value", p_gizmo, p_id);
+ }
+ return Variant();
+}
+
+void EditorNode3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
+ if (get_script_instance() && get_script_instance()->has_method("_set_handle")) {
+ get_script_instance()->call("_set_handle", p_gizmo, p_id, p_camera, p_point);
+ }
+}
+
+void EditorNode3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
+ if (get_script_instance() && get_script_instance()->has_method("_commit_handle")) {
+ get_script_instance()->call("_commit_handle", p_gizmo, p_id, p_restore, p_cancel);
+ }
+}
+
+int EditorNode3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const {
+ if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_ray")) {
+ return get_script_instance()->call("_subgizmos_intersect_ray", p_camera, p_point);
+ }
+ return -1;
+}
+
+Vector<int> EditorNode3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const {
+ if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_frustum")) {
+ Array frustum;
+ for (int i = 0; i < p_frustum.size(); i++) {
+ frustum[i] = p_frustum[i];
+ }
+ return get_script_instance()->call("_subgizmos_intersect_frustum", p_camera, frustum);
+ }
+
+ return Vector<int>();
+}
+
+Transform3D EditorNode3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ if (get_script_instance() && get_script_instance()->has_method("_get_subgizmo_transform")) {
+ return get_script_instance()->call("_get_subgizmo_transform", p_id);
+ }
+
+ return Transform3D();
+}
+
+void EditorNode3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) const {
+ if (get_script_instance() && get_script_instance()->has_method("_set_subgizmo_transform")) {
+ get_script_instance()->call("_set_subgizmo_transform", p_id, p_transform);
+ }
+}
+
+void EditorNode3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) const {
+ if (get_script_instance() && get_script_instance()->has_method("_commit_subgizmos")) {
+ Array ids;
+ for (int i = 0; i < p_ids.size(); i++) {
+ ids[i] = p_ids[i];
+ }
+
+ Array restore;
+ for (int i = 0; i < p_restore.size(); i++) {
+ restore[i] = p_restore[i];
+ }
+
+ get_script_instance()->call("_commit_subgizmos", ids, restore, p_cancel);
+ }
+}
+
+void EditorNode3DGizmoPlugin::set_state(int p_state) {
+ current_state = p_state;
+ for (int i = 0; i < current_gizmos.size(); ++i) {
+ current_gizmos[i]->set_hidden(current_state == HIDDEN);
+ }
+}
+
+int EditorNode3DGizmoPlugin::get_state() const {
+ return current_state;
+}
+
+void EditorNode3DGizmoPlugin::unregister_gizmo(EditorNode3DGizmo *p_gizmo) {
+ current_gizmos.erase(p_gizmo);
+}
+
+EditorNode3DGizmoPlugin::EditorNode3DGizmoPlugin() {
+ current_state = VISIBLE;
+}
+
+EditorNode3DGizmoPlugin::~EditorNode3DGizmoPlugin() {
+ for (int i = 0; i < current_gizmos.size(); ++i) {
+ current_gizmos[i]->set_plugin(nullptr);
+ current_gizmos[i]->get_spatial_node()->remove_gizmo(current_gizmos[i]);
+ }
+ if (Node3DEditor::get_singleton()) {
+ Node3DEditor::get_singleton()->update_all_gizmos();
+ }
}
//// light gizmo
@@ -802,20 +1263,20 @@ int Light3DGizmoPlugin::get_priority() const {
return -1;
}
-String Light3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (p_idx == 0) {
+String Light3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ if (p_id == 0) {
return "Radius";
} else {
return "Aperture";
}
}
-Variant Light3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant Light3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
- if (p_idx == 0) {
+ if (p_id == 0) {
return light->get_param(Light3D::PARAM_RANGE);
}
- if (p_idx == 1) {
+ if (p_id == 1) {
return light->get_param(Light3D::PARAM_SPOT_ANGLE);
}
@@ -849,7 +1310,7 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec
return Math::rad2deg(a);
}
-void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void Light3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
Transform3D gt = light->get_global_transform();
Transform3D gi = gt.affine_inverse();
@@ -858,7 +1319,7 @@ void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
Vector3 s[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 4096) };
- if (p_idx == 0) {
+ if (p_id == 0) {
if (Object::cast_to<SpotLight3D>(light)) {
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(0, 0, -4096), s[0], s[1], ra, rb);
@@ -887,24 +1348,24 @@ void Light3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
}
}
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], light->get_param(Light3D::PARAM_RANGE), gt);
light->set_param(Light3D::PARAM_SPOT_ANGLE, CLAMP(a, 0.01, 89.99));
}
}
-void Light3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void Light3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Light3D *light = Object::cast_to<Light3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
- light->set_param(p_idx == 0 ? Light3D::PARAM_RANGE : Light3D::PARAM_SPOT_ANGLE, p_restore);
+ light->set_param(p_id == 0 ? Light3D::PARAM_RANGE : Light3D::PARAM_SPOT_ANGLE, p_restore);
- } else if (p_idx == 0) {
+ } else if (p_id == 0) {
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
ur->create_action(TTR("Change Light Radius"));
ur->add_do_method(light, "set_param", Light3D::PARAM_RANGE, light->get_param(Light3D::PARAM_RANGE));
ur->add_undo_method(light, "set_param", Light3D::PARAM_RANGE, p_restore);
ur->commit_action();
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
ur->create_action(TTR("Change Light Radius"));
ur->add_do_method(light, "set_param", Light3D::PARAM_SPOT_ANGLE, light->get_param(Light3D::PARAM_SPOT_ANGLE));
@@ -996,7 +1457,7 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector<Vector3> handles;
handles.push_back(Vector3(r, 0, 0));
- p_gizmo->add_handles(handles, get_material("handles_billboard"), true);
+ p_gizmo->add_handles(handles, get_material("handles_billboard"), Vector<int>(), true);
}
if (Object::cast_to<SpotLight3D>(light)) {
@@ -1068,16 +1529,16 @@ int AudioStreamPlayer3DGizmoPlugin::get_priority() const {
return -1;
}
-String AudioStreamPlayer3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String AudioStreamPlayer3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "Emission Radius";
}
-Variant AudioStreamPlayer3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant AudioStreamPlayer3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node());
return player->get_emission_angle();
}
-void AudioStreamPlayer3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void AudioStreamPlayer3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node());
Transform3D gt = player->get_global_transform();
@@ -1114,7 +1575,7 @@ void AudioStreamPlayer3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int
}
}
-void AudioStreamPlayer3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void AudioStreamPlayer3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
AudioStreamPlayer3D *player = Object::cast_to<AudioStreamPlayer3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
@@ -1203,7 +1664,7 @@ int Camera3DGizmoPlugin::get_priority() const {
return -1;
}
-String Camera3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String Camera3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
@@ -1213,7 +1674,7 @@ String Camera3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, in
}
}
-Variant Camera3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant Camera3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
@@ -1223,7 +1684,7 @@ Variant Camera3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_
}
}
-void Camera3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void Camera3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
Transform3D gt = camera->get_global_transform();
@@ -1252,7 +1713,7 @@ void Camera3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Came
}
}
-void Camera3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void Camera3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Camera3D *camera = Object::cast_to<Camera3D>(p_gizmo->get_spatial_node());
if (camera->get_projection() == Camera3D::PROJECTION_PERSPECTIVE) {
@@ -1761,7 +2222,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
}
Ref<ArrayMesh> m = surface_tool->commit();
- p_gizmo->add_mesh(m, false, skel->register_skin(Ref<Skin>()));
+ p_gizmo->add_mesh(m, Ref<Material>(), Transform3D(), skel->register_skin(Ref<Skin>()));
}
////
@@ -2102,23 +2563,23 @@ void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
p_gizmo->add_collision_triangles(tm);
}
-String SoftBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String SoftBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "SoftBody3D pin point";
}
-Variant SoftBody3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant SoftBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node());
- return Variant(soft_body->is_point_pinned(p_idx));
+ return Variant(soft_body->is_point_pinned(p_id));
}
-void SoftBody3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void SoftBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node());
- soft_body->pin_point_toggle(p_idx);
+ soft_body->pin_point_toggle(p_id);
}
-bool SoftBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int idx) const {
+bool SoftBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const {
SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node());
- return soft_body->is_point_pinned(idx);
+ return soft_body->is_point_pinned(p_id);
}
///////////
@@ -2143,8 +2604,8 @@ int VisibleOnScreenNotifier3DGizmoPlugin::get_priority() const {
return -1;
}
-String VisibleOnScreenNotifier3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String VisibleOnScreenNotifier3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Size X";
case 1:
@@ -2162,20 +2623,20 @@ String VisibleOnScreenNotifier3DGizmoPlugin::get_handle_name(const EditorNode3DG
return "";
}
-Variant VisibleOnScreenNotifier3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant VisibleOnScreenNotifier3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
VisibleOnScreenNotifier3D *notifier = Object::cast_to<VisibleOnScreenNotifier3D>(p_gizmo->get_spatial_node());
return notifier->get_aabb();
}
-void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
VisibleOnScreenNotifier3D *notifier = Object::cast_to<VisibleOnScreenNotifier3D>(p_gizmo->get_spatial_node());
Transform3D gt = notifier->get_global_transform();
Transform3D gi = gt.affine_inverse();
- bool move = p_idx >= 3;
- p_idx = p_idx % 3;
+ bool move = p_id >= 3;
+ p_id = p_id % 3;
AABB aabb = notifier->get_aabb();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
@@ -2186,25 +2647,25 @@ void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo
Vector3 ofs = aabb.position + aabb.size * 0.5;
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
if (move) {
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
- aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5;
+ aabb.position[p_id] = d - 1.0 - aabb.size[p_id] * 0.5;
notifier->set_aabb(aabb);
} else {
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx] - ofs[p_idx];
+ float d = ra[p_id] - ofs[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2213,13 +2674,13 @@ void VisibleOnScreenNotifier3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo
d = 0.001;
}
//resize
- aabb.position[p_idx] = (aabb.position[p_idx] + aabb.size[p_idx] * 0.5) - d;
- aabb.size[p_idx] = d * 2;
+ aabb.position[p_id] = (aabb.position[p_id] + aabb.size[p_id] * 0.5) - d;
+ aabb.size[p_id] = d * 2;
notifier->set_aabb(aabb);
}
}
-void VisibleOnScreenNotifier3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void VisibleOnScreenNotifier3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
VisibleOnScreenNotifier3D *notifier = Object::cast_to<VisibleOnScreenNotifier3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
@@ -2335,8 +2796,8 @@ bool GPUParticles3DGizmoPlugin::is_selectable_when_hidden() const {
return true;
}
-String GPUParticles3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String GPUParticles3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Size X";
case 1:
@@ -2354,19 +2815,19 @@ String GPUParticles3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_giz
return "";
}
-Variant GPUParticles3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant GPUParticles3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_spatial_node());
return particles->get_visibility_aabb();
}
-void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void GPUParticles3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_spatial_node());
Transform3D gt = particles->get_global_transform();
Transform3D gi = gt.affine_inverse();
- bool move = p_idx >= 3;
- p_idx = p_idx % 3;
+ bool move = p_id >= 3;
+ p_id = p_id % 3;
AABB aabb = particles->get_visibility_aabb();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
@@ -2377,25 +2838,25 @@ void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx
Vector3 ofs = aabb.position + aabb.size * 0.5;
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
if (move) {
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(ofs - axis * 4096, ofs + axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
- aabb.position[p_idx] = d - 1.0 - aabb.size[p_idx] * 0.5;
+ aabb.position[p_id] = d - 1.0 - aabb.size[p_id] * 0.5;
particles->set_visibility_aabb(aabb);
} else {
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(ofs, ofs + axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx] - ofs[p_idx];
+ float d = ra[p_id] - ofs[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2404,13 +2865,13 @@ void GPUParticles3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx
d = 0.001;
}
//resize
- aabb.position[p_idx] = (aabb.position[p_idx] + aabb.size[p_idx] * 0.5) - d;
- aabb.size[p_idx] = d * 2;
+ aabb.position[p_id] = (aabb.position[p_id] + aabb.size[p_id] * 0.5) - d;
+ aabb.size[p_id] = d * 2;
particles->set_visibility_aabb(aabb);
}
}
-void GPUParticles3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void GPUParticles3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
GPUParticles3D *particles = Object::cast_to<GPUParticles3D>(p_gizmo->get_spatial_node());
if (p_cancel) {
@@ -2475,8 +2936,6 @@ void GPUParticles3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
////
-////
-
GPUParticlesCollision3DGizmoPlugin::GPUParticlesCollision3DGizmoPlugin() {
Color gizmo_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/particle_collision", Color(0.5, 0.7, 1));
create_material("shape_material", gizmo_color);
@@ -2498,7 +2957,7 @@ int GPUParticlesCollision3DGizmoPlugin::get_priority() const {
return -1;
}
-String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
const Node3D *cs = p_gizmo->get_spatial_node();
if (Object::cast_to<GPUParticlesCollisionSphere>(cs) || Object::cast_to<GPUParticlesAttractorSphere>(cs)) {
@@ -2512,7 +2971,7 @@ String GPUParticlesCollision3DGizmoPlugin::get_handle_name(const EditorNode3DGiz
return "";
}
-Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
const Node3D *cs = p_gizmo->get_spatial_node();
if (Object::cast_to<GPUParticlesCollisionSphere>(cs) || Object::cast_to<GPUParticlesAttractorSphere>(cs)) {
@@ -2526,7 +2985,7 @@ Variant GPUParticlesCollision3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *
return Variant();
}
-void GPUParticlesCollision3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void GPUParticlesCollision3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Node3D *sn = p_gizmo->get_spatial_node();
Transform3D gt = sn->get_global_transform();
@@ -2554,10 +3013,10 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo,
if (Object::cast_to<GPUParticlesCollisionBox>(sn) || Object::cast_to<GPUParticlesAttractorBox>(sn) || Object::cast_to<GPUParticlesAttractorVectorField>(sn) || Object::cast_to<GPUParticlesCollisionSDF>(sn) || Object::cast_to<GPUParticlesCollisionHeightField>(sn)) {
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2567,12 +3026,12 @@ void GPUParticlesCollision3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo,
}
Vector3 he = sn->call("get_extents");
- he[p_idx] = d;
+ he[p_id] = d;
sn->call("set_extents", he);
}
}
-void GPUParticlesCollision3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void GPUParticlesCollision3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Node3D *sn = p_gizmo->get_spatial_node();
if (Object::cast_to<GPUParticlesCollisionSphere>(sn) || Object::cast_to<GPUParticlesAttractorSphere>(sn)) {
@@ -2762,8 +3221,8 @@ int ReflectionProbeGizmoPlugin::get_priority() const {
return -1;
}
-String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Extents X";
case 1:
@@ -2781,18 +3240,18 @@ String ReflectionProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gi
return "";
}
-Variant ReflectionProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant ReflectionProbeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node());
return AABB(probe->get_extents(), probe->get_origin_offset());
}
-void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void ReflectionProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node());
Transform3D gt = probe->get_global_transform();
Transform3D gi = gt.affine_inverse();
- if (p_idx < 3) {
+ if (p_id < 3) {
Vector3 extents = probe->get_extents();
Vector3 ray_from = p_camera->project_ray_origin(p_point);
@@ -2801,11 +3260,11 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2814,13 +3273,13 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
d = 0.001;
}
- extents[p_idx] = d;
+ extents[p_id] = d;
probe->set_extents(extents);
} else {
- p_idx -= 3;
+ p_id -= 3;
Vector3 origin = probe->get_origin_offset();
- origin[p_idx] = 0;
+ origin[p_id] = 0;
Vector3 ray_from = p_camera->project_ray_origin(p_point);
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
@@ -2828,22 +3287,22 @@ void ReflectionProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_id
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(origin - axis * 16384, origin + axis * 16384, sg[0], sg[1], ra, rb);
// Adjust the actual position to account for the gizmo handle position
- float d = ra[p_idx] + 0.25;
+ float d = ra[p_id] + 0.25;
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
- origin[p_idx] = d;
+ origin[p_id] = d;
probe->set_origin_offset(origin);
}
}
-void ReflectionProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void ReflectionProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
ReflectionProbe *probe = Object::cast_to<ReflectionProbe>(p_gizmo->get_spatial_node());
AABB restore = p_restore;
@@ -2947,8 +3406,8 @@ int DecalGizmoPlugin::get_priority() const {
return -1;
}
-String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Extents X";
case 1:
@@ -2960,12 +3419,12 @@ String DecalGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p
return "";
}
-Variant DecalGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant DecalGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
return decal->get_extents();
}
-void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void DecalGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
Transform3D gt = decal->get_global_transform();
@@ -2979,11 +3438,11 @@ void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -2992,11 +3451,11 @@ void DecalGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3
d = 0.001;
}
- extents[p_idx] = d;
+ extents[p_id] = d;
decal->set_extents(extents);
}
-void DecalGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void DecalGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
Decal *decal = Object::cast_to<Decal>(p_gizmo->get_spatial_node());
Vector3 restore = p_restore;
@@ -3055,7 +3514,6 @@ void DecalGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<Material> material = get_material("decal_material", p_gizmo);
p_gizmo->add_lines(lines, material);
-
p_gizmo->add_handles(handles, get_material("handles"));
}
@@ -3088,8 +3546,8 @@ int VoxelGIGizmoPlugin::get_priority() const {
return -1;
}
-String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- switch (p_idx) {
+String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
+ switch (p_id) {
case 0:
return "Extents X";
case 1:
@@ -3101,12 +3559,12 @@ String VoxelGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int
return "";
}
-Variant VoxelGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant VoxelGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
return probe->get_extents();
}
-void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void VoxelGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
Transform3D gt = probe->get_global_transform();
@@ -3120,11 +3578,11 @@ void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
Vector3 sg[2] = { gi.xform(ray_from), gi.xform(ray_from + ray_dir * 16384) };
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 16384, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -3133,11 +3591,11 @@ void VoxelGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camer
d = 0.001;
}
- extents[p_idx] = d;
+ extents[p_id] = d;
probe->set_extents(extents);
}
-void VoxelGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void VoxelGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
VoxelGI *probe = Object::cast_to<VoxelGI>(p_gizmo->get_spatial_node());
Vector3 restore = p_restore;
@@ -3257,18 +3715,18 @@ LightmapGIGizmoPlugin::LightmapGIGizmoPlugin() {
create_icon_material("baked_indirect_light_icon", Node3DEditor::get_singleton()->get_theme_icon(SNAME("GizmoLightmapGI"), SNAME("EditorIcons")));
}
-String LightmapGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String LightmapGIGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "";
}
-Variant LightmapGIGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant LightmapGIGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return Variant();
}
-void LightmapGIGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void LightmapGIGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
}
-void LightmapGIGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void LightmapGIGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
}
bool LightmapGIGizmoPlugin::has_gizmo(Node3D *p_spatial) {
@@ -3439,18 +3897,18 @@ LightmapProbeGizmoPlugin::LightmapProbeGizmoPlugin() {
create_material("lightprobe_lines", gizmo_color);
}
-String LightmapProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String LightmapProbeGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return "";
}
-Variant LightmapProbeGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant LightmapProbeGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
return Variant();
}
-void LightmapProbeGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void LightmapProbeGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
}
-void LightmapProbeGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void LightmapProbeGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
}
bool LightmapProbeGizmoPlugin::has_gizmo(Node3D *p_spatial) {
@@ -3555,8 +4013,7 @@ void CollisionObject3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
List<uint32_t> owners;
co->get_shape_owners(&owners);
- for (List<uint32_t>::Element *E = owners.front(); E; E = E->next()) {
- uint32_t owner_id = E->get();
+ for (uint32_t &owner_id : owners) {
Transform3D xform = co->shape_owner_get_transform(owner_id);
Object *owner = co->shape_owner_get_owner(owner_id);
// Exclude CollisionShape3D and CollisionPolygon3D as they have their gizmo.
@@ -3570,7 +4027,7 @@ void CollisionObject3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
SurfaceTool st;
st.append_from(s->get_debug_mesh(), 0, xform);
- p_gizmo->add_mesh(st.commit(), false, Ref<SkinReference>(), material);
+ p_gizmo->add_mesh(st.commit(), material);
p_gizmo->add_collision_segments(s->get_debug_mesh_lines());
}
}
@@ -3600,7 +4057,7 @@ int CollisionShape3DGizmoPlugin::get_priority() const {
return -1;
}
-String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
const CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3617,11 +4074,11 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
}
if (Object::cast_to<CapsuleShape3D>(*s)) {
- return p_idx == 0 ? "Radius" : "Height";
+ return p_id == 0 ? "Radius" : "Height";
}
if (Object::cast_to<CylinderShape3D>(*s)) {
- return p_idx == 0 ? "Radius" : "Height";
+ return p_id == 0 ? "Radius" : "Height";
}
if (Object::cast_to<RayShape3D>(*s)) {
@@ -3631,7 +4088,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g
return "";
}
-Variant CollisionShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3651,12 +4108,12 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo
if (Object::cast_to<CapsuleShape3D>(*s)) {
Ref<CapsuleShape3D> cs2 = s;
- return p_idx == 0 ? cs2->get_radius() : cs2->get_height();
+ return p_id == 0 ? cs2->get_radius() : cs2->get_height();
}
if (Object::cast_to<CylinderShape3D>(*s)) {
Ref<CylinderShape3D> cs2 = s;
- return p_idx == 0 ? cs2->get_radius() : cs2->get_height();
+ return p_id == 0 ? cs2->get_radius() : cs2->get_height();
}
if (Object::cast_to<RayShape3D>(*s)) {
@@ -3667,7 +4124,7 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo
return Variant();
}
-void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3717,11 +4174,11 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
if (Object::cast_to<BoxShape3D>(*s)) {
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Ref<BoxShape3D> bs = s;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -3731,18 +4188,18 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
}
Vector3 he = bs->get_size();
- he[p_idx] = d * 2;
+ he[p_id] = d * 2;
bs->set_size(he);
}
if (Object::cast_to<CapsuleShape3D>(*s)) {
Vector3 axis;
- axis[p_idx == 0 ? 0 : 2] = 1.0;
+ axis[p_id == 0 ? 0 : 2] = 1.0;
Ref<CapsuleShape3D> cs2 = s;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
float d = axis.dot(ra);
- if (p_idx == 1) {
+ if (p_id == 1) {
d -= cs2->get_radius();
}
@@ -3754,16 +4211,16 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
d = 0.001;
}
- if (p_idx == 0) {
+ if (p_id == 0) {
cs2->set_radius(d);
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
cs2->set_height(d * 2.0);
}
}
if (Object::cast_to<CylinderShape3D>(*s)) {
Vector3 axis;
- axis[p_idx == 0 ? 0 : 1] = 1.0;
+ axis[p_id == 0 ? 0 : 1] = 1.0;
Ref<CylinderShape3D> cs2 = s;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
@@ -3776,15 +4233,15 @@ void CollisionShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_i
d = 0.001;
}
- if (p_idx == 0) {
+ if (p_id == 0) {
cs2->set_radius(d);
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
cs2->set_height(d * 2.0);
}
}
}
-void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
CollisionShape3D *cs = Object::cast_to<CollisionShape3D>(p_gizmo->get_spatial_node());
Ref<Shape3D> s = cs->get_shape();
@@ -3823,7 +4280,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
if (Object::cast_to<CapsuleShape3D>(*s)) {
Ref<CapsuleShape3D> ss = s;
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
ss->set_radius(p_restore);
} else {
ss->set_height(p_restore);
@@ -3832,7 +4289,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
}
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx == 0) {
+ if (p_id == 0) {
ur->create_action(TTR("Change Capsule Shape Radius"));
ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
ur->add_undo_method(ss.ptr(), "set_radius", p_restore);
@@ -3848,7 +4305,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
if (Object::cast_to<CylinderShape3D>(*s)) {
Ref<CylinderShape3D> ss = s;
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
ss->set_radius(p_restore);
} else {
ss->set_height(p_restore);
@@ -3857,7 +4314,7 @@ void CollisionShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int
}
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx == 0) {
+ if (p_id == 0) {
ur->create_action(TTR("Change Cylinder Shape Radius"));
ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius());
ur->add_undo_method(ss.ptr(), "set_radius", p_restore);
@@ -4153,7 +4610,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
if (Object::cast_to<ConcavePolygonShape3D>(*s)) {
Ref<ConcavePolygonShape3D> cs2 = s;
Ref<ArrayMesh> mesh = cs2->get_debug_mesh();
- p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material);
+ p_gizmo->add_mesh(mesh, material);
p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines());
}
@@ -4174,7 +4631,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Ref<HeightMapShape3D> hms = s;
Ref<ArrayMesh> mesh = hms->get_debug_mesh();
- p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), material);
+ p_gizmo->add_mesh(mesh, material);
}
}
@@ -4289,9 +4746,7 @@ void NavigationRegion3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
Vector3 *tw = tmeshfaces.ptrw();
int tidx = 0;
- for (List<Face3>::Element *E = faces.front(); E; E = E->next()) {
- const Face3 &f = E->get();
-
+ for (const Face3 &f : faces) {
for (int j = 0; j < 3; j++) {
tw[tidx++] = f.vertex[j];
_EdgeKey ek;
diff --git a/editor/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index 6f071859ec..61ee3a95a9 100644
--- a/editor/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -28,13 +28,156 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SPATIAL_EDITOR_GIZMOS_H
-#define SPATIAL_EDITOR_GIZMOS_H
+#ifndef NODE_3D_EDITOR_GIZMOS_H
+#define NODE_3D_EDITOR_GIZMOS_H
-#include "editor/plugins/node_3d_editor_plugin.h"
-#include "scene/3d/camera_3d.h"
+#include "core/templates/ordered_hash_map.h"
+#include "scene/3d/node_3d.h"
+#include "scene/3d/skeleton_3d.h"
class Camera3D;
+class Timer;
+class EditorNode3DGizmoPlugin;
+
+class EditorNode3DGizmo : public Node3DGizmo {
+ GDCLASS(EditorNode3DGizmo, Node3DGizmo);
+
+ struct Instance {
+ RID instance;
+ Ref<ArrayMesh> mesh;
+ Ref<Material> material;
+ Ref<SkinReference> skin_reference;
+ bool extra_margin = false;
+ Transform3D xform;
+
+ void create_instance(Node3D *p_base, bool p_hidden = false);
+ };
+
+ bool selected;
+
+ Vector<Vector3> collision_segments;
+ Ref<TriangleMesh> collision_mesh;
+
+ Vector<Vector3> handles;
+ Vector<int> handle_ids;
+ Vector<Vector3> secondary_handles;
+ Vector<int> secondary_handle_ids;
+
+ float selectable_icon_size;
+ bool billboard_handle;
+
+ bool valid;
+ bool hidden;
+ Vector<Instance> instances;
+ Node3D *spatial_node;
+
+ void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Node3D>(p_node)); }
+
+protected:
+ static void _bind_methods();
+
+ EditorNode3DGizmoPlugin *gizmo_plugin;
+
+public:
+ void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
+ void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
+ void add_mesh(const Ref<ArrayMesh> &p_mesh, const Ref<Material> &p_material = Ref<Material>(), const Transform3D &p_xform = Transform3D(), const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>());
+ void add_collision_segments(const Vector<Vector3> &p_lines);
+ void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
+ void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1));
+ void add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, const Vector<int> &p_ids = Vector<int>(), bool p_billboard = false, bool p_secondary = false);
+ void add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position = Vector3(), const Transform3D &p_xform = Transform3D());
+
+ virtual bool is_handle_highlighted(int p_id) const;
+ virtual String get_handle_name(int p_id) const;
+ virtual Variant get_handle_value(int p_id) const;
+ virtual void set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const;
+ virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false) const;
+
+ virtual int subgizmos_intersect_ray(Camera3D *p_camera, const Vector2 &p_point) const;
+ virtual Vector<int> subgizmos_intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum) const;
+ virtual Transform3D get_subgizmo_transform(int p_id) const;
+ virtual void set_subgizmo_transform(int p_id, Transform3D p_transform) const;
+ virtual void commit_subgizmos(const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel = false) const;
+
+ void set_selected(bool p_selected) { selected = p_selected; }
+ bool is_selected() const { return selected; }
+
+ void set_spatial_node(Node3D *p_node);
+ Node3D *get_spatial_node() const { return spatial_node; }
+ Ref<EditorNode3DGizmoPlugin> get_plugin() const { return gizmo_plugin; }
+ bool intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum);
+ void handles_intersect_ray(Camera3D *p_camera, const Vector2 &p_point, bool p_shift_pressed, int &r_id);
+ bool intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal);
+ bool is_subgizmo_selected(int p_id) const;
+ Vector<int> get_subgizmo_selection() const;
+
+ virtual void clear() override;
+ virtual void create() override;
+ virtual void transform() override;
+ virtual void redraw() override;
+ virtual void free() override;
+
+ virtual bool is_editable() const;
+
+ void set_hidden(bool p_hidden);
+ void set_plugin(EditorNode3DGizmoPlugin *p_plugin);
+
+ EditorNode3DGizmo();
+ ~EditorNode3DGizmo();
+};
+
+class EditorNode3DGizmoPlugin : public Resource {
+ GDCLASS(EditorNode3DGizmoPlugin, Resource);
+
+public:
+ static const int VISIBLE = 0;
+ static const int HIDDEN = 1;
+ static const int ON_TOP = 2;
+
+protected:
+ int current_state;
+ List<EditorNode3DGizmo *> current_gizmos;
+ HashMap<String, Vector<Ref<StandardMaterial3D>>> materials;
+
+ static void _bind_methods();
+ virtual bool has_gizmo(Node3D *p_spatial);
+ virtual Ref<EditorNode3DGizmo> create_gizmo(Node3D *p_spatial);
+
+public:
+ void create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false);
+ void create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top = false, const Color &p_albedo = Color(1, 1, 1, 1));
+ void create_handle_material(const String &p_name, bool p_billboard = false, const Ref<Texture2D> &p_texture = nullptr);
+ void add_material(const String &p_name, Ref<StandardMaterial3D> p_material);
+
+ Ref<StandardMaterial3D> get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo = Ref<EditorNode3DGizmo>());
+
+ virtual String get_gizmo_name() const;
+ virtual int get_priority() const;
+ virtual bool can_be_hidden() const;
+ virtual bool is_selectable_when_hidden() const;
+
+ virtual void redraw(EditorNode3DGizmo *p_gizmo);
+ virtual bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const;
+ virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const;
+
+ virtual int subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const;
+ virtual Vector<int> subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const;
+ virtual Transform3D get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const;
+ virtual void set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) const;
+ virtual void commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel = false) const;
+
+ Ref<EditorNode3DGizmo> get_gizmo(Node3D *p_spatial);
+ void set_state(int p_state);
+ int get_state() const;
+ void unregister_gizmo(EditorNode3DGizmo *p_gizmo);
+
+ EditorNode3DGizmoPlugin();
+ virtual ~EditorNode3DGizmoPlugin();
+};
class Light3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(Light3DGizmoPlugin, EditorNode3DGizmoPlugin);
@@ -44,10 +187,10 @@ public:
String get_gizmo_name() const override;
int get_priority() const override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
Light3DGizmoPlugin();
@@ -61,10 +204,10 @@ public:
String get_gizmo_name() const override;
int get_priority() const override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
AudioStreamPlayer3DGizmoPlugin();
@@ -78,10 +221,10 @@ public:
String get_gizmo_name() const override;
int get_priority() const override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
Camera3DGizmoPlugin();
@@ -210,10 +353,10 @@ public:
bool is_selectable_when_hidden() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) override;
- bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int idx) const override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
+ bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
SoftBody3DGizmoPlugin();
};
@@ -227,10 +370,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
VisibleOnScreenNotifier3DGizmoPlugin();
};
@@ -257,10 +400,10 @@ public:
bool is_selectable_when_hidden() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
GPUParticles3DGizmoPlugin();
};
@@ -274,10 +417,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
GPUParticlesCollision3DGizmoPlugin();
};
@@ -291,10 +434,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
ReflectionProbeGizmoPlugin();
};
@@ -308,10 +451,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
DecalGizmoPlugin();
};
@@ -325,10 +468,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
VoxelGIGizmoPlugin();
};
@@ -342,10 +485,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
LightmapGIGizmoPlugin();
};
@@ -359,10 +502,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
LightmapProbeGizmoPlugin();
};
@@ -388,10 +531,10 @@ public:
int get_priority() const override;
void redraw(EditorNode3DGizmo *p_gizmo) override;
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel = false) const override;
CollisionShape3DGizmoPlugin();
};
@@ -489,4 +632,4 @@ public:
Joint3DGizmoPlugin();
};
-#endif // SPATIAL_EDITOR_GIZMOS_H
+#endif // NODE_3D_EDITOR_GIZMOS_H
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index a0884a81cd..3b9c0ff699 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -35,20 +35,20 @@
#include "core/math/camera_matrix.h"
#include "core/math/math_funcs.h"
#include "core/os/keyboard.h"
-#include "core/string/print_string.h"
#include "core/templates/sort_array.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
-#include "editor/node_3d_editor_gizmos.h"
#include "editor/plugins/animation_player_editor_plugin.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
#include "editor/plugins/script_editor_plugin.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/collision_shape_3d.h"
+#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
#include "scene/3d/physics_body_3d.h"
#include "scene/3d/visual_instance_3d.h"
+#include "scene/3d/world_environment.h"
#include "scene/gui/center_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/resources/packed_scene.h"
@@ -58,7 +58,6 @@
#define GIZMO_ARROW_SIZE 0.35
#define GIZMO_RING_HALF_WIDTH 0.1
-#define GIZMO_SCALE_DEFAULT 0.15
#define GIZMO_PLANE_SIZE 0.2
#define GIZMO_PLANE_DST 0.3
#define GIZMO_CIRCLE_SIZE 1.1
@@ -436,16 +435,29 @@ Vector3 Node3DEditorViewport::_get_ray(const Vector2 &p_pos) const {
}
void Node3DEditorViewport::_clear_selected() {
- editor_selection->clear();
-}
-
-void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_allow_locked) {
- if (clicked.is_null()) {
- return;
+ _edit.gizmo = Ref<EditorNode3DGizmo>();
+ _edit.gizmo_handle = -1;
+ _edit.gizmo_initial_value = Variant();
+
+ Node3D *selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
+
+ if (se && se->gizmo.is_valid()) {
+ se->subgizmos.clear();
+ se->gizmo->redraw();
+ se->gizmo.unref();
+ spatial_editor->update_transform_gizmo();
+ } else {
+ editor_selection->clear();
+ Node3DEditor::get_singleton()->edit(nullptr);
}
+}
- Node *node = Object::cast_to<Node>(ObjectDB::get_instance(clicked));
+void Node3DEditorViewport::_select_clicked(bool p_allow_locked) {
+ Node *node = Object::cast_to<Node3D>(ObjectDB::get_instance(clicked));
Node3D *selected = Object::cast_to<Node3D>(node);
+ clicked = ObjectID();
+
if (!selected) {
return;
}
@@ -462,43 +474,27 @@ void Node3DEditorViewport::_select_clicked(bool p_append, bool p_single, bool p_
}
if (p_allow_locked || !_is_node_locked(selected)) {
- _select(selected, clicked_wants_append, true);
- }
-}
-
-void Node3DEditorViewport::_select(Node *p_node, bool p_append, bool p_single) {
- // Add or remove a single node from the selection
- if (p_append && p_single) {
- if (editor_selection->is_selected(p_node)) {
- // Already in the selection, remove it from the selected nodes
- editor_selection->remove_node(p_node);
+ if (clicked_wants_append) {
+ if (editor_selection->is_selected(selected)) {
+ editor_selection->remove_node(selected);
+ } else {
+ editor_selection->add_node(selected);
+ }
} else {
- // Add the item to the selection
- editor_selection->add_node(p_node);
- }
- } else if (p_append && !p_single) {
- // Add the item to the selection
- editor_selection->add_node(p_node);
- } else {
- // No append; single select
- editor_selection->clear();
- editor_selection->add_node(p_node);
- // Reselect
- if (Engine::get_singleton()->is_editor_hint()) {
- editor->call("edit_node", p_node);
+ if (!editor_selection->is_selected(selected)) {
+ editor_selection->clear();
+ editor_selection->add_node(selected);
+ editor->edit_node(selected);
+ }
}
- }
- if (editor_selection->get_selected_node_list().size() == 1) {
- editor->push_item(editor_selection->get_selected_node_list()[0]);
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ editor->edit_node(editor_selection->get_selected_node_list()[0]);
+ }
}
}
-ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle, bool p_alt_select) {
- if (r_gizmo_handle) {
- *r_gizmo_handle = -1;
- }
-
+ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos) {
Vector3 ray = _get_ray(p_pos);
Vector3 pos = _get_ray_pos(p_pos);
Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink();
@@ -514,7 +510,6 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
ObjectID closest;
Node *item = nullptr;
float closest_dist = 1e20;
- int selected_handle = -1;
for (int i = 0; i < instances.size(); i++) {
Node3D *spat = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i]));
@@ -523,38 +518,40 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
continue;
}
- Ref<EditorNode3DGizmo> seg = spat->get_gizmo();
+ Vector<Ref<Node3DGizmo>> gizmos = spat->get_gizmos();
- if ((!seg.is_valid()) || found_gizmos.has(seg)) {
- continue;
- }
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
- found_gizmos.insert(seg);
- Vector3 point;
- Vector3 normal;
+ if ((!seg.is_valid()) || found_gizmos.has(seg)) {
+ continue;
+ }
- int handle = -1;
- bool inters = seg->intersect_ray(camera, shrinked_pos, point, normal, &handle, p_alt_select);
+ found_gizmos.insert(seg);
+ Vector3 point;
+ Vector3 normal;
- if (!inters) {
- continue;
- }
+ bool inters = seg->intersect_ray(camera, shrinked_pos, point, normal);
- float dist = pos.distance_to(point);
+ if (!inters) {
+ continue;
+ }
- if (dist < 0) {
- continue;
- }
+ float dist = pos.distance_to(point);
- if (dist < closest_dist) {
- item = Object::cast_to<Node>(spat);
- if (item != edited_scene) {
- item = edited_scene->get_deepest_editable_node(item);
+ if (dist < 0) {
+ continue;
}
- closest = item->get_instance_id();
- closest_dist = dist;
- selected_handle = handle;
+ if (dist < closest_dist) {
+ item = Object::cast_to<Node>(spat);
+ if (item != edited_scene) {
+ item = edited_scene->get_deepest_editable_node(item);
+ }
+
+ closest = item->get_instance_id();
+ closest_dist = dist;
+ }
}
}
@@ -562,23 +559,15 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b
return ObjectID();
}
- if (!editor_selection->is_selected(item) || (r_gizmo_handle && selected_handle >= 0)) {
- if (r_gizmo_handle) {
- *r_gizmo_handle = selected_handle;
- }
- }
-
return closest;
}
-void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select, bool p_include_locked_nodes) {
+void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked_nodes) {
Vector3 ray = _get_ray(p_pos);
Vector3 pos = _get_ray_pos(p_pos);
Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world_3d()->get_scenario());
- Set<Ref<EditorNode3DGizmo>> found_gizmos;
-
- r_includes_current = false;
+ Set<Node3D *> found_nodes;
for (int i = 0; i < instances.size(); i++) {
Node3D *spat = Object::cast_to<Node3D>(ObjectDB::get_instance(instances[i]));
@@ -587,53 +576,48 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_inclu
continue;
}
- Ref<EditorNode3DGizmo> seg = spat->get_gizmo();
-
- if (!seg.is_valid()) {
+ if (found_nodes.has(spat)) {
continue;
}
- if (found_gizmos.has(seg)) {
+ if (!p_include_locked_nodes && _is_node_locked(spat)) {
continue;
}
- found_gizmos.insert(seg);
- Vector3 point;
- Vector3 normal;
+ Vector<Ref<Node3DGizmo>> gizmos = spat->get_gizmos();
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
- int handle = -1;
- bool inters = seg->intersect_ray(camera, p_pos, point, normal, nullptr, p_alt_select);
+ if (!seg.is_valid()) {
+ continue;
+ }
- if (!inters) {
- continue;
- }
+ Vector3 point;
+ Vector3 normal;
- float dist = pos.distance_to(point);
+ bool inters = seg->intersect_ray(camera, p_pos, point, normal);
- if (dist < 0) {
- continue;
- }
+ if (!inters) {
+ continue;
+ }
- if (!p_include_locked_nodes && _is_node_locked(spat)) {
- continue;
- }
+ float dist = pos.distance_to(point);
- if (editor_selection->is_selected(spat)) {
- r_includes_current = true;
- }
+ if (dist < 0) {
+ continue;
+ }
- _RayResult res;
- res.item = spat;
- res.depth = dist;
- res.handle = handle;
- results.push_back(res);
- }
+ found_nodes.insert(spat);
- if (results.is_empty()) {
- return;
+ _RayResult res;
+ res.item = spat;
+ res.depth = dist;
+ r_results.push_back(res);
+ break;
+ }
}
- results.sort();
+ r_results.sort();
}
Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
@@ -656,6 +640,9 @@ Vector3 Node3DEditorViewport::_get_screen_to_space(const Vector3 &p_vector3) {
void Node3DEditorViewport::_select_region() {
if (cursor.region_begin == cursor.region_end) {
+ if (!clicked_wants_append) {
+ _clear_selected();
+ }
return; //nothing really
}
@@ -702,7 +689,66 @@ void Node3DEditorViewport::_select_region() {
far.d += get_zfar();
frustum.push_back(far);
+ if (spatial_editor->get_single_selected_node()) {
+ Node3D *single_selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(single_selected);
+
+ Ref<EditorNode3DGizmo> old_gizmo;
+ if (!clicked_wants_append) {
+ se->subgizmos.clear();
+ old_gizmo = se->gizmo;
+ se->gizmo.unref();
+ }
+
+ bool found_subgizmos = false;
+ Vector<Ref<Node3DGizmo>> gizmos = single_selected->get_gizmos();
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
+ if (!seg.is_valid()) {
+ continue;
+ }
+
+ if (se->gizmo.is_valid() && se->gizmo != seg) {
+ continue;
+ }
+
+ Vector<int> subgizmos = seg->subgizmos_intersect_frustum(camera, frustum);
+ if (!subgizmos.is_empty()) {
+ se->gizmo = seg;
+ for (int i = 0; i < subgizmos.size(); i++) {
+ int subgizmo_id = subgizmos[i];
+ if (!se->subgizmos.has(subgizmo_id)) {
+ se->subgizmos.insert(subgizmo_id, se->gizmo->get_subgizmo_transform(subgizmo_id));
+ }
+ }
+ found_subgizmos = true;
+ break;
+ }
+ }
+
+ if (!clicked_wants_append || found_subgizmos) {
+ if (se->gizmo.is_valid()) {
+ se->gizmo->redraw();
+ }
+
+ if (old_gizmo != se->gizmo && old_gizmo.is_valid()) {
+ old_gizmo->redraw();
+ }
+
+ spatial_editor->update_transform_gizmo();
+ }
+
+ if (found_subgizmos) {
+ return;
+ }
+ }
+
+ if (!clicked_wants_append) {
+ _clear_selected();
+ }
+
Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world_3d()->get_scenario());
+ Set<Node3D *> found_nodes;
Vector<Node *> selected;
Node *edited_scene = get_tree()->get_edited_scene_root();
@@ -713,6 +759,12 @@ void Node3DEditorViewport::_select_region() {
continue;
}
+ if (found_nodes.has(sp)) {
+ continue;
+ }
+
+ found_nodes.insert(sp);
+
Node *item = Object::cast_to<Node>(sp);
if (item != edited_scene) {
item = edited_scene->get_deepest_editable_node(item);
@@ -731,28 +783,31 @@ void Node3DEditorViewport::_select_region() {
item = sel;
}
- if (selected.find(item) != -1) {
- continue;
- }
-
if (_is_node_locked(item)) {
continue;
}
- Ref<EditorNode3DGizmo> seg = sp->get_gizmo();
+ Vector<Ref<Node3DGizmo>> gizmos = sp->get_gizmos();
+ for (int j = 0; j < gizmos.size(); j++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[j];
+ if (!seg.is_valid()) {
+ continue;
+ }
- if (!seg.is_valid()) {
- continue;
+ if (seg->intersect_frustum(camera, frustum)) {
+ selected.push_back(item);
+ }
}
+ }
- if (seg->intersect_frustum(camera, frustum)) {
- selected.push_back(item);
+ for (int i = 0; i < selected.size(); i++) {
+ if (!editor_selection->is_selected(selected[i])) {
+ editor_selection->add_node(selected[i]);
}
}
- bool single = selected.size() == 1;
- for (int i = 0; i < selected.size(); i++) {
- _select(selected[i], true, single);
+ if (editor_selection->get_selected_node_list().size() == 1) {
+ editor->edit_node(editor_selection->get_selected_node_list()[0]);
}
}
@@ -779,21 +834,34 @@ void Node3DEditorViewport::_compute_edit(const Point2 &p_point) {
spatial_editor->update_transform_gizmo();
_edit.center = spatial_editor->get_gizmo_transform().origin;
- List<Node *> &selection = editor_selection->get_selected_node_list();
+ Node3D *selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
- if (!sp) {
- continue;
+ if (se && se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) {
+ int subgizmo_id = E->key();
+ se->subgizmos[subgizmo_id] = se->gizmo->get_subgizmo_transform(subgizmo_id);
}
+ se->original_local = selected->get_transform();
+ se->original = selected->get_global_transform();
+ } else {
+ List<Node *> &selection = editor_selection->get_selected_node_list();
- Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
- if (!se) {
- continue;
- }
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node3D *sp = Object::cast_to<Node3D>(E->get());
+ if (!sp) {
+ continue;
+ }
+
+ Node3DEditorSelectedItem *sel_item = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
+
+ if (!sel_item) {
+ continue;
+ }
- se->original = se->sp->get_global_gizmo_transform();
- se->original_local = se->sp->get_local_gizmo_transform();
+ sel_item->original_local = sel_item->sp->get_local_gizmo_transform();
+ sel_item->original = sel_item->sp->get_global_gizmo_transform();
+ }
}
}
@@ -829,7 +897,7 @@ static int _get_key_modifier(Ref<InputEventWithModifiers> e) {
return 0;
}
-bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) {
+bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only) {
if (!spatial_editor->is_gizmo_visible()) {
return false;
}
@@ -1015,6 +1083,88 @@ bool Node3DEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_high
return false;
}
+void Node3DEditorViewport::_transform_gizmo_apply(Node3D *p_node, const Transform3D &p_transform, bool p_local) {
+ if (p_transform.basis.determinant() == 0) {
+ return;
+ }
+
+ if (p_local) {
+ p_node->set_transform(p_transform);
+ } else {
+ p_node->set_global_transform(p_transform);
+ }
+}
+
+Transform3D Node3DEditorViewport::_compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local) {
+ switch (p_mode) {
+ case TRANSFORM_SCALE: {
+ if (p_local) {
+ Basis g = p_original.basis.orthonormalized();
+ Vector3 local_motion = g.inverse().xform(p_motion);
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ local_motion.snap(Vector3(p_extra, p_extra, p_extra));
+ }
+
+ Vector3 local_scale = p_original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1));
+ Transform3D local_t = p_original_local;
+ local_t.basis.set_euler_scale(p_original_local.basis.get_rotation_euler(), local_scale);
+ return local_t;
+ } else {
+ Transform3D base = Transform3D(Basis(), _edit.center);
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ p_motion.snap(Vector3(p_extra, p_extra, p_extra));
+ }
+
+ Transform3D r;
+ r.basis.scale(p_motion + Vector3(1, 1, 1));
+ return base * (r * (base.inverse() * p_original));
+ }
+ }
+ case TRANSFORM_TRANSLATE: {
+ if (p_local) {
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ Basis g = p_original.basis.orthonormalized();
+ Vector3 local_motion = g.inverse().xform(p_motion);
+ local_motion.snap(Vector3(p_extra, p_extra, p_extra));
+
+ p_motion = g.xform(local_motion);
+ }
+
+ } else {
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ p_motion.snap(Vector3(p_extra, p_extra, p_extra));
+ }
+ }
+
+ // Apply translation
+ Transform3D t = p_original;
+ t.origin += p_motion;
+ return t;
+ }
+ case TRANSFORM_ROTATE: {
+ if (p_local) {
+ Basis rot = Basis(p_motion, p_extra);
+
+ Vector3 scale = p_original_local.basis.get_scale();
+ Vector3 euler = (p_original_local.get_basis().orthonormalized() * rot).get_euler();
+ Transform3D t;
+ t.basis.set_euler_scale(euler, scale);
+ t.origin = p_original_local.origin;
+ return t;
+ } else {
+ Transform3D r;
+ r.basis.rotate(p_motion, p_extra);
+ Transform3D base = Transform3D(Basis(), _edit.center);
+ return base * r * base.inverse() * p_original;
+ }
+ }
+ default: {
+ ERR_FAIL_V_MSG(Transform3D(), "Invalid mode in '_compute_transform'");
+ }
+ }
+}
+
void Node3DEditorViewport::_surface_mouse_enter() {
if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) {
surface->grab_focus();
@@ -1038,7 +1188,7 @@ bool Node3DEditorViewport ::_is_node_locked(const Node *p_node) {
}
void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
- _find_items_at_pos(b->get_position(), clicked_includes_current, selection_results, b->is_shift_pressed(), spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
+ _find_items_at_pos(b->get_position(), selection_results, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
Node *scene = editor->get_edited_scene();
@@ -1058,10 +1208,8 @@ void Node3DEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
selection_results.clear();
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
- clicked = ObjectID();
+ _select_clicked(spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
}
-
} else if (!selection_results.is_empty()) {
NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
StringName root_name = root_path.get_name(root_path.get_name_count() - 1);
@@ -1179,8 +1327,8 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -1190,7 +1338,20 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- sp->set_global_transform(se->original);
+ if (se->gizmo.is_valid()) {
+ Vector<int> ids;
+ Vector<Transform3D> restore;
+
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ ids.push_back(GE->key());
+ restore.push_back(GE->value());
+ }
+
+ se->gizmo->commit_subgizmos(ids, restore, true);
+ spatial_editor->update_transform_gizmo();
+ } else {
+ sp->set_global_transform(se->original);
+ }
}
surface->update();
set_message(TTR("Transform Aborted."), 3);
@@ -1262,37 +1423,92 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_edit.snap = spatial_editor->is_snap_enabled();
_edit.mode = TRANSFORM_NONE;
- //gizmo has priority over everything
-
- bool can_select_gizmos = true;
+ bool can_select_gizmos = spatial_editor->get_single_selected_node();
{
int idx = view_menu->get_popup()->get_item_index(VIEW_GIZMOS);
- can_select_gizmos = view_menu->get_popup()->is_item_checked(idx);
+ can_select_gizmos = can_select_gizmos && view_menu->get_popup()->is_item_checked(idx);
}
- if (can_select_gizmos && spatial_editor->get_selected()) {
- Ref<EditorNode3DGizmo> seg = spatial_editor->get_selected()->get_gizmo();
- if (seg.is_valid()) {
- int handle = -1;
- Vector3 point;
- Vector3 normal;
- bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, b->is_shift_pressed());
- if (inters && handle != -1) {
+ // Gizmo handles
+ if (can_select_gizmos) {
+ Vector<Ref<Node3DGizmo>> gizmos = spatial_editor->get_single_selected_node()->get_gizmos();
+
+ bool intersected_handle = false;
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+
+ if ((!seg.is_valid())) {
+ continue;
+ }
+
+ int gizmo_handle = -1;
+ seg->handles_intersect_ray(camera, _edit.mouse_pos, b->is_shift_pressed(), gizmo_handle);
+ if (gizmo_handle != -1) {
_edit.gizmo = seg;
- _edit.gizmo_handle = handle;
- _edit.gizmo_initial_value = seg->get_handle_value(handle);
+ _edit.gizmo_handle = gizmo_handle;
+ _edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle);
+ intersected_handle = true;
break;
}
}
+
+ if (intersected_handle) {
+ break;
+ }
}
- if (_gizmo_select(_edit.mouse_pos)) {
+ // Transform gizmo
+ if (_transform_gizmo_select(_edit.mouse_pos)) {
break;
}
+ // Subgizmos
+ if (can_select_gizmos) {
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(spatial_editor->get_single_selected_node());
+ Vector<Ref<Node3DGizmo>> gizmos = spatial_editor->get_single_selected_node()->get_gizmos();
+
+ bool intersected_subgizmo = false;
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+
+ if ((!seg.is_valid())) {
+ continue;
+ }
+
+ int subgizmo_id = seg->subgizmos_intersect_ray(camera, _edit.mouse_pos);
+ if (subgizmo_id != -1) {
+ ERR_CONTINUE(!se);
+ if (b->is_shift_pressed()) {
+ if (se->subgizmos.has(subgizmo_id)) {
+ se->subgizmos.erase(subgizmo_id);
+ } else {
+ se->subgizmos.insert(subgizmo_id, seg->get_subgizmo_transform(subgizmo_id));
+ }
+ } else {
+ se->subgizmos.clear();
+ se->subgizmos.insert(subgizmo_id, seg->get_subgizmo_transform(subgizmo_id));
+ }
+
+ if (se->subgizmos.is_empty()) {
+ se->gizmo = Ref<EditorNode3DGizmo>();
+ } else {
+ se->gizmo = seg;
+ }
+
+ seg->redraw();
+ spatial_editor->update_transform_gizmo();
+ intersected_subgizmo = true;
+ break;
+ }
+ }
+
+ if (intersected_subgizmo) {
+ break;
+ }
+ }
+
clicked = ObjectID();
- clicked_includes_current = false;
if ((spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT && b->is_command_pressed()) || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE) {
/* HANDLE ROTATION */
@@ -1325,40 +1541,19 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
break;
}
- // todo scale
-
- int gizmo_handle = -1;
-
- clicked = _select_ray(b->get_position(), b->is_shift_pressed(), clicked_includes_current, &gizmo_handle, b->is_shift_pressed());
+ clicked = _select_ray(b->get_position());
//clicking is always deferred to either move or release
clicked_wants_append = b->is_shift_pressed();
if (clicked.is_null()) {
- if (!clicked_wants_append) {
- _clear_selected();
- }
-
//default to regionselect
cursor.region_select = true;
cursor.region_begin = b->get_position();
cursor.region_end = b->get_position();
}
- if (clicked.is_valid() && gizmo_handle >= 0) {
- Node3D *spa = Object::cast_to<Node3D>(ObjectDB::get_instance(clicked));
- if (spa) {
- Ref<EditorNode3DGizmo> seg = spa->get_gizmo();
- if (seg.is_valid()) {
- _edit.gizmo = seg;
- _edit.gizmo_handle = gizmo_handle;
- _edit.gizmo_initial_value = seg->get_handle_value(gizmo_handle);
- break;
- }
- }
- }
-
surface->update();
} else {
if (_edit.gizmo.is_valid()) {
@@ -1366,47 +1561,57 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_edit.gizmo = Ref<EditorNode3DGizmo>();
break;
}
+
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true);
- // Processing was deferred.
- clicked = ObjectID();
+ _select_clicked(false);
}
if (cursor.region_select) {
- if (!clicked_wants_append) {
- _clear_selected();
- }
-
_select_region();
cursor.region_select = false;
surface->update();
}
if (_edit.mode != TRANSFORM_NONE) {
- static const char *_transform_name[4] = { "None", "Rotate", "Translate", "Scale" };
- undo_redo->create_action(_transform_name[_edit.mode]);
+ Node3D *selected = spatial_editor->get_single_selected_node();
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
- List<Node *> &selection = editor_selection->get_selected_node_list();
+ if (se && se->gizmo.is_valid()) {
+ Vector<int> ids;
+ Vector<Transform3D> restore;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
- if (!sp) {
- continue;
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ ids.push_back(GE->key());
+ restore.push_back(GE->value());
}
- Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
- if (!se) {
- continue;
- }
+ se->gizmo->commit_subgizmos(ids, restore, false);
+ spatial_editor->update_transform_gizmo();
+ } else {
+ static const char *_transform_name[4] = { "None", "Rotate", "Translate", "Scale" };
+ undo_redo->create_action(_transform_name[_edit.mode]);
+
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node3D *sp = Object::cast_to<Node3D>(E->get());
+ if (!sp) {
+ continue;
+ }
- undo_redo->add_do_method(sp, "set_global_transform", sp->get_global_gizmo_transform());
- undo_redo->add_undo_method(sp, "set_global_transform", se->original);
+ Node3DEditorSelectedItem *sel_item = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
+ if (!sel_item) {
+ continue;
+ }
+
+ undo_redo->add_do_method(sp, "set_global_transform", sp->get_global_gizmo_transform());
+ undo_redo->add_undo_method(sp, "set_global_transform", sel_item->original);
+ }
+ undo_redo->commit_action();
}
- undo_redo->commit_action();
_edit.mode = TRANSFORM_NONE;
set_message("");
}
-
surface->update();
}
@@ -1421,31 +1626,39 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (m.is_valid()) {
_edit.mouse_pos = m->get_position();
- if (spatial_editor->get_selected()) {
- Ref<EditorNode3DGizmo> seg = spatial_editor->get_selected()->get_gizmo();
- if (seg.is_valid()) {
- int selected_handle = -1;
-
- int handle = -1;
- Vector3 point;
- Vector3 normal;
- bool inters = seg->intersect_ray(camera, _edit.mouse_pos, point, normal, &handle, false);
- if (inters && handle != -1) {
- selected_handle = handle;
+ if (spatial_editor->get_single_selected_node()) {
+ Vector<Ref<Node3DGizmo>> gizmos = spatial_editor->get_single_selected_node()->get_gizmos();
+
+ Ref<EditorNode3DGizmo> found_gizmo;
+ int found_handle = -1;
+
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+ if (!seg.is_valid()) {
+ continue;
}
- if (selected_handle != spatial_editor->get_over_gizmo_handle()) {
- spatial_editor->set_over_gizmo_handle(selected_handle);
- spatial_editor->get_selected()->update_gizmo();
- if (selected_handle != -1) {
- spatial_editor->select_gizmo_highlight_axis(-1);
- }
+ seg->handles_intersect_ray(camera, _edit.mouse_pos, false, found_handle);
+
+ if (found_handle != -1) {
+ found_gizmo = seg;
+ break;
}
}
+
+ if (found_gizmo.is_valid()) {
+ spatial_editor->select_gizmo_highlight_axis(-1);
+ }
+
+ if (found_gizmo != spatial_editor->get_current_hover_gizmo() || found_handle != spatial_editor->get_current_hover_gizmo_handle()) {
+ spatial_editor->set_current_hover_gizmo(found_gizmo);
+ spatial_editor->set_current_hover_gizmo_handle(found_handle);
+ spatial_editor->get_single_selected_node()->update_gizmos();
+ }
}
- if (spatial_editor->get_over_gizmo_handle() == -1 && !(m->get_button_mask() & 1) && !_edit.gizmo.is_valid()) {
- _gizmo_select(_edit.mouse_pos, true);
+ if (spatial_editor->get_current_hover_gizmo().is_null() && !(m->get_button_mask() & 1) && !_edit.gizmo.is_valid()) {
+ _transform_gizmo_select(_edit.mouse_pos, true);
}
NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
@@ -1469,11 +1682,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
} else {
const bool movement_threshold_passed = _edit.original_mouse_pos.distance_to(_edit.mouse_pos) > 8 * EDSCALE;
if (clicked.is_valid() && movement_threshold_passed) {
- if (!clicked_includes_current) {
- _select_clicked(clicked_wants_append, true);
- // Processing was deferred.
- }
-
_compute_edit(_edit.mouse_pos);
clicked = ObjectID();
@@ -1568,8 +1776,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
motion = Vector3(scale, scale, scale);
}
- List<Node *> &selection = editor_selection->get_selected_node_list();
-
// Disable local transformation for TRANSFORM_VIEW
bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW);
@@ -1582,8 +1788,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(TTR("Scaling: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " +
String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")");
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -1597,44 +1804,22 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform3D original = se->original;
- Transform3D original_local = se->original_local;
- Transform3D base = Transform3D(Basis(), _edit.center);
- Transform3D t;
- Vector3 local_scale;
-
- if (local_coords) {
- Basis g = original.basis.orthonormalized();
- Vector3 local_motion = g.inverse().xform(motion);
-
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- local_motion.snap(Vector3(snap, snap, snap));
- }
-
- local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1));
-
- // Prevent scaling to 0 it would break the gizmo
- Basis check = original_local.basis;
- check.scale(local_scale);
- if (check.determinant() != 0) {
- // Apply scale
- sp->set_scale(local_scale);
+ if (se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ Transform3D xform = GE->get();
+ Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original * xform, xform, motion, snap, local_coords);
+ if (!local_coords) {
+ new_xform = se->original.affine_inverse() * new_xform;
+ }
+ se->gizmo->set_subgizmo_transform(GE->key(), new_xform);
}
-
} else {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- motion.snap(Vector3(snap, snap, snap));
- }
-
- Transform3D r;
- r.basis.scale(motion + Vector3(1, 1, 1));
- t = base * (r * (base.inverse() * original));
-
- // Apply scale
- sp->set_global_transform(t);
+ Transform3D new_xform = _compute_transform(TRANSFORM_SCALE, se->original, se->original_local, motion, snap, local_coords);
+ _transform_gizmo_apply(se->sp, new_xform, local_coords);
}
}
+ spatial_editor->update_transform_gizmo();
surface->update();
} break;
@@ -1691,8 +1876,6 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
}
}
- List<Node *> &selection = editor_selection->get_selected_node_list();
-
// Disable local transformation for TRANSFORM_VIEW
bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW);
@@ -1704,8 +1887,9 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(TTR("Translating: ") + "(" + String::num(motion_snapped.x, snap_step_decimals) + ", " +
String::num(motion_snapped.y, snap_step_decimals) + ", " + String::num(motion_snapped.z, snap_step_decimals) + ")");
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -1719,30 +1903,20 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform3D original = se->original;
- Transform3D t;
-
- if (local_coords) {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- Basis g = original.basis.orthonormalized();
- Vector3 local_motion = g.inverse().xform(motion);
- local_motion.snap(Vector3(snap, snap, snap));
-
- motion = g.xform(local_motion);
+ if (se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ Transform3D xform = GE->get();
+ Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original * xform, xform, motion, snap, local_coords);
+ new_xform = se->original.affine_inverse() * new_xform;
+ se->gizmo->set_subgizmo_transform(GE->key(), new_xform);
}
-
} else {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
- motion.snap(Vector3(snap, snap, snap));
- }
+ Transform3D new_xform = _compute_transform(TRANSFORM_TRANSLATE, se->original, se->original_local, motion, snap, local_coords);
+ _transform_gizmo_apply(se->sp, new_xform, false);
}
-
- // Apply translation
- t = original;
- t.origin += motion;
- sp->set_global_transform(t);
}
+ spatial_editor->update_transform_gizmo();
surface->update();
} break;
@@ -1796,12 +1970,11 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
set_message(vformat(TTR("Rotating %s degrees."), String::num(angle, snap_step_decimals)));
angle = Math::deg2rad(angle);
- List<Node *> &selection = editor_selection->get_selected_node_list();
-
bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -1815,32 +1988,24 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
continue;
}
- Transform3D t;
-
- if (local_coords) {
- Transform3D original_local = se->original_local;
- Basis rot = Basis(axis, angle);
-
- t.basis = original_local.get_basis().orthonormalized() * rot;
- t.origin = original_local.origin;
-
- // Apply rotation
- sp->set_transform(t);
- sp->set_scale(original_local.basis.get_scale()); // re-apply original scale
+ Vector3 compute_axis = local_coords ? axis : plane.normal;
+ if (se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ Transform3D xform = GE->get();
+ Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original * xform, xform, compute_axis, angle, local_coords);
+ if (!local_coords) {
+ new_xform = se->original.affine_inverse() * new_xform;
+ }
+ se->gizmo->set_subgizmo_transform(GE->key(), new_xform);
+ }
} else {
- Transform3D original = se->original;
- Transform3D r;
- Transform3D base = Transform3D(Basis(), _edit.center);
-
- r.basis.rotate(plane.normal, angle);
- t = base * r * base.inverse() * original;
-
- // Apply rotation
- sp->set_global_transform(t);
+ Transform3D new_xform = _compute_transform(TRANSFORM_ROTATE, se->original, se->original_local, compute_axis, angle, local_coords);
+ _transform_gizmo_apply(se->sp, new_xform, local_coords);
}
}
+ spatial_editor->update_transform_gizmo();
surface->update();
} break;
@@ -2039,8 +2204,8 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -2905,8 +3070,8 @@ void Node3DEditorViewport::_menu_option(int p_option) {
undo_redo->create_action(TTR("Align Transform with View"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -2941,8 +3106,8 @@ void Node3DEditorViewport::_menu_option(int p_option) {
List<Node *> &selection = editor_selection->get_selected_node_list();
undo_redo->create_action(TTR("Align Rotation with View"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -3310,8 +3475,7 @@ void Node3DEditorViewport::_selection_result_pressed(int p_result) {
clicked = selection_results[p_result].item->get_instance_id();
if (clicked.is_valid()) {
- _select_clicked(clicked_wants_append, true, spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
- clicked = ObjectID();
+ _select_clicked(spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT);
}
}
@@ -3338,7 +3502,7 @@ void Node3DEditorViewport::update_transform_gizmo_view() {
Transform3D camera_xform = camera->get_transform();
- if (xform.origin.distance_squared_to(camera_xform.origin) < 0.01) {
+ if (xform.origin.is_equal_approx(camera_xform.origin)) {
for (int i = 0; i < 3; i++) {
RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], false);
RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], false);
@@ -3595,8 +3759,8 @@ void Node3DEditorViewport::focus_selection() {
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -3606,6 +3770,13 @@ void Node3DEditorViewport::focus_selection() {
continue;
}
+ if (se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *GE = se->subgizmos.front(); GE; GE = GE->next()) {
+ center += se->gizmo->get_subgizmo_transform(GE->key()).origin;
+ count++;
+ }
+ }
+
center += sp->get_global_gizmo_transform().origin;
count++;
}
@@ -3629,58 +3800,16 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const
Vector3 world_ray = _get_ray(p_pos);
Vector3 world_pos = _get_ray_pos(p_pos);
- Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world_3d()->get_scenario());
- Set<Ref<EditorNode3DGizmo>> found_gizmos;
-
- float closest_dist = MAX_DISTANCE;
-
Vector3 point = world_pos + world_ray * MAX_DISTANCE;
- Vector3 normal = Vector3(0.0, 0.0, 0.0);
-
- for (int i = 0; i < instances.size(); i++) {
- MeshInstance3D *mesh_instance = Object::cast_to<MeshInstance3D>(ObjectDB::get_instance(instances[i]));
-
- if (!mesh_instance) {
- continue;
- }
-
- Ref<EditorNode3DGizmo> seg = mesh_instance->get_gizmo();
-
- if ((!seg.is_valid()) || found_gizmos.has(seg)) {
- continue;
- }
-
- found_gizmos.insert(seg);
-
- Vector3 hit_point;
- Vector3 hit_normal;
- bool inters = seg->intersect_ray(camera, p_pos, hit_point, hit_normal, nullptr, false);
-
- if (!inters) {
- continue;
- }
- float dist = world_pos.distance_to(hit_point);
-
- if (dist < 0) {
- continue;
- }
+ PhysicsDirectSpaceState3D *ss = get_tree()->get_root()->get_world_3d()->get_direct_space_state();
+ PhysicsDirectSpaceState3D::RayResult result;
- if (dist < closest_dist) {
- closest_dist = dist;
- point = hit_point;
- normal = hit_normal;
- }
+ if (ss->intersect_ray(world_pos, world_pos + world_ray * MAX_DISTANCE, result)) {
+ point = result.position;
}
- Vector3 offset = Vector3();
- for (int i = 0; i < 3; i++) {
- if (normal[i] > 0.0) {
- offset[i] = (preview_bounds->get_size()[i] - (preview_bounds->get_size()[i] + preview_bounds->get_position()[i]));
- } else if (normal[i] < 0.0) {
- offset[i] = -(preview_bounds->get_size()[i] + preview_bounds->get_position()[i]);
- }
- }
- return point + offset;
+
+ return point;
}
AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform) {
@@ -3972,9 +4101,8 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
_edit.mode = TRANSFORM_NONE;
_edit.plane = TRANSFORM_VIEW;
- _edit.edited_gizmo = 0;
_edit.snap = true;
- _edit.gizmo_handle = 0;
+ _edit.gizmo_handle = -1;
index = p_index;
editor = p_editor;
@@ -3982,7 +4110,6 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
editor_selection = editor->get_editor_selection();
undo_redo = editor->get_undo_redo();
- clicked_includes_current = false;
orthogonal = false;
auto_orthogonal = false;
lock_rotation = false;
@@ -4005,7 +4132,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
surface->set_anchors_and_offsets_preset(Control::PRESET_WIDE);
surface->set_clip_contents(true);
camera = memnew(Camera3D);
- camera->set_disable_gizmo(true);
+ camera->set_disable_gizmos(true);
camera->set_cull_mask(((1 << 20) - 1) | (1 << (GIZMO_BASE_LAYER + p_index)) | (1 << GIZMO_EDIT_LAYER) | (1 << GIZMO_GRID_LAYER) | (1 << MISC_TOOL_LAYER));
viewport->add_child(camera);
camera->make_current();
@@ -4134,6 +4261,7 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito
preview_camera = memnew(CheckBox);
preview_camera->set_text(TTR("Preview"));
+ preview_camera->set_shortcut(ED_SHORTCUT("spatial_editor/toggle_camera_preview", TTR("Toggle Camera Preview"), KEY_MASK_CMD | KEY_P));
vbox->add_child(preview_camera);
preview_camera->set_h_size_flags(0);
preview_camera->hide();
@@ -4574,43 +4702,54 @@ void Node3DEditor::select_gizmo_highlight_axis(int p_axis) {
}
void Node3DEditor::update_transform_gizmo() {
- List<Node *> &selection = editor_selection->get_selected_node_list();
- AABB center;
- bool first = true;
+ int count = 0;
+ bool local_gizmo_coords = are_local_coords_enabled();
+ Vector3 gizmo_center;
Basis gizmo_basis;
- bool local_gizmo_coords = are_local_coords_enabled();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
- if (!sp) {
- continue;
- }
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
- Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
- if (!se) {
- continue;
+ if (se && se->gizmo.is_valid()) {
+ for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) {
+ Transform3D xf = se->sp->get_global_transform() * se->gizmo->get_subgizmo_transform(E->key());
+ gizmo_center += xf.origin;
+ if (count == 0 && local_gizmo_coords) {
+ gizmo_basis = xf.basis;
+ gizmo_basis.orthonormalize();
+ }
+ count++;
}
+ } else {
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ Node3D *sp = Object::cast_to<Node3D>(E->get());
+ if (!sp) {
+ continue;
+ }
+
+ if (sp->has_meta("_edit_lock_")) {
+ continue;
+ }
- Transform3D xf = se->sp->get_global_gizmo_transform();
+ Node3DEditorSelectedItem *sel_item = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
+ if (!sel_item) {
+ continue;
+ }
- if (first) {
- center.position = xf.origin;
- first = false;
- if (local_gizmo_coords) {
+ Transform3D xf = sel_item->sp->get_global_transform();
+ gizmo_center += xf.origin;
+ if (count == 0 && local_gizmo_coords) {
gizmo_basis = xf.basis;
gizmo_basis.orthonormalize();
}
- } else {
- center.expand_to(xf.origin);
- gizmo_basis = Basis();
+ count++;
}
}
- Vector3 pcenter = center.position + center.size * 0.5;
- gizmo.visible = !first;
- gizmo.transform.origin = pcenter;
- gizmo.transform.basis = gizmo_basis;
+ gizmo.visible = count > 0;
+ gizmo.transform.origin = (count > 0) ? gizmo_center / count : Vector3();
+ gizmo.transform.basis = (count == 1) ? gizmo_basis : Basis();
for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) {
viewports[i]->update_transform_gizmo_view();
@@ -4621,7 +4760,7 @@ void _update_all_gizmos(Node *p_node) {
for (int i = p_node->get_child_count() - 1; 0 <= i; --i) {
Node3D *spatial_node = Object::cast_to<Node3D>(p_node->get_child(i));
if (spatial_node) {
- spatial_node->update_gizmo();
+ spatial_node->update_gizmos();
}
_update_all_gizmos(p_node->get_child(i));
@@ -4655,7 +4794,9 @@ Object *Node3DEditor::_get_editor_data(Object *p_what) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(
si->sbox_instance,
RS::SHADOW_CASTING_SETTING_OFF);
- RS::get_singleton()->instance_set_layer_mask(si->sbox_instance, 1 << Node3DEditorViewport::MISC_TOOL_LAYER);
+ // Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting.
+ // It's still possible to approximately guess what is selected by looking at the manipulation gizmo position.
+ RS::get_singleton()->instance_set_layer_mask(si->sbox_instance, 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER);
RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
si->sbox_instance_xray = RenderingServer::get_singleton()->instance_create2(
selection_box_xray->get_rid(),
@@ -4663,7 +4804,9 @@ Object *Node3DEditor::_get_editor_data(Object *p_what) {
RS::get_singleton()->instance_geometry_set_cast_shadows_setting(
si->sbox_instance_xray,
RS::SHADOW_CASTING_SETTING_OFF);
- RS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray, 1 << Node3DEditorViewport::MISC_TOOL_LAYER);
+ // Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting.
+ // It's still possible to approximately guess what is selected by looking at the manipulation gizmo position.
+ RS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray, 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER);
RS::get_singleton()->instance_geometry_set_flag(si->sbox_instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
return si;
@@ -4940,22 +5083,38 @@ void Node3DEditor::set_state(const Dictionary &p_state) {
void Node3DEditor::edit(Node3D *p_spatial) {
if (p_spatial != selected) {
if (selected) {
- Ref<EditorNode3DGizmo> seg = selected->get_gizmo();
- if (seg.is_valid()) {
+ Vector<Ref<Node3DGizmo>> gizmos = selected->get_gizmos();
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+ if (!seg.is_valid()) {
+ continue;
+ }
seg->set_selected(false);
- selected->update_gizmo();
}
+
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected);
+ if (se) {
+ se->gizmo.unref();
+ se->subgizmos.clear();
+ }
+
+ selected->update_gizmos();
}
selected = p_spatial;
- over_gizmo_handle = -1;
+ current_hover_gizmo = Ref<EditorNode3DGizmo>();
+ current_hover_gizmo_handle = -1;
if (selected) {
- Ref<EditorNode3DGizmo> seg = selected->get_gizmo();
- if (seg.is_valid()) {
+ Vector<Ref<Node3DGizmo>> gizmos = selected->get_gizmos();
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+ if (!seg.is_valid()) {
+ continue;
+ }
seg->set_selected(true);
- selected->update_gizmo();
}
+ selected->update_gizmos();
}
}
}
@@ -4993,8 +5152,8 @@ void Node3DEditor::_xform_dialog_action() {
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (!sp) {
continue;
}
@@ -5230,8 +5389,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *spatial = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *spatial = Object::cast_to<Node3D>(E);
if (!spatial || !spatial->is_inside_tree()) {
continue;
}
@@ -5255,8 +5414,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *spatial = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *spatial = Object::cast_to<Node3D>(E);
if (!spatial || !spatial->is_inside_tree()) {
continue;
}
@@ -5280,8 +5439,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) {
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *spatial = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *spatial = Object::cast_to<Node3D>(E);
if (!spatial || !spatial->is_inside_tree()) {
continue;
}
@@ -5304,8 +5463,8 @@ void Node3DEditor::_menu_item_pressed(int p_option) {
undo_redo->create_action(TTR("Ungroup Selected"));
List<Node *> &selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *spatial = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *spatial = Object::cast_to<Node3D>(E);
if (!spatial || !spatial->is_inside_tree()) {
continue;
}
@@ -6027,13 +6186,27 @@ void Node3DEditor::update_grid() {
_init_grid();
}
-bool Node3DEditor::is_any_freelook_active() const {
- for (unsigned int i = 0; i < VIEWPORTS_COUNT; ++i) {
- if (viewports[i]->is_freelook_active()) {
- return true;
+void Node3DEditor::_selection_changed() {
+ _refresh_menu_icons();
+ if (selected && editor_selection->get_selected_node_list().size() != 1) {
+ Vector<Ref<Node3DGizmo>> gizmos = selected->get_gizmos();
+ for (int i = 0; i < gizmos.size(); i++) {
+ Ref<EditorNode3DGizmo> seg = gizmos[i];
+ if (!seg.is_valid()) {
+ continue;
+ }
+ seg->set_selected(false);
}
+
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected);
+ if (se) {
+ se->gizmo.unref();
+ se->subgizmos.clear();
+ }
+ selected->update_gizmos();
+ selected = nullptr;
}
- return false;
+ update_transform_gizmo();
}
void Node3DEditor::_refresh_menu_icons() {
@@ -6046,14 +6219,14 @@ void Node3DEditor::_refresh_menu_icons() {
all_locked = false;
all_grouped = false;
} else {
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- if (Object::cast_to<Node3D>(E->get()) && !Object::cast_to<Node3D>(E->get())->has_meta("_edit_lock_")) {
+ for (Node *E : selection) {
+ if (Object::cast_to<Node3D>(E) && !Object::cast_to<Node3D>(E)->has_meta("_edit_lock_")) {
all_locked = false;
break;
}
}
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- if (Object::cast_to<Node3D>(E->get()) && !Object::cast_to<Node3D>(E->get())->has_meta("_edit_group_")) {
+ for (Node *E : selection) {
+ if (Object::cast_to<Node3D>(E) && !Object::cast_to<Node3D>(E)->has_meta("_edit_group_")) {
all_grouped = false;
break;
}
@@ -6106,8 +6279,8 @@ void Node3DEditor::snap_selected_nodes_to_floor() {
List<Node *> &selection = editor_selection->get_selected_node_list();
Dictionary snap_data;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node3D *sp = Object::cast_to<Node3D>(E->get());
+ for (Node *E : selection) {
+ Node3D *sp = Object::cast_to<Node3D>(E);
if (sp) {
Vector3 from = Vector3();
Vector3 position_offset = Vector3();
@@ -6295,93 +6468,113 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) {
undo_redo->commit_action();
}
+void Node3DEditor::_update_theme() {
+ tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons")));
+ tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons")));
+
+ tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")));
+ tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
+ tool_option_button[Node3DEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons")));
+
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels2Alt"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon(SNAME("Panels3"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons")));
+ view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons")));
+
+ sun_button->set_icon(get_theme_icon(SNAME("DirectionalLight3D"), SNAME("EditorIcons")));
+ environ_button->set_icon(get_theme_icon(SNAME("WorldEnvironment"), SNAME("EditorIcons")));
+ sun_environ_settings->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+
+ sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
+ environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
+}
+
void Node3DEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_READY) {
- tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons")));
-
- tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")));
- tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
- tool_option_button[Node3DEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons")));
-
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels2Alt"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon(SNAME("Panels3"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons")));
-
- _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
-
- _refresh_menu_icons();
-
- get_tree()->connect("node_removed", callable_mp(this, &Node3DEditor::_node_removed));
- get_tree()->connect("node_added", callable_mp(this, &Node3DEditor::_node_added));
- EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
- editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
-
- editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false));
- editor->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true));
-
- sun_button->set_icon(get_theme_icon(SNAME("DirectionalLight3D"), SNAME("EditorIcons")));
- environ_button->set_icon(get_theme_icon(SNAME("WorldEnvironment"), SNAME("EditorIcons")));
- sun_environ_settings->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
+ switch (p_what) {
+ case NOTIFICATION_READY: {
+ _menu_item_pressed(MENU_VIEW_USE_1_VIEWPORT);
- _update_preview_environment();
- sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
- environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
+ _refresh_menu_icons();
- sun_state->set_custom_minimum_size(sun_vb->get_combined_minimum_size());
- environ_state->set_custom_minimum_size(environ_vb->get_combined_minimum_size());
- } else if (p_what == NOTIFICATION_ENTER_TREE) {
- _register_all_gizmos();
- _update_gizmos_menu();
- _init_indicators();
- } else if (p_what == NOTIFICATION_THEME_CHANGED) {
- _update_gizmos_menu_theme();
- sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
- environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
- } else if (p_what == NOTIFICATION_EXIT_TREE) {
- _finish_indicators();
- } else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
- tool_button[Node3DEditor::TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons")));
- tool_button[Node3DEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons")));
-
- tool_option_button[Node3DEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons")));
- tool_option_button[Node3DEditor::TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons")));
-
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels2Alt"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon(SNAME("Panels3"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons")));
- view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons")));
-
- // Update grid color by rebuilding grid.
- _finish_grid();
- _init_grid();
- } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- if (!is_visible() && tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->is_pressed()) {
- EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
+ get_tree()->connect("node_removed", callable_mp(this, &Node3DEditor::_node_removed));
+ get_tree()->connect("node_added", callable_mp(this, &Node3DEditor::_node_added));
+ EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", callable_mp(this, &Node3DEditor::_refresh_menu_icons));
+ editor_selection->connect("selection_changed", callable_mp(this, &Node3DEditor::_selection_changed));
+
+ editor->connect("stop_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(false));
+ editor->connect("play_pressed", callable_mp(this, &Node3DEditor::_update_camera_override_button), make_binds(true));
+
+ _update_preview_environment();
+
+ sun_state->set_custom_minimum_size(sun_vb->get_combined_minimum_size());
+ environ_state->set_custom_minimum_size(environ_vb->get_combined_minimum_size());
+ } break;
+ case NOTIFICATION_ENTER_TREE: {
+ _update_theme();
+ _register_all_gizmos();
+ _update_gizmos_menu();
+ _init_indicators();
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ _finish_indicators();
+ } break;
+ case NOTIFICATION_THEME_CHANGED: {
+ _update_theme();
+ _update_gizmos_menu_theme();
+ sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
+ environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window")));
+ } break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ // Update grid color by rebuilding grid.
+ _finish_grid();
+ _init_grid();
+ } break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible() && tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->is_pressed()) {
+ EditorDebuggerNode *debugger = EditorDebuggerNode::get_singleton();
+
+ debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE);
+ tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_pressed(false);
+ }
+ } break;
+ }
+}
+
+bool Node3DEditor::is_subgizmo_selected(int p_id) {
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
+ if (se) {
+ return se->subgizmos.has(p_id);
+ }
+ return false;
+}
- debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE);
- tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_pressed(false);
+bool Node3DEditor::is_current_selected_gizmo(const EditorNode3DGizmo *p_gizmo) {
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
+ if (se) {
+ return se->gizmo == p_gizmo;
+ }
+ return false;
+}
+
+Vector<int> Node3DEditor::get_subgizmo_selection() {
+ Node3DEditorSelectedItem *se = selected ? editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected) : nullptr;
+
+ Vector<int> ret;
+ if (se) {
+ for (Map<int, Transform3D>::Element *E = se->subgizmos.front(); E; E = E->next()) {
+ ret.push_back(E->key());
}
}
+ return ret;
}
void Node3DEditor::add_control_to_menu_panel(Control *p_control) {
@@ -6411,23 +6604,43 @@ void Node3DEditor::_request_gizmo(Object *p_obj) {
if (!sp) {
return;
}
- if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_ancestor_of(sp)))) {
- Ref<EditorNode3DGizmo> seg;
+ bool is_selected = (sp == selected);
+
+ if (editor->get_edited_scene() && (sp == editor->get_edited_scene() || (sp->get_owner() && editor->get_edited_scene()->is_ancestor_of(sp)))) {
for (int i = 0; i < gizmo_plugins_by_priority.size(); ++i) {
- seg = gizmo_plugins_by_priority.write[i]->get_gizmo(sp);
+ Ref<EditorNode3DGizmo> seg = gizmo_plugins_by_priority.write[i]->get_gizmo(sp);
if (seg.is_valid()) {
- sp->set_gizmo(seg);
+ sp->add_gizmo(seg);
- if (sp == selected) {
- seg->set_selected(true);
- selected->update_gizmo();
+ if (is_selected != seg->is_selected()) {
+ seg->set_selected(is_selected);
}
-
- break;
}
}
+ sp->update_gizmos();
+ }
+}
+
+void Node3DEditor::_clear_subgizmo_selection(Object *p_obj) {
+ Node3D *sp = nullptr;
+ if (p_obj) {
+ sp = Object::cast_to<Node3D>(p_obj);
+ } else {
+ sp = selected;
+ }
+
+ if (!sp) {
+ return;
+ }
+
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(sp);
+ if (se) {
+ se->subgizmos.clear();
+ se->gizmo.unref();
+ sp->update_gizmos();
+ update_transform_gizmo();
}
}
@@ -6516,7 +6729,13 @@ void Node3DEditor::_node_removed(Node *p_node) {
}
if (p_node == selected) {
+ Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(selected);
+ if (se) {
+ se->gizmo.unref();
+ se->subgizmos.clear();
+ }
selected = nullptr;
+ update_transform_gizmo();
}
}
@@ -6554,6 +6773,7 @@ void Node3DEditor::_bind_methods() {
ClassDB::bind_method("_unhandled_key_input", &Node3DEditor::_unhandled_key_input);
ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data);
ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo);
+ ClassDB::bind_method("_clear_subgizmo_selection", &Node3DEditor::_clear_subgizmo_selection);
ClassDB::bind_method("_refresh_menu_icons", &Node3DEditor::_refresh_menu_icons);
ADD_SIGNAL(MethodInfo("transform_key_request"));
@@ -6769,8 +6989,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds);
tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), KEY_Q));
tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this);
- tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Show list of all nodes at position clicked, including locked."));
-
+ tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked."));
hbc_menu->add_child(memnew(VSeparator));
tool_button[TOOL_MODE_MOVE] = memnew(Button);
@@ -7130,7 +7349,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::FLOAT, "editors/3d/manipulator_gizmo_opacity", PROPERTY_HINT_RANGE, "0,1,0.01"));
EDITOR_DEF("editors/3d/navigation/show_viewport_rotation_gizmo", true);
- over_gizmo_handle = -1;
+ current_hover_gizmo_handle = -1;
{
//sun popup
@@ -7444,303 +7663,3 @@ Node3DEditorPlugin::Node3DEditorPlugin(EditorNode *p_node) {
Node3DEditorPlugin::~Node3DEditorPlugin() {
}
-
-void EditorNode3DGizmoPlugin::create_material(const String &p_name, const Color &p_color, bool p_billboard, bool p_on_top, bool p_use_vertex_color) {
- Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
-
- Vector<Ref<StandardMaterial3D>> mats;
-
- for (int i = 0; i < 4; i++) {
- bool selected = i % 2 == 1;
- bool instantiated = i < 2;
-
- Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
-
- Color color = instantiated ? instantiated_color : p_color;
-
- if (!selected) {
- color.a *= 0.3;
- }
-
- material->set_albedo(color);
- material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
- material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN + 1);
- material->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
-
- if (p_use_vertex_color) {
- material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- }
-
- if (p_billboard) {
- material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
- }
-
- if (p_on_top && selected) {
- material->set_on_top_of_alpha();
- }
-
- mats.push_back(material);
- }
-
- materials[p_name] = mats;
-}
-
-void EditorNode3DGizmoPlugin::create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top, const Color &p_albedo) {
- Color instantiated_color = EDITOR_DEF("editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6));
-
- Vector<Ref<StandardMaterial3D>> icons;
-
- for (int i = 0; i < 4; i++) {
- bool selected = i % 2 == 1;
- bool instantiated = i < 2;
-
- Ref<StandardMaterial3D> icon = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
-
- Color color = instantiated ? instantiated_color : p_albedo;
-
- if (!selected) {
- color.a *= 0.85;
- }
-
- icon->set_albedo(color);
-
- icon->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- icon->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- icon->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- icon->set_cull_mode(StandardMaterial3D::CULL_DISABLED);
- icon->set_depth_draw_mode(StandardMaterial3D::DEPTH_DRAW_DISABLED);
- icon->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
- icon->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, p_texture);
- icon->set_flag(StandardMaterial3D::FLAG_FIXED_SIZE, true);
- icon->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
- icon->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MIN);
-
- if (p_on_top && selected) {
- icon->set_on_top_of_alpha();
- }
-
- icons.push_back(icon);
- }
-
- materials[p_name] = icons;
-}
-
-void EditorNode3DGizmoPlugin::create_handle_material(const String &p_name, bool p_billboard, const Ref<Texture2D> &p_icon) {
- Ref<StandardMaterial3D> handle_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
-
- handle_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
- handle_material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true);
- Ref<Texture2D> handle_t = p_icon != nullptr ? p_icon : Node3DEditor::get_singleton()->get_theme_icon(SNAME("Editor3DHandle"), SNAME("EditorIcons"));
- handle_material->set_point_size(handle_t->get_width());
- handle_material->set_texture(StandardMaterial3D::TEXTURE_ALBEDO, handle_t);
- handle_material->set_albedo(Color(1, 1, 1));
- handle_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
- handle_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
- handle_material->set_on_top_of_alpha();
- if (p_billboard) {
- handle_material->set_billboard_mode(StandardMaterial3D::BILLBOARD_ENABLED);
- handle_material->set_on_top_of_alpha();
- }
- handle_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
-
- materials[p_name] = Vector<Ref<StandardMaterial3D>>();
- materials[p_name].push_back(handle_material);
-}
-
-void EditorNode3DGizmoPlugin::add_material(const String &p_name, Ref<StandardMaterial3D> p_material) {
- materials[p_name] = Vector<Ref<StandardMaterial3D>>();
- materials[p_name].push_back(p_material);
-}
-
-Ref<StandardMaterial3D> EditorNode3DGizmoPlugin::get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo) {
- ERR_FAIL_COND_V(!materials.has(p_name), Ref<StandardMaterial3D>());
- ERR_FAIL_COND_V(materials[p_name].size() == 0, Ref<StandardMaterial3D>());
-
- if (p_gizmo.is_null() || materials[p_name].size() == 1) {
- return materials[p_name][0];
- }
-
- int index = (p_gizmo->is_selected() ? 1 : 0) + (p_gizmo->is_editable() ? 2 : 0);
-
- Ref<StandardMaterial3D> mat = materials[p_name][index];
-
- if (current_state == ON_TOP && p_gizmo->is_selected()) {
- mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
- } else {
- mat->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, false);
- }
-
- return mat;
-}
-
-String EditorNode3DGizmoPlugin::get_gizmo_name() const {
- if (get_script_instance() && get_script_instance()->has_method("_get_gizmo_name")) {
- return get_script_instance()->call("_get_gizmo_name");
- }
- return TTR("Nameless gizmo");
-}
-
-int EditorNode3DGizmoPlugin::get_priority() const {
- if (get_script_instance() && get_script_instance()->has_method("_get_priority")) {
- return get_script_instance()->call("_get_priority");
- }
- return 0;
-}
-
-Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) {
- if (get_script_instance() && get_script_instance()->has_method("get_gizmo")) {
- return get_script_instance()->call("get_gizmo", p_spatial);
- }
-
- Ref<EditorNode3DGizmo> ref = create_gizmo(p_spatial);
-
- if (ref.is_null()) {
- return ref;
- }
-
- ref->set_plugin(this);
- ref->set_spatial_node(p_spatial);
- ref->set_hidden(current_state == HIDDEN);
-
- current_gizmos.push_back(ref.ptr());
- return ref;
-}
-
-void EditorNode3DGizmoPlugin::_bind_methods() {
-#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo")
-
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
- BIND_VMETHOD(MethodInfo(GIZMO_REF, "_create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D")));
-
- ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorNode3DGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorNode3DGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1)));
- ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorNode3DGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("add_material", "name", "material"), &EditorNode3DGizmoPlugin::add_material);
-
- ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>()));
-
- BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_gizmo_name"));
- BIND_VMETHOD(MethodInfo(Variant::INT, "_get_priority"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_can_be_hidden"));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_selectable_when_hidden"));
-
- BIND_VMETHOD(MethodInfo("_redraw", GIZMO_REF));
- BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", GIZMO_REF, PropertyInfo(Variant::INT, "index")));
-
- MethodInfo hvget(Variant::NIL, "_get_handle_value", GIZMO_REF, PropertyInfo(Variant::INT, "index"));
- hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- BIND_VMETHOD(hvget);
-
- BIND_VMETHOD(MethodInfo("_set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point")));
- MethodInfo cm = MethodInfo("_commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel"));
- cm.default_arguments.push_back(false);
- BIND_VMETHOD(cm);
-
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", GIZMO_REF, PropertyInfo(Variant::INT, "index")));
-
-#undef GIZMO_REF
-}
-
-bool EditorNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
- if (get_script_instance() && get_script_instance()->has_method("_has_gizmo")) {
- return get_script_instance()->call("_has_gizmo", p_spatial);
- }
- return false;
-}
-
-Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) {
- if (get_script_instance() && get_script_instance()->has_method("_create_gizmo")) {
- return get_script_instance()->call("_create_gizmo", p_spatial);
- }
-
- Ref<EditorNode3DGizmo> ref;
- if (has_gizmo(p_spatial)) {
- ref.instantiate();
- }
- return ref;
-}
-
-bool EditorNode3DGizmoPlugin::can_be_hidden() const {
- if (get_script_instance() && get_script_instance()->has_method("_can_be_hidden")) {
- return get_script_instance()->call("_can_be_hidden");
- }
- return true;
-}
-
-bool EditorNode3DGizmoPlugin::is_selectable_when_hidden() const {
- if (get_script_instance() && get_script_instance()->has_method("_is_selectable_when_hidden")) {
- return get_script_instance()->call("_is_selectable_when_hidden");
- }
- return false;
-}
-
-void EditorNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
- if (get_script_instance() && get_script_instance()->has_method("_redraw")) {
- Ref<EditorNode3DGizmo> ref(p_gizmo);
- get_script_instance()->call("_redraw", ref);
- }
-}
-
-String EditorNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("_get_handle_name")) {
- return get_script_instance()->call("_get_handle_name", p_gizmo, p_idx);
- }
- return "";
-}
-
-Variant EditorNode3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("_get_handle_value")) {
- return get_script_instance()->call("_get_handle_value", p_gizmo, p_idx);
- }
- return Variant();
-}
-
-void EditorNode3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
- if (get_script_instance() && get_script_instance()->has_method("_set_handle")) {
- get_script_instance()->call("_set_handle", p_gizmo, p_idx, p_camera, p_point);
- }
-}
-
-void EditorNode3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
- if (get_script_instance() && get_script_instance()->has_method("_commit_handle")) {
- get_script_instance()->call("_commit_handle", p_gizmo, p_idx, p_restore, p_cancel);
- }
-}
-
-bool EditorNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
- if (get_script_instance() && get_script_instance()->has_method("_is_handle_highlighted")) {
- return get_script_instance()->call("_is_handle_highlighted", p_gizmo, p_idx);
- }
- return false;
-}
-
-void EditorNode3DGizmoPlugin::set_state(int p_state) {
- current_state = p_state;
- for (int i = 0; i < current_gizmos.size(); ++i) {
- current_gizmos[i]->set_hidden(current_state == HIDDEN);
- }
-}
-
-int EditorNode3DGizmoPlugin::get_state() const {
- return current_state;
-}
-
-void EditorNode3DGizmoPlugin::unregister_gizmo(EditorNode3DGizmo *p_gizmo) {
- current_gizmos.erase(p_gizmo);
-}
-
-EditorNode3DGizmoPlugin::EditorNode3DGizmoPlugin() {
- current_state = VISIBLE;
-}
-
-EditorNode3DGizmoPlugin::~EditorNode3DGizmoPlugin() {
- for (int i = 0; i < current_gizmos.size(); ++i) {
- current_gizmos[i]->set_plugin(nullptr);
- current_gizmos[i]->get_spatial_node()->set_gizmo(nullptr);
- }
- if (Node3DEditor::get_singleton()) {
- Node3DEditor::get_singleton()->update_all_gizmos();
- }
-}
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index cc65cb53ca..0c7a0d14a2 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -34,6 +34,7 @@
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
#include "editor/editor_scale.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/visual_instance_3d.h"
#include "scene/3d/world_environment.h"
@@ -43,96 +44,10 @@
class Camera3D;
class Node3DEditor;
-class EditorNode3DGizmoPlugin;
class Node3DEditorViewport;
class SubViewportContainer;
-
-class EditorNode3DGizmo : public Node3DGizmo {
- GDCLASS(EditorNode3DGizmo, Node3DGizmo);
-
- bool selected;
- bool instantiated;
-
-public:
- void set_selected(bool p_selected) { selected = p_selected; }
- bool is_selected() const { return selected; }
-
- struct Instance {
- RID instance;
- Ref<ArrayMesh> mesh;
- Ref<Material> material;
- Ref<SkinReference> skin_reference;
- RID skeleton;
- bool billboard = false;
- bool unscaled = false;
- bool can_intersect = false;
- bool extra_margin = false;
-
- void create_instance(Node3D *p_base, bool p_hidden = false);
- };
-
- Vector<Vector3> collision_segments;
- Ref<TriangleMesh> collision_mesh;
-
- struct Handle {
- Vector3 pos;
- bool billboard = false;
- };
-
- Vector<Vector3> handles;
- Vector<Vector3> secondary_handles;
- float selectable_icon_size;
- bool billboard_handle;
-
- bool valid;
- bool hidden;
- Node3D *base;
- Vector<Instance> instances;
- Node3D *spatial_node;
- EditorNode3DGizmoPlugin *gizmo_plugin;
-
- void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Node3D>(p_node)); }
-
-protected:
- static void _bind_methods();
-
-public:
- void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
- void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1));
- void add_mesh(const Ref<ArrayMesh> &p_mesh, bool p_billboard = false, const Ref<SkinReference> &p_skin_reference = Ref<SkinReference>(), const Ref<Material> &p_material = Ref<Material>());
- void add_collision_segments(const Vector<Vector3> &p_lines);
- void add_collision_triangles(const Ref<TriangleMesh> &p_tmesh);
- void add_unscaled_billboard(const Ref<Material> &p_material, float p_scale = 1, const Color &p_modulate = Color(1, 1, 1));
- void add_handles(const Vector<Vector3> &p_handles, const Ref<Material> &p_material, bool p_billboard = false, bool p_secondary = false);
- void add_solid_box(Ref<Material> &p_material, Vector3 p_size, Vector3 p_position = Vector3());
-
- virtual bool is_handle_highlighted(int p_idx) const;
- virtual String get_handle_name(int p_idx) const;
- virtual Variant get_handle_value(int p_idx);
- virtual void set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point);
- virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false);
-
- void set_spatial_node(Node3D *p_node);
- Node3D *get_spatial_node() const { return spatial_node; }
- Ref<EditorNode3DGizmoPlugin> get_plugin() const { return gizmo_plugin; }
- Vector3 get_handle_pos(int p_idx) const;
- bool intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum);
- bool intersect_ray(Camera3D *p_camera, const Point2 &p_point, Vector3 &r_pos, Vector3 &r_normal, int *r_gizmo_handle = nullptr, bool p_sec_first = false);
-
- virtual void clear() override;
- virtual void create() override;
- virtual void transform() override;
- virtual void redraw() override;
- virtual void free() override;
-
- virtual bool is_editable() const;
-
- void set_hidden(bool p_hidden);
- void set_plugin(EditorNode3DGizmoPlugin *p_plugin);
-
- EditorNode3DGizmo();
- ~EditorNode3DGizmo();
-};
+class DirectionalLight3D;
+class WorldEnvironment;
class ViewportRotationControl : public Control {
GDCLASS(ViewportRotationControl, Control);
@@ -307,17 +222,15 @@ private:
struct _RayResult {
Node3D *item = nullptr;
float depth = 0;
- int handle = 0;
_FORCE_INLINE_ bool operator<(const _RayResult &p_rr) const { return depth < p_rr.depth; }
};
void _update_name();
void _compute_edit(const Point2 &p_point);
void _clear_selected();
- void _select_clicked(bool p_append, bool p_single, bool p_allow_locked = false);
- void _select(Node *p_node, bool p_append, bool p_single);
- ObjectID _select_ray(const Point2 &p_pos, bool p_append, bool &r_includes_current, int *r_gizmo_handle = nullptr, bool p_alt_select = false);
- void _find_items_at_pos(const Point2 &p_pos, bool &r_includes_current, Vector<_RayResult> &results, bool p_alt_select = false, bool p_include_locked_nodes = false);
+ void _select_clicked(bool p_allow_locked);
+ ObjectID _select_ray(const Point2 &p_pos);
+ void _find_items_at_pos(const Point2 &p_pos, Vector<_RayResult> &r_results, bool p_include_locked);
Vector3 _get_ray_pos(const Vector2 &p_pos) const;
Vector3 _get_ray(const Vector2 &p_pos) const;
Point2 _point_to_screen(const Vector3 &p_point);
@@ -329,7 +242,8 @@ private:
Vector3 _get_screen_to_space(const Vector3 &p_vector3);
void _select_region();
- bool _gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false);
+ bool _transform_gizmo_select(const Vector2 &p_screenpos, bool p_highlight_only = false);
+ void _transform_gizmo_apply(Node3D *p_node, const Transform3D &p_transform, bool p_local);
void _nav_pan(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
void _nav_zoom(Ref<InputEventWithModifiers> p_event, const Vector2 &p_relative);
@@ -342,7 +256,6 @@ private:
ObjectID clicked;
Vector<_RayResult> selection_results;
- bool clicked_includes_current;
bool clicked_wants_append;
PopupMenu *selection_menu;
@@ -383,15 +296,12 @@ private:
Vector3 click_ray;
Vector3 click_ray_pos;
Vector3 center;
- Vector3 orig_gizmo_pos;
- int edited_gizmo = 0;
Point2 mouse_pos;
Point2 original_mouse_pos;
bool snap = false;
Ref<EditorNode3DGizmo> gizmo;
int gizmo_handle = 0;
Variant gizmo_initial_value;
- Vector3 gizmo_initial_pos;
} _edit;
struct Cursor {
@@ -472,6 +382,8 @@ private:
void _project_settings_changed();
+ Transform3D _compute_transform(TransformMode p_mode, const Transform3D &p_original, const Transform3D &p_original_local, Vector3 p_motion, double p_extra, bool p_local);
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -512,6 +424,8 @@ public:
Node3D *sp;
RID sbox_instance;
RID sbox_instance_xray;
+ Ref<EditorNode3DGizmo> gizmo;
+ Map<int, Transform3D> subgizmos; // map ID -> initial transform
Node3DEditorSelectedItem() {
sp = nullptr;
@@ -617,7 +531,9 @@ private:
Ref<StandardMaterial3D> plane_gizmo_color_hl[3];
Ref<ShaderMaterial> rotate_gizmo_color_hl[3];
- int over_gizmo_handle;
+ Ref<Node3DGizmo> current_hover_gizmo;
+ int current_hover_gizmo_handle;
+
float snap_translate_value;
float snap_rotate_value;
float snap_scale_value;
@@ -688,7 +604,6 @@ private:
LineEdit *snap_translate;
LineEdit *snap_rotate;
LineEdit *snap_scale;
- PanelContainer *menu_panel;
LineEdit *xform_translate[3];
LineEdit *xform_rotate[3];
@@ -734,6 +649,7 @@ private:
Node3D *selected;
void _request_gizmo(Object *p_obj);
+ void _clear_subgizmo_selection(Object *p_obj = nullptr);
static Node3DEditor *singleton;
@@ -746,8 +662,7 @@ private:
Node3DEditor();
- bool is_any_freelook_active() const;
-
+ void _selection_changed();
void _refresh_menu_icons();
// Preview Sun and Environment
@@ -808,6 +723,8 @@ private:
void _add_sun_to_scene(bool p_already_added_environment = false);
void _add_environment_to_scene(bool p_already_added_sun = false);
+ void _update_theme();
+
protected:
void _notification(int p_what);
//void _gui_input(InputEvent p_event);
@@ -861,10 +778,16 @@ public:
VSplitContainer *get_shader_split();
HSplitContainer *get_palette_split();
- Node3D *get_selected() { return selected; }
+ Node3D *get_single_selected_node() { return selected; }
+ bool is_current_selected_gizmo(const EditorNode3DGizmo *p_gizmo);
+ bool is_subgizmo_selected(int p_id);
+ Vector<int> get_subgizmo_selection();
+
+ Ref<EditorNode3DGizmo> get_current_hover_gizmo() const { return current_hover_gizmo; }
+ void set_current_hover_gizmo(Ref<EditorNode3DGizmo> p_gizmo) { current_hover_gizmo = p_gizmo; }
- int get_over_gizmo_handle() const { return over_gizmo_handle; }
- void set_over_gizmo_handle(int idx) { over_gizmo_handle = idx; }
+ void set_current_hover_gizmo_handle(int p_id) { current_hover_gizmo_handle = p_id; }
+ int get_current_hover_gizmo_handle() const { return current_hover_gizmo_handle; }
void set_can_preview(Camera3D *p_preview);
@@ -907,50 +830,4 @@ public:
~Node3DEditorPlugin();
};
-class EditorNode3DGizmoPlugin : public Resource {
- GDCLASS(EditorNode3DGizmoPlugin, Resource);
-
-public:
- static const int VISIBLE = 0;
- static const int HIDDEN = 1;
- static const int ON_TOP = 2;
-
-protected:
- int current_state;
- List<EditorNode3DGizmo *> current_gizmos;
- HashMap<String, Vector<Ref<StandardMaterial3D>>> materials;
-
- static void _bind_methods();
- virtual bool has_gizmo(Node3D *p_spatial);
- virtual Ref<EditorNode3DGizmo> create_gizmo(Node3D *p_spatial);
-
-public:
- void create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false);
- void create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top = false, const Color &p_albedo = Color(1, 1, 1, 1));
- void create_handle_material(const String &p_name, bool p_billboard = false, const Ref<Texture2D> &p_texture = nullptr);
- void add_material(const String &p_name, Ref<StandardMaterial3D> p_material);
-
- Ref<StandardMaterial3D> get_material(const String &p_name, const Ref<EditorNode3DGizmo> &p_gizmo = Ref<EditorNode3DGizmo>());
-
- virtual String get_gizmo_name() const;
- virtual int get_priority() const;
- virtual bool can_be_hidden() const;
- virtual bool is_selectable_when_hidden() const;
-
- virtual void redraw(EditorNode3DGizmo *p_gizmo);
- virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const;
- virtual Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const;
- virtual void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point);
- virtual void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel = false);
- virtual bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_idx) const;
-
- Ref<EditorNode3DGizmo> get_gizmo(Node3D *p_spatial);
- void set_state(int p_state);
- int get_state() const;
- void unregister_gizmo(EditorNode3DGizmo *p_gizmo);
-
- EditorNode3DGizmoPlugin();
- virtual ~EditorNode3DGizmoPlugin();
-};
-
#endif // NODE_3D_EDITOR_PLUGIN_H
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 8861fee7a6..8866e8c53e 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -481,7 +481,7 @@ void Path2DEditor::_mode_selected(int p_mode) {
Vector2 begin = node->get_curve()->get_point_position(0);
Vector2 end = node->get_curve()->get_point_position(node->get_curve()->get_point_count() - 1);
- if (begin.distance_to(end) < CMP_EPSILON) {
+ if (begin.is_equal_approx(end)) {
return;
}
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 0a95986fe2..63b89aea35 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -36,20 +36,20 @@
#include "node_3d_editor_plugin.h"
#include "scene/resources/curve.h"
-String Path3DGizmo::get_handle_name(int p_idx) const {
+String Path3DGizmo::get_handle_name(int p_id) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return "";
}
- if (p_idx < c->get_point_count()) {
- return TTR("Curve Point #") + itos(p_idx);
+ if (p_id < c->get_point_count()) {
+ return TTR("Curve Point #") + itos(p_id);
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
String n = TTR("Curve Point #") + itos(idx);
if (t == 0) {
n += " In";
@@ -60,21 +60,21 @@ String Path3DGizmo::get_handle_name(int p_idx) const {
return n;
}
-Variant Path3DGizmo::get_handle_value(int p_idx) {
+Variant Path3DGizmo::get_handle_value(int p_id) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return Variant();
}
- if (p_idx < c->get_point_count()) {
- original = c->get_point_position(p_idx);
+ if (p_id < c->get_point_count()) {
+ original = c->get_point_position(p_id);
return original;
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
Vector3 ofs;
if (t == 0) {
@@ -88,7 +88,7 @@ Variant Path3DGizmo::get_handle_value(int p_idx) {
return ofs;
}
-void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void Path3DGizmo::set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return;
@@ -100,7 +100,7 @@ void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_poin
Vector3 ray_dir = p_camera->project_ray_normal(p_point);
// Setting curve point positions
- if (p_idx < c->get_point_count()) {
+ if (p_id < c->get_point_count()) {
Plane p(gt.xform(original), p_camera->get_transform().basis.get_axis(2));
Vector3 inters;
@@ -112,16 +112,16 @@ void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_poin
}
Vector3 local = gi.xform(inters);
- c->set_point_position(p_idx, local);
+ c->set_point_position(p_id, local);
}
return;
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
Vector3 base = c->get_point_position(idx);
@@ -157,7 +157,7 @@ void Path3DGizmo::set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_poin
}
}
-void Path3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) {
+void Path3DGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) const {
Ref<Curve3D> c = path->get_curve();
if (c.is_null()) {
return;
@@ -165,27 +165,27 @@ void Path3DGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_canc
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx < c->get_point_count()) {
+ if (p_id < c->get_point_count()) {
if (p_cancel) {
- c->set_point_position(p_idx, p_restore);
+ c->set_point_position(p_id, p_restore);
return;
}
ur->create_action(TTR("Set Curve Point Position"));
- ur->add_do_method(c.ptr(), "set_point_position", p_idx, c->get_point_position(p_idx));
- ur->add_undo_method(c.ptr(), "set_point_position", p_idx, p_restore);
+ ur->add_do_method(c.ptr(), "set_point_position", p_id, c->get_point_position(p_id));
+ ur->add_undo_method(c.ptr(), "set_point_position", p_id, p_restore);
ur->commit_action();
return;
}
- p_idx = p_idx - c->get_point_count() + 1;
+ p_id = p_id - c->get_point_count() + 1;
- int idx = p_idx / 2;
- int t = p_idx % 2;
+ int idx = p_id / 2;
+ int t = p_id % 2;
if (t == 0) {
if (p_cancel) {
- c->set_point_in(p_idx, p_restore);
+ c->set_point_in(p_id, p_restore);
return;
}
@@ -282,7 +282,7 @@ void Path3DGizmo::redraw() {
add_handles(handles, handles_material);
}
if (sec_handles.size()) {
- add_handles(sec_handles, sec_handles_material, false, true);
+ add_handles(sec_handles, sec_handles_material, Vector<int>(), false, true);
}
}
}
diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h
index 13870d7591..5902500526 100644
--- a/editor/plugins/path_3d_editor_plugin.h
+++ b/editor/plugins/path_3d_editor_plugin.h
@@ -31,7 +31,9 @@
#ifndef PATH_EDITOR_PLUGIN_H
#define PATH_EDITOR_PLUGIN_H
-#include "editor/node_3d_editor_gizmos.h"
+#include "editor/editor_plugin.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
+#include "scene/3d/camera_3d.h"
#include "scene/3d/path_3d.h"
class Path3DGizmo : public EditorNode3DGizmo {
@@ -44,9 +46,9 @@ class Path3DGizmo : public EditorNode3DGizmo {
public:
virtual String get_handle_name(int p_idx) const override;
- virtual Variant get_handle_value(int p_idx) override;
- virtual void set_handle(int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- virtual void commit_handle(int p_idx, const Variant &p_restore, bool p_cancel = false) override;
+ virtual Variant get_handle_value(int p_id) const override;
+ virtual void set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ virtual void commit_handle(int p_id, const Variant &p_restore, bool p_cancel = false) const override;
virtual void redraw() override;
Path3DGizmo(Path3D *p_path = nullptr);
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index e099c8b5fd..cbea2405b8 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -181,21 +181,21 @@ void ResourcePreloaderEditor::_update_library() {
preloader->get_resource_list(&rnames);
List<String> names;
- for (List<StringName>::Element *E = rnames.front(); E; E = E->next()) {
- names.push_back(E->get());
+ for (const StringName &E : rnames) {
+ names.push_back(E);
}
names.sort();
- for (List<String>::Element *E = names.front(); E; E = E->next()) {
+ for (const String &E : names) {
TreeItem *ti = tree->create_item(root);
ti->set_cell_mode(0, TreeItem::CELL_MODE_STRING);
ti->set_editable(0, true);
ti->set_selectable(0, true);
- ti->set_text(0, E->get());
- ti->set_metadata(0, E->get());
+ ti->set_text(0, E);
+ ti->set_metadata(0, E);
- RES r = preloader->get_resource(E->get());
+ RES r = preloader->get_resource(E);
ERR_CONTINUE(r.is_null());
diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp
index cea76f5233..ed91f174d1 100644
--- a/editor/plugins/root_motion_editor_plugin.cpp
+++ b/editor/plugins/root_motion_editor_plugin.cpp
@@ -70,8 +70,8 @@ void EditorPropertyRootMotion::_node_assign() {
List<StringName> animations;
player->get_animation_list(&animations);
- for (List<StringName>::Element *E = animations.front(); E; E = E->next()) {
- Ref<Animation> anim = player->get_animation(E->get());
+ for (const StringName &E : animations) {
+ Ref<Animation> anim = player->get_animation(E);
for (int i = 0; i < anim->get_track_count(); i++) {
paths.insert(anim->track_get_path(i));
}
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 1851ffdc34..668a15da37 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -103,8 +103,8 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
const Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
List<StringName> types;
ClassDB::get_class_list(&types);
- for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
- String n = E->get();
+ for (const StringName &E : types) {
+ String n = E;
if (n.begins_with("_")) {
n = n.substr(1, n.length());
}
@@ -115,8 +115,8 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
- for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
- highlighter->add_keyword_color(E->get(), usertype_color);
+ for (const StringName &E : global_classes) {
+ highlighter->add_keyword_color(E, usertype_color);
}
/* Autoloads. */
@@ -134,8 +134,8 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
List<String> core_types;
script->get_language()->get_core_type_words(&core_types);
- for (List<String>::Element *E = core_types.front(); E; E = E->next()) {
- highlighter->add_keyword_color(E->get(), basetype_color);
+ for (const String &E : core_types) {
+ highlighter->add_keyword_color(E, basetype_color);
}
/* Reserved words. */
@@ -143,11 +143,11 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
List<String> keywords;
script->get_language()->get_reserved_words(&keywords);
- for (List<String>::Element *E = keywords.front(); E; E = E->next()) {
- if (script->get_language()->is_control_flow_keyword(E->get())) {
- highlighter->add_keyword_color(E->get(), control_flow_keyword_color);
+ for (const String &E : keywords) {
+ if (script->get_language()->is_control_flow_keyword(E)) {
+ highlighter->add_keyword_color(E, control_flow_keyword_color);
} else {
- highlighter->add_keyword_color(E->get(), keyword_color);
+ highlighter->add_keyword_color(E, keyword_color);
}
}
@@ -157,9 +157,9 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
if (instance_base != StringName()) {
List<PropertyInfo> plist;
ClassDB::get_property_list(instance_base, &plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- String name = E->get().name;
- if (E->get().usage & PROPERTY_USAGE_CATEGORY || E->get().usage & PROPERTY_USAGE_GROUP || E->get().usage & PROPERTY_USAGE_SUBGROUP) {
+ for (const PropertyInfo &E : plist) {
+ String name = E.name;
+ if (E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP) {
continue;
}
if (name.find("/") != -1) {
@@ -170,8 +170,8 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
List<String> clist;
ClassDB::get_integer_constant_list(instance_base, &clist);
- for (List<String>::Element *E = clist.front(); E; E = E->next()) {
- highlighter->add_member_keyword_color(E->get(), member_variable_color);
+ for (const String &E : clist) {
+ highlighter->add_member_keyword_color(E, member_variable_color);
}
}
@@ -179,8 +179,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
List<String> comments;
script->get_language()->get_comment_delimiters(&comments);
- for (List<String>::Element *E = comments.front(); E; E = E->next()) {
- String comment = E->get();
+ for (const String &comment : comments) {
String beg = comment.get_slice(" ", 0);
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
highlighter->add_color_region(beg, end, comment_color, end == "");
@@ -190,8 +189,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
const Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
List<String> strings;
script->get_language()->get_string_delimiters(&strings);
- for (List<String>::Element *E = strings.front(); E; E = E->next()) {
- String string = E->get();
+ for (const String &string : strings) {
String beg = string.get_slice(" ", 0);
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
highlighter->add_color_region(beg, end, string_color, end == "");
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 1a6dfa273e..65459d159d 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -50,9 +50,7 @@ void ConnectionInfoDialog::popup_connections(String p_method, Vector<Node *> p_n
List<Connection> all_connections;
p_nodes[i]->get_signals_connected_to_this(&all_connections);
- for (List<Connection>::Element *E = all_connections.front(); E; E = E->next()) {
- Connection connection = E->get();
-
+ for (const Connection &connection : all_connections) {
if (connection.callable.get_method() != p_method) {
continue;
}
@@ -116,8 +114,8 @@ Vector<String> ScriptTextEditor::get_functions() {
if (script->get_language()->validate(text, script->get_path(), &fnc)) {
//if valid rewrite functions to latest
functions.clear();
- for (List<String>::Element *E = fnc.front(); E; E = E->next()) {
- functions.push_back(E->get());
+ for (const String &E : fnc) {
+ functions.push_back(E);
}
}
@@ -203,8 +201,7 @@ void ScriptTextEditor::_set_theme_for_script() {
List<String> strings;
script->get_language()->get_string_delimiters(&strings);
text_edit->clear_string_delimiters();
- for (List<String>::Element *E = strings.front(); E; E = E->next()) {
- String string = E->get();
+ for (const String &string : strings) {
String beg = string.get_slice(" ", 0);
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
text_edit->add_string_delimiter(beg, end, end == "");
@@ -213,8 +210,7 @@ void ScriptTextEditor::_set_theme_for_script() {
List<String> comments;
script->get_language()->get_comment_delimiters(&comments);
text_edit->clear_comment_delimiters();
- for (List<String>::Element *E = comments.front(); E; E = E->next()) {
- String comment = E->get();
+ for (const String &comment : comments) {
String beg = comment.get_slice(" ", 0);
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
text_edit->add_comment_delimiter(beg, end, end == "");
@@ -417,8 +413,8 @@ void ScriptTextEditor::_validate_script() {
}
functions.clear();
- for (List<String>::Element *E = fnc.front(); E; E = E->next()) {
- functions.push_back(E->get());
+ for (const String &E : fnc) {
+ functions.push_back(E);
}
script_is_valid = true;
}
@@ -432,9 +428,7 @@ void ScriptTextEditor::_validate_script() {
Node *base = get_tree()->get_edited_scene_root();
if (base && missing_connections.size() > 0) {
warnings_panel->push_table(1);
- for (List<Connection>::Element *E = missing_connections.front(); E; E = E->next()) {
- Connection connection = E->get();
-
+ for (const Connection &connection : missing_connections) {
String base_path = base->get_name();
String source_path = base == connection.signal.get_object() ? base_path : base_path + "/" + base->get_path_to(Object::cast_to<Node>(connection.signal.get_object()));
String target_path = base == connection.callable.get_object() ? base_path : base_path + "/" + base->get_path_to(Object::cast_to<Node>(connection.callable.get_object()));
@@ -456,9 +450,7 @@ void ScriptTextEditor::_validate_script() {
// Add script warnings.
warnings_panel->push_table(3);
- for (List<ScriptLanguage::Warning>::Element *E = warnings.front(); E; E = E->next()) {
- ScriptLanguage::Warning w = E->get();
-
+ for (const ScriptLanguage::Warning &w : warnings) {
Dictionary ignore_meta;
ignore_meta["line"] = w.start_line;
ignore_meta["code"] = w.string_code.to_lower();
@@ -488,9 +480,7 @@ void ScriptTextEditor::_validate_script() {
errors_panel->clear();
errors_panel->push_table(2);
- for (List<ScriptLanguage::ScriptError>::Element *E = errors.front(); E; E = E->next()) {
- ScriptLanguage::ScriptError err = E->get();
-
+ for (const ScriptLanguage::ScriptError &err : errors) {
errors_panel->push_cell();
errors_panel->push_meta(err.line - 1);
errors_panel->push_color(warnings_panel->get_theme_color(SNAME("error_color"), SNAME("Editor")));
@@ -511,8 +501,8 @@ void ScriptTextEditor::_validate_script() {
if (errors.is_empty()) {
te->set_line_background_color(i, Color(0, 0, 0, 0));
} else {
- for (List<ScriptLanguage::ScriptError>::Element *E = errors.front(); E; E = E->next()) {
- bool error_line = i == E->get().line - 1;
+ for (const ScriptLanguage::ScriptError &E : errors) {
+ bool error_line = i == E.line - 1;
te->set_line_background_color(i, error_line ? marked_line_color : Color(0, 0, 0, 0));
if (error_line) {
break;
@@ -910,8 +900,7 @@ void ScriptTextEditor::_update_connected_methods() {
List<Connection> connections;
nodes[i]->get_signals_connected_to_this(&connections);
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- Connection connection = E->get();
+ for (const Connection &connection : connections) {
if (!(connection.flags & CONNECT_PERSIST)) {
continue;
}
@@ -1286,8 +1275,7 @@ void ScriptTextEditor::_edit_option_toggle_inline_comment() {
List<String> comment_delimiters;
script->get_language()->get_comment_delimiters(&comment_delimiters);
- for (List<String>::Element *E = comment_delimiters.front(); E; E = E->next()) {
- String script_delimiter = E->get();
+ for (const String &script_delimiter : comment_delimiters) {
if (script_delimiter.find(" ") == -1) {
delimiter = script_delimiter;
break;
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 0d65dec87b..2c45b96106 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -118,11 +118,11 @@ void ShaderTextEditor::_load_theme_settings() {
const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color");
const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
- for (List<String>::Element *E = keywords.front(); E; E = E->next()) {
- if (ShaderLanguage::is_control_flow_keyword(E->get())) {
- syntax_highlighter->add_keyword_color(E->get(), control_flow_keyword_color);
+ for (const String &E : keywords) {
+ if (ShaderLanguage::is_control_flow_keyword(E)) {
+ syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
} else {
- syntax_highlighter->add_keyword_color(E->get(), keyword_color);
+ syntax_highlighter->add_keyword_color(E, keyword_color);
}
}
@@ -144,8 +144,8 @@ void ShaderTextEditor::_load_theme_settings() {
const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color");
- for (List<String>::Element *E = built_ins.front(); E; E = E->next()) {
- syntax_highlighter->add_keyword_color(E->get(), member_variable_color);
+ for (const String &E : built_ins) {
+ syntax_highlighter->add_keyword_color(E, member_variable_color);
}
// Colorize comments.
@@ -770,7 +770,7 @@ ShaderEditor::ShaderEditor(EditorNode *p_node) {
disk_changed->add_child(vbc);
Label *dl = memnew(Label);
- dl->set_text(TTR("This shader has been modified on on disk.\nWhat action should be taken?"));
+ dl->set_text(TTR("This shader has been modified on disk.\nWhat action should be taken?"));
vbc->add_child(dl);
disk_changed->connect("confirmed", callable_mp(this, &ShaderEditor::_reload_shader_from_disk));
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index 66d2b36be1..1e62261244 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -55,7 +55,7 @@ void ShaderFileEditor::_version_selected(int p_option) {
RD::ShaderStage stage = RD::SHADER_STAGE_MAX;
int first_found = -1;
- Ref<RDShaderBytecode> bytecode = shader_file->get_bytecode(version_txt);
+ Ref<RDShaderSPIRV> bytecode = shader_file->get_spirv(version_txt);
ERR_FAIL_COND(bytecode.is_null());
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
@@ -142,7 +142,7 @@ void ShaderFileEditor::_update_options() {
Ref<Texture2D> icon;
- Ref<RDShaderBytecode> bytecode = shader_file->get_bytecode(version_list[i]);
+ Ref<RDShaderSPIRV> bytecode = shader_file->get_spirv(version_list[i]);
ERR_FAIL_COND(bytecode.is_null());
bool failed = false;
@@ -175,7 +175,7 @@ void ShaderFileEditor::_update_options() {
return;
}
- Ref<RDShaderBytecode> bytecode = shader_file->get_bytecode(current_version);
+ Ref<RDShaderSPIRV> bytecode = shader_file->get_spirv(current_version);
ERR_FAIL_COND(bytecode.is_null());
int first_valid = -1;
int current = -1;
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index cd06fdc757..42f7d23da2 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -65,13 +65,11 @@ void SpriteFramesEditor::_sheet_preview_draw() {
int x = i * width;
split_sheet_preview->draw_line(Point2(x, 0), Point2(x, size.height), Color(1, 1, 1, a));
split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, size.height), Color(0, 0, 0, a));
-
- for (int j = 1; j < v; j++) {
- int y = j * height;
-
- split_sheet_preview->draw_line(Point2(0, y), Point2(size.width, y), Color(1, 1, 1, a));
- split_sheet_preview->draw_line(Point2(0, y + 1), Point2(size.width, y + 1), Color(0, 0, 0, a));
- }
+ }
+ for (int i = 1; i < v; i++) {
+ int y = i * height;
+ split_sheet_preview->draw_line(Point2(0, y), Point2(size.width, y), Color(1, 1, 1, a));
+ split_sheet_preview->draw_line(Point2(0, y + 1), Point2(size.width, y + 1), Color(0, 0, 0, a));
}
if (frames_selected.size() == 0) {
@@ -367,8 +365,8 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
int count = 0;
- for (List<Ref<Texture2D>>::Element *E = resources.front(); E; E = E->next()) {
- undo_redo->add_do_method(frames, "add_frame", edited_anim, E->get(), p_at_pos == -1 ? -1 : p_at_pos + count);
+ for (const Ref<Texture2D> &E : resources) {
+ undo_redo->add_do_method(frames, "add_frame", edited_anim, E, p_at_pos == -1 ? -1 : p_at_pos + count);
undo_redo->add_undo_method(frames, "remove_frame", edited_anim, p_at_pos == -1 ? fc : p_at_pos);
count++;
}
@@ -626,10 +624,10 @@ void SpriteFramesEditor::_animation_name_edited() {
undo_redo->add_do_method(frames, "rename_animation", edited_anim, name);
undo_redo->add_undo_method(frames, "rename_animation", name, edited_anim);
- for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) {
- String current = E->get()->call("get_animation");
- undo_redo->add_do_method(E->get(), "set_animation", name);
- undo_redo->add_undo_method(E->get(), "set_animation", edited_anim);
+ for (Node *E : nodes) {
+ String current = E->call("get_animation");
+ undo_redo->add_do_method(E, "set_animation", name);
+ undo_redo->add_undo_method(E, "set_animation", edited_anim);
}
undo_redo->add_do_method(this, "_update_library");
@@ -657,10 +655,10 @@ void SpriteFramesEditor::_animation_add() {
undo_redo->add_do_method(this, "_update_library");
undo_redo->add_undo_method(this, "_update_library");
- for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) {
- String current = E->get()->call("get_animation");
- undo_redo->add_do_method(E->get(), "set_animation", name);
- undo_redo->add_undo_method(E->get(), "set_animation", current);
+ for (Node *E : nodes) {
+ String current = E->call("get_animation");
+ undo_redo->add_do_method(E, "set_animation", name);
+ undo_redo->add_undo_method(E, "set_animation", current);
}
edited_anim = name;
@@ -790,8 +788,8 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
anim_names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = anim_names.front(); E; E = E->next()) {
- String name = E->get();
+ for (const StringName &E : anim_names) {
+ String name = E;
TreeItem *it = animations->create_item(anim_root);
@@ -800,7 +798,7 @@ void SpriteFramesEditor::_update_library(bool p_skip_selector) {
it->set_text(0, name);
it->set_editable(0, true);
- if (E->get() == edited_anim) {
+ if (E == edited_anim) {
it->select(0);
}
}
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 4029d6785c..44db06bcfd 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -36,9 +36,30 @@ TextureRect *TexturePreview::get_texture_display() {
return texture_display;
}
+void TexturePreview::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ if (!is_inside_tree()) {
+ // TODO: This is a workaround because `NOTIFICATION_THEME_CHANGED`
+ // is getting called for some reason when the `TexturePreview` is
+ // getting destroyed, which causes `get_theme_font()` to return `nullptr`.
+ // See https://github.com/godotengine/godot/issues/50743.
+ break;
+ }
+
+ if (metadata_label) {
+ Ref<Font> metadata_label_font = get_theme_font(SNAME("expression"), SNAME("EditorFonts"));
+ metadata_label->add_theme_font_override("font", metadata_label_font);
+ }
+
+ checkerboard->set_texture(get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")));
+ } break;
+ }
+}
+
TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
- TextureRect *checkerboard = memnew(TextureRect);
- checkerboard->set_texture(get_theme_icon("Checkerboard", "EditorIcons"));
+ checkerboard = memnew(TextureRect);
checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
checkerboard->set_texture_repeat(CanvasItem::TEXTURE_REPEAT_ENABLED);
checkerboard->set_custom_minimum_size(Size2(0.0, 256.0) * EDSCALE);
@@ -52,7 +73,7 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
add_child(texture_display);
if (p_show_metadata) {
- Label *metadata_label = memnew(Label);
+ metadata_label = memnew(Label);
String format;
if (Object::cast_to<ImageTexture>(*p_texture)) {
@@ -65,16 +86,14 @@ TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
metadata_label->set_text(itos(p_texture->get_width()) + "x" + itos(p_texture->get_height()) + " " + format);
- metadata_label->add_theme_font_size_override("font_size", 16 * EDSCALE);
- metadata_label->add_theme_color_override("font_outline_color", Color::named("black"));
- metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE);
- Ref<Font> metadata_label_font = get_theme_font("expression", "EditorFonts");
- metadata_label->add_theme_font_override("font", metadata_label_font);
-
// It's okay that these colors are static since the grid color is static too.
metadata_label->add_theme_color_override("font_color", Color::named("white"));
metadata_label->add_theme_color_override("font_color_shadow", Color::named("black"));
+ metadata_label->add_theme_font_size_override("font_size", 16 * EDSCALE);
+ metadata_label->add_theme_color_override("font_outline_color", Color::named("black"));
+ metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE);
+
metadata_label->add_theme_constant_override("shadow_as_outline", 1);
metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END);
metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END);
diff --git a/editor/plugins/texture_editor_plugin.h b/editor/plugins/texture_editor_plugin.h
index 165090be93..36a5513ea6 100644
--- a/editor/plugins/texture_editor_plugin.h
+++ b/editor/plugins/texture_editor_plugin.h
@@ -39,7 +39,13 @@ class TexturePreview : public MarginContainer {
GDCLASS(TexturePreview, MarginContainer);
private:
- TextureRect *texture_display;
+ TextureRect *texture_display = nullptr;
+
+ TextureRect *checkerboard = nullptr;
+ Label *metadata_label = nullptr;
+
+protected:
+ void _notification(int p_what);
public:
TextureRect *get_texture_display();
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index e323f1571d..b277f2ab42 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -144,8 +144,7 @@ void TextureRegionEditor::_region_draw() {
}
}
} else if (snap_mode == SNAP_AUTOSLICE) {
- for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
- Rect2 r = E->get();
+ for (const Rect2 &r : autoslice_cache) {
Vector2 endpoints[4] = {
mtx.basis_xform(r.position),
mtx.basis_xform(r.position + Vector2(r.size.x, 0)),
@@ -328,9 +327,9 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
}
if (edited_margin < 0 && snap_mode == SNAP_AUTOSLICE) {
Vector2 point = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y));
- for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
- if (E->get().has_point(point)) {
- rect = E->get();
+ for (const Rect2 &E : autoslice_cache) {
+ if (E.has_point(point)) {
+ rect = E;
if (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !(Input::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) {
Rect2 r;
if (node_sprite) {
@@ -749,12 +748,12 @@ void TextureRegionEditor::_update_autoslice() {
for (int x = 0; x < texture->get_width(); x++) {
if (texture->is_pixel_opaque(x, y)) {
bool found = false;
- for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
- Rect2 grown = E->get().grow(1.5);
+ for (Rect2 &E : autoslice_cache) {
+ Rect2 grown = E.grow(1.5);
if (grown.has_point(Point2(x, y))) {
- E->get().expand_to(Point2(x, y));
- E->get().expand_to(Point2(x + 1, y + 1));
- x = E->get().position.x + E->get().size.x - 1;
+ E.expand_to(Point2(x, y));
+ E.expand_to(Point2(x + 1, y + 1));
+ x = E.position.x + E.size.x - 1;
bool merged = true;
while (merged) {
merged = false;
@@ -764,12 +763,12 @@ void TextureRegionEditor::_update_autoslice() {
autoslice_cache.erase(F->prev());
queue_erase = false;
}
- if (F == E) {
+ if (F->get() == E) {
continue;
}
- if (E->get().grow(1).intersects(F->get())) {
- E->get().expand_to(F->get().position);
- E->get().expand_to(F->get().position + F->get().size);
+ if (E.grow(1).intersects(F->get())) {
+ E.expand_to(F->get().position);
+ E.expand_to(F->get().position + F->get().size);
if (F->prev()) {
F = F->prev();
autoslice_cache.erase(F->next());
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 9338ea6ddd..6bcc65e30c 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -65,8 +65,8 @@ void ThemeItemImportTree::_update_items_tree() {
tree_icon_items.clear();
tree_stylebox_items.clear();
- for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
- String type_name = (String)E->get();
+ for (const StringName &E : types) {
+ String type_name = (String)E;
TreeItem *type_node = import_items_tree->create_item(root);
type_node->set_meta("_can_be_imported", false);
@@ -89,12 +89,12 @@ void ThemeItemImportTree::_update_items_tree() {
names.clear();
filtered_names.clear();
- base_theme->get_theme_item_list(dt, E->get(), &names);
+ base_theme->get_theme_item_list(dt, E, &names);
bool data_type_has_filtered_items = false;
- for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
- String item_name = (String)F->get();
+ for (const StringName &F : names) {
+ String item_name = (String)F;
bool is_item_matching_filter = (item_name.findn(filter_text) > -1);
if (!filter_text.is_empty() && !is_matching_filter && !is_item_matching_filter) {
continue;
@@ -105,7 +105,7 @@ void ThemeItemImportTree::_update_items_tree() {
has_filtered_items = true;
data_type_has_filtered_items = true;
}
- filtered_names.push_back(F->get());
+ filtered_names.push_back(F);
}
if (filtered_names.size() == 0) {
@@ -182,10 +182,10 @@ void ThemeItemImportTree::_update_items_tree() {
bool data_type_any_checked_with_data = false;
filtered_names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *F = filtered_names.front(); F; F = F->next()) {
+ for (const StringName &F : filtered_names) {
TreeItem *item_node = import_items_tree->create_item(data_type_node);
item_node->set_meta("_can_be_imported", true);
- item_node->set_text(0, F->get());
+ item_node->set_text(0, F);
item_node->set_cell_mode(IMPORT_ITEM, TreeItem::CELL_MODE_CHECK);
item_node->set_checked(IMPORT_ITEM, false);
item_node->set_editable(IMPORT_ITEM, true);
@@ -754,7 +754,7 @@ void ThemeItemImportTree::_import_selected() {
return;
}
- // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ // Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
ProgressDialog::get_singleton()->add_task("import_theme_items", TTR("Importing Theme Items"), selected_items.size() + 2);
@@ -1236,16 +1236,16 @@ void ThemeItemEditorDialog::_update_edit_types() {
bool item_reselected = false;
edit_type_list->clear();
int e_idx = 0;
- for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) {
+ for (const StringName &E : theme_types) {
Ref<Texture2D> item_icon;
- if (E->get() == "") {
+ if (E == "") {
item_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons"));
} else {
- item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ item_icon = EditorNode::get_singleton()->get_class_icon(E, "NodeDisabled");
}
- edit_type_list->add_item(E->get(), item_icon);
+ edit_type_list->add_item(E, item_icon);
- if (E->get() == edited_item_type) {
+ if (E == edited_item_type) {
edit_type_list->select(e_idx);
item_reselected = true;
}
@@ -1318,9 +1318,9 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
color_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Color Items"));
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
TreeItem *item = edit_items_tree->create_item(color_root);
- item->set_text(0, E->get());
+ item->set_text(0, E);
item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
@@ -1339,9 +1339,9 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
constant_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Constant Items"));
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
TreeItem *item = edit_items_tree->create_item(constant_root);
- item->set_text(0, E->get());
+ item->set_text(0, E);
item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
@@ -1360,9 +1360,9 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
font_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Items"));
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
TreeItem *item = edit_items_tree->create_item(font_root);
- item->set_text(0, E->get());
+ item->set_text(0, E);
item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
@@ -1381,9 +1381,9 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
font_size_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Font Size Items"));
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
TreeItem *item = edit_items_tree->create_item(font_size_root);
- item->set_text(0, E->get());
+ item->set_text(0, E);
item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
@@ -1402,9 +1402,9 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
icon_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All Icon Items"));
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
TreeItem *item = edit_items_tree->create_item(icon_root);
- item->set_text(0, E->get());
+ item->set_text(0, E);
item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
@@ -1423,9 +1423,9 @@ void ThemeItemEditorDialog::_update_edit_item_tree(String p_item_type) {
stylebox_root->add_button(0, get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_DATA_TYPE, false, TTR("Remove All StyleBox Items"));
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
TreeItem *item = edit_items_tree->create_item(stylebox_root);
- item->set_text(0, E->get());
+ item->set_text(0, E);
item->add_button(0, get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), ITEMS_TREE_RENAME_ITEM, false, TTR("Rename Item"));
item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), ITEMS_TREE_REMOVE_ITEM, false, TTR("Remove Item"));
}
@@ -1503,12 +1503,12 @@ void ThemeItemEditorDialog::_add_theme_item(Theme::DataType p_data_type, String
void ThemeItemEditorDialog::_remove_data_type_items(Theme::DataType p_data_type, String p_item_type) {
List<StringName> names;
- // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ // Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
edited_theme->get_theme_item_list(p_data_type, p_item_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->clear_theme_item(p_data_type, E->get(), p_item_type);
+ for (const StringName &E : names) {
+ edited_theme->clear_theme_item(p_data_type, E, p_item_type);
}
// Allow changes to be reported now that the operation is finished.
@@ -1518,7 +1518,7 @@ void ThemeItemEditorDialog::_remove_data_type_items(Theme::DataType p_data_type,
void ThemeItemEditorDialog::_remove_class_items() {
List<StringName> names;
- // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ // Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
@@ -1526,9 +1526,9 @@ void ThemeItemEditorDialog::_remove_class_items() {
names.clear();
Theme::get_default()->get_theme_item_list(data_type, edited_item_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (edited_theme->has_theme_item_nocheck(data_type, E->get(), edited_item_type)) {
- edited_theme->clear_theme_item(data_type, E->get(), edited_item_type);
+ for (const StringName &E : names) {
+ if (edited_theme->has_theme_item_nocheck(data_type, E, edited_item_type)) {
+ edited_theme->clear_theme_item(data_type, E, edited_item_type);
}
}
}
@@ -1542,7 +1542,7 @@ void ThemeItemEditorDialog::_remove_class_items() {
void ThemeItemEditorDialog::_remove_custom_items() {
List<StringName> names;
- // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ // Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
@@ -1550,9 +1550,9 @@ void ThemeItemEditorDialog::_remove_custom_items() {
names.clear();
edited_theme->get_theme_item_list(data_type, edited_item_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!Theme::get_default()->has_theme_item_nocheck(data_type, E->get(), edited_item_type)) {
- edited_theme->clear_theme_item(data_type, E->get(), edited_item_type);
+ for (const StringName &E : names) {
+ if (!Theme::get_default()->has_theme_item_nocheck(data_type, E, edited_item_type)) {
+ edited_theme->clear_theme_item(data_type, E, edited_item_type);
}
}
}
@@ -1566,7 +1566,7 @@ void ThemeItemEditorDialog::_remove_custom_items() {
void ThemeItemEditorDialog::_remove_all_items() {
List<StringName> names;
- // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ // Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
for (int dt = 0; dt < Theme::DATA_TYPE_MAX; dt++) {
@@ -1574,8 +1574,8 @@ void ThemeItemEditorDialog::_remove_all_items() {
names.clear();
edited_theme->get_theme_item_list(data_type, edited_item_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- edited_theme->clear_theme_item(data_type, E->get(), edited_item_type);
+ for (const StringName &E : names) {
+ edited_theme->clear_theme_item(data_type, E, edited_item_type);
}
}
@@ -1927,8 +1927,8 @@ ThemeItemEditorDialog::ThemeItemEditorDialog() {
import_another_theme_dialog->set_title(TTR("Select Another Theme Resource:"));
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("Theme", &ext);
- for (List<String>::Element *E = ext.front(); E; E = E->next()) {
- import_another_theme_dialog->add_filter("*." + E->get() + "; Theme Resource");
+ for (const String &E : ext) {
+ import_another_theme_dialog->add_filter("*." + E + "; Theme Resource");
}
import_another_file_hb->add_child(import_another_theme_dialog);
import_another_theme_dialog->connect("file_selected", callable_mp(this, &ThemeItemEditorDialog::_select_another_theme_cbk));
@@ -1969,26 +1969,26 @@ void ThemeTypeDialog::_update_add_type_options(const String &p_filter) {
names.sort_custom<StringName::AlphCompare>();
Vector<StringName> unique_names;
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
// Filter out undesired values.
- if (!p_filter.is_subsequence_ofi(String(E->get()))) {
+ if (!p_filter.is_subsequence_ofi(String(E))) {
continue;
}
// Skip duplicate values.
- if (unique_names.has(E->get())) {
+ if (unique_names.has(E)) {
continue;
}
- unique_names.append(E->get());
+ unique_names.append(E);
Ref<Texture2D> item_icon;
- if (E->get() == "") {
+ if (E == "") {
item_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons"));
} else {
- item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ item_icon = EditorNode::get_singleton()->get_class_icon(E, "NodeDisabled");
}
- add_type_options->add_item(E->get(), item_icon);
+ add_type_options->add_item(E, item_icon);
}
}
@@ -2132,16 +2132,16 @@ void ThemeTypeEditor::_update_type_list() {
bool item_reselected = false;
int e_idx = 0;
- for (List<StringName>::Element *E = theme_types.front(); E; E = E->next()) {
+ for (const StringName &E : theme_types) {
Ref<Texture2D> item_icon;
- if (E->get() == "") {
+ if (E == "") {
item_icon = get_theme_icon(SNAME("NodeDisabled"), SNAME("EditorIcons"));
} else {
- item_icon = EditorNode::get_singleton()->get_class_icon(E->get(), "NodeDisabled");
+ item_icon = EditorNode::get_singleton()->get_class_icon(E, "NodeDisabled");
}
- theme_type_list->add_icon_item(item_icon, E->get());
+ theme_type_list->add_icon_item(item_icon, E);
- if (E->get() == edited_type) {
+ if (E == edited_type) {
theme_type_list->select(e_idx);
item_reselected = true;
}
@@ -2182,8 +2182,8 @@ OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_
(Theme::get_default().operator->()->*get_list_func)(default_type, &names);
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- items[E->get()] = false;
+ for (const StringName &E : names) {
+ items[E] = false;
}
}
@@ -2191,8 +2191,8 @@ OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_
names.clear();
(edited_theme.operator->()->*get_list_func)(p_type_name, &names);
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- items[E->get()] = true;
+ for (const StringName &E : names) {
+ items[E] = true;
}
}
@@ -2203,8 +2203,8 @@ OrderedHashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_
keys.sort_custom<StringName::AlphCompare>();
OrderedHashMap<StringName, bool> ordered_items;
- for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
- ordered_items[E->get()] = items[E->get()];
+ for (const StringName &E : keys) {
+ ordered_items[E] = items[E];
}
return ordered_items;
@@ -2574,60 +2574,60 @@ void ThemeTypeEditor::_add_default_type_items() {
}
updating = true;
- // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ // Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
{
names.clear();
Theme::get_default()->get_icon_list(default_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!edited_theme->has_icon(E->get(), edited_type)) {
- edited_theme->set_icon(E->get(), edited_type, Ref<Texture2D>());
+ for (const StringName &E : names) {
+ if (!edited_theme->has_icon(E, edited_type)) {
+ edited_theme->set_icon(E, edited_type, Ref<Texture2D>());
}
}
}
{
names.clear();
Theme::get_default()->get_stylebox_list(default_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!edited_theme->has_stylebox(E->get(), edited_type)) {
- edited_theme->set_stylebox(E->get(), edited_type, Ref<StyleBox>());
+ for (const StringName &E : names) {
+ if (!edited_theme->has_stylebox(E, edited_type)) {
+ edited_theme->set_stylebox(E, edited_type, Ref<StyleBox>());
}
}
}
{
names.clear();
Theme::get_default()->get_font_list(default_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!edited_theme->has_font(E->get(), edited_type)) {
- edited_theme->set_font(E->get(), edited_type, Ref<Font>());
+ for (const StringName &E : names) {
+ if (!edited_theme->has_font(E, edited_type)) {
+ edited_theme->set_font(E, edited_type, Ref<Font>());
}
}
}
{
names.clear();
Theme::get_default()->get_font_size_list(default_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!edited_theme->has_font_size(E->get(), edited_type)) {
- edited_theme->set_font_size(E->get(), edited_type, Theme::get_default()->get_font_size(E->get(), default_type));
+ for (const StringName &E : names) {
+ if (!edited_theme->has_font_size(E, edited_type)) {
+ edited_theme->set_font_size(E, edited_type, Theme::get_default()->get_font_size(E, default_type));
}
}
}
{
names.clear();
Theme::get_default()->get_color_list(default_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!edited_theme->has_color(E->get(), edited_type)) {
- edited_theme->set_color(E->get(), edited_type, Theme::get_default()->get_color(E->get(), default_type));
+ for (const StringName &E : names) {
+ if (!edited_theme->has_color(E, edited_type)) {
+ edited_theme->set_color(E, edited_type, Theme::get_default()->get_color(E, default_type));
}
}
}
{
names.clear();
Theme::get_default()->get_constant_list(default_type, &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (!edited_theme->has_constant(E->get(), edited_type)) {
- edited_theme->set_constant(E->get(), edited_type, Theme::get_default()->get_constant(E->get(), default_type));
+ for (const StringName &E : names) {
+ if (!edited_theme->has_constant(E, edited_type)) {
+ edited_theme->set_constant(E, edited_type, Theme::get_default()->get_constant(E, default_type));
}
}
}
@@ -2876,18 +2876,18 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
return;
}
- // Prevent changes from immediatelly being reported while the operation is still ongoing.
+ // Prevent changes from immediately being reported while the operation is still ongoing.
edited_theme->_freeze_change_propagation();
List<StringName> names;
edited_theme->get_stylebox_list(edited_type, &names);
List<Ref<StyleBox>> styleboxes;
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- if (E->get() == leading_stylebox.item_name) {
+ for (const StringName &E : names) {
+ if (E == leading_stylebox.item_name) {
continue;
}
- Ref<StyleBox> sb = edited_theme->get_stylebox(E->get(), edited_type);
+ Ref<StyleBox> sb = edited_theme->get_stylebox(E, edited_type);
if (sb->get_class() == leading_stylebox.stylebox->get_class()) {
styleboxes.push_back(sb);
}
@@ -2895,20 +2895,20 @@ void ThemeTypeEditor::_update_stylebox_from_leading() {
List<PropertyInfo> props;
leading_stylebox.stylebox->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant value = leading_stylebox.stylebox->get(E->get().name);
- Variant ref_value = leading_stylebox.ref_stylebox->get(E->get().name);
+ Variant value = leading_stylebox.stylebox->get(E.name);
+ Variant ref_value = leading_stylebox.ref_stylebox->get(E.name);
if (value == ref_value) {
continue;
}
- for (List<Ref<StyleBox>>::Element *F = styleboxes.front(); F; F = F->next()) {
- Ref<StyleBox> sb = F->get();
- sb->set(E->get().name, value);
+ for (const Ref<StyleBox> &F : styleboxes) {
+ Ref<StyleBox> sb = F;
+ sb->set(E.name, value);
}
}
@@ -3301,8 +3301,8 @@ ThemeEditor::ThemeEditor() {
preview_scene_dialog->set_title(TTR("Select UI Scene:"));
List<String> ext;
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &ext);
- for (List<String>::Element *E = ext.front(); E; E = E->next()) {
- preview_scene_dialog->add_filter("*." + E->get() + "; Scene");
+ for (const String &E : ext) {
+ preview_scene_dialog->add_filter("*." + E + "; Scene");
}
main_hs->add_child(preview_scene_dialog);
preview_scene_dialog->connect("file_selected", callable_mp(this, &ThemeEditor::_preview_scene_dialog_cbk));
@@ -3343,12 +3343,12 @@ bool ThemeEditorPlugin::handles(Object *p_node) const {
List<StringName> names;
edited_theme->get_font_type_list(&types);
- for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ for (const StringName &E : types) {
names.clear();
- edited_theme->get_font_list(E->get(), &names);
+ edited_theme->get_font_list(E, &names);
- for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
- if (font_item == edited_theme->get_font(F->get(), E->get())) {
+ for (const StringName &F : names) {
+ if (font_item == edited_theme->get_font(F, E)) {
belongs_to_theme = true;
break;
}
@@ -3360,12 +3360,12 @@ bool ThemeEditorPlugin::handles(Object *p_node) const {
List<StringName> names;
edited_theme->get_stylebox_type_list(&types);
- for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ for (const StringName &E : types) {
names.clear();
- edited_theme->get_stylebox_list(E->get(), &names);
+ edited_theme->get_stylebox_list(E, &names);
- for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
- if (stylebox_item == edited_theme->get_stylebox(F->get(), E->get())) {
+ for (const StringName &F : names) {
+ if (stylebox_item == edited_theme->get_stylebox(F, E)) {
belongs_to_theme = true;
break;
}
@@ -3377,12 +3377,12 @@ bool ThemeEditorPlugin::handles(Object *p_node) const {
List<StringName> names;
edited_theme->get_icon_type_list(&types);
- for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
+ for (const StringName &E : types) {
names.clear();
- edited_theme->get_icon_list(E->get(), &names);
+ edited_theme->get_icon_list(E, &names);
- for (List<StringName>::Element *F = names.front(); F; F = F->next()) {
- if (icon_item == edited_theme->get_icon(F->get(), E->get())) {
+ for (const StringName &F : names) {
+ if (icon_item == edited_theme->get_icon(F, E)) {
belongs_to_theme = true;
break;
}
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
new file mode 100644
index 0000000000..bbafc7802b
--- /dev/null
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -0,0 +1,320 @@
+/*************************************************************************/
+/* atlas_merging_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "atlas_merging_dialog.h"
+
+#include "editor/editor_scale.h"
+
+#include "scene/gui/control.h"
+#include "scene/gui/split_container.h"
+
+void AtlasMergingDialog::_property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
+ _set(p_property, p_value);
+}
+
+void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atlas_sources, int p_max_columns) {
+ merged.instantiate();
+ merged_mapping.clear();
+
+ if (p_atlas_sources.size() >= 2) {
+ Ref<Image> output_image;
+ output_image.instantiate();
+ output_image->create(1, 1, false, Image::FORMAT_RGBA8);
+
+ // Compute the new texture region size.
+ Vector2i new_texture_region_size;
+ for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) {
+ Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index];
+ new_texture_region_size = new_texture_region_size.max(atlas_source->get_texture_region_size());
+ }
+
+ // Generate the merged TileSetAtlasSource.
+ Vector2i atlas_offset;
+ int line_height = 0;
+ for (int source_index = 0; source_index < p_atlas_sources.size(); source_index++) {
+ Ref<TileSetAtlasSource> atlas_source = p_atlas_sources[source_index];
+ merged_mapping.push_back(Map<Vector2i, Vector2i>());
+
+ // Layout the tiles.
+ Vector2i atlas_size;
+
+ for (int tile_index = 0; tile_index < atlas_source->get_tiles_count(); tile_index++) {
+ Vector2i tile_id = atlas_source->get_tile_id(tile_index);
+ atlas_size = atlas_size.max(tile_id + atlas_source->get_tile_size_in_atlas(tile_id));
+
+ Rect2i new_tile_rect_in_altas = Rect2i(atlas_offset + tile_id, atlas_source->get_tile_size_in_atlas(tile_id));
+
+ // Create tiles and alternatives, then copy their properties.
+ for (int alternative_index = 0; alternative_index < atlas_source->get_alternative_tiles_count(tile_id); alternative_index++) {
+ int alternative_id = atlas_source->get_alternative_tile_id(tile_id, alternative_index);
+ if (alternative_id == 0) {
+ merged->create_tile(new_tile_rect_in_altas.position, new_tile_rect_in_altas.size);
+ } else {
+ merged->create_alternative_tile(new_tile_rect_in_altas.position, alternative_index);
+ }
+
+ // Copy the properties.
+ TileData *original_tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(tile_id, alternative_id));
+ List<PropertyInfo> properties;
+ original_tile_data->get_property_list(&properties);
+ for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ const StringName &property_name = E->get().name;
+ merged->set(property_name, original_tile_data->get(property_name));
+ }
+
+ // Add to the mapping.
+ merged_mapping[source_index][tile_id] = new_tile_rect_in_altas.position;
+ }
+
+ // Copy the texture.
+ Rect2i src_rect = atlas_source->get_tile_texture_region(tile_id);
+ Rect2 dst_rect_wide = Rect2i(new_tile_rect_in_altas.position * new_texture_region_size, new_tile_rect_in_altas.size * new_texture_region_size);
+ if (dst_rect_wide.get_end().x > output_image->get_width() || dst_rect_wide.get_end().y > output_image->get_height()) {
+ output_image->crop(MAX(dst_rect_wide.get_end().x, output_image->get_width()), MAX(dst_rect_wide.get_end().y, output_image->get_height()));
+ }
+ output_image->blit_rect(atlas_source->get_texture()->get_image(), src_rect, (dst_rect_wide.get_position() + dst_rect_wide.get_end()) / 2 - src_rect.size / 2);
+ }
+
+ // Compute the atlas offset.
+ line_height = MAX(atlas_size.y, line_height);
+ atlas_offset.x += atlas_size.x;
+ if (atlas_offset.x >= p_max_columns) {
+ atlas_offset.x = 0;
+ atlas_offset.y += line_height;
+ line_height = 0;
+ }
+ }
+
+ Ref<ImageTexture> output_image_texture;
+ output_image_texture.instantiate();
+ output_image_texture->create_from_image(output_image);
+
+ merged->set_texture(output_image_texture);
+ merged->set_texture_region_size(new_texture_region_size);
+ }
+}
+
+void AtlasMergingDialog::_update_texture() {
+ Vector<int> selected = atlas_merging_atlases_list->get_selected_items();
+ if (selected.size() >= 2) {
+ Vector<Ref<TileSetAtlasSource>> to_merge;
+ for (int i = 0; i < selected.size(); i++) {
+ int source_id = atlas_merging_atlases_list->get_item_metadata(selected[i]);
+ to_merge.push_back(tile_set->get_source(source_id));
+ }
+ _generate_merged(to_merge, next_line_after_column);
+ preview->set_texture(merged->get_texture());
+ preview->show();
+ select_2_atlases_label->hide();
+ get_ok_button()->set_disabled(false);
+ merge_button->set_disabled(false);
+ } else {
+ _generate_merged(Vector<Ref<TileSetAtlasSource>>(), next_line_after_column);
+ preview->set_texture(Ref<Texture2D>());
+ preview->hide();
+ select_2_atlases_label->show();
+ get_ok_button()->set_disabled(true);
+ merge_button->set_disabled(true);
+ }
+}
+
+void AtlasMergingDialog::_merge_confirmed(String p_path) {
+ ERR_FAIL_COND(!merged.is_valid());
+
+ Ref<ImageTexture> output_image_texture = merged->get_texture();
+ output_image_texture->get_image()->save_png(p_path);
+
+ Ref<Texture2D> new_texture_resource = ResourceLoader::load(p_path, "Texture2D");
+ merged->set_texture(new_texture_resource);
+
+ undo_redo->create_action("Merge TileSetAtlasSource");
+ int next_id = tile_set->get_next_source_id();
+ undo_redo->add_do_method(*tile_set, "add_source", merged, next_id);
+ undo_redo->add_undo_method(*tile_set, "remove_source", next_id);
+
+ if (delete_original_atlases) {
+ // Delete originals if needed.
+ Vector<int> selected = atlas_merging_atlases_list->get_selected_items();
+ for (int i = 0; i < selected.size(); i++) {
+ int source_id = atlas_merging_atlases_list->get_item_metadata(selected[i]);
+ Ref<TileSetAtlasSource> tas = tile_set->get_source(source_id);
+ undo_redo->add_do_method(*tile_set, "remove_source", source_id);
+ undo_redo->add_undo_method(*tile_set, "add_source", tas, source_id);
+
+ // Add the tile proxies.
+ for (int tile_index = 0; tile_index < tas->get_tiles_count(); tile_index++) {
+ Vector2i tile_id = tas->get_tile_id(tile_index);
+ undo_redo->add_do_method(*tile_set, "set_coords_level_tile_proxy", source_id, tile_id, next_id, merged_mapping[i][tile_id]);
+ if (tile_set->has_coords_level_tile_proxy(source_id, tile_id)) {
+ Array a = tile_set->get_coords_level_tile_proxy(source_id, tile_id);
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", a[0], a[1]);
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_coords_level_tile_proxy", source_id, tile_id);
+ }
+ }
+ }
+ }
+ undo_redo->commit_action();
+ commited_actions_count++;
+
+ hide();
+}
+
+void AtlasMergingDialog::ok_pressed() {
+ delete_original_atlases = false;
+ editor_file_dialog->popup_file_dialog();
+}
+
+void AtlasMergingDialog::cancel_pressed() {
+ for (int i = 0; i < commited_actions_count; i++) {
+ undo_redo->undo();
+ }
+ commited_actions_count = 0;
+}
+
+void AtlasMergingDialog::custom_action(const String &p_action) {
+ if (p_action == "merge") {
+ delete_original_atlases = true;
+ editor_file_dialog->popup_file_dialog();
+ }
+}
+
+bool AtlasMergingDialog::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "next_line_after_column" && p_value.get_type() == Variant::INT) {
+ next_line_after_column = p_value;
+ _update_texture();
+ return true;
+ }
+ return false;
+}
+
+bool AtlasMergingDialog::_get(const StringName &p_name, Variant &r_ret) const {
+ if (p_name == "next_line_after_column") {
+ r_ret = next_line_after_column;
+ return true;
+ }
+ return false;
+}
+
+void AtlasMergingDialog::update_tile_set(Ref<TileSet> p_tile_set) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ tile_set = p_tile_set;
+
+ atlas_merging_atlases_list->clear();
+ for (int i = 0; i < p_tile_set->get_source_count(); i++) {
+ int source_id = p_tile_set->get_source_id(i);
+ Ref<TileSetAtlasSource> atlas_source = p_tile_set->get_source(source_id);
+ if (atlas_source.is_valid()) {
+ Ref<Texture2D> texture = atlas_source->get_texture();
+ 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);
+ }
+ }
+ }
+
+ get_ok_button()->set_disabled(true);
+ merge_button->set_disabled(true);
+
+ commited_actions_count = 0;
+}
+
+AtlasMergingDialog::AtlasMergingDialog() {
+ // Atlas merging window.
+ set_title(TTR("Atlas Merging"));
+ set_hide_on_ok(false);
+
+ // Ok buttons
+ get_ok_button()->set_text(TTR("Merge (Keep original Atlases)"));
+ get_ok_button()->set_disabled(true);
+ merge_button = add_button(TTR("Merge"), true, "merge");
+ merge_button->set_disabled(true);
+
+ HSplitContainer *atlas_merging_h_split_container = memnew(HSplitContainer);
+ atlas_merging_h_split_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_h_split_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(atlas_merging_h_split_container);
+
+ // Atlas sources item list.
+ atlas_merging_atlases_list = memnew(ItemList);
+ atlas_merging_atlases_list->set_fixed_icon_size(Size2i(60, 60) * EDSCALE);
+ atlas_merging_atlases_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_atlases_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_atlases_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
+ atlas_merging_atlases_list->set_custom_minimum_size(Size2(100, 200));
+ atlas_merging_atlases_list->set_select_mode(ItemList::SELECT_MULTI);
+ atlas_merging_atlases_list->connect("multi_selected", callable_mp(this, &AtlasMergingDialog::_update_texture).unbind(2));
+ atlas_merging_h_split_container->add_child(atlas_merging_atlases_list);
+
+ VBoxContainer *atlas_merging_right_panel = memnew(VBoxContainer);
+ atlas_merging_right_panel->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ atlas_merging_h_split_container->add_child(atlas_merging_right_panel);
+
+ // Settings.
+ Label *settings_label = memnew(Label);
+ settings_label->set_text(TTR("Settings:"));
+ atlas_merging_right_panel->add_child(settings_label);
+
+ columns_editor_property = memnew(EditorPropertyInteger);
+ columns_editor_property->set_label(TTR("Next Line After Column"));
+ columns_editor_property->set_object_and_property(this, "next_line_after_column");
+ columns_editor_property->update_property();
+ columns_editor_property->connect("property_changed", callable_mp(this, &AtlasMergingDialog::_property_changed));
+ atlas_merging_right_panel->add_child(columns_editor_property);
+
+ // Preview.
+ Label *preview_label = memnew(Label);
+ preview_label->set_text(TTR("Preview:"));
+ atlas_merging_right_panel->add_child(preview_label);
+
+ preview = memnew(TextureRect);
+ preview->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ preview->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ preview->set_expand(true);
+ preview->hide();
+ preview->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
+ atlas_merging_right_panel->add_child(preview);
+
+ select_2_atlases_label = memnew(Label);
+ select_2_atlases_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ select_2_atlases_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ select_2_atlases_label->set_align(Label::ALIGN_CENTER);
+ select_2_atlases_label->set_valign(Label::VALIGN_CENTER);
+ select_2_atlases_label->set_text(TTR("Please select two atlases or more."));
+ atlas_merging_right_panel->add_child(select_2_atlases_label);
+
+ // The file dialog to choose the texture path.
+ editor_file_dialog = memnew(EditorFileDialog);
+ editor_file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ editor_file_dialog->add_filter("*.png");
+ editor_file_dialog->connect("file_selected", callable_mp(this, &AtlasMergingDialog::_merge_confirmed));
+ add_child(editor_file_dialog);
+}
diff --git a/editor/plugins/tiles/atlas_merging_dialog.h b/editor/plugins/tiles/atlas_merging_dialog.h
new file mode 100644
index 0000000000..7cb54bc17e
--- /dev/null
+++ b/editor/plugins/tiles/atlas_merging_dialog.h
@@ -0,0 +1,86 @@
+/*************************************************************************/
+/* atlas_merging_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 ATLAS_MERGING_DIALOG_H
+#define ATLAS_MERGING_DIALOG_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_properties.h"
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/item_list.h"
+#include "scene/gui/texture_rect.h"
+#include "scene/resources/tile_set.h"
+
+class AtlasMergingDialog : public ConfirmationDialog {
+ GDCLASS(AtlasMergingDialog, ConfirmationDialog);
+
+private:
+ int commited_actions_count = 0;
+ bool delete_original_atlases = true;
+ Ref<TileSetAtlasSource> merged;
+ LocalVector<Map<Vector2i, Vector2i>> merged_mapping;
+ Ref<TileSet> tile_set;
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ // Settings.
+ int next_line_after_column = 30;
+
+ // GUI.
+ ItemList *atlas_merging_atlases_list;
+ EditorPropertyVector2i *texture_region_size_editor_property;
+ EditorPropertyInteger *columns_editor_property;
+ TextureRect *preview;
+ Label *select_2_atlases_label;
+ EditorFileDialog *editor_file_dialog;
+ Button *merge_button;
+
+ void _property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
+
+ void _generate_merged(Vector<Ref<TileSetAtlasSource>> p_atlas_sources, int p_max_columns);
+ void _update_texture();
+ void _merge_confirmed(String p_path);
+
+protected:
+ virtual void ok_pressed() override;
+ virtual void cancel_pressed() override;
+ virtual void custom_action(const String &) override;
+
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+
+public:
+ void update_tile_set(Ref<TileSet> p_tile_set);
+
+ AtlasMergingDialog();
+};
+
+#endif // ATLAS_MERGING_DIALOG_H
diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h
index bafc2b3985..b2046f4322 100644
--- a/editor/plugins/tiles/tile_atlas_view.h
+++ b/editor/plugins/tiles/tile_atlas_view.h
@@ -47,7 +47,7 @@ class TileAtlasView : public Control {
private:
TileSet *tile_set;
TileSetAtlasSource *tile_set_atlas_source;
- int source_id = -1;
+ int source_id = TileSet::INVALID_SOURCE;
enum DragType {
DRAG_TYPE_NONE,
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index dd2922286f..bab55df65a 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -1244,7 +1244,7 @@ void TileDataCollisionEditor::_polygons_changed() {
}
}
- // Remove uneeded properties and their editors.
+ // Remove unneeded properties and their editors.
for (int i = polygon_editor->get_polygon_count(); dummy_object->has_dummy_property(vformat("polygon_%d_one_way", i)); i++) {
dummy_object->remove_dummy_property(vformat("polygon_%d_one_way", i));
}
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index 6e3c55d801..4a4e81dae3 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -56,18 +56,11 @@ void TileMapEditorTilesPlugin::_notification(int p_what) {
picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons")));
erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons")));
- toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
-
missing_atlas_texture_icon = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
-
- toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
break;
case NOTIFICATION_VISIBILITY_CHANGED:
_stop_dragging();
break;
- case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED:
- toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
- break;
}
}
@@ -85,10 +78,6 @@ void TileMapEditorTilesPlugin::_on_scattering_spinbox_changed(double p_value) {
scattering = p_value;
}
-void TileMapEditorTilesPlugin::_on_grid_toggled(bool p_pressed) {
- EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
-}
-
void TileMapEditorTilesPlugin::_update_toolbar() {
// Stop draggig if needed.
_stop_dragging();
@@ -204,7 +193,7 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() {
}
// Synchronize
- TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
+ TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current());
}
void TileMapEditorTilesPlugin::_update_bottom_panel() {
@@ -410,7 +399,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
undo_redo->create_action(TTR("Delete tiles"));
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
- undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
@@ -441,7 +430,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!tile_map_selection.is_empty()) {
undo_redo->create_action(TTR("Delete tiles"));
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
- undo_redo->add_do_method(tile_map, "set_cell", E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ undo_redo->add_do_method(tile_map, "set_cell", E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
undo_redo->add_undo_method(tile_map, "set_cell", E->get(), tile_map->get_cell_source_id(E->get()), tile_map->get_cell_atlas_coords(E->get()), tile_map->get_cell_alternative_tile(E->get()));
}
undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection());
@@ -462,12 +451,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
case DRAG_TYPE_PAINT: {
Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_last_mouse_pos, mpos);
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -478,12 +467,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!drag_modified.has(line[i])) {
Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed());
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -516,8 +505,8 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
drag_modified.clear();
for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) {
Vector2i coords = E->get();
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
- tile_map->set_cell(coords, -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ drag_modified.insert(coords, tile_map->get_cell(coords));
+ tile_map->set_cell(coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
} else {
// Select tiles
@@ -536,12 +525,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
drag_modified.clear();
Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, mpos, mpos);
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -562,12 +551,12 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p
if (!drag_modified.has(line[i])) {
Map<Vector2i, TileMapCell> to_draw = _draw_bucket_fill(line[i], bucket_continuous_checkbox->is_pressed());
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
Vector2i coords = E->key();
if (!drag_modified.has(coords)) {
- drag_modified.insert(coords, TileMapCell(tile_map->get_cell_source_id(coords), tile_map->get_cell_atlas_coords(coords), tile_map->get_cell_alternative_tile(coords)));
+ drag_modified.insert(coords, tile_map->get_cell(coords));
}
tile_map->set_cell(coords, E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -634,7 +623,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
for (int x = rect.position.x; x < rect.get_end().x; x++) {
for (int y = rect.position.y; y < rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_map->get_cell_source_id(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - tile_shape_size / 2, tile_shape_size));
tile_set->draw_tile_shape(p_overlay, cell_region, Color(1.0, 1.0, 1.0), false);
}
@@ -648,7 +637,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over
for (int x = rect.position.x; x < rect.get_end().x; x++) {
for (int y = rect.position.y; y < rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_map->get_cell_source_id(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
to_draw.insert(coords);
}
}
@@ -871,7 +860,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -923,7 +912,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
// Compute the offset to align things to the bottom or right.
@@ -974,7 +963,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
// Get or create the pattern.
TileMapPattern erase_pattern;
- erase_pattern.set_cell(Vector2i(0, 0), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
TileMapPattern *pattern = erase_button->is_pressed() ? &erase_pattern : selection_pattern;
Map<Vector2i, TileMapCell> output;
@@ -983,7 +972,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
// If we are filling empty tiles, compute the tilemap boundaries.
Rect2i boundaries;
- if (source.source_id == -1) {
+ if (source.source_id == TileSet::INVALID_SOURCE) {
boundaries = tile_map->get_used_rect();
}
@@ -999,7 +988,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
if (source.source_id == tile_map->get_cell_source_id(coords) &&
source.get_atlas_coords() == tile_map->get_cell_atlas_coords(coords) &&
source.alternative_tile == tile_map->get_cell_alternative_tile(coords) &&
- (source.source_id != -1 || boundaries.has_point(coords))) {
+ (source.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
// Paint a random tile.
output.insert(coords, _pick_random_tile(pattern));
@@ -1027,7 +1016,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
} else {
// Replace all tiles like the source.
TypedArray<Vector2i> to_check;
- if (source.source_id == -1) {
+ if (source.source_id == TileSet::INVALID_SOURCE) {
Rect2i rect = tile_map->get_used_rect();
if (rect.size.x <= 0 || rect.size.y <= 0) {
rect = Rect2i(p_coords, Vector2i(1, 1));
@@ -1045,7 +1034,7 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i
if (source.source_id == tile_map->get_cell_source_id(coords) &&
source.get_atlas_coords() == tile_map->get_cell_atlas_coords(coords) &&
source.alternative_tile == tile_map->get_cell_alternative_tile(coords) &&
- (source.source_id != -1 || boundaries.has_point(coords))) {
+ (source.source_id != TileSet::INVALID_SOURCE || boundaries.has_point(coords))) {
if (!erase_button->is_pressed() && random_tile_checkbox->is_pressed()) {
// Paint a random tile.
output.insert(coords, _pick_random_tile(pattern));
@@ -1102,7 +1091,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
tile_map_selection.erase(coords);
}
} else {
- if (tile_map->get_cell_source_id(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
tile_map_selection.insert(coords);
}
}
@@ -1173,7 +1162,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
for (int x = rect.position.x; x < rect.get_end().x; x++) {
for (int y = rect.position.y; y < rect.get_end().y; y++) {
Vector2i coords = Vector2i(x, y);
- if (tile_map->get_cell_source_id(coords) != -1) {
+ if (tile_map->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
coords_array.push_back(coords);
}
}
@@ -1198,7 +1187,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
Map<Vector2i, TileMapCell> to_draw = _draw_line(drag_start_mouse_pos, drag_start_mouse_pos, mpos);
undo_redo->create_action(TTR("Paint tiles"));
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
undo_redo->add_do_method(tile_map, "set_cell", E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
@@ -1210,7 +1199,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
Map<Vector2i, TileMapCell> to_draw = _draw_rect(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos));
undo_redo->create_action(TTR("Paint tiles"));
for (Map<Vector2i, TileMapCell>::Element *E = to_draw.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
+ if (!erase_button->is_pressed() && E->get().source_id == TileSet::INVALID_SOURCE) {
continue;
}
undo_redo->add_do_method(tile_map, "set_cell", E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
@@ -1221,9 +1210,6 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
case DRAG_TYPE_BUCKET: {
undo_redo->create_action(TTR("Paint tiles"));
for (Map<Vector2i, TileMapCell>::Element *E = drag_modified.front(); E; E = E->next()) {
- if (!erase_button->is_pressed() && E->get().source_id == -1) {
- continue;
- }
undo_redo->add_do_method(tile_map, "set_cell", E->key(), tile_map->get_cell_source_id(E->key()), tile_map->get_cell_atlas_coords(E->key()), tile_map->get_cell_alternative_tile(E->key()));
undo_redo->add_undo_method(tile_map, "set_cell", E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
}
@@ -1249,7 +1235,7 @@ void TileMapEditorTilesPlugin::_stop_dragging() {
void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
if (!tile_map) {
- hovered_tile.source_id = -1;
+ hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
@@ -1260,7 +1246,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
Ref<TileSet> tile_set = tile_map->get_tileset();
if (!tile_set.is_valid()) {
- hovered_tile.source_id = -1;
+ hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
@@ -1271,7 +1257,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
int source_index = sources_list->get_current();
if (source_index < 0 || source_index >= sources_list->get_item_count()) {
- hovered_tile.source_id = -1;
+ hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_selection.clear();
@@ -1287,7 +1273,7 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() {
!tile_set->has_source(hovered_tile.source_id) ||
!tile_set->get_source(hovered_tile.source_id)->has_tile(hovered_tile.get_atlas_coords()) ||
!tile_set->get_source(hovered_tile.source_id)->has_alternative_tile(hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)) {
- hovered_tile.source_id = -1;
+ hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
}
@@ -1403,7 +1389,7 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern(
TypedArray<Vector2i> used_cells = selection_pattern->get_used_cells();
for (int i = 0; i < used_cells.size(); i++) {
Vector2i coords = used_cells[i];
- if (selection_pattern->get_cell_source_id(coords) != -1) {
+ if (selection_pattern->get_cell_source_id(coords) != TileSet::INVALID_SOURCE) {
tile_set_selection.insert(TileMapCell(selection_pattern->get_cell_source_id(coords), selection_pattern->get_cell_atlas_coords(coords), selection_pattern->get_cell_alternative_tile(coords)));
}
}
@@ -1475,7 +1461,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_draw() {
}
void TileMapEditorTilesPlugin::_tile_atlas_control_mouse_exited() {
- hovered_tile.source_id = -1;
+ hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_dragging_selection = false;
@@ -1634,7 +1620,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_draw() {
}
void TileMapEditorTilesPlugin::_tile_alternatives_control_mouse_exited() {
- hovered_tile.source_id = -1;
+ hovered_tile.source_id = TileSet::INVALID_SOURCE;
hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
tile_set_dragging_selection = false;
@@ -1856,19 +1842,6 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
_on_random_tile_checkbox_toggled(false);
- // Wide empty separation control.
- Control *h_empty_space = memnew(Control);
- h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
- toolbar->add_child(h_empty_space);
-
- // Grid toggle.
- toggle_grid_button = memnew(Button);
- toggle_grid_button->set_flat(true);
- toggle_grid_button->set_toggle_mode(true);
- toggle_grid_button->set_tooltip(TTR("Toggle grid visibility."));
- toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_grid_toggled));
- toolbar->add_child(toggle_grid_button);
-
// Default tool.
paint_tool_button->set_pressed(true);
_update_toolbar();
@@ -1898,8 +1871,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() {
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1));
sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_bottom_panel).unbind(1));
- sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
- sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
+ sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current));
+ sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list));
atlas_sources_split_container->add_child(sources_list);
// Tile atlas source.
@@ -2968,7 +2941,7 @@ void TileMapEditorTerrainsPlugin::_update_terrains_cache() {
}
TileMapCell empty_cell;
- empty_cell.source_id = -1;
+ empty_cell.source_id = TileSet::INVALID_SOURCE;
empty_cell.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
empty_cell.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
per_terrain_terrains_tile_patterns_tiles[i][empty_pattern].insert(empty_cell);
@@ -3190,6 +3163,9 @@ void TileMapEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
missing_tile_texture = get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"));
warning_pattern_texture = get_theme_icon(SNAME("WarningPattern"), SNAME("EditorIcons"));
+ advanced_menu_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons")));
+ toggle_grid_button->set_icon(get_theme_icon(SNAME("Grid"), SNAME("EditorIcons")));
+ toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
break;
case NOTIFICATION_INTERNAL_PROCESS:
if (is_visible_in_tree() && tileset_changed_needs_update) {
@@ -3199,6 +3175,44 @@ void TileMapEditor::_notification(int p_what) {
tileset_changed_needs_update = false;
}
break;
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED:
+ toggle_grid_button->set_pressed(EditorSettings::get_singleton()->get("editors/tiles_editor/display_grid"));
+ break;
+ }
+}
+
+void TileMapEditor::_on_grid_toggled(bool p_pressed) {
+ EditorSettings::get_singleton()->set("editors/tiles_editor/display_grid", p_pressed);
+}
+
+void TileMapEditor::_advanced_menu_button_id_pressed(int p_id) {
+ TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
+ if (!tile_map) {
+ return;
+ }
+
+ Ref<TileSet> tile_set = tile_map->get_tileset();
+ if (!tile_set.is_valid()) {
+ return;
+ }
+
+ if (p_id == 0) { // Replace Tile Proxies
+ undo_redo->create_action(TTR("Replace Tiles with Proxies"));
+ TypedArray<Vector2i> used_cells = tile_map->get_used_cells();
+ for (int i = 0; i < used_cells.size(); i++) {
+ Vector2i cell_coords = used_cells[i];
+ TileMapCell from = tile_map->get_cell(cell_coords);
+ Array to_array = tile_set->map_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ TileMapCell to;
+ to.source_id = to_array[0];
+ to.set_atlas_coords(to_array[1]);
+ to.alternative_tile = to_array[2];
+ if (from != to) {
+ undo_redo->add_do_method(tile_map, "set_cell", cell_coords, to.source_id, to.get_atlas_coords(), to.alternative_tile);
+ undo_redo->add_undo_method(tile_map, "set_cell", cell_coords, from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ }
+ }
+ undo_redo->commit_action();
}
}
@@ -3349,7 +3363,6 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
Vector2i tile_shape_size = tile_set->get_tile_size();
// Draw tiles with invalid IDs in the grid.
- float icon_ratio = MIN(missing_tile_texture->get_size().x / tile_set->get_tile_size().x, missing_tile_texture->get_size().y / tile_set->get_tile_size().y) / 3;
TypedArray<Vector2i> used_cells = tile_map->get_used_cells();
for (int i = 0; i < used_cells.size(); i++) {
Vector2i coords = used_cells[i];
@@ -3365,25 +3378,33 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
if (!source || !source->has_tile(tile_atlas_coords) || !source->has_alternative_tile(tile_atlas_coords, tile_alternative_tile)) {
// Generate a random color from the hashed values of the tiles.
- Array to_hash;
- to_hash.push_back(tile_source_id);
- to_hash.push_back(tile_atlas_coords);
- to_hash.push_back(tile_alternative_tile);
- uint32_t hash = RandomPCG(to_hash.hash()).rand();
-
- Color color;
- color = color.from_hsv(
- (float)((hash >> 24) & 0xFF) / 256.0,
- Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
- Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
- 0.8);
-
- // Draw the scaled tile.
- Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - Vector2(tile_shape_size) / 2, Vector2(tile_shape_size)));
- tile_set->draw_tile_shape(p_overlay, cell_region, color, true, warning_pattern_texture);
+ Array a = tile_set->map_tile_proxy(tile_source_id, tile_atlas_coords, tile_alternative_tile);
+ if (int(a[0]) == tile_source_id && Vector2i(a[1]) == tile_atlas_coords && int(a[2]) == tile_alternative_tile) {
+ // Only display the pattern if we have no proxy tile.
+ Array to_hash;
+ to_hash.push_back(tile_source_id);
+ to_hash.push_back(tile_atlas_coords);
+ to_hash.push_back(tile_alternative_tile);
+ uint32_t hash = RandomPCG(to_hash.hash()).rand();
+
+ Color color;
+ color = color.from_hsv(
+ (float)((hash >> 24) & 0xFF) / 256.0,
+ Math::lerp(0.5, 1.0, (float)((hash >> 16) & 0xFF) / 256.0),
+ Math::lerp(0.5, 1.0, (float)((hash >> 8) & 0xFF) / 256.0),
+ 0.8);
+
+ // Draw the scaled tile.
+ Rect2 cell_region = xform.xform(Rect2(tile_map->map_to_world(coords) - Vector2(tile_shape_size) / 2, Vector2(tile_shape_size)));
+ tile_set->draw_tile_shape(p_overlay, cell_region, color, true, warning_pattern_texture);
+ }
// Draw the warning icon.
- Rect2 rect = Rect2(xform.xform(tile_map->map_to_world(coords)) - (icon_ratio * missing_tile_texture->get_size() * xform.get_scale() / 2), icon_ratio * missing_tile_texture->get_size() * xform.get_scale());
+ int min_axis = missing_tile_texture->get_size().min_axis();
+ Vector2 icon_size;
+ icon_size[min_axis] = tile_set->get_tile_size()[min_axis] / 3;
+ icon_size[(min_axis + 1) % 2] = (icon_size[min_axis] * missing_tile_texture->get_size()[(min_axis + 1) % 2] / missing_tile_texture->get_size()[min_axis]);
+ Rect2 rect = Rect2(xform.xform(tile_map->map_to_world(coords)) - (icon_size * xform.get_scale() / 2), icon_size * xform.get_scale());
p_overlay->draw_texture_rect(missing_tile_texture, rect);
}
}
@@ -3503,6 +3524,26 @@ TileMapEditor::TileMapEditor() {
tilemap_toolbar->add_child(tile_map_editor_plugins[i]->get_toolbar());
}
+ // Wide empty separation control.
+ Control *h_empty_space = memnew(Control);
+ h_empty_space->set_h_size_flags(SIZE_EXPAND_FILL);
+ tilemap_toolbar->add_child(h_empty_space);
+
+ // Grid toggle.
+ toggle_grid_button = memnew(Button);
+ toggle_grid_button->set_flat(true);
+ toggle_grid_button->set_toggle_mode(true);
+ toggle_grid_button->set_tooltip(TTR("Toggle grid visibility."));
+ toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditor::_on_grid_toggled));
+ tilemap_toolbar->add_child(toggle_grid_button);
+
+ // Advanced settings menu button.
+ advanced_menu_button = memnew(MenuButton);
+ advanced_menu_button->set_flat(true);
+ advanced_menu_button->get_popup()->add_item(TTR("Automatically Replace Tiles with Proxies"));
+ advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileMapEditor::_advanced_menu_button_id_pressed));
+ tilemap_toolbar->add_child(advanced_menu_button);
+
missing_tileset_label = memnew(Label);
missing_tileset_label->set_text(TTR("The edited TileMap node has no TileSet resource."));
missing_tileset_label->set_h_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index a6f4ec3021..236774a06b 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -82,9 +82,6 @@ private:
void _on_random_tile_checkbox_toggled(bool p_pressed);
void _on_scattering_spinbox_changed(double p_value);
- Button *toggle_grid_button;
- void _on_grid_toggled(bool p_pressed);
-
void _update_toolbar();
///// Tilemap editing. /////
@@ -300,6 +297,7 @@ class TileMapEditor : public VBoxContainer {
GDCLASS(TileMapEditor, VBoxContainer);
private:
+ UndoRedo *undo_redo = EditorNode::get_undo_redo();
bool tileset_changed_needs_update = false;
ObjectID tile_map_id;
@@ -309,6 +307,12 @@ private:
// Toolbar.
HBoxContainer *tilemap_toolbar;
+ Button *toggle_grid_button;
+ void _on_grid_toggled(bool p_pressed);
+
+ MenuButton *advanced_menu_button;
+ void _advanced_menu_button_id_pressed(int p_id);
+
// Bottom panel
Label *missing_tileset_label;
Tabs *tabs;
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
new file mode 100644
index 0000000000..e5e7efa531
--- /dev/null
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
@@ -0,0 +1,476 @@
+/*************************************************************************/
+/* tile_proxies_manager_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 "tile_proxies_manager_dialog.h"
+
+#include "editor/editor_scale.h"
+
+void TileProxiesManagerDialog::_right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list) {
+ ItemList *item_list = Object::cast_to<ItemList>(p_item_list);
+ popup_menu->set_size(Vector2(1, 1));
+ popup_menu->set_position(get_position() + item_list->get_global_mouse_position());
+ popup_menu->popup();
+}
+
+void TileProxiesManagerDialog::_menu_id_pressed(int p_id) {
+ if (p_id == 0) {
+ // Delete.
+ _delete_selected_bindings();
+ }
+}
+
+void TileProxiesManagerDialog::_delete_selected_bindings() {
+ undo_redo->create_action("Remove Tile Proxies");
+
+ Vector<int> source_level_selected = source_level_list->get_selected_items();
+ for (int i = 0; i < source_level_selected.size(); i++) {
+ int key = source_level_list->get_item_metadata(source_level_selected[i]);
+ int val = tile_set->get_source_level_tile_proxy(key);
+ undo_redo->add_do_method(*tile_set, "remove_source_level_tile_proxy", key);
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", key, val);
+ }
+
+ Vector<int> coords_level_selected = coords_level_list->get_selected_items();
+ for (int i = 0; i < coords_level_selected.size(); i++) {
+ Array key = coords_level_list->get_item_metadata(coords_level_selected[i]);
+ Array val = tile_set->get_coords_level_tile_proxy(key[0], key[1]);
+ undo_redo->add_do_method(*tile_set, "remove_coords_level_tile_proxy", key[0], key[1]);
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", key[0], key[1], val[0], val[1]);
+ }
+
+ Vector<int> alternative_level_selected = alternative_level_list->get_selected_items();
+ for (int i = 0; i < alternative_level_selected.size(); i++) {
+ Array key = alternative_level_list->get_item_metadata(alternative_level_selected[i]);
+ Array val = tile_set->get_coords_level_tile_proxy(key[0], key[1]);
+ undo_redo->add_do_method(*tile_set, "remove_alternative_level_tile_proxy", key[0], key[1], key[2]);
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", key[0], key[1], key[2], val[0], val[1], val[2]);
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+
+ commited_actions_count += 1;
+}
+
+void TileProxiesManagerDialog::_update_lists() {
+ source_level_list->clear();
+ coords_level_list->clear();
+ alternative_level_list->clear();
+
+ Array proxies = tile_set->get_source_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ String text = vformat("%s", proxy[0]).rpad(5) + "-> " + vformat("%s", proxy[1]);
+ int id = source_level_list->add_item(text);
+ source_level_list->set_item_metadata(id, proxy[0]);
+ }
+
+ proxies = tile_set->get_coords_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ String text = vformat("%s, %s", proxy[0], proxy[1]).rpad(17) + "-> " + vformat("%s, %s", proxy[2], proxy[3]);
+ int id = coords_level_list->add_item(text);
+ coords_level_list->set_item_metadata(id, proxy.slice(0, 2));
+ }
+
+ proxies = tile_set->get_alternative_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ String text = vformat("%s, %s, %s", proxy[0], proxy[1], proxy[2]).rpad(24) + "-> " + vformat("%s, %s, %s", proxy[3], proxy[4], proxy[5]);
+ int id = alternative_level_list->add_item(text);
+ alternative_level_list->set_item_metadata(id, proxy.slice(0, 3));
+ }
+}
+
+void TileProxiesManagerDialog::_update_enabled_property_editors() {
+ if (from.source_id == TileSet::INVALID_SOURCE) {
+ from.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ to.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS);
+ from.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ to.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ coords_from_property_editor->hide();
+ coords_to_property_editor->hide();
+ alternative_from_property_editor->hide();
+ alternative_to_property_editor->hide();
+ } else if (from.get_atlas_coords().x == -1 || from.get_atlas_coords().y == -1) {
+ from.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ to.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
+ coords_from_property_editor->show();
+ coords_to_property_editor->show();
+ alternative_from_property_editor->hide();
+ alternative_to_property_editor->hide();
+ } else {
+ coords_from_property_editor->show();
+ coords_to_property_editor->show();
+ alternative_from_property_editor->show();
+ alternative_to_property_editor->show();
+ }
+
+ source_from_property_editor->update_property();
+ source_to_property_editor->update_property();
+ coords_from_property_editor->update_property();
+ coords_to_property_editor->update_property();
+ alternative_from_property_editor->update_property();
+ alternative_to_property_editor->update_property();
+}
+
+void TileProxiesManagerDialog::_property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing) {
+ _set(p_path, p_value);
+}
+
+void TileProxiesManagerDialog::_add_button_pressed() {
+ if (from.source_id != TileSet::INVALID_SOURCE && to.source_id != TileSet::INVALID_SOURCE) {
+ Vector2i from_coords = from.get_atlas_coords();
+ Vector2i to_coords = to.get_atlas_coords();
+ if (from_coords.x >= 0 && from_coords.y >= 0 && to_coords.x >= 0 && to_coords.y >= 0) {
+ if (from.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE && to.alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE) {
+ undo_redo->create_action("Create Alternative-level Tile Proxy");
+ undo_redo->add_do_method(*tile_set, "set_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile, to.source_id, to.get_atlas_coords(), to.alternative_tile);
+ if (tile_set->has_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile)) {
+ Array a = tile_set->get_alternative_level_tile_proxy(from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", to.source_id, to.get_atlas_coords(), to.alternative_tile, a[0], a[1], a[2]);
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_alternative_level_tile_proxy", from.source_id, from.get_atlas_coords(), from.alternative_tile);
+ }
+ } else {
+ undo_redo->create_action("Create Coords-level Tile Proxy");
+ undo_redo->add_do_method(*tile_set, "set_coords_level_tile_proxy", from.source_id, from.get_atlas_coords(), to.source_id, to.get_atlas_coords());
+ if (tile_set->has_coords_level_tile_proxy(from.source_id, from.get_atlas_coords())) {
+ Array a = tile_set->get_coords_level_tile_proxy(from.source_id, from.get_atlas_coords());
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", to.source_id, to.get_atlas_coords(), a[0], a[1]);
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_coords_level_tile_proxy", from.source_id, from.get_atlas_coords());
+ }
+ }
+ } else {
+ undo_redo->create_action("Create source-level Tile Proxy");
+ undo_redo->add_do_method(*tile_set, "set_source_level_tile_proxy", from.source_id, to.source_id);
+ if (tile_set->has_source_level_tile_proxy(from.source_id)) {
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", to.source_id, tile_set->get_source_level_tile_proxy(from.source_id));
+ } else {
+ undo_redo->add_undo_method(*tile_set, "remove_source_level_tile_proxy", from.source_id);
+ }
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+ commited_actions_count++;
+ }
+}
+
+void TileProxiesManagerDialog::_clear_invalid_button_pressed() {
+ undo_redo->create_action("Delete All Invalid Tile Proxies");
+
+ undo_redo->add_do_method(*tile_set, "cleanup_invalid_tile_proxies");
+
+ Array proxies = tile_set->get_source_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", proxy[0], proxy[1]);
+ }
+
+ proxies = tile_set->get_coords_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3]);
+ }
+
+ proxies = tile_set->get_alternative_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3], proxy[4], proxy[5]);
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+}
+
+void TileProxiesManagerDialog::_clear_all_button_pressed() {
+ undo_redo->create_action("Delete All Tile Proxies");
+
+ undo_redo->add_do_method(*tile_set, "clear_tile_proxies");
+
+ Array proxies = tile_set->get_source_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_source_level_tile_proxy", proxy[0], proxy[1]);
+ }
+
+ proxies = tile_set->get_coords_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_coords_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3]);
+ }
+
+ proxies = tile_set->get_alternative_level_tile_proxies();
+ for (int i = 0; i < proxies.size(); i++) {
+ Array proxy = proxies[i];
+ undo_redo->add_undo_method(*tile_set, "set_alternative_level_tile_proxy", proxy[0], proxy[1], proxy[2], proxy[3], proxy[4], proxy[5]);
+ }
+ undo_redo->add_do_method(this, "_update_lists");
+ undo_redo->add_undo_method(this, "_update_lists");
+ undo_redo->commit_action();
+}
+
+bool TileProxiesManagerDialog::_set(const StringName &p_name, const Variant &p_value) {
+ if (p_name == "from_source") {
+ from.source_id = MAX(int(p_value), -1);
+ } else if (p_name == "from_coords") {
+ from.set_atlas_coords(Vector2i(p_value).max(Vector2i(-1, -1)));
+ } else if (p_name == "from_alternative") {
+ from.alternative_tile = MAX(int(p_value), -1);
+ } else if (p_name == "to_source") {
+ to.source_id = MAX(int(p_value), 0);
+ } else if (p_name == "to_coords") {
+ to.set_atlas_coords(Vector2i(p_value).max(Vector2i(0, 0)));
+ } else if (p_name == "to_alternative") {
+ to.alternative_tile = MAX(int(p_value), 0);
+ } else {
+ return false;
+ }
+ _update_enabled_property_editors();
+ return true;
+}
+
+bool TileProxiesManagerDialog::_get(const StringName &p_name, Variant &r_ret) const {
+ if (p_name == "from_source") {
+ r_ret = from.source_id;
+ } else if (p_name == "from_coords") {
+ r_ret = from.get_atlas_coords();
+ } else if (p_name == "from_alternative") {
+ r_ret = from.alternative_tile;
+ } else if (p_name == "to_source") {
+ r_ret = to.source_id;
+ } else if (p_name == "to_coords") {
+ r_ret = to.get_atlas_coords();
+ } else if (p_name == "to_alternative") {
+ r_ret = to.alternative_tile;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void TileProxiesManagerDialog::_unhandled_key_input(Ref<InputEvent> p_event) {
+ ERR_FAIL_COND(p_event.is_null());
+
+ if (p_event->is_pressed() && !p_event->is_echo() && (Object::cast_to<InputEventKey>(p_event.ptr()) || Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventAction>(*p_event))) {
+ if (!is_inside_tree() || !is_visible()) {
+ return;
+ }
+
+ if (popup_menu->activate_item_by_event(p_event, false)) {
+ set_input_as_handled();
+ }
+ }
+}
+
+void TileProxiesManagerDialog::cancel_pressed() {
+ for (int i = 0; i < commited_actions_count; i++) {
+ undo_redo->undo();
+ }
+ commited_actions_count = 0;
+}
+
+void TileProxiesManagerDialog::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_update_lists"), &TileProxiesManagerDialog::_update_lists);
+ ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &TileProxiesManagerDialog::_unhandled_key_input);
+}
+
+void TileProxiesManagerDialog::update_tile_set(Ref<TileSet> p_tile_set) {
+ ERR_FAIL_COND(!p_tile_set.is_valid());
+ tile_set = p_tile_set;
+ commited_actions_count = 0;
+ _update_lists();
+}
+
+TileProxiesManagerDialog::TileProxiesManagerDialog() {
+ // Tile proxy management window.
+ set_title(TTR("Tile Proxies Management"));
+ set_process_unhandled_key_input(true);
+
+ to.source_id = 0;
+ to.set_atlas_coords(Vector2i());
+ to.alternative_tile = 0;
+
+ VBoxContainer *vbox_container = memnew(VBoxContainer);
+ vbox_container->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vbox_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(vbox_container);
+
+ Label *source_level_label = memnew(Label);
+ source_level_label->set_text(TTR("Source-level proxies"));
+ vbox_container->add_child(source_level_label);
+
+ source_level_list = memnew(ItemList);
+ source_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ source_level_list->set_select_mode(ItemList::SELECT_MULTI);
+ source_level_list->set_allow_rmb_select(true);
+ source_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(source_level_list));
+ vbox_container->add_child(source_level_list);
+
+ Label *coords_level_label = memnew(Label);
+ coords_level_label->set_text(TTR("Coords-level proxies"));
+ vbox_container->add_child(coords_level_label);
+
+ coords_level_list = memnew(ItemList);
+ coords_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ coords_level_list->set_select_mode(ItemList::SELECT_MULTI);
+ coords_level_list->set_allow_rmb_select(true);
+ coords_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(coords_level_list));
+ vbox_container->add_child(coords_level_list);
+
+ Label *alternative_level_label = memnew(Label);
+ alternative_level_label->set_text(TTR("Alternative-level proxies"));
+ vbox_container->add_child(alternative_level_label);
+
+ alternative_level_list = memnew(ItemList);
+ alternative_level_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ alternative_level_list->set_select_mode(ItemList::SELECT_MULTI);
+ alternative_level_list->set_allow_rmb_select(true);
+ alternative_level_list->connect("item_rmb_selected", callable_mp(this, &TileProxiesManagerDialog::_right_clicked), varray(alternative_level_list));
+ vbox_container->add_child(alternative_level_list);
+
+ popup_menu = memnew(PopupMenu);
+ popup_menu->add_shortcut(ED_GET_SHORTCUT("ui_text_delete"));
+ popup_menu->connect("id_pressed", callable_mp(this, &TileProxiesManagerDialog::_menu_id_pressed));
+ add_child(popup_menu);
+
+ // Add proxy panel.
+ HSeparator *h_separator = memnew(HSeparator);
+ vbox_container->add_child(h_separator);
+
+ Label *add_label = memnew(Label);
+ add_label->set_text(TTR("Add a new tile proxy:"));
+ vbox_container->add_child(add_label);
+
+ HBoxContainer *hboxcontainer = memnew(HBoxContainer);
+ vbox_container->add_child(hboxcontainer);
+
+ // From
+ VBoxContainer *vboxcontainer_from = memnew(VBoxContainer);
+ vboxcontainer_from->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hboxcontainer->add_child(vboxcontainer_from);
+
+ source_from_property_editor = memnew(EditorPropertyInteger);
+ source_from_property_editor->set_label(TTR("From Source"));
+ source_from_property_editor->set_object_and_property(this, "from_source");
+ source_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ source_from_property_editor->set_selectable(false);
+ source_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ source_from_property_editor->setup(-1, 99999, 1, true, false);
+ vboxcontainer_from->add_child(source_from_property_editor);
+
+ coords_from_property_editor = memnew(EditorPropertyVector2i);
+ coords_from_property_editor->set_label(TTR("From Coords"));
+ coords_from_property_editor->set_object_and_property(this, "from_coords");
+ coords_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ coords_from_property_editor->set_selectable(false);
+ coords_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ coords_from_property_editor->setup(-1, 99999, true);
+ coords_from_property_editor->hide();
+ vboxcontainer_from->add_child(coords_from_property_editor);
+
+ alternative_from_property_editor = memnew(EditorPropertyInteger);
+ alternative_from_property_editor->set_label(TTR("From Alternative"));
+ alternative_from_property_editor->set_object_and_property(this, "from_alternative");
+ alternative_from_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ alternative_from_property_editor->set_selectable(false);
+ alternative_from_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ alternative_from_property_editor->setup(-1, 99999, 1, true, false);
+ alternative_from_property_editor->hide();
+ vboxcontainer_from->add_child(alternative_from_property_editor);
+
+ // To
+ VBoxContainer *vboxcontainer_to = memnew(VBoxContainer);
+ vboxcontainer_to->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hboxcontainer->add_child(vboxcontainer_to);
+
+ source_to_property_editor = memnew(EditorPropertyInteger);
+ source_to_property_editor->set_label(TTR("To Source"));
+ source_to_property_editor->set_object_and_property(this, "to_source");
+ source_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ source_to_property_editor->set_selectable(false);
+ source_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ source_to_property_editor->setup(-1, 99999, 1, true, false);
+ vboxcontainer_to->add_child(source_to_property_editor);
+
+ coords_to_property_editor = memnew(EditorPropertyVector2i);
+ coords_to_property_editor->set_label(TTR("To Coords"));
+ coords_to_property_editor->set_object_and_property(this, "to_coords");
+ coords_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ coords_to_property_editor->set_selectable(false);
+ coords_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ coords_to_property_editor->setup(-1, 99999, true);
+ coords_to_property_editor->hide();
+ vboxcontainer_to->add_child(coords_to_property_editor);
+
+ alternative_to_property_editor = memnew(EditorPropertyInteger);
+ alternative_to_property_editor->set_label(TTR("To Alternative"));
+ alternative_to_property_editor->set_object_and_property(this, "to_alternative");
+ alternative_to_property_editor->connect("property_changed", callable_mp(this, &TileProxiesManagerDialog::_property_changed));
+ alternative_to_property_editor->set_selectable(false);
+ alternative_to_property_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ alternative_to_property_editor->setup(-1, 99999, 1, true, false);
+ alternative_to_property_editor->hide();
+ vboxcontainer_to->add_child(alternative_to_property_editor);
+
+ Button *add_button = memnew(Button);
+ add_button->set_text(TTR("Add"));
+ add_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
+ add_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_add_button_pressed));
+ vbox_container->add_child(add_button);
+
+ h_separator = memnew(HSeparator);
+ vbox_container->add_child(h_separator);
+
+ // Generic actions.
+ Label *generic_actions_label = memnew(Label);
+ generic_actions_label->set_text(TTR("Global actions:"));
+ vbox_container->add_child(generic_actions_label);
+
+ hboxcontainer = memnew(HBoxContainer);
+ vbox_container->add_child(hboxcontainer);
+
+ Button *clear_invalid_button = memnew(Button);
+ clear_invalid_button->set_text(TTR("Clear Invalid"));
+ clear_invalid_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
+ clear_invalid_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_clear_invalid_button_pressed));
+ hboxcontainer->add_child(clear_invalid_button);
+
+ Button *clear_all_button = memnew(Button);
+ clear_all_button->set_text(TTR("Clear All"));
+ clear_all_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
+ clear_all_button->connect("pressed", callable_mp(this, &TileProxiesManagerDialog::_clear_all_button_pressed));
+ hboxcontainer->add_child(clear_all_button);
+
+ h_separator = memnew(HSeparator);
+ vbox_container->add_child(h_separator);
+}
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.h b/editor/plugins/tiles/tile_proxies_manager_dialog.h
new file mode 100644
index 0000000000..f6898e960b
--- /dev/null
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.h
@@ -0,0 +1,90 @@
+/*************************************************************************/
+/* tile_proxies_manager_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 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 TILE_PROXIES_MANAGER_DIALOG_H
+#define TILE_PROXIES_MANAGER_DIALOG_H
+
+#include "editor/editor_node.h"
+#include "editor/editor_properties.h"
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/item_list.h"
+#include "scene/resources/tile_set.h"
+
+class TileProxiesManagerDialog : public ConfirmationDialog {
+ GDCLASS(TileProxiesManagerDialog, ConfirmationDialog);
+
+private:
+ int commited_actions_count = 0;
+ Ref<TileSet> tile_set;
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ TileMapCell from;
+ TileMapCell to;
+
+ // GUI
+ ItemList *source_level_list;
+ ItemList *coords_level_list;
+ ItemList *alternative_level_list;
+
+ EditorPropertyInteger *source_from_property_editor;
+ EditorPropertyVector2i *coords_from_property_editor;
+ EditorPropertyInteger *alternative_from_property_editor;
+ EditorPropertyInteger *source_to_property_editor;
+ EditorPropertyVector2i *coords_to_property_editor;
+ EditorPropertyInteger *alternative_to_property_editor;
+
+ PopupMenu *popup_menu;
+ void _right_clicked(int p_item, Vector2 p_local_mouse_pos, Object *p_item_list);
+ void _menu_id_pressed(int p_id);
+ void _delete_selected_bindings();
+ void _update_lists();
+ void _update_enabled_property_editors();
+ void _property_changed(const String &p_path, const Variant &p_value, const String &p_name, bool p_changing);
+ void _add_button_pressed();
+
+ void _clear_invalid_button_pressed();
+ void _clear_all_button_pressed();
+
+protected:
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _unhandled_key_input(Ref<InputEvent> p_event);
+ virtual void cancel_pressed() override;
+ static void _bind_methods();
+
+public:
+ void update_tile_set(Ref<TileSet> p_tile_set);
+
+ TileProxiesManagerDialog();
+};
+
+#endif // TILE_PROXIES_MANAGER_DIALOG_H
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index 6b617cf4d8..432f48fa85 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -303,9 +303,9 @@ void TileSetAtlasSourceEditor::AtlasTileProxyObject::_get_property_list(List<Pro
}
// Add only properties that are common to all tiles.
- for (List<PLData *>::Element *E = data_list.front(); E; E = E->next()) {
- if (E->get()->uses == tiles.size()) {
- p_list->push_back(E->get()->property_info);
+ for (const PLData *E : data_list) {
+ if (E->uses == tiles.size()) {
+ p_list->push_back(E->property_info);
}
}
}
@@ -745,7 +745,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() {
button->add_theme_style_override("hover", memnew(StyleBoxEmpty));
button->add_theme_style_override("focus", memnew(StyleBoxEmpty));
button->add_theme_style_override("pressed", memnew(StyleBoxEmpty));
- button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, -1));
+ button->connect("pressed", callable_mp(tile_set_atlas_source, &TileSetAtlasSource::create_alternative_tile), varray(tile_id, TileSetSource::INVALID_TILE_ALTERNATIVE));
button->set_rect(Rect2(Vector2(pos.x, pos.y + (y_increment - texture_region_base_size.y) / 2.0), Vector2(texture_region_base_size_min, texture_region_base_size_min)));
button->set_expand_icon(true);
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index dbb0756a16..501416c340 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -65,7 +65,7 @@ private:
private:
Ref<TileSet> tile_set;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
- int source_id = -1;
+ int source_id = TileSet::INVALID_SOURCE;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
@@ -108,7 +108,7 @@ private:
Ref<TileSet> tile_set;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
- int tile_set_atlas_source_id = -1;
+ int tile_set_atlas_source_id = TileSet::INVALID_SOURCE;
UndoRedo *undo_redo = EditorNode::get_undo_redo();
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index 76ce6f0065..ba98a7d6b3 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -50,7 +50,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C
if (p_from == sources_list) {
// Handle dropping a texture in the list of atlas resources.
- int source_id = -1;
+ int source_id = TileSet::INVALID_SOURCE;
int added = 0;
Dictionary d = p_data;
Vector<String> files = d["files"];
@@ -77,7 +77,7 @@ void TileSetEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, C
}
// Update the selected source (thus triggering an update).
- _update_atlas_sources_list(source_id);
+ _update_sources_list(source_id);
}
}
@@ -114,11 +114,11 @@ bool TileSetEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_dat
return false;
}
-void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
+void TileSetEditor::_update_sources_list(int force_selected_id) {
ERR_FAIL_COND(!tile_set.is_valid());
// Get the previously selected id.
- int old_selected = -1;
+ int old_selected = TileSet::INVALID_SOURCE;
if (sources_list->get_current() >= 0) {
int source_id = sources_list->get_item_metadata(sources_list->get_current());
if (tile_set->has_source(source_id)) {
@@ -126,7 +126,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
}
}
- int to_select = -1;
+ int to_select = TileSet::INVALID_SOURCE;
if (force_selected_id >= 0) {
to_select = force_selected_id;
} else if (old_selected >= 0) {
@@ -200,7 +200,7 @@ void TileSetEditor::_update_atlas_sources_list(int force_selected_id) {
_source_selected(sources_list->get_current());
// Synchronize the lists.
- TilesEditor::get_singleton()->set_atlas_sources_lists_current(sources_list->get_current());
+ TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current());
}
void TileSetEditor::_source_selected(int p_source_index) {
@@ -235,6 +235,23 @@ void TileSetEditor::_source_selected(int p_source_index) {
}
}
+void TileSetEditor::_source_delete_pressed() {
+ ERR_FAIL_COND(!tile_set.is_valid());
+
+ // Update the selected source.
+ int to_delete = sources_list->get_item_metadata(sources_list->get_current());
+
+ Ref<TileSetSource> source = tile_set->get_source(to_delete);
+
+ // Remove the source.
+ undo_redo->create_action(TTR("Remove source"));
+ undo_redo->add_do_method(*tile_set, "remove_source", to_delete);
+ undo_redo->add_undo_method(*tile_set, "add_source", source, to_delete);
+ undo_redo->commit_action();
+
+ _update_sources_list();
+}
+
void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
ERR_FAIL_COND(!tile_set.is_valid());
@@ -251,7 +268,7 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
undo_redo->commit_action();
- _update_atlas_sources_list(source_id);
+ _update_sources_list(source_id);
} break;
case 1: {
int source_id = tile_set->get_next_source_id();
@@ -264,28 +281,26 @@ void TileSetEditor::_source_add_id_pressed(int p_id_pressed) {
undo_redo->add_undo_method(*tile_set, "remove_source", source_id);
undo_redo->commit_action();
- _update_atlas_sources_list(source_id);
+ _update_sources_list(source_id);
} break;
default:
ERR_FAIL();
}
}
-void TileSetEditor::_source_delete_pressed() {
+void TileSetEditor::_sources_advanced_menu_id_pressed(int p_id_pressed) {
ERR_FAIL_COND(!tile_set.is_valid());
- // Update the selected source.
- int to_delete = sources_list->get_item_metadata(sources_list->get_current());
-
- Ref<TileSetSource> source = tile_set->get_source(to_delete);
-
- // Remove the source.
- undo_redo->create_action(TTR("Remove source"));
- undo_redo->add_do_method(*tile_set, "remove_source", to_delete);
- undo_redo->add_undo_method(*tile_set, "add_source", source, to_delete);
- undo_redo->commit_action();
-
- _update_atlas_sources_list();
+ switch (p_id_pressed) {
+ case 0: {
+ atlas_merging_dialog->update_tile_set(tile_set);
+ atlas_merging_dialog->popup_centered_ratio(0.5);
+ } break;
+ case 1: {
+ tile_proxies_manager_dialog->update_tile_set(tile_set);
+ tile_proxies_manager_dialog->popup_centered_ratio(0.5);
+ } break;
+ }
}
void TileSetEditor::_notification(int p_what) {
@@ -294,6 +309,7 @@ void TileSetEditor::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED:
sources_delete_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
sources_add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ sources_advanced_menu_button->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons")));
missing_texture_texture = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"));
break;
case NOTIFICATION_INTERNAL_PROCESS:
@@ -301,7 +317,7 @@ void TileSetEditor::_notification(int p_what) {
if (tile_set.is_valid()) {
tile_set->set_edited(true);
}
- _update_atlas_sources_list();
+ _update_sources_list();
tile_set_changed_needs_update = false;
}
break;
@@ -414,7 +430,7 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) {
// Add the listener again.
if (tile_set.is_valid()) {
tile_set->connect("changed", callable_mp(this, &TileSetEditor::_tile_set_changed));
- _update_atlas_sources_list();
+ _update_sources_list();
}
tile_set_atlas_source_editor->hide();
@@ -447,8 +463,8 @@ TileSetEditor::TileSetEditor() {
sources_list->set_h_size_flags(SIZE_EXPAND_FILL);
sources_list->set_v_size_flags(SIZE_EXPAND_FILL);
sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected));
- sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_sources_lists_current));
- sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_atlas_sources_list), varray(sources_list));
+ sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current));
+ sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list));
sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST);
sources_list->set_drag_forwarding(this);
split_container_left_side->add_child(sources_list);
@@ -470,6 +486,19 @@ TileSetEditor::TileSetEditor() {
sources_add_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_source_add_id_pressed));
sources_bottom_actions->add_child(sources_add_button);
+ sources_advanced_menu_button = memnew(MenuButton);
+ sources_advanced_menu_button->set_flat(true);
+ sources_advanced_menu_button->get_popup()->add_item(TTR("Open Atlas Merging Tool"));
+ sources_advanced_menu_button->get_popup()->add_item(TTR("Manage Tile Proxies"));
+ sources_advanced_menu_button->get_popup()->connect("id_pressed", callable_mp(this, &TileSetEditor::_sources_advanced_menu_id_pressed));
+ sources_bottom_actions->add_child(sources_advanced_menu_button);
+
+ atlas_merging_dialog = memnew(AtlasMergingDialog);
+ add_child(atlas_merging_dialog);
+
+ tile_proxies_manager_dialog = memnew(TileProxiesManagerDialog);
+ add_child(tile_proxies_manager_dialog);
+
// Right side container.
VBoxContainer *split_container_right_side = memnew(VBoxContainer);
split_container_right_side->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -489,7 +518,7 @@ TileSetEditor::TileSetEditor() {
tile_set_atlas_source_editor = memnew(TileSetAtlasSourceEditor);
tile_set_atlas_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
tile_set_atlas_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
+ tile_set_atlas_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_sources_list));
split_container_right_side->add_child(tile_set_atlas_source_editor);
tile_set_atlas_source_editor->hide();
@@ -497,7 +526,7 @@ TileSetEditor::TileSetEditor() {
tile_set_scenes_collection_source_editor = memnew(TileSetScenesCollectionSourceEditor);
tile_set_scenes_collection_source_editor->set_h_size_flags(SIZE_EXPAND_FILL);
tile_set_scenes_collection_source_editor->set_v_size_flags(SIZE_EXPAND_FILL);
- tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_atlas_sources_list));
+ tile_set_scenes_collection_source_editor->connect("source_id_changed", callable_mp(this, &TileSetEditor::_update_sources_list));
split_container_right_side->add_child(tile_set_scenes_collection_source_editor);
tile_set_scenes_collection_source_editor->hide();
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index 9e50aca62f..970e3fabb6 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -31,8 +31,10 @@
#ifndef TILE_SET_EDITOR_H
#define TILE_SET_EDITOR_H
+#include "atlas_merging_dialog.h"
#include "scene/gui/box_container.h"
#include "scene/resources/tile_set.h"
+#include "tile_proxies_manager_dialog.h"
#include "tile_set_atlas_source_editor.h"
#include "tile_set_scenes_collection_source_editor.h"
@@ -51,16 +53,21 @@ private:
UndoRedo *undo_redo = EditorNode::get_undo_redo();
- void _update_atlas_sources_list(int force_selected_id = -1);
+ void _update_sources_list(int force_selected_id = -1);
- // -- Sources management --
+ // Sources management.
Button *sources_delete_button;
MenuButton *sources_add_button;
+ MenuButton *sources_advanced_menu_button;
ItemList *sources_list;
Ref<Texture2D> missing_texture_texture;
void _source_selected(int p_source_index);
- void _source_add_id_pressed(int p_id_pressed);
void _source_delete_pressed();
+ void _source_add_id_pressed(int p_id_pressed);
+ void _sources_advanced_menu_id_pressed(int p_id_pressed);
+
+ AtlasMergingDialog *atlas_merging_dialog;
+ TileProxiesManagerDialog *tile_proxies_manager_dialog;
void _tile_set_changed();
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index 339efc7b99..79b869b511 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -118,11 +118,11 @@ void TilesEditor::_update_editors() {
CanvasItemEditor::get_singleton()->update_viewport();
}
-void TilesEditor::set_atlas_sources_lists_current(int p_current) {
+void TilesEditor::set_sources_lists_current(int p_current) {
atlas_sources_lists_current = p_current;
}
-void TilesEditor::synchronize_atlas_sources_list(Object *p_current) {
+void TilesEditor::synchronize_sources_list(Object *p_current) {
ItemList *item_list = Object::cast_to<ItemList>(p_current);
ERR_FAIL_COND(!item_list);
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index 6cc6f51598..f976d68938 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -76,8 +76,8 @@ public:
void forward_canvas_draw_over_viewport(Control *p_overlay) { tilemap_editor->forward_canvas_draw_over_viewport(p_overlay); }
// To synchronize the atlas sources lists.
- void set_atlas_sources_lists_current(int p_current);
- void synchronize_atlas_sources_list(Object *p_current);
+ void set_sources_lists_current(int p_current);
+ void synchronize_sources_list(Object *p_current);
void set_atlas_view_transform(float p_zoom, Vector2 p_scroll);
void synchronize_atlas_view(Object *p_current);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index f49279aa33..46818afe45 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -666,8 +666,8 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
if (valid_left) {
name_left = vsnode->get_input_port_name(i);
port_left = vsnode->get_input_port_type(i);
- for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
- if (E->get().to_node == p_id && E->get().to_port == j) {
+ for (const VisualShader::Connection &E : connections) {
+ if (E.to_node == p_id && E.to_port == j) {
port_left_used = true;
}
}
@@ -899,11 +899,11 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
expression_box->set_syntax_highlighter(expression_syntax_highlighter);
expression_box->add_theme_color_override("background_color", background_color);
- for (List<String>::Element *E = VisualShaderEditor::get_singleton()->keyword_list.front(); E; E = E->next()) {
- if (ShaderLanguage::is_control_flow_keyword(E->get())) {
- expression_syntax_highlighter->add_keyword_color(E->get(), control_flow_keyword_color);
+ for (const String &E : VisualShaderEditor::get_singleton()->keyword_list) {
+ if (ShaderLanguage::is_control_flow_keyword(E)) {
+ expression_syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
} else {
- expression_syntax_highlighter->add_keyword_color(E->get(), keyword_color);
+ expression_syntax_highlighter->add_keyword_color(E, keyword_color);
}
}
@@ -961,7 +961,7 @@ void VisualShaderGraphPlugin::connect_nodes(VisualShader::Type p_type, int p_fro
void VisualShaderGraphPlugin::disconnect_nodes(VisualShader::Type p_type, int p_from_node, int p_from_port, int p_to_node, int p_to_port) {
if (visual_shader->get_shader_type() == p_type) {
VisualShaderEditor::get_singleton()->graph->disconnect_node(itos(p_from_node), p_from_port, itos(p_to_node), p_to_port);
- for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
+ for (const List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
connections.erase(E);
break;
@@ -1470,11 +1470,11 @@ void VisualShaderEditor::_update_graph() {
graph_plugin->make_dirty(false);
- for (List<VisualShader::Connection>::Element *E = connections.front(); E; E = E->next()) {
- int from = E->get().from_node;
- int from_idx = E->get().from_port;
- int to = E->get().to_node;
- int to_idx = E->get().to_port;
+ for (const VisualShader::Connection &E : connections) {
+ int from = E.from_node;
+ int from_idx = E.from_port;
+ int to = E.to_node;
+ int to_idx = E.to_port;
graph->connect_node(itos(from), from_idx, itos(to), to_idx);
}
@@ -1634,11 +1634,11 @@ void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expa
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- int from_node = E->get().from_node;
- int from_port = E->get().from_port;
- int to_node = E->get().to_node;
- int to_port = E->get().to_port;
+ for (const VisualShader::Connection &E : conns) {
+ int from_node = E.from_node;
+ int from_port = E.from_port;
+ int to_node = E.to_node;
+ int to_port = E.to_port;
if (from_node == p_node) {
if (p_expand) {
@@ -1708,11 +1708,11 @@ void VisualShaderEditor::_remove_input_port(int p_node, int p_port) {
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- int from_node = E->get().from_node;
- int from_port = E->get().from_port;
- int to_node = E->get().to_node;
- int to_port = E->get().to_port;
+ for (const VisualShader::Connection &E : conns) {
+ int from_node = E.from_node;
+ int from_port = E.from_port;
+ int to_node = E.to_node;
+ int to_port = E.to_port;
if (to_node == p_node) {
if (to_port == p_port) {
@@ -1757,11 +1757,11 @@ void VisualShaderEditor::_remove_output_port(int p_node, int p_port) {
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- int from_node = E->get().from_node;
- int from_port = E->get().from_port;
- int to_node = E->get().to_node;
- int to_port = E->get().to_port;
+ for (const VisualShader::Connection &E : conns) {
+ int from_node = E.from_node;
+ int from_port = E.from_port;
+ int to_node = E.to_node;
+ int to_port = E.to_port;
if (from_node == p_node) {
if (from_port == p_port) {
@@ -2518,11 +2518,11 @@ void VisualShaderEditor::_nodes_dragged() {
undo_redo->create_action(TTR("Node(s) Moved"));
- for (List<DragOp>::Element *E = drag_buffer.front(); E; E = E->next()) {
- undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", E->get().type, E->get().node, E->get().to);
- undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", E->get().type, E->get().node, E->get().from);
- undo_redo->add_do_method(graph_plugin.ptr(), "set_node_position", E->get().type, E->get().node, E->get().to);
- undo_redo->add_undo_method(graph_plugin.ptr(), "set_node_position", E->get().type, E->get().node, E->get().from);
+ for (const DragOp &E : drag_buffer) {
+ undo_redo->add_do_method(visual_shader.ptr(), "set_node_position", E.type, E.node, E.to);
+ undo_redo->add_undo_method(visual_shader.ptr(), "set_node_position", E.type, E.node, E.from);
+ undo_redo->add_do_method(graph_plugin.ptr(), "set_node_position", E.type, E.node, E.to);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "set_node_position", E.type, E.node, E.from);
}
drag_buffer.clear();
@@ -2544,12 +2544,12 @@ void VisualShaderEditor::_connection_request(const String &p_from, int p_from_in
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().to_node == to && E->get().to_port == p_to_index) {
- undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const VisualShader::Connection &E : conns) {
+ if (E.to_node == to && E.to_port == p_to_index) {
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
}
}
@@ -2597,22 +2597,22 @@ void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) {
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
- undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const int &F : p_nodes) {
+ for (const VisualShader::Connection &E : conns) {
+ if (E.from_node == F || E.to_node == F) {
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
}
}
}
Set<String> uniform_names;
- for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
- Ref<VisualShaderNode> node = visual_shader->get_node(type, F->get());
+ for (const int &F : p_nodes) {
+ Ref<VisualShaderNode> node = visual_shader->get_node(type, F);
- undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F->get());
- undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F->get()), F->get());
- undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F->get());
+ undo_redo->add_do_method(visual_shader.ptr(), "remove_node", type, F);
+ undo_redo->add_undo_method(visual_shader.ptr(), "add_node", type, node, visual_shader->get_node_position(type, F), F);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "add_node", type, F);
undo_redo->add_do_method(this, "_clear_buffer");
undo_redo->add_undo_method(this, "_clear_buffer");
@@ -2638,28 +2638,28 @@ void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) {
}
List<VisualShader::Connection> used_conns;
- for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
+ for (const int &F : p_nodes) {
+ for (const VisualShader::Connection &E : conns) {
+ if (E.from_node == F || E.to_node == F) {
bool cancel = false;
for (List<VisualShader::Connection>::Element *R = used_conns.front(); R; R = R->next()) {
- if (R->get().from_node == E->get().from_node && R->get().from_port == E->get().from_port && R->get().to_node == E->get().to_node && R->get().to_port == E->get().to_port) {
+ if (R->get().from_node == E.from_node && R->get().from_port == E.from_port && R->get().to_node == E.to_node && R->get().to_port == E.to_port) {
cancel = true; // to avoid ERR_ALREADY_EXISTS warning
break;
}
}
if (!cancel) {
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- used_conns.push_back(E->get());
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ used_conns.push_back(E);
}
}
}
}
// delete nodes from the graph
- for (const List<int>::Element *F = p_nodes.front(); F; F = F->next()) {
- undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F->get());
+ for (const int &F : p_nodes) {
+ undo_redo->add_do_method(graph_plugin.ptr(), "remove_node", type, F);
}
// update uniform refs if any uniform has been deleted
@@ -3094,11 +3094,11 @@ void VisualShaderEditor::_notification(int p_what) {
preview_text->add_theme_color_override("background_color", background_color);
- for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) {
- if (ShaderLanguage::is_control_flow_keyword(E->get())) {
- syntax_highlighter->add_keyword_color(E->get(), control_flow_keyword_color);
+ for (const String &E : keyword_list) {
+ if (ShaderLanguage::is_control_flow_keyword(E)) {
+ syntax_highlighter->add_keyword_color(E, control_flow_keyword_color);
} else {
- syntax_highlighter->add_keyword_color(E->get(), keyword_color);
+ syntax_highlighter->add_keyword_color(E, keyword_color);
}
}
@@ -3206,9 +3206,9 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in
Map<int, int> connection_remap;
Set<int> unsupported_set;
- for (List<int>::Element *E = r_nodes.front(); E; E = E->next()) {
- connection_remap[E->get()] = id_from;
- Ref<VisualShaderNode> node = visual_shader->get_node(pasted_type, E->get());
+ for (int &E : r_nodes) {
+ connection_remap[E] = id_from;
+ Ref<VisualShaderNode> node = visual_shader->get_node(pasted_type, E);
bool unsupported = false;
for (int i = 0; i < add_options.size(); i++) {
@@ -3220,13 +3220,13 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in
}
}
if (unsupported) {
- unsupported_set.insert(E->get());
+ unsupported_set.insert(E);
continue;
}
Ref<VisualShaderNode> dupli = node->duplicate();
- undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(pasted_type, E->get()) + p_offset, id_from);
+ undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(pasted_type, E) + p_offset, id_from);
undo_redo->add_do_method(graph_plugin.ptr(), "add_node", type, id_from);
// duplicate size, inputs and outputs if node is group
@@ -3249,19 +3249,19 @@ void VisualShaderEditor::_dup_paste_nodes(int p_type, int p_pasted_type, List<in
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(pasted_type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (unsupported_set.has(E->get().from_node) || unsupported_set.has(E->get().to_node)) {
+ for (const VisualShader::Connection &E : conns) {
+ if (unsupported_set.has(E.from_node) || unsupported_set.has(E.to_node)) {
continue;
}
- if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) {
- undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port);
- undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port);
+ if (connection_remap.has(E.from_node) && connection_remap.has(E.to_node)) {
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E.from_node], E.from_port, connection_remap[E.to_node], E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "connect_nodes", type, connection_remap[E.from_node], E.from_port, connection_remap[E.to_node], E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "disconnect_nodes", type, connection_remap[E.from_node], E.from_port, connection_remap[E.to_node], E.to_port);
}
}
id_from = base_id;
- for (List<int>::Element *E = r_nodes.front(); E; E = E->next()) {
+ for (int i = 0; i < r_nodes.size(); i++) {
undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from);
undo_redo->add_undo_method(graph_plugin.ptr(), "remove_node", type, id_from);
id_from++;
@@ -3399,17 +3399,17 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input,
if (type_changed) {
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == id) {
- if (visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, E->get().to_node)->get_input_port_type(E->get().to_port))) {
- undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const VisualShader::Connection &E : conns) {
+ if (E.from_node == id) {
+ if (visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, E.to_node)->get_input_port_type(E.to_port))) {
+ undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
continue;
}
- undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
}
}
}
@@ -3445,15 +3445,15 @@ void VisualShaderEditor::_uniform_select_item(Ref<VisualShaderNodeUniformRef> p_
if (type_changed) {
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().from_node == id) {
- if (visual_shader->is_port_types_compatible(p_uniform_ref->get_uniform_type_by_name(p_name), visual_shader->get_node(type, E->get().to_node)->get_input_port_type(E->get().to_port))) {
+ for (const VisualShader::Connection &E : conns) {
+ if (E.from_node == id) {
+ if (visual_shader->is_port_types_compatible(p_uniform_ref->get_uniform_type_by_name(p_name), visual_shader->get_node(type, E.to_node)->get_input_port_type(E.to_port))) {
continue;
}
- undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
}
}
}
@@ -4825,10 +4825,10 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
Vector<PropertyInfo> pinfo;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ for (const PropertyInfo &E : props) {
for (int i = 0; i < properties.size(); i++) {
- if (E->get().name == String(properties[i])) {
- pinfo.push_back(E->get());
+ if (E.name == String(properties[i])) {
+ pinfo.push_back(E);
}
}
}
@@ -4894,9 +4894,9 @@ void EditorPropertyShaderMode::_option_selected(int p_which) {
VisualShader::Type type = VisualShader::Type(i);
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
- for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().to_node == VisualShader::NODE_ID_OUTPUT) {
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const VisualShader::Connection &E : conns) {
+ if (E.to_node == VisualShader::NODE_ID_OUTPUT) {
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
}
}
}
@@ -4918,9 +4918,9 @@ void EditorPropertyShaderMode::_option_selected(int p_which) {
List<PropertyInfo> props;
visual_shader->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (E->get().name.begins_with("flags/") || E->get().name.begins_with("modes/")) {
- undo_redo->add_undo_property(visual_shader.ptr(), E->get().name, visual_shader->get(E->get().name));
+ for (const PropertyInfo &E : props) {
+ if (E.name.begins_with("flags/") || E.name.begins_with("modes/")) {
+ undo_redo->add_undo_property(visual_shader.ptr(), E.name, visual_shader->get(E.name));
}
}
@@ -5024,8 +5024,8 @@ void VisualShaderNodePortPreview::_shader_changed() {
if (src_mat && src_mat->get_shader().is_valid()) {
List<PropertyInfo> params;
src_mat->get_shader()->get_param_list(&params);
- for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
- material->set(E->get().name, src_mat->get(E->get().name));
+ for (const PropertyInfo &E : params) {
+ material->set(E.name, src_mat->get(E.name));
}
}
}
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index 1e818b9d43..fcb714bdf7 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -340,8 +340,8 @@ void ProjectExportDialog::_update_feature_list() {
}
}
- for (List<String>::Element *E = features.front(); E; E = E->next()) {
- fset.insert(E->get());
+ for (const String &E : features) {
+ fset.insert(E);
}
custom_feature_display->clear();
@@ -567,8 +567,8 @@ void ProjectExportDialog::_duplicate_preset() {
preset->set_exclude_filter(current->get_exclude_filter());
preset->set_custom_features(current->get_custom_features());
- for (const List<PropertyInfo>::Element *E = current->get_properties().front(); E; E = E->next()) {
- preset->set(E->get().name, current->get(E->get().name));
+ for (const PropertyInfo &E : current->get_properties()) {
+ preset->set(E.name, current->get(E.name));
}
EditorExport::get_singleton()->add_export_preset(preset);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 46a1253ca0..fd4f22425f 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -494,13 +494,13 @@ private:
if (!f) {
set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
} else {
- f->store_line("[gd_resource type=\"Environment\" load_steps=2 format=2]");
+ f->store_line("[gd_resource type=\"Environment\" load_steps=2 format=3]");
f->store_line("");
- f->store_line("[sub_resource type=\"Sky\" id=1]");
+ f->store_line("[sub_resource type=\"Sky\" id=\"1\"]");
f->store_line("");
f->store_line("[resource]");
f->store_line("background_mode = 2");
- f->store_line("sky = SubResource( 1 )");
+ f->store_line("sky = SubResource( \"1\" )");
memdelete(f);
}
}
@@ -1238,16 +1238,16 @@ void ProjectList::load_projects() {
Set<String> favorites;
// Find favourites...
- for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- String property_key = E->get().name;
+ for (const PropertyInfo &E : properties) {
+ String property_key = E.name;
if (property_key.begins_with("favorite_projects/")) {
favorites.insert(property_key);
}
}
- for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
+ for (const PropertyInfo &E : properties) {
// This is actually something like "projects/C:::Documents::Godot::Projects::MyGame"
- String property_key = E->get().name;
+ String property_key = E.name;
if (!property_key.begins_with("projects/")) {
continue;
}
@@ -1582,8 +1582,8 @@ int ProjectList::refresh_project(const String &dir_path) {
String favorite_property_key = "favorite_projects/" + project_key;
bool found = false;
- for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- String prop = E->get().name;
+ for (const PropertyInfo &E : properties) {
+ String prop = E.name;
if (!found && prop == property_key) {
found = true;
} else if (!is_favourite && prop == favorite_property_key) {
@@ -2188,9 +2188,9 @@ void ProjectManager::_scan_begin(const String &p_base) {
_scan_dir(p_base, &projects);
print_line("Found " + itos(projects.size()) + " projects.");
- for (List<String>::Element *E = projects.front(); E; E = E->next()) {
- String proj = get_project_key_from_path(E->get());
- EditorSettings::get_singleton()->set("projects/" + proj, E->get());
+ for (const String &E : projects) {
+ String proj = get_project_key_from_path(E);
+ EditorSettings::get_singleton()->set("projects/" + proj, E);
}
EditorSettings::get_singleton()->save();
_load_recent_projects();
@@ -2625,8 +2625,7 @@ ProjectManager::ProjectManager() {
Vector<String> editor_languages;
List<PropertyInfo> editor_settings_properties;
EditorSettings::get_singleton()->get_property_list(&editor_settings_properties);
- for (List<PropertyInfo>::Element *E = editor_settings_properties.front(); E; E = E->next()) {
- PropertyInfo &pi = E->get();
+ for (const PropertyInfo &pi : editor_settings_properties) {
if (pi.name == "interface/editor/editor_language") {
editor_languages = pi.hint_string.split(",");
break;
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 2c4b28e13d..b8ccab78dd 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -229,16 +229,16 @@ void ProjectSettingsEditor::_add_feature_overrides() {
for (int i = 0; i < ee->get_export_platform_count(); i++) {
List<String> p;
ee->get_export_platform(i)->get_platform_features(&p);
- for (List<String>::Element *E = p.front(); E; E = E->next()) {
- presets.insert(E->get());
+ for (const String &E : p) {
+ presets.insert(E);
}
}
for (int i = 0; i < ee->get_export_preset_count(); i++) {
List<String> p;
ee->get_export_preset(i)->get_platform()->get_preset_features(ee->get_export_preset(i), &p);
- for (List<String>::Element *E = p.front(); E; E = E->next()) {
- presets.insert(E->get());
+ for (const String &E : p) {
+ presets.insert(E);
}
String custom = ee->get_export_preset(i)->get_custom_features();
@@ -391,8 +391,7 @@ void ProjectSettingsEditor::_action_reordered(const String &p_action_name, const
undo_redo->create_action(TTR("Update Input Action Order"));
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- PropertyInfo prop = E->get();
+ for (const PropertyInfo &prop : props) {
// Skip builtins and non-inputs
if (ProjectSettings::get_singleton()->is_builtin_setting(prop.name) || !prop.name.begins_with("input/")) {
continue;
@@ -445,8 +444,8 @@ void ProjectSettingsEditor::_update_action_map_editor() {
ProjectSettings::get_singleton()->get_property_list(&props);
const Ref<Texture2D> builtin_icon = get_theme_icon(SNAME("PinPressed"), SNAME("EditorIcons"));
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- const String property_name = E->get().name;
+ for (const PropertyInfo &E : props) {
+ const String property_name = E.name;
if (!property_name.begins_with("input/")) {
continue;
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index db8334b485..7338588d56 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -143,8 +143,8 @@ void CustomPropertyEditor::_menu_option(int p_which) {
}
Set<String> valid_extensions;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- valid_extensions.insert(E->get());
+ for (const String &E : extensions) {
+ valid_extensions.insert(E);
}
file->clear_filters();
@@ -179,9 +179,8 @@ void CustomPropertyEditor::_menu_option(int p_which) {
res_orig->get_property_list(&property_list);
List<Pair<String, Variant>> propvalues;
- for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+ for (const PropertyInfo &pi : property_list) {
Pair<String, Variant> p;
- PropertyInfo &pi = E->get();
if (pi.usage & PROPERTY_USAGE_STORAGE) {
p.first = pi.name;
p.second = res_orig->get(pi.name);
@@ -198,8 +197,7 @@ void CustomPropertyEditor::_menu_option(int p_which) {
ERR_FAIL_COND(res.is_null());
- for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) {
- Pair<String, Variant> &p = E->get();
+ for (const Pair<String, Variant> &p : propvalues) {
res->set(p.first, p.second);
}
@@ -1293,8 +1291,8 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
ResourceLoader::get_recognized_extensions_for_type(type, &extensions);
file->clear_filters();
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- file->add_filter("*." + E->get() + " ; " + E->get().to_upper());
+ for (const String &E : extensions) {
+ file->add_filter("*." + E + " ; " + E.to_upper());
}
file->popup_file_dialog();
@@ -1321,9 +1319,8 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
res_orig->get_property_list(&property_list);
List<Pair<String, Variant>> propvalues;
- for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
+ for (const PropertyInfo &pi : property_list) {
Pair<String, Variant> p;
- PropertyInfo &pi = E->get();
if (pi.usage & PROPERTY_USAGE_STORAGE) {
p.first = pi.name;
p.second = res_orig->get(pi.name);
@@ -1336,8 +1333,7 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
ERR_FAIL_COND(res.is_null());
- for (List<Pair<String, Variant>>::Element *E = propvalues.front(); E; E = E->next()) {
- Pair<String, Variant> &p = E->get();
+ for (const Pair<String, Variant> &p : propvalues) {
res->set(p.first, p.second);
}
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index d26fc6ad9d..a1deae92a4 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -156,43 +156,43 @@ void PropertySelector::_update_search() {
search_options->get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons"))
};
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (E->get().usage == PROPERTY_USAGE_CATEGORY) {
+ for (const PropertyInfo &E : props) {
+ if (E.usage == PROPERTY_USAGE_CATEGORY) {
if (category && category->get_first_child() == nullptr) {
memdelete(category); //old category was unused
}
category = search_options->create_item(root);
- category->set_text(0, E->get().name);
+ category->set_text(0, E.name);
category->set_selectable(0, false);
Ref<Texture2D> icon;
- if (E->get().name == "Script Variables") {
+ if (E.name == "Script Variables") {
icon = search_options->get_theme_icon(SNAME("Script"), SNAME("EditorIcons"));
} else {
- icon = EditorNode::get_singleton()->get_class_icon(E->get().name);
+ icon = EditorNode::get_singleton()->get_class_icon(E.name);
}
category->set_icon(0, icon);
continue;
}
- if (!(E->get().usage & PROPERTY_USAGE_EDITOR) && !(E->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) {
+ if (!(E.usage & PROPERTY_USAGE_EDITOR) && !(E.usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) {
continue;
}
- if (search_box->get_text() != String() && E->get().name.findn(search_text) == -1) {
+ if (search_box->get_text() != String() && E.name.findn(search_text) == -1) {
continue;
}
- if (type_filter.size() && type_filter.find(E->get().type) == -1) {
+ if (type_filter.size() && type_filter.find(E.type) == -1) {
continue;
}
TreeItem *item = search_options->create_item(category ? category : root);
- item->set_text(0, E->get().name);
- item->set_metadata(0, E->get().name);
- item->set_icon(0, type_icons[E->get().type]);
+ item->set_text(0, E.name);
+ item->set_metadata(0, E.name);
+ item->set_icon(0, type_icons[E.type]);
- if (!found && search_box->get_text() != String() && E->get().name.findn(search_text) != -1) {
+ if (!found && search_box->get_text() != String() && E.name.findn(search_text) != -1) {
item->select(0);
found = true;
}
@@ -231,19 +231,19 @@ void PropertySelector::_update_search() {
bool found = false;
bool script_methods = false;
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name.begins_with("*")) {
+ for (MethodInfo &mi : methods) {
+ if (mi.name.begins_with("*")) {
if (category && category->get_first_child() == nullptr) {
memdelete(category); //old category was unused
}
category = search_options->create_item(root);
- category->set_text(0, E->get().name.replace_first("*", ""));
+ category->set_text(0, mi.name.replace_first("*", ""));
category->set_selectable(0, false);
Ref<Texture2D> icon;
script_methods = false;
- String rep = E->get().name.replace("*", "");
- if (E->get().name == "*Script Methods") {
+ String rep = mi.name.replace("*", "");
+ if (mi.name == "*Script Methods") {
icon = search_options->get_theme_icon(SNAME("Script"), SNAME("EditorIcons"));
script_methods = true;
} else {
@@ -254,16 +254,16 @@ void PropertySelector::_update_search() {
continue;
}
- String name = E->get().name.get_slice(":", 0);
- if (!script_methods && name.begins_with("_") && !(E->get().flags & METHOD_FLAG_VIRTUAL)) {
+ String name = mi.name.get_slice(":", 0);
+ if (!script_methods && name.begins_with("_") && !(mi.flags & METHOD_FLAG_VIRTUAL)) {
continue;
}
- if (virtuals_only && !(E->get().flags & METHOD_FLAG_VIRTUAL)) {
+ if (virtuals_only && !(mi.flags & METHOD_FLAG_VIRTUAL)) {
continue;
}
- if (!virtuals_only && (E->get().flags & METHOD_FLAG_VIRTUAL)) {
+ if (!virtuals_only && (mi.flags & METHOD_FLAG_VIRTUAL)) {
continue;
}
@@ -273,8 +273,6 @@ void PropertySelector::_update_search() {
TreeItem *item = search_options->create_item(category ? category : root);
- MethodInfo mi = E->get();
-
String desc;
if (mi.name.find(":") != -1) {
desc = mi.name.get_slice(":", 1) + " ";
@@ -306,11 +304,11 @@ void PropertySelector::_update_search() {
desc += ")";
- if (E->get().flags & METHOD_FLAG_CONST) {
+ if (mi.flags & METHOD_FLAG_CONST) {
desc += " const";
}
- if (E->get().flags & METHOD_FLAG_VIRTUAL) {
+ if (mi.flags & METHOD_FLAG_VIRTUAL) {
desc += " virtual";
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 6d1deb86c6..c4d47c7594 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -263,8 +263,8 @@ void SceneTreeDock::_replace_with_branch_scene(const String &p_file, Node *base)
List<Node *> owned;
base->get_owned_by(base->get_owner(), &owned);
Array owners;
- for (List<Node *>::Element *F = owned.front(); F; F = F->next()) {
- owners.push_back(F->get());
+ for (Node *F : owned) {
+ owners.push_back(F);
}
undo_redo->add_do_method(instantiated_scene, "set_owner", edited_scene);
undo_redo->add_undo_method(this, "_set_owners", edited_scene, owners);
@@ -441,8 +441,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
selection.sort_custom<Node::Comparator>();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node *node = E->get();
+ for (Node *node : selection) {
Map<const Node *, Node *> duplimap;
Node *dup = node->duplicate_from_editor(duplimap);
@@ -462,8 +461,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
bool has_cycle = false;
if (edited_scene->get_filename() != String()) {
- for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
- if (edited_scene->get_filename() == E->get()->get_filename()) {
+ for (Node *E : node_clipboard) {
+ if (edited_scene->get_filename() == E->get_filename()) {
has_cycle = true;
break;
}
@@ -496,16 +495,15 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (target_scene != clipboard_source_scene) {
if (!clipboard_resource_remap.has(target_scene)) {
Map<RES, RES> remap;
- for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
- _create_remap_for_node(E->get(), remap);
+ for (Node *E : node_clipboard) {
+ _create_remap_for_node(E, remap);
}
clipboard_resource_remap[target_scene] = remap;
}
resource_remap = clipboard_resource_remap[target_scene];
}
- for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
- Node *node = E->get();
+ for (Node *node : node_clipboard) {
Map<const Node *, Node *> duplimap;
Node *dup = node->duplicate_from_editor(duplimap, resource_remap);
@@ -627,8 +625,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
int lowest_id = common_parent->get_child_count() - 1;
int highest_id = 0;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- int index = E->get()->get_index();
+ for (Node *E : selection) {
+ int index = E->get_index();
if (index > highest_id) {
highest_id = index;
@@ -637,7 +635,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
lowest_id = index;
}
- if (E->get()->get_parent() != common_parent) {
+ if (E->get_parent() != common_parent) {
common_parent = nullptr;
}
}
@@ -704,8 +702,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
Node *add_below_node = selection.back()->get();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node *node = E->get();
+ for (Node *node : selection) {
Node *parent = node->get_parent();
List<Node *> owned;
@@ -724,11 +721,11 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editor_data->get_undo_redo().add_do_method(add_below_node, "add_sibling", dup);
- for (List<Node *>::Element *F = owned.front(); F; F = F->next()) {
- if (!duplimap.has(F->get())) {
+ for (Node *F : owned) {
+ if (!duplimap.has(F)) {
continue;
}
- Node *d = duplimap[F->get()];
+ Node *d = duplimap[F];
editor_data->get_undo_redo().add_do_method(d, "set_owner", node->get_owner());
}
editor_data->get_undo_redo().add_do_method(editor_selection, "add_node", dup);
@@ -771,8 +768,8 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
List<Node *> nodes = editor_selection->get_selected_node_list();
Set<Node *> nodeset;
- for (List<Node *>::Element *E = nodes.front(); E; E = E->next()) {
- nodeset.insert(E->get());
+ for (Node *E : nodes) {
+ nodeset.insert(E);
}
reparent_dialog->set_current(nodeset);
reparent_dialog->popup_centered_clamped(Size2(350, 700) * EDSCALE);
@@ -1384,30 +1381,25 @@ void SceneTreeDock::_set_owners(Node *p_owner, const Array &p_nodes) {
}
}
-void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, List<Pair<NodePath, NodePath>> *p_renames) {
+void SceneTreeDock::_fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, Map<Node *, NodePath> *p_renames) {
base_path.push_back(p_node->get_name());
if (new_base_path.size()) {
new_base_path.push_back(p_node->get_name());
}
- NodePath from(base_path, true);
- NodePath to;
+ NodePath new_path;
if (new_base_path.size()) {
- to = NodePath(new_base_path, true);
+ new_path = NodePath(new_base_path, true);
}
- Pair<NodePath, NodePath> npp;
- npp.first = from;
- npp.second = to;
-
- p_renames->push_back(npp);
+ p_renames->insert(p_node, new_path);
for (int i = 0; i < p_node->get_child_count(); i++) {
_fill_path_renames(base_path, new_base_path, p_node->get_child(i), p_renames);
}
}
-void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, List<Pair<NodePath, NodePath>> *p_renames) {
+void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, Map<Node *, NodePath> *p_renames) {
Vector<StringName> base_path;
Node *n = p_node->get_parent();
while (n) {
@@ -1430,50 +1422,41 @@ void SceneTreeDock::fill_path_renames(Node *p_node, Node *p_new_parent, List<Pai
_fill_path_renames(base_path, new_base_path, p_node, p_renames);
}
-bool SceneTreeDock::_update_node_path(const NodePath &p_root_path, NodePath &r_node_path, List<Pair<NodePath, NodePath>> *p_renames) {
- NodePath root_path_new = p_root_path;
- for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
- if (p_root_path == F->get().first) {
- root_path_new = F->get().second;
- break;
- }
- }
-
- // Goes through all paths to check if it's matching.
- for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
- NodePath rel_path_old = p_root_path.rel_path_to(F->get().first);
+bool SceneTreeDock::_update_node_path(Node *p_root_node, NodePath &r_node_path, Map<Node *, NodePath> *p_renames) const {
+ Node *target_node = p_root_node->get_node_or_null(r_node_path);
+ ERR_FAIL_NULL_V_MSG(target_node, false, "Found invalid node path '" + String(r_node_path) + "' on node '" + String(scene_root->get_path_to(p_root_node)) + "'");
- // If old path detected, then it needs to be replaced with the new one.
- if (r_node_path == rel_path_old) {
- NodePath rel_path_new = F->get().second;
+ // Try to find the target node in modified node paths.
+ Map<Node *, NodePath>::Element *found_node_path = p_renames->find(target_node);
+ if (found_node_path) {
+ Map<Node *, NodePath>::Element *found_root_path = p_renames->find(p_root_node);
+ NodePath root_path_new = found_root_path ? found_root_path->get() : p_root_node->get_path();
+ r_node_path = root_path_new.rel_path_to(found_node_path->get());
- // If not empty, get new relative path.
- if (!rel_path_new.is_empty()) {
- rel_path_new = root_path_new.rel_path_to(rel_path_new);
- }
+ return true;
+ }
- r_node_path = rel_path_new;
- return true;
+ // Update the path if the base node has changed and has not been deleted.
+ Map<Node *, NodePath>::Element *found_root_path = p_renames->find(p_root_node);
+ if (found_root_path) {
+ NodePath root_path_new = found_root_path->get();
+ if (!root_path_new.is_empty()) {
+ NodePath old_abs_path = NodePath(String(p_root_node->get_path()).plus_file(r_node_path));
+ old_abs_path.simplify();
+ r_node_path = root_path_new.rel_path_to(old_abs_path);
}
- // Update the node itself if it has a valid node path and has not been deleted.
- if (p_root_path == F->get().first && r_node_path != NodePath() && F->get().second != NodePath()) {
- NodePath abs_path = NodePath(String(root_path_new).plus_file(r_node_path)).simplified();
- NodePath rel_path_new = F->get().second.rel_path_to(abs_path);
-
- r_node_path = rel_path_new;
- return true;
- }
+ return true;
}
return false;
}
-bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Variant &r_variant, List<Pair<NodePath, NodePath>> *p_renames) {
+bool SceneTreeDock::_check_node_path_recursive(Node *p_root_node, Variant &r_variant, Map<Node *, NodePath> *p_renames) const {
switch (r_variant.get_type()) {
case Variant::NODE_PATH: {
NodePath node_path = r_variant;
- if (_update_node_path(p_root_path, node_path, p_renames)) {
+ if (!node_path.is_empty() && _update_node_path(p_root_node, node_path, p_renames)) {
r_variant = node_path;
return true;
}
@@ -1484,7 +1467,7 @@ bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Vari
bool updated = false;
for (int i = 0; i < a.size(); i++) {
Variant value = a[i];
- if (_check_node_path_recursive(p_root_path, value, p_renames)) {
+ if (_check_node_path_recursive(p_root_node, value, p_renames)) {
if (!updated) {
a = a.duplicate(); // Need to duplicate for undo-redo to work.
updated = true;
@@ -1503,7 +1486,7 @@ bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Vari
bool updated = false;
for (int i = 0; i < d.size(); i++) {
Variant value = d.get_value_at_index(i);
- if (_check_node_path_recursive(p_root_path, value, p_renames)) {
+ if (_check_node_path_recursive(p_root_node, value, p_renames)) {
if (!updated) {
d = d.duplicate(); // Need to duplicate for undo-redo to work.
updated = true;
@@ -1524,7 +1507,7 @@ bool SceneTreeDock::_check_node_path_recursive(const NodePath &p_root_path, Vari
return false;
}
-void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodePath>> *p_renames, Map<Ref<Animation>, Set<int>> *r_rem_anims) {
+void SceneTreeDock::perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_renames, Map<Ref<Animation>, Set<int>> *r_rem_anims) {
Map<Ref<Animation>, Set<int>> rem_anims;
if (!r_rem_anims) {
r_rem_anims = &rem_anims;
@@ -1538,19 +1521,24 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP
return;
}
+ // No renaming if base node is deleted.
+ Map<Node *, NodePath>::Element *found_base_path = p_renames->find(p_base);
+ if (found_base_path && found_base_path->get().is_empty()) {
+ return;
+ }
+
// Renaming node paths used in node properties.
List<PropertyInfo> properties;
p_base->get_property_list(&properties);
- NodePath base_root_path = p_base->get_path();
- for (List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (!(E->get().usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR))) {
+ for (const PropertyInfo &E : properties) {
+ if (!(E.usage & (PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR))) {
continue;
}
- String propertyname = E->get().name;
+ String propertyname = E.name;
Variant old_variant = p_base->get(propertyname);
Variant updated_variant = old_variant;
- if (_check_node_path_recursive(base_root_path, updated_variant, p_renames)) {
+ if (_check_node_path_recursive(p_base, updated_variant, p_renames)) {
editor_data->get_undo_redo().add_do_property(p_base, propertyname, updated_variant);
editor_data->get_undo_redo().add_undo_property(p_base, propertyname, old_variant);
p_base->set(propertyname, updated_variant);
@@ -1566,21 +1554,11 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP
Node *root = ap->get_node(ap->get_root());
if (root) {
- NodePath root_path = root->get_path();
- NodePath new_root_path = root_path;
-
- for (List<Pair<NodePath, NodePath>>::Element *E = p_renames->front(); E; E = E->next()) {
- if (E->get().first == root_path) {
- new_root_path = E->get().second;
- break;
- }
- }
-
- if (new_root_path != NodePath()) {
- //will not be erased
-
- for (List<StringName>::Element *E = anims.front(); E; E = E->next()) {
- Ref<Animation> anim = ap->get_animation(E->get());
+ Map<Node *, NodePath>::Element *found_root_path = p_renames->find(root);
+ NodePath new_root_path = found_root_path ? found_root_path->get() : root->get_path();
+ if (!new_root_path.is_empty()) { // No renaming if root node is deleted.
+ for (const StringName &E : anims) {
+ Ref<Animation> anim = ap->get_animation(E);
if (!r_rem_anims->has(anim)) {
r_rem_anims->insert(anim, Set<int>());
Set<int> &ran = r_rem_anims->find(anim)->get();
@@ -1602,47 +1580,44 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP
continue;
}
- NodePath old_np = n->get_path();
-
if (!ran.has(i)) {
continue; //channel was removed
}
- for (List<Pair<NodePath, NodePath>>::Element *F = p_renames->front(); F; F = F->next()) {
- if (F->get().first == old_np) {
- if (F->get().second == NodePath()) {
- //will be erased
-
- int idx = 0;
- Set<int>::Element *EI = ran.front();
- ERR_FAIL_COND(!EI); //bug
- while (EI->get() != i) {
- idx++;
- EI = EI->next();
- ERR_FAIL_COND(!EI); //another bug
- }
-
- editor_data->get_undo_redo().add_do_method(anim.ptr(), "remove_track", idx);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_set_path", idx, track_np);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_set_interpolation_type", idx, anim->track_get_interpolation_type(i));
- for (int j = 0; j < anim->track_get_key_count(i); j++) {
- editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_insert_key", idx, anim->track_get_key_time(i, j), anim->track_get_key_value(i, j), anim->track_get_key_transition(i, j));
- }
-
- ran.erase(i); //byebye channel
-
- } else {
- //will be renamed
- NodePath rel_path = new_root_path.rel_path_to(F->get().second);
-
- NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false);
- if (new_path == track_np) {
- continue; //bleh
- }
- editor_data->get_undo_redo().add_do_method(anim.ptr(), "track_set_path", i, new_path);
- editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_set_path", i, track_np);
+ Map<Node *, NodePath>::Element *found_path = p_renames->find(n);
+ if (found_path) {
+ if (found_path->get() == NodePath()) {
+ //will be erased
+
+ int idx = 0;
+ Set<int>::Element *EI = ran.front();
+ ERR_FAIL_COND(!EI); //bug
+ while (EI->get() != i) {
+ idx++;
+ EI = EI->next();
+ ERR_FAIL_COND(!EI); //another bug
+ }
+
+ editor_data->get_undo_redo().add_do_method(anim.ptr(), "remove_track", idx);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(), "add_track", anim->track_get_type(i), idx);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_set_path", idx, track_np);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_set_interpolation_type", idx, anim->track_get_interpolation_type(i));
+ for (int j = 0; j < anim->track_get_key_count(i); j++) {
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_insert_key", idx, anim->track_get_key_time(i, j), anim->track_get_key_value(i, j), anim->track_get_key_transition(i, j));
+ }
+
+ ran.erase(i); //byebye channel
+
+ } else {
+ //will be renamed
+ NodePath rel_path = new_root_path.rel_path_to(found_path->get());
+
+ NodePath new_path = NodePath(rel_path.get_names(), track_np.get_subnames(), false);
+ if (new_path == track_np) {
+ continue; //bleh
}
+ editor_data->get_undo_redo().add_do_method(anim.ptr(), "track_set_path", i, new_path);
+ editor_data->get_undo_redo().add_undo_method(anim.ptr(), "track_set_path", i, track_np);
}
}
}
@@ -1657,7 +1632,7 @@ void SceneTreeDock::perform_node_renames(Node *p_base, List<Pair<NodePath, NodeP
}
void SceneTreeDock::_node_prerenamed(Node *p_node, const String &p_new_name) {
- List<Pair<NodePath, NodePath>> path_renames;
+ Map<Node *, NodePath> path_renames;
Vector<StringName> base_path;
Node *n = p_node->get_parent();
@@ -1672,10 +1647,8 @@ void SceneTreeDock::_node_prerenamed(Node *p_node, const String &p_new_name) {
new_base_path.push_back(p_new_name);
- Pair<NodePath, NodePath> npp;
- npp.first = NodePath(base_path, true);
- npp.second = NodePath(new_base_path, true);
- path_renames.push_back(npp);
+ NodePath new_path(new_base_path, true);
+ path_renames[p_node] = new_path;
for (int i = 0; i < p_node->get_child_count(); i++) {
_fill_path_renames(base_path, new_base_path, p_node->get_child(i), &path_renames);
@@ -1687,8 +1660,8 @@ void SceneTreeDock::_node_prerenamed(Node *p_node, const String &p_new_name) {
bool SceneTreeDock::_validate_no_foreign() {
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- if (E->get() != edited_scene && E->get()->get_owner() != edited_scene) {
+ for (Node *E : selection) {
+ if (E != edited_scene && E->get_owner() != edited_scene) {
accept->set_text(TTR("Can't operate on nodes from a foreign scene!"));
accept->popup_centered();
return false;
@@ -1697,11 +1670,11 @@ bool SceneTreeDock::_validate_no_foreign() {
// When edited_scene inherits from another one the root Node will be the parent Scene,
// we don't want to consider that Node a foreign one otherwise we would not be able to
// delete it.
- if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene == E->get()) {
+ if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene == E) {
continue;
}
- if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E->get())) >= 0) {
+ if (edited_scene->get_scene_inherited_state().is_valid() && edited_scene->get_scene_inherited_state()->find_node_by_path(edited_scene->get_path_to(E)) >= 0) {
accept->set_text(TTR("Can't operate on nodes the current scene inherits from!"));
accept->popup_centered();
return false;
@@ -1714,8 +1687,8 @@ bool SceneTreeDock::_validate_no_foreign() {
bool SceneTreeDock::_validate_no_instance() {
List<Node *> selection = editor_selection->get_selected_node_list();
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- if (E->get() != edited_scene && E->get()->get_filename() != "") {
+ for (Node *E : selection) {
+ if (E != edited_scene && E->get_filename() != "") {
accept->set_text(TTR("This operation can't be done on instantiated scenes."));
accept->popup_centered();
return false;
@@ -1737,8 +1710,8 @@ void SceneTreeDock::_node_reparent(NodePath p_path, bool p_keep_global_xform) {
Vector<Node *> nodes;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- nodes.push_back(E->get());
+ for (Node *E : selection) {
+ nodes.push_back(E);
}
_do_reparent(new_parent, -1, nodes, p_keep_global_xform);
@@ -1780,7 +1753,7 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
editor_data->get_undo_redo().create_action(TTR("Reparent Node"));
- List<Pair<NodePath, NodePath>> path_renames;
+ Map<Node *, NodePath> path_renames;
Vector<StringName> former_names;
int inc = 0;
@@ -1795,8 +1768,8 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
List<Node *> owned;
node->get_owned_by(node->get_owner(), &owned);
Array owners;
- for (List<Node *>::Element *E = owned.front(); E; E = E->next()) {
- owners.push_back(E->get());
+ for (Node *E : owned) {
+ owners.push_back(E);
}
if (new_parent == node->get_parent() && node->get_index() < p_position_in_parent + ni) {
@@ -1817,21 +1790,24 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
// Name was modified, fix the path renames.
if (old_name.casecmp_to(new_name) != 0) {
// Fix the to name to have the new name.
- NodePath old_new_name = path_renames[ni].second;
- NodePath new_path;
-
- Vector<StringName> unfixed_new_names = old_new_name.get_names();
- Vector<StringName> fixed_new_names;
+ Map<Node *, NodePath>::Element *found_path = path_renames.find(node);
+ if (found_path) {
+ NodePath old_new_name = found_path->get();
- // Get last name and replace with fixed new name.
- for (int a = 0; a < (unfixed_new_names.size() - 1); a++) {
- fixed_new_names.push_back(unfixed_new_names[a]);
- }
- fixed_new_names.push_back(new_name);
+ Vector<StringName> unfixed_new_names = old_new_name.get_names();
+ Vector<StringName> fixed_new_names;
- NodePath fixed_node_path = NodePath(fixed_new_names, true);
+ // Get last name and replace with fixed new name.
+ for (int a = 0; a < (unfixed_new_names.size() - 1); a++) {
+ fixed_new_names.push_back(unfixed_new_names[a]);
+ }
+ fixed_new_names.push_back(new_name);
- path_renames[ni].second = fixed_node_path;
+ NodePath fixed_node_path = NodePath(fixed_new_names, true);
+ path_renames[node] = fixed_node_path;
+ } else {
+ ERR_PRINT("Internal error. Can't find renamed path for node '" + node->get_path() + "'");
+ }
}
editor_data->get_undo_redo().add_do_method(ed, "live_debug_reparent_node", edited_scene->get_path_to(node), edited_scene->get_path_to(new_parent), new_name, p_position_in_parent + inc);
@@ -1868,8 +1844,8 @@ void SceneTreeDock::_do_reparent(Node *p_new_parent, int p_position_in_parent, V
List<Node *> owned;
node->get_owned_by(node->get_owner(), &owned);
Array owners;
- for (List<Node *>::Element *E = owned.front(); E; E = E->next()) {
- owners.push_back(E->get());
+ for (Node *E : owned) {
+ owners.push_back(E);
}
int child_pos = node->get_index();
@@ -1949,10 +1925,10 @@ void SceneTreeDock::_script_created(Ref<Script> p_script) {
}
editor_data->get_undo_redo().create_action(TTR("Attach Script"));
- for (List<Node *>::Element *E = selected.front(); E; E = E->next()) {
- Ref<Script> existing = E->get()->get_script();
- editor_data->get_undo_redo().add_do_method(E->get(), "set_script", p_script);
- editor_data->get_undo_redo().add_undo_method(E->get(), "set_script", existing);
+ for (Node *E : selected) {
+ Ref<Script> existing = E->get_script();
+ editor_data->get_undo_redo().add_do_method(E, "set_script", p_script);
+ editor_data->get_undo_redo().add_undo_method(E, "set_script", existing);
editor_data->get_undo_redo().add_do_method(this, "_update_script_button");
editor_data->get_undo_redo().add_undo_method(this, "_update_script_button");
}
@@ -2027,8 +2003,8 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
bool entire_scene = false;
- for (List<Node *>::Element *E = remove_list.front(); E; E = E->next()) {
- if (E->get() == edited_scene) {
+ for (Node *E : remove_list) {
+ if (E == edited_scene) {
entire_scene = true;
}
}
@@ -2042,11 +2018,10 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
} else {
remove_list.sort_custom<Node::Comparator>(); //sort nodes to keep positions
- List<Pair<NodePath, NodePath>> path_renames;
+ Map<Node *, NodePath> path_renames;
//delete from animation
- for (List<Node *>::Element *E = remove_list.front(); E; E = E->next()) {
- Node *n = E->get();
+ for (Node *n : remove_list) {
if (!n->is_inside_tree() || !n->get_parent()) {
continue;
}
@@ -2056,8 +2031,7 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
perform_node_renames(nullptr, &path_renames);
//delete for read
- for (List<Node *>::Element *E = remove_list.front(); E; E = E->next()) {
- Node *n = E->get();
+ for (Node *n : remove_list) {
if (!n->is_inside_tree() || !n->get_parent()) {
continue;
}
@@ -2065,8 +2039,8 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
List<Node *> owned;
n->get_owned_by(n->get_owner(), &owned);
Array owners;
- for (List<Node *>::Element *F = owned.front(); F; F = F->next()) {
- owners.push_back(F->get());
+ for (Node *F : owned) {
+ owners.push_back(F);
}
editor_data->get_undo_redo().add_do_method(n->get_parent(), "remove_child", n);
@@ -2219,8 +2193,7 @@ void SceneTreeDock::_create() {
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action(TTR("Change type of node(s)"));
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node *n = E->get();
+ for (Node *n : selection) {
ERR_FAIL_COND(!n);
Variant c = create_dialog->instance_selected();
@@ -2277,8 +2250,8 @@ void SceneTreeDock::_create() {
_do_create(parent);
Vector<Node *> nodes;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- nodes.push_back(E->get());
+ for (Node *E : selection) {
+ nodes.push_back(E);
}
// This works because editor_selection was cleared and populated with last created node in _do_create()
@@ -2298,13 +2271,13 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop
List<PropertyInfo> pinfo;
n->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : pinfo) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- if (E->get().name == "__meta__") {
- Dictionary metadata = n->get(E->get().name);
+ if (E.name == "__meta__") {
+ Dictionary metadata = n->get(E.name);
if (metadata.has("_editor_description_")) {
newnode->set_meta("_editor_description_", metadata["_editor_description_"]);
}
@@ -2321,8 +2294,8 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop
continue;
}
- if (default_oldnode->get(E->get().name) != n->get(E->get().name)) {
- newnode->set(E->get().name, n->get(E->get().name));
+ if (default_oldnode->get(E.name) != n->get(E.name)) {
+ newnode->set(E.name, n->get(E.name));
}
}
@@ -2335,12 +2308,11 @@ void SceneTreeDock::replace_node(Node *p_node, Node *p_by_node, bool p_keep_prop
List<MethodInfo> sl;
n->get_signal_list(&sl);
- for (List<MethodInfo>::Element *E = sl.front(); E; E = E->next()) {
+ for (const MethodInfo &E : sl) {
List<Object::Connection> cl;
- n->get_signal_connection_list(E->get().name, &cl);
+ n->get_signal_connection_list(E.name, &cl);
- for (List<Object::Connection>::Element *F = cl.front(); F; F = F->next()) {
- Object::Connection &c = F->get();
+ for (const Object::Connection &c : cl) {
if (!(c.flags & Object::CONNECT_PERSIST)) {
continue;
}
@@ -2546,13 +2518,13 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_
List<PropertyInfo> pinfo;
node->get_property_list(&pinfo);
- for (PropertyInfo &p : pinfo) {
+ for (const PropertyInfo &p : pinfo) {
if (!(p.usage & PROPERTY_USAGE_EDITOR) || !(p.usage & PROPERTY_USAGE_STORAGE) || p.hint != PROPERTY_HINT_RESOURCE_TYPE) {
continue;
}
Vector<String> valid_types = p.hint_string.split(",");
- for (String &prop_type : valid_types) {
+ for (const String &prop_type : valid_types) {
if (res_type == prop_type || ClassDB::is_parent_class(res_type, prop_type) || EditorNode::get_editor_data().script_class_is_parent(res_type, prop_type)) {
valid_properties.push_back(p.name);
break;
@@ -2566,7 +2538,7 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files, NodePath p_to, int p_
bool capitalize = bool(EDITOR_GET("interface/inspector/capitalize_properties"));
menu_properties->clear();
- for (String &p : valid_properties) {
+ 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);
}
@@ -2607,8 +2579,8 @@ void SceneTreeDock::_nodes_dragged(Array p_nodes, NodePath p_to, int p_type) {
}
Vector<Node *> nodes;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- nodes.push_back(E->get());
+ for (Node *E : selection) {
+ nodes.push_back(E);
}
int to_pos = -1;
@@ -2624,15 +2596,15 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {
List<PropertyInfo> pinfo;
p_obj->get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_EDITOR)) {
+ for (const PropertyInfo &E : pinfo) {
+ if (!(E.usage & PROPERTY_USAGE_EDITOR)) {
continue;
}
- if (E->get().hint != PROPERTY_HINT_RESOURCE_TYPE) {
+ if (E.hint != PROPERTY_HINT_RESOURCE_TYPE) {
continue;
}
- Variant value = p_obj->get(E->get().name);
+ Variant value = p_obj->get(E.name);
if (value.get_type() != Variant::OBJECT) {
continue;
}
@@ -2647,7 +2619,7 @@ void SceneTreeDock::_add_children_to_popup(Object *p_obj, int p_depth) {
menu->add_submenu_item(TTR("Sub-Resources"), "Sub-Resources");
}
int index = menu_subresources->get_item_count();
- menu_subresources->add_icon_item(icon, E->get().name.capitalize(), EDIT_SUBRESOURCE_BASE + subresources.size());
+ menu_subresources->add_icon_item(icon, E.name.capitalize(), EDIT_SUBRESOURCE_BASE + subresources.size());
menu_subresources->set_item_h_offset(index, p_depth * 10 * EDSCALE);
subresources.push_back(obj->get_instance_id());
@@ -2729,8 +2701,8 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_icon_shortcut(get_theme_icon(SNAME("ScriptRemove"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/detach_script"), TOOL_DETACH_SCRIPT);
} else if (full_selection.size() > 1) {
bool script_exists = false;
- for (List<Node *>::Element *E = full_selection.front(); E; E = E->next()) {
- if (!E->get()->get_script().is_null()) {
+ for (Node *E : full_selection) {
+ if (!E->get_script().is_null()) {
script_exists = true;
break;
}
@@ -2753,8 +2725,8 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
}
bool can_replace = true;
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- if (E->get() != edited_scene && (E->get()->get_owner() != edited_scene || E->get()->get_filename() != "")) {
+ for (Node *E : selection) {
+ if (E != edited_scene && (E->get_owner() != edited_scene || E->get_filename() != "")) {
can_replace = false;
break;
}
@@ -3067,8 +3039,8 @@ void SceneTreeDock::_feature_profile_changed() {
}
void SceneTreeDock::_clear_clipboard() {
- for (List<Node *>::Element *E = node_clipboard.front(); E; E = E->next()) {
- memdelete(E->get());
+ for (Node *E : node_clipboard) {
+ memdelete(E);
}
node_clipboard.clear();
clipboard_resource_remap.clear();
@@ -3079,18 +3051,18 @@ void SceneTreeDock::_create_remap_for_node(Node *p_node, Map<RES, RES> &r_remap)
p_node->get_property_list(&props);
bool is_instantiated = EditorPropertyRevert::may_node_be_in_instance(p_node);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant v = p_node->get(E->get().name);
+ Variant v = p_node->get(E.name);
if (v.is_ref()) {
RES res = v;
if (res.is_valid()) {
if (is_instantiated) {
Variant orig;
- if (EditorPropertyRevert::get_instantiated_node_original_property(p_node, E->get().name, orig)) {
+ if (EditorPropertyRevert::get_instantiated_node_original_property(p_node, E.name, orig)) {
if (!EditorPropertyRevert::is_node_property_different(p_node, v, orig)) {
continue;
}
@@ -3115,12 +3087,12 @@ void SceneTreeDock::_create_remap_for_resource(RES p_resource, Map<RES, RES> &r_
List<PropertyInfo> props;
p_resource->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant v = p_resource->get(E->get().name);
+ Variant v = p_resource->get(E.name);
if (v.is_ref()) {
RES res = v;
if (res.is_valid()) {
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index fd9299fb2b..4952122cb7 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -217,7 +217,7 @@ class SceneTreeDock : public VBoxContainer {
void _selection_changed();
void _update_script_button();
- void _fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, List<Pair<NodePath, NodePath>> *p_renames);
+ void _fill_path_renames(Vector<StringName> base_path, Vector<StringName> new_base_path, Node *p_node, Map<Node *, NodePath> *p_renames);
void _normalize_drop(Node *&to_node, int &to_pos, int p_type);
@@ -253,8 +253,8 @@ class SceneTreeDock : public VBoxContainer {
static SceneTreeDock *singleton;
static void _update_configuration_warning();
- static bool _update_node_path(const NodePath &p_root_path, NodePath &r_node_path, List<Pair<NodePath, NodePath>> *p_renames);
- static bool _check_node_path_recursive(const NodePath &p_root_path, Variant &r_variant, List<Pair<NodePath, NodePath>> *p_renames);
+ bool _update_node_path(Node *p_root_node, NodePath &r_node_path, Map<Node *, NodePath> *p_renames) const;
+ bool _check_node_path_recursive(Node *p_root_node, Variant &r_variant, Map<Node *, NodePath> *p_renames) const;
protected:
void _notification(int p_what);
@@ -272,8 +272,8 @@ public:
void instantiate(const String &p_file);
void instantiate_scenes(const Vector<String> &p_files, Node *p_parent = nullptr);
void set_selected(Node *p_node, bool p_emit_selected = false);
- void fill_path_renames(Node *p_node, Node *p_new_parent, List<Pair<NodePath, NodePath>> *p_renames);
- void perform_node_renames(Node *p_base, List<Pair<NodePath, NodePath>> *p_renames, Map<Ref<Animation>, Set<int>> *r_rem_anims = nullptr);
+ void fill_path_renames(Node *p_node, Node *p_new_parent, Map<Node *, NodePath> *p_renames);
+ void perform_node_renames(Node *p_base, Map<Node *, NodePath> *p_renames, Map<Ref<Animation>, Set<int>> *r_rem_anims = nullptr);
SceneTreeEditor *get_tree_editor() { return scene_tree; }
EditorData *get_editor_data() { return editor_data; }
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index c6f2c9253e..83b0203f32 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -79,8 +79,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
_toggle_visible(n);
List<Node *> selection = editor_selection->get_selected_node_list();
if (selection.size() > 1 && selection.find(n) != nullptr) {
- for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
- Node *nv = E->get();
+ for (Node *nv : selection) {
ERR_FAIL_COND(!nv);
if (nv == n) {
continue;
@@ -521,7 +520,7 @@ void SceneTreeEditor::_node_removed(Node *p_node) {
if (p_node == selected) {
selected = nullptr;
- _emit_node_selected();
+ emit_signal("node_selected");
}
}
@@ -615,6 +614,24 @@ void SceneTreeEditor::_tree_changed() {
pending_test_update = true;
}
+void SceneTreeEditor::_selected_changed() {
+ TreeItem *s = tree->get_selected();
+ ERR_FAIL_COND(!s);
+ NodePath np = s->get_metadata(0);
+
+ Node *n = get_node(np);
+
+ if (n == selected) {
+ return;
+ }
+
+ selected = get_node(np);
+
+ blocked++;
+ emit_signal("node_selected");
+ blocked--;
+}
+
void SceneTreeEditor::_deselect_items() {
// Clear currently selected items in scene tree dock.
if (editor_selection) {
@@ -623,12 +640,6 @@ void SceneTreeEditor::_deselect_items() {
}
}
-void SceneTreeEditor::_emit_node_selected() {
- blocked++;
- emit_signal(SNAME("node_selected"));
- blocked--;
-}
-
void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_selected) {
TreeItem *item = Object::cast_to<TreeItem>(p_object);
ERR_FAIL_COND(!item);
@@ -652,11 +663,8 @@ void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_
editor_selection->remove_node(n);
}
- // Selection changed to be single node, so emit "selected" (for single node) rather than "changed" (for multiple nodes)
- if (editor_selection->get_selected_nodes().size() == 1) {
- selected = editor_selection->get_selected_node_list()[0];
- _emit_node_selected();
- } else {
+ // Emitted "selected" in _selected_changed() when select single node, so select multiple node emit "changed"
+ if (editor_selection->get_selected_nodes().size() > 1) {
emit_signal(SNAME("node_changed"));
}
}
@@ -747,7 +755,7 @@ void SceneTreeEditor::set_selected(Node *p_node, bool p_emit_selected) {
}
if (p_emit_selected) {
- _emit_node_selected();
+ emit_signal("node_selected");
}
}
@@ -1197,6 +1205,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
tree->connect("empty_tree_rmb_selected", callable_mp(this, &SceneTreeEditor::_rmb_select));
}
+ tree->connect("cell_selected", callable_mp(this, &SceneTreeEditor::_selected_changed));
tree->connect("item_edited", callable_mp(this, &SceneTreeEditor::_renamed), varray(), CONNECT_DEFERRED);
tree->connect("multi_selected", callable_mp(this, &SceneTreeEditor::_cell_multi_selected));
tree->connect("button_pressed", callable_mp(this, &SceneTreeEditor::_cell_button_pressed));
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index e833bf93e0..acd49e8d92 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -81,6 +81,7 @@ class SceneTreeEditor : public Control {
TreeItem *_find(TreeItem *p_node, const NodePath &p_path);
void _notification(int p_what);
+ void _selected_changed();
void _deselect_items();
void _rename_node(ObjectID p_node, const String &p_name);
@@ -132,8 +133,6 @@ class SceneTreeEditor : public Control {
Vector<StringName> valid_types;
- void _emit_node_selected();
-
public:
void set_filter(const String &p_filter);
String get_filter() const;
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 2601382009..9a4b38db74 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -205,12 +205,12 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
bool found = false;
bool match = false;
int index = 0;
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(extension) == 0) {
+ for (const String &E : extensions) {
+ if (E.nocasecmp_to(extension) == 0) {
//FIXME (?) - changing language this way doesn't update controls, needs rework
//language_menu->select(index); // change Language option by extension
found = true;
- if (E->get() == ScriptServer::get_language(language_menu->get_selected())->get_extension()) {
+ if (E == ScriptServer::get_language(language_menu->get_selected())->get_extension()) {
match = true;
}
break;
@@ -373,8 +373,8 @@ void ScriptCreateDialog::_lang_changed(int l) {
ScriptServer::get_language(m)->get_recognized_extensions(&extensions);
}
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- if (E->get().nocasecmp_to(extension) == 0) {
+ for (const String &E : extensions) {
+ if (E.nocasecmp_to(extension) == 0) {
path = path.get_basename() + selected_ext;
_path_changed(path);
break;
@@ -534,8 +534,8 @@ void ScriptCreateDialog::_browse_path(bool browse_parent, bool p_save) {
int lang = language_menu->get_selected();
ScriptServer::get_language(lang)->get_recognized_extensions(&extensions);
- for (List<String>::Element *E = extensions.front(); E; E = E->next()) {
- file_browse->add_filter("*." + E->get());
+ for (const String &E : extensions) {
+ file_browse->add_filter("*." + E);
}
file_browse->set_current_path(file_path->get_text());
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 0524b91634..b3ec0c96c4 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -324,15 +324,15 @@ void EditorSettingsDialog::_update_shortcuts() {
List<String> slist;
EditorSettings::get_singleton()->get_shortcut_list(&slist);
- for (List<String>::Element *E = slist.front(); E; E = E->next()) {
- Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(E->get());
+ for (const String &E : slist) {
+ Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(E);
if (!sc->has_meta("original")) {
continue;
}
Ref<InputEvent> original = sc->get_meta("original");
- String section_name = E->get().get_slice("/", 0);
+ String section_name = E.get_slice("/", 0);
TreeItem *section;
@@ -372,8 +372,8 @@ void EditorSettingsDialog::_update_shortcuts() {
item->add_button(1, shortcuts->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0);
item->add_button(1, shortcuts->get_theme_icon(SNAME("Close"), SNAME("EditorIcons")), 1);
- item->set_tooltip(0, E->get());
- item->set_metadata(0, E->get());
+ item->set_tooltip(0, E);
+ item->set_metadata(0, E);
}
}
@@ -403,10 +403,9 @@ void EditorSettingsDialog::_shortcut_button_pressed(Object *p_item, int p_column
List<Ref<InputEvent>> defaults = InputMap::get_singleton()->get_builtins()[current_action];
// Convert the list to an array, and only keep key events as this is for the editor.
- for (List<Ref<InputEvent>>::Element *E = defaults.front(); E; E = E->next()) {
- Ref<InputEventKey> k = E->get();
+ for (const Ref<InputEvent> &k : defaults) {
if (k.is_valid()) {
- events.append(E->get());
+ events.append(k);
}
}
diff --git a/editor/translations/af.po b/editor/translations/af.po
index bb7e7ca553..6a74789da2 100644
--- a/editor/translations/af.po
+++ b/editor/translations/af.po
@@ -5251,8 +5251,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index 6d8db6f47b..b851db361f 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -52,12 +52,13 @@
# ILG - Game <moegypt277@gmail.com>, 2021.
# Hatim Jamal <hatimjamal8@gmail.com>, 2021.
# HASSAN GAMER - حسن جيمر <gamerhassan55@gmail.com>, 2021.
+# abubakrAlsaab <madeinsudan19@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-07-09 14:32+0000\n"
-"Last-Translator: HASSAN GAMER - حسن جيمر <gamerhassan55@gmail.com>\n"
+"PO-Revision-Date: 2021-07-16 05:47+0000\n"
+"Last-Translator: abubakrAlsaab <madeinsudan19@gmail.com>\n"
"Language-Team: Arabic <https://hosted.weblate.org/projects/godot-engine/"
"godot/ar/>\n"
"Language: ar\n"
@@ -66,7 +67,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
-"X-Generator: Weblate 4.8-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -3021,7 +3022,7 @@ msgstr "حول"
#: editor/editor_node.cpp
msgid "Support Godot Development"
-msgstr ""
+msgstr "إدعم تطوير محرك غو-دوت"
#: editor/editor_node.cpp
msgid "Play the project."
@@ -5215,9 +5216,10 @@ msgstr ""
"الضوء المعدة مسبقا."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"لايوجد ميش لكي يتم تجهيزة. تاكد من انه يحتوي على منفذ UV2 و ان زر الضوء "
"'المعد' مفعل."
@@ -5342,7 +5344,7 @@ msgstr "تعديل حجم العقدة \"Node2D \"%s إلى (s, %s%)"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Resize Control \"%s\" to (%d, %d)"
-msgstr ""
+msgstr "تغيير حجم عنصر التحكم \"٪ s\" إلى (٪ d،٪ d)"
#: editor/plugins/canvas_item_editor_plugin.cpp
#, fuzzy
@@ -7566,6 +7568,7 @@ msgstr "تدوير الرؤية مقفول"
msgid ""
"To zoom further, change the camera's clipping planes (View -> Settings...)"
msgstr ""
+"للتكبير بشكل أكبر ، قم بتغيير مستويات اقتصاص الكاميرا (عرض -> الإعدادات ...)"
#: editor/plugins/spatial_editor_plugin.cpp
msgid ""
@@ -9536,7 +9539,7 @@ msgstr ""
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "A reference to an existing uniform."
-msgstr ""
+msgstr "إشارة إلى زي موحد موجود."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "(Fragment/Light mode only) Scalar derivative function."
@@ -9903,7 +9906,7 @@ msgstr "OpenGL ES 3.0"
#: editor/project_manager.cpp
msgid "Not supported by your GPU drivers."
-msgstr ""
+msgstr "غير مدعوم من قبل برامج تشغيل GPU(اجهزة اارسوم) الخاصة بك."
#: editor/project_manager.cpp
msgid ""
@@ -10959,6 +10962,9 @@ msgid ""
"every time it updates.\n"
"Switch back to the Local scene tree dock to improve performance."
msgstr ""
+"إذا تم تحديده ، فسيؤدي شجرة المشهد إلى توقف المشروع في كل مرة يتم فيها "
+"تحديثه.\n"
+"قم بالتبديل مرة أخرى إلى رصيف شجرة المشهد المحلي لتحسين الأداء."
#: editor/scene_tree_dock.cpp
msgid "Local"
@@ -11657,11 +11663,11 @@ msgstr ""
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Begin Bake"
-msgstr ""
+msgstr "ابدأ الخبز (دمج تاثير الضوء في الصورة )"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
msgid "Preparing data structures"
-msgstr ""
+msgstr "تحضير هياكل البيانات"
#: modules/lightmapper_cpu/lightmapper_cpu.cpp
#, fuzzy
@@ -12192,7 +12198,7 @@ msgstr "اختر جهازاً من القائمة"
#: platform/android/export/export.cpp
msgid "Unable to find the 'apksigner' tool."
-msgstr ""
+msgstr "تعذر العثور على أداة توقيع تطبيق اندرويد\"apksigner\"."
#: platform/android/export/export.cpp
msgid ""
diff --git a/editor/translations/az.po b/editor/translations/az.po
index 054bc9263d..be05c12c5c 100644
--- a/editor/translations/az.po
+++ b/editor/translations/az.po
@@ -5056,8 +5056,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index 7bf3d40805..9759e3d1e5 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -5042,9 +5042,10 @@ msgstr ""
"Запазете сцената и опитайте отново."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Няма полигонни мрежи за изпичане. Уверете се, че те съдържат канал UV2 и че "
"флагът „Изпичане на светлината“ е включен."
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index 70a66820fb..f4a10f7dea 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -5526,8 +5526,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/br.po b/editor/translations/br.po
index 9d1e52e009..0fe39331f9 100644
--- a/editor/translations/br.po
+++ b/editor/translations/br.po
@@ -5000,8 +5000,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index 1032b7cdeb..40429cc0e0 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -5277,9 +5277,10 @@ msgstr ""
"camí des de les propietats de BakedLightmap."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Cap Malla per precalcular. Comproveu que disposin d'un canal d'UV2 i que "
"l'indicador 'Bake Light' és activat."
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index 3aaf91d758..281bc500f2 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -30,8 +30,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-25 02:57+0000\n"
-"Last-Translator: Vojtěch Šamla <auzkok@seznam.cz>\n"
+"PO-Revision-Date: 2021-07-26 14:18+0000\n"
+"Last-Translator: Zbyněk <zbynek.fiala@gmail.com>\n"
"Language-Team: Czech <https://hosted.weblate.org/projects/godot-engine/godot/"
"cs/>\n"
"Language: cs\n"
@@ -39,7 +39,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-"X-Generator: Weblate 4.7.1-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -5139,7 +5139,7 @@ msgstr "Poslední"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "All"
-msgstr "Všechny"
+msgstr "všichni"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "No results for \"%s\"."
@@ -5194,9 +5194,10 @@ msgstr ""
"Uložte scénu a zkuste to znovu."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Žádné sítě k zapečení. Ujistěte se, že obsahují kanál UV2 a že je nastaven "
"příznak \"Zapéct světlo\"."
@@ -10546,7 +10547,7 @@ msgstr "Hodnota, o kterou se počítadlo zvýší za každý uzel"
#: editor/rename_dialog.cpp
msgid "Padding"
-msgstr "Odsazení"
+msgstr "Zarovnávání"
#: editor/rename_dialog.cpp
msgid ""
diff --git a/editor/translations/da.po b/editor/translations/da.po
index 9e09250fbc..c86ec25b4b 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -5390,8 +5390,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/de.po b/editor/translations/de.po
index bbf72f815b..954f8426f8 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -5289,9 +5289,10 @@ msgstr ""
"Ein Speichern der Szene sollte dieses Problem beheben."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Keine Meshes zum vorrendern vorhanden. Meshes, die vorgerendert werden "
"sollen, müssen einen UV2-Kanal beinhalten und die ‚Bake Light‘-Option "
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index a0f4654639..ae7b6b37dc 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -4980,8 +4980,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -6979,7 +6979,7 @@ msgstr ""
#: editor/plugins/shader_editor_plugin.cpp
msgid ""
-"This shader has been modified on on disk.\n"
+"This shader has been modified on disk.\n"
"What action should be taken?"
msgstr ""
diff --git a/editor/translations/el.po b/editor/translations/el.po
index 035a82f99f..40d8ab46cc 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -5239,9 +5239,10 @@ msgstr ""
"Αποθηκεύστε τη σκηνή σας και δοκιμάστε ξανα."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Δεν υπάρχουν πλέγματα για προετοιμασία. Σιγουρευτείτε ότι εμπεριέχουν κανάλι "
"UV2 και πως η σημαία 'Bake Light' είναι ενεργοποιημένη."
diff --git a/editor/translations/eo.po b/editor/translations/eo.po
index 0523742303..38c72380da 100644
--- a/editor/translations/eo.po
+++ b/editor/translations/eo.po
@@ -5204,8 +5204,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/es.po b/editor/translations/es.po
index 5953536c60..e09d1df8c7 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -72,7 +72,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-07-05 21:41+0000\n"
+"PO-Revision-Date: 2021-07-16 05:47+0000\n"
"Last-Translator: Erick Figueroa <querecuto@hotmail.com>\n"
"Language-Team: Spanish <https://hosted.weblate.org/projects/godot-engine/"
"godot/es/>\n"
@@ -81,7 +81,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.8-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1205,7 +1205,7 @@ msgstr "Desarrollador Principal"
#. you do not have to keep it in your translation.
#: editor/editor_about.cpp
msgid "Project Manager "
-msgstr "Gestor del Proyecto "
+msgstr "Administrador de Proyectos "
#: editor/editor_about.cpp
msgid "Developers"
@@ -3078,7 +3078,7 @@ msgstr "Apoyar el desarrollo de Godot"
#: editor/editor_node.cpp
msgid "Play the project."
-msgstr "Reproducir el proyecto."
+msgstr "Ejecutar el proyecto."
#: editor/editor_node.cpp
msgid "Play"
@@ -5293,9 +5293,10 @@ msgstr ""
"Guarda tu escena e inténtalo de nuevo."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"No hay mallas para hacer bake. Asegúrate que contengan un canal UV2 y que la "
"opción de 'Bake Light' está activada."
@@ -10154,8 +10155,8 @@ msgid ""
"The interface will update after restarting the editor or project manager."
msgstr ""
"Idioma cambiado.\n"
-"La interfaz se actualizará después de reiniciar el editor o el gestor de "
-"proyectos."
+"La interfaz se actualizará después de reiniciar el editor o el administrador "
+"de proyectos."
#: editor/project_manager.cpp
msgid ""
@@ -11737,7 +11738,7 @@ msgstr "Eliminar Rotación del Cursor"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Paste Selects"
-msgstr "Pegar Selecciona"
+msgstr "Pegar Seleccionados"
#: modules/gridmap/grid_map_editor_plugin.cpp
msgid "Clear Selection"
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index d1fe06a565..33c29d9c6e 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -5237,9 +5237,10 @@ msgstr ""
"Guardá tu escena e inténtalo de nuevo."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"No hay meshes para hacer bake. Asegúrate que contienen un canal UV2 y que el "
"flag 'Bake Light' esta activado."
diff --git a/editor/translations/et.po b/editor/translations/et.po
index 05a414f5a9..fd534943b1 100644
--- a/editor/translations/et.po
+++ b/editor/translations/et.po
@@ -10,7 +10,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2021-05-10 15:32+0000\n"
+"PO-Revision-Date: 2021-07-16 05:47+0000\n"
"Last-Translator: Kritzmensch <streef.gtx@gmail.com>\n"
"Language-Team: Estonian <https://hosted.weblate.org/projects/godot-engine/"
"godot/et/>\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1090,7 +1090,7 @@ msgstr "Suur tänu Godot kogukonnalt!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Klõpsa, et kopeerida."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -5039,8 +5039,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -7244,7 +7244,7 @@ msgstr "Kuva tavaliselt"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Wireframe"
-msgstr "Kuva traadiraamina"
+msgstr "Kuva traatraamina"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Display Overdraw"
diff --git a/editor/translations/eu.po b/editor/translations/eu.po
index 87c91de10e..f9f2d97348 100644
--- a/editor/translations/eu.po
+++ b/editor/translations/eu.po
@@ -5012,8 +5012,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index ddccfeaebe..ab4157565e 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -5191,8 +5191,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index 834d1894e3..1007ee660b 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -5195,9 +5195,10 @@ msgstr ""
"Tallenna skenesi ja yritä uudelleen."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Ei meshejä kehitettävänä. Varmista, että ne sisältävät UV2-kanavan, ja että "
"'Bake Light' asetus on päällä."
diff --git a/editor/translations/fil.po b/editor/translations/fil.po
index 892968821b..b23a43088c 100644
--- a/editor/translations/fil.po
+++ b/editor/translations/fil.po
@@ -4998,8 +4998,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index 6fad70a7c2..d4ded02294 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -85,8 +85,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-07-01 14:33+0000\n"
-"Last-Translator: Clément Topy <topy72.mine@gmail.com>\n"
+"PO-Revision-Date: 2021-07-16 05:47+0000\n"
+"Last-Translator: Pierre Caye <pierrecaye@laposte.net>\n"
"Language-Team: French <https://hosted.weblate.org/projects/godot-engine/"
"godot/fr/>\n"
"Language: fr\n"
@@ -94,7 +94,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
-"X-Generator: Weblate 4.8-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -5258,7 +5258,7 @@ msgstr "Dernier"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "All"
-msgstr "Tout"
+msgstr "All"
#: editor/plugins/asset_library_editor_plugin.cpp
msgid "No results for \"%s\"."
@@ -5314,11 +5314,12 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
-"Aucun maillage à transférer. Assurez-vous qu'ils contiennent un canal UV2 et "
-"que l'indicateur « Bake Light » est activé."
+"Aucun maillage à précalculer. Assurez-vous qu'ils contiennent un canal UV2 "
+"et que les propriétés « Use In Bake Light » et « Generate Lightmap » soient "
+"activées."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid "Failed creating lightmap images, make sure path is writable."
diff --git a/editor/translations/ga.po b/editor/translations/ga.po
index 8168c1a440..9db93e38f8 100644
--- a/editor/translations/ga.po
+++ b/editor/translations/ga.po
@@ -4995,8 +4995,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/gl.po b/editor/translations/gl.po
index 016a3ab589..68e7b47599 100644
--- a/editor/translations/gl.po
+++ b/editor/translations/gl.po
@@ -5162,8 +5162,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/he.po b/editor/translations/he.po
index 5dc30a6cc2..a989a8aad0 100644
--- a/editor/translations/he.po
+++ b/editor/translations/he.po
@@ -5214,9 +5214,10 @@ msgstr ""
"ממאפייני BakedLightmap."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr "אין רשתות לאפייה. ודא/י שהם מכילים ערוץ UV2 והדגל 'Bake Light' מאופשר."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/hi.po b/editor/translations/hi.po
index db1dcd67e6..70187feed0 100644
--- a/editor/translations/hi.po
+++ b/editor/translations/hi.po
@@ -5137,8 +5137,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/hr.po b/editor/translations/hr.po
index d737bb04b7..c62d3f3eb5 100644
--- a/editor/translations/hr.po
+++ b/editor/translations/hr.po
@@ -9,7 +9,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
-"PO-Revision-Date: 2021-04-11 22:02+0000\n"
+"PO-Revision-Date: 2021-07-16 05:47+0000\n"
"Last-Translator: LeoClose <leoclose575@gmail.com>\n"
"Language-Team: Croatian <https://hosted.weblate.org/projects/godot-engine/"
"godot/hr/>\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8-bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.6-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -41,7 +41,7 @@ msgstr "Neispravan unos %i (nije uspio) u izrazu"
#: core/math/expression.cpp
msgid "self can't be used because instance is null (not passed)"
-msgstr "self nije moguće koristiti jer je jedinka null (nije uspio)"
+msgstr "self se ne može koristiti jer instanca je null (nije prosljeđena)"
#: core/math/expression.cpp
msgid "Invalid operands to operator %s, %s and %s."
@@ -1716,7 +1716,7 @@ msgstr "Novo"
#: editor/editor_feature_profile.cpp editor/editor_node.cpp
#: editor/project_manager.cpp
msgid "Import"
-msgstr "Uvoz"
+msgstr "Uvezi"
#: editor/editor_feature_profile.cpp editor/project_export.cpp
msgid "Export"
@@ -2861,7 +2861,7 @@ msgstr "Zajednica"
#: editor/editor_node.cpp
msgid "About"
-msgstr ""
+msgstr "U vezi s"
#: editor/editor_node.cpp
msgid "Support Godot Development"
@@ -5009,8 +5009,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index 85933dc05d..7a2e35e37b 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -5180,9 +5180,10 @@ msgstr ""
"tulajdonságaiból."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Nincs mesh, amibe adatokat süthetne. Bizonyosodjon meg arról, hogy "
"tartalmaznak egy UV2 csatornát, és hogy a 'Fény Besütése' opció be van "
diff --git a/editor/translations/id.po b/editor/translations/id.po
index e1029fc231..4dce64fd92 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -5210,9 +5210,10 @@ msgstr ""
"Simpan skena Anda dan coba lagi."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Tidak ada mesh-mesh untuk di bake. Pastikan mereka punya kanal UV2 dan 'Bake "
"Cahaya' menyala."
diff --git a/editor/translations/is.po b/editor/translations/is.po
index fc1423d841..c7d7023690 100644
--- a/editor/translations/is.po
+++ b/editor/translations/is.po
@@ -5051,8 +5051,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/it.po b/editor/translations/it.po
index 60c362c63a..f1de95dac6 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -59,12 +59,13 @@
# Alessandro Mandelli <mandelli.alessandro@ngi.it>, 2021.
# Jusef Azzolina <rosarioazzolina33@gmail.com>, 2021.
# Daniele Basso <tiziodcaio@gmail.com>, 2021.
+# Riteo Siuga <riteo@posteo.net>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-15 19:34+0000\n"
-"Last-Translator: Riteo Siuga <lorenzocerqua@tutanota.com>\n"
+"PO-Revision-Date: 2021-07-26 14:18+0000\n"
+"Last-Translator: Riteo Siuga <riteo@posteo.net>\n"
"Language-Team: Italian <https://hosted.weblate.org/projects/godot-engine/"
"godot/it/>\n"
"Language: it\n"
@@ -72,7 +73,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -876,6 +877,7 @@ msgid "Deferred"
msgstr "Differita"
#: editor/connections_dialog.cpp
+#, fuzzy
msgid ""
"Defers the signal, storing it in a queue and only firing it at idle time."
msgstr ""
@@ -1172,7 +1174,7 @@ msgstr "Grazie dalla comunità di Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Clicca per copiare."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -2348,7 +2350,7 @@ msgid ""
msgstr ""
"Questa scena non può essere salvata perché contiene un'istanziazione "
"ciclica.\n"
-"Riprovare ad eseguire il salvataggio dopo aver risolto il problema."
+"Riprovare a eseguire il salvataggio dopo aver risolto il problema."
#: editor/editor_node.cpp
msgid ""
@@ -2962,7 +2964,7 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Synchronize Scene Changes"
-msgstr "Sincronizza i cambi della scena"
+msgstr "Sincronizza i cambiamenti delle scene"
#: editor/editor_node.cpp
msgid ""
@@ -2978,9 +2980,10 @@ msgstr ""
#: editor/editor_node.cpp
msgid "Synchronize Script Changes"
-msgstr "Sincronizza Modifiche Script"
+msgstr "Sincronizza le modifiche degli script"
#: editor/editor_node.cpp
+#, fuzzy
msgid ""
"When this option is enabled, any script that is saved will be reloaded in "
"the running project.\n"
@@ -2989,7 +2992,7 @@ msgid ""
msgstr ""
"Quando questa opzione è abilitata, qualsiasi script salvato verrà ricaricato "
"nel progetto in esecuzione.\n"
-"Quando usato in remoto su un dispositivo, essa risulta più efficate "
+"Quando usato in remoto su un dispositivo, essa risulta più efficace "
"abilitando l'opzione \"network filesystem\"."
#: editor/editor_node.cpp editor/script_create_dialog.cpp
@@ -3062,6 +3065,7 @@ msgid "Report a Bug"
msgstr "Segnala un problema"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Send Docs Feedback"
msgstr "Valuta la documentazione"
@@ -3078,6 +3082,7 @@ msgid "Support Godot Development"
msgstr "Supporta lo sviluppo di Godot"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Play the project."
msgstr "Esegui il progetto."
@@ -3091,7 +3096,7 @@ msgstr "Metti in pausa l'esecuzione della scena per eseguire il debug."
#: editor/editor_node.cpp
msgid "Pause Scene"
-msgstr "Pausa scena"
+msgstr "Pausa la scena"
#: editor/editor_node.cpp
msgid "Stop the scene."
@@ -3115,7 +3120,7 @@ msgstr "Avvia una scena personalizzata"
#: editor/editor_node.cpp
msgid "Changing the video driver requires restarting the editor."
-msgstr "Il cambiamento dei driver video necessita il riavvio dell'editor."
+msgstr "Il cambiamento dei driver video necessita di un riavvio dell'editor."
#: editor/editor_node.cpp editor/project_settings_editor.cpp
#: editor/settings_config_dialog.cpp
@@ -3131,6 +3136,7 @@ msgid "Update Continuously"
msgstr "Aggiorna continuamente"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Update When Changed"
msgstr "Aggiorna quando modificata"
@@ -3209,16 +3215,17 @@ msgid "Template Package"
msgstr "Pacchetto di modelli"
#: editor/editor_node.cpp
+#, fuzzy
msgid "Export Library"
msgstr "Esporta Libreria"
#: editor/editor_node.cpp
msgid "Merge With Existing"
-msgstr "Unisci Con Esistente"
+msgstr "Unisci con una esistente"
#: editor/editor_node.cpp
msgid "Open & Run a Script"
-msgstr "Apri ed Esegui uno Script"
+msgstr "Apri ed esegui uno script"
#: editor/editor_node.cpp
msgid ""
@@ -3244,7 +3251,7 @@ msgstr "Nuova ereditata"
#: editor/editor_node.cpp
msgid "Load Errors"
-msgstr "Carica errori"
+msgstr "Errori di caricamento"
#: editor/editor_node.cpp editor/plugins/tile_map_editor_plugin.cpp
msgid "Select"
@@ -3252,27 +3259,28 @@ msgstr "Seleziona"
#: editor/editor_node.cpp
msgid "Open 2D Editor"
-msgstr "Apri Editor 2D"
+msgstr "Apri l'editor 2D"
#: editor/editor_node.cpp
msgid "Open 3D Editor"
-msgstr "Apri Editor 3D"
+msgstr "Apri l'editor 3D"
#: editor/editor_node.cpp
msgid "Open Script Editor"
-msgstr "Apri Editor degli script"
+msgstr "Apri l'editor degli script"
#: editor/editor_node.cpp editor/project_manager.cpp
+#, fuzzy
msgid "Open Asset Library"
-msgstr "Apri Libreria degli Asset"
+msgstr "Apri la libreria degli Asset"
#: editor/editor_node.cpp
msgid "Open the next Editor"
-msgstr "Apri l'Editor successivo"
+msgstr "Apri l'editor successivo"
#: editor/editor_node.cpp
msgid "Open the previous Editor"
-msgstr "Apri l'Editor precedente"
+msgstr "Apri l'editor precedente"
#: editor/editor_node.h
msgid "Warning!"
@@ -3284,7 +3292,7 @@ msgstr "Nessuna sottorisorsa trovata."
#: editor/editor_plugin.cpp
msgid "Creating Mesh Previews"
-msgstr "Creazione Anteprime Mesh"
+msgstr "Creando le anteprime delle mesh"
#: editor/editor_plugin.cpp
msgid "Thumbnail..."
@@ -3292,11 +3300,11 @@ msgstr "Miniatura..."
#: editor/editor_plugin_settings.cpp
msgid "Main Script:"
-msgstr "Script Principale:"
+msgstr "Script principale:"
#: editor/editor_plugin_settings.cpp
msgid "Edit Plugin"
-msgstr "Modifica estensione"
+msgstr "Modifica l'estensione"
#: editor/editor_plugin_settings.cpp
msgid "Installed Plugins:"
@@ -3328,32 +3336,37 @@ msgid "Measure:"
msgstr "Misura:"
#: editor/editor_profiler.cpp
+#, fuzzy
msgid "Frame Time (sec)"
-msgstr "Tempo Frame (sec)"
+msgstr "Tempo fotogramma (sec)"
#: editor/editor_profiler.cpp
+#, fuzzy
msgid "Average Time (sec)"
-msgstr "Tempo Medio (sec)"
+msgstr "Tempo medio (sec)"
#: editor/editor_profiler.cpp
+#, fuzzy
msgid "Frame %"
-msgstr "Frame %"
+msgstr "% fotogramma"
#: editor/editor_profiler.cpp
+#, fuzzy
msgid "Physics Frame %"
-msgstr "Fotogramma della Fisica %"
+msgstr "% fotogramma fisico"
#: editor/editor_profiler.cpp
msgid "Inclusive"
msgstr "Inclusivo"
#: editor/editor_profiler.cpp
+#, fuzzy
msgid "Self"
msgstr "Se stesso"
#: editor/editor_profiler.cpp
msgid "Frame #:"
-msgstr "Frame #:"
+msgstr "Fotogramma #:"
#: editor/editor_profiler.cpp
msgid "Time"
@@ -3365,7 +3378,7 @@ msgstr "Chiamate"
#: editor/editor_properties.cpp
msgid "Edit Text:"
-msgstr "Modifica Testo:"
+msgstr "Modifica il testo:"
#: editor/editor_properties.cpp editor/script_create_dialog.cpp
msgid "On"
@@ -3389,55 +3402,57 @@ msgstr "Assegna..."
#: editor/editor_properties.cpp
msgid "Invalid RID"
-msgstr "RID Invalido"
+msgstr "RID non valido"
#: editor/editor_properties.cpp
msgid ""
"The selected resource (%s) does not match any type expected for this "
"property (%s)."
msgstr ""
-"La risorsa selezionata (%s) non corrisponde ad alcun tipo atteso per questa "
-"proprietà (%s)."
+"La risorsa selezionata (%s) non corrisponde ad alcun tipo previsto per "
+"questa proprietà (%s)."
#: editor/editor_properties.cpp
msgid ""
"Can't create a ViewportTexture on resources saved as a file.\n"
"Resource needs to belong to a scene."
msgstr ""
-"Impossibile creare ViewportTexture da risorse salvate come file.\n"
-"La risorsa deve appartenere ad una scena."
+"Impossibile creare un ViewportTexture su delle risorse salvate come file.\n"
+"Esse devono appartenere a una scena."
#: editor/editor_properties.cpp
+#, fuzzy
msgid ""
"Can't create a ViewportTexture on this resource because it's not set as "
"local to scene.\n"
"Please switch on the 'local to scene' property on it (and all resources "
"containing it up to a node)."
msgstr ""
-"Impossibile creare ViewportTexture da questa risorsa perché non è definita "
-"localmente in una scena.\n"
-"Per favore attivare la proprietà \"local to scene\" sulla risorsa (e su "
-"tutte le risorse che la contengono, fino al nodo che le utilizza)."
+"Impossibile creare un VieportTexture su questa risorsa perché non è stata "
+"impostata come locale alla scena.\n"
+"Per favore attivare la properietà \"local to scene\" su di essa (e su tutte "
+"quelle che la contengono fino ad arrivare a un nodo)."
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "Pick a Viewport"
-msgstr "Scegli una Vista"
+msgstr "Selezionare una vista"
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "New Script"
-msgstr "Nuovo Script"
+msgstr "Nuovo script"
#: editor/editor_properties.cpp editor/scene_tree_dock.cpp
msgid "Extend Script"
-msgstr "Estendi Script"
+msgstr "Estendi script"
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "New %s"
msgstr "Nuovo %s"
#: editor/editor_properties.cpp editor/property_editor.cpp
+#, fuzzy
msgid "Make Unique"
-msgstr "Rendi Unico"
+msgstr "Rendi unico"
#: editor/editor_properties.cpp
#: editor/plugins/animation_blend_space_1d_editor.cpp
@@ -3455,11 +3470,12 @@ msgstr "Incolla"
#: editor/editor_properties.cpp editor/property_editor.cpp
msgid "Convert To %s"
-msgstr "Converti In %s"
+msgstr "Converti in %s"
#: editor/editor_properties.cpp editor/property_editor.cpp
+#, fuzzy
msgid "Selected node is not a Viewport!"
-msgstr "Il nodo selezionato non è una Viewport!"
+msgstr "Il nodo selezionato non è un Viewport!"
#: editor/editor_properties_array_dict.cpp
msgid "Size: "
@@ -3472,19 +3488,19 @@ msgstr "Pagina: "
#: editor/editor_properties_array_dict.cpp
#: editor/plugins/theme_editor_plugin.cpp
msgid "Remove Item"
-msgstr "Rimuovi Elemento"
+msgstr "Rimuovi l'elemento"
#: editor/editor_properties_array_dict.cpp
msgid "New Key:"
-msgstr "Nuova Chiave:"
+msgstr "Nuova chiave:"
#: editor/editor_properties_array_dict.cpp
msgid "New Value:"
-msgstr "Nuovo Valore:"
+msgstr "Nuovo valore:"
#: editor/editor_properties_array_dict.cpp
msgid "Add Key/Value Pair"
-msgstr "Aggiungi Coppia Chiave/Valore"
+msgstr "Aggiungi una coppia chiave/valore"
#: editor/editor_run_native.cpp
msgid ""
@@ -3492,13 +3508,15 @@ msgid ""
"Please add a runnable preset in the Export menu or define an existing preset "
"as runnable."
msgstr ""
-"Nessuna esportazione eseguibile trovata per questa piattaforma.\n"
-"Per favore, aggiungi un preset eseguibile nel menù Export oppure definisci "
-"un preset già esistente come \"eseguibile\"."
+"Nessuna preimpostazione di esportazione eseguibile trovata per questa "
+"piattaforma.\n"
+"Per favore, aggiungerne una nel menù di esportazione o impostarne una già "
+"esistente come eseguibile."
#: editor/editor_run_script.cpp
+#, fuzzy
msgid "Write your logic in the _run() method."
-msgstr "Scrivi la logica nel metodo _run()."
+msgstr "Inserire la logica dello script nel metodo _run()."
#: editor/editor_run_script.cpp
msgid "There is an edited scene already."
@@ -4499,7 +4517,7 @@ msgstr "Rimuovi Triangolo BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "BlendSpace2D does not belong to an AnimationTree node."
-msgstr "BlendSpace2D non appartiene ad un nodo AnimationTree."
+msgstr "BlendSpace2D non appartiene a un nodo AnimationTree."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "No triangles exist, so no blending can take place."
@@ -5292,9 +5310,10 @@ msgstr ""
"Salva la scena e riprova."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Nessuna mesh da preprocessare. Assicurarsi che contengano un canale UV2 e "
"che la spunta \"Bake Light\" sia abilitata."
@@ -6658,7 +6677,7 @@ msgstr "Spostare il giunto"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid ""
"The skeleton property of the Polygon2D does not point to a Skeleton2D node"
-msgstr "La proprietà scheletro del Polygon2D non punta ad un nodo Skeleton2D"
+msgstr "La proprietà scheletro del Polygon2D non punta a un nodo Skeleton2D"
#: editor/plugins/polygon_2d_editor_plugin.cpp
msgid "Sync Bones"
@@ -6914,7 +6933,7 @@ msgstr "Preloader Risorsa"
#: editor/plugins/root_motion_editor_plugin.cpp
msgid "AnimationTree has no path set to an AnimationPlayer"
-msgstr "AnimationTree non ha nessun percorso impostato ad un AnimationPlayer"
+msgstr "AnimationTree non ha nessun percorso impostato a un AnimationPlayer"
#: editor/plugins/root_motion_editor_plugin.cpp
msgid "Path to AnimationPlayer is invalid"
@@ -6982,10 +7001,11 @@ msgid "Script is not in tool mode, will not be able to run."
msgstr "Lo script non è in modalità tool, non sarà possibile eseguirlo."
#: editor/plugins/script_editor_plugin.cpp
+#, fuzzy
msgid ""
"To run this script, it must inherit EditorScript and be set to tool mode."
msgstr ""
-"Per eseguire questo script, esso deve ereditare EditorScript ed essere "
+"Per eseguire questo script, esso deve ereditare da EditorScript ed essere "
"impostato in modalità tool."
#: editor/plugins/script_editor_plugin.cpp
@@ -9322,8 +9342,9 @@ msgid "Finds the nearest even integer to the parameter."
msgstr "Trova il numero intero pari più vicino al parametro."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid "Clamps the value between 0.0 and 1.0."
-msgstr "Blocca il valore tra 0.0 ed 1.0."
+msgstr "Blocca il valore tra 0.0 e 1.0."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "Extracts the sign of the parameter."
@@ -9342,6 +9363,7 @@ msgid "Returns the square root of the parameter."
msgstr "Restituisce la radice quadrata del parametro."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"SmoothStep function( scalar(edge0), scalar(edge1), scalar(x) ).\n"
"\n"
@@ -9353,7 +9375,7 @@ msgstr ""
"\n"
"Restituisce 0.0 se \"x\" è più piccolo di \"edge0\", o 1.0 se \"x\" è più "
"grande di \"edge1\". Altrimenti, il valore di ritorno è interpolato tra 0.0 "
-"ed 1.0 usando i polinomi di Hermite."
+"e 1.0 usando i polinomi di Hermite."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid ""
@@ -9430,6 +9452,7 @@ msgid "Transform function."
msgstr "Funzione di trasformazione."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"Calculate the outer product of a pair of vectors.\n"
"\n"
@@ -9513,6 +9536,7 @@ msgid "Calculates the dot product of two vectors."
msgstr "Calcola il prodotto scalare di due vettori."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"Returns the vector that points in the same direction as a reference vector. "
"The function has three vector parameters : N, the vector to orient, I, the "
@@ -9562,6 +9586,7 @@ msgid "Returns the vector that points in the direction of refraction."
msgstr "Restituisce un vettore che punta nella direzione della refrazione."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n"
"\n"
@@ -9571,11 +9596,12 @@ msgid ""
msgstr ""
"SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n"
"\n"
-"Restituisce 0.0 se \"x\" è minore di \"edge0\", ed 1.0 se \"x\" è più grande "
-"di \"edge1\". Altrimenti, il valore di ritorno è interpolato tra 0.0 ed 1.0 "
+"Restituisce 0.0 se \"x\" è minore di \"edge0\", e 1.0 se \"x\" è più grande "
+"di \"edge1\". Altrimenti, il valore di ritorno è interpolato tra 0.0 e 1.0 "
"usando i polinomiali di Hermite."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n"
"\n"
@@ -9585,8 +9611,8 @@ msgid ""
msgstr ""
"SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n"
"\n"
-"Restituisce 0.0 se \"x\" è minore di \"edge0\", ed 1.0 se \"x\" è più grande "
-"di \"edge1\". Altrimenti, il valore di ritorno è interpolato tra 0.0 ed 1.0 "
+"Restituisce 0.0 se \"x\" è minore di \"edge0\", e 1.0 se \"x\" è più grande "
+"di \"edge1\". Altrimenti, il valore di ritorno è interpolato tra 0.0 e 1.0 "
"usando i polinomiali di Hermite."
#: editor/plugins/visual_shader_editor_plugin.cpp
@@ -9638,13 +9664,14 @@ msgid "Vector uniform."
msgstr "Uniforme vettore."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"Custom Godot Shader Language expression, with custom amount of input and "
"output ports. This is a direct injection of code into the vertex/fragment/"
"light function, do not use it to write the function declarations inside."
msgstr ""
"Una espressione del Custom Godot Shader Language, con quantità "
-"personalizzabile di porte input ed output. Questa è una iniezione diretta di "
+"personalizzabile di porte input e output. Questa è una iniezione diretta di "
"codice nella funzione vertex/fragment/light. Non usarla per scrivere le "
"dichiarazione della funzione all'interno."
@@ -9654,7 +9681,7 @@ msgid ""
"direction of camera (pass associated inputs to it)."
msgstr ""
"Restituisce il decadimento in base al prodotto scalare della normale della "
-"superfice e direzione della telecamera (passa gli input associati ad essa)."
+"superfice e direzione della telecamera (passa gli input associati a essa)."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid ""
@@ -9669,8 +9696,9 @@ msgstr ""
"dichiarare varianti, uniformi e costanti."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid "A reference to an existing uniform."
-msgstr "Un riferimento ad una uniform esistente."
+msgstr "Un riferimento a una uniform esistente."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "(Fragment/Light mode only) Scalar derivative function."
@@ -9713,20 +9741,22 @@ msgstr ""
"differenziazione locale."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and "
"'y'."
msgstr ""
"(Soltanto modalità Fragment/Light) (Vettore) Somma delle derivate assolute "
-"in \"x\" ed \"y\"."
+"in \"x\" e \"y\"."
#: editor/plugins/visual_shader_editor_plugin.cpp
+#, fuzzy
msgid ""
"(Fragment/Light mode only) (Scalar) Sum of absolute derivative in 'x' and "
"'y'."
msgstr ""
"(Soltanto modalità Fragment/Light) (Scalare) Somma delle derivate assolute "
-"in \"x\" ed \"y\"."
+"in \"x\" e \"y\"."
#: editor/plugins/visual_shader_editor_plugin.cpp
msgid "VisualShader"
@@ -9757,13 +9787,14 @@ msgstr ""
"I template di esportazione sembrano essere mancanti o non validi."
#: editor/project_export.cpp
+#, fuzzy
msgid ""
"Failed to export the project for platform '%s'.\n"
"This might be due to a configuration issue in the export preset or your "
"export settings."
msgstr ""
"Impossibile esportare il progetto per la piattaforma \"%s\".\n"
-"Questo potrebbe essere dovuto ad un problema di configurazione nel preset di "
+"Questo potrebbe essere dovuto a un problema di configurazione nel preset di "
"esportazione o nelle impostazioni di esportazione."
#: editor/project_export.cpp
@@ -12264,7 +12295,7 @@ msgstr "L'oggetto base non è un Nodo!"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Path does not lead Node!"
-msgstr "Il percorso non conduce ad un Nodo!"
+msgstr "Il percorso non conduce a un Nodo!"
#: modules/visual_script/visual_script_func_nodes.cpp
msgid "Invalid index property name '%s' in node %s."
@@ -12676,7 +12707,7 @@ msgid ""
"CollisionObject2D derived node. Please only use it as a child of Area2D, "
"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
msgstr ""
-"CollisionPolygon2D serve a fornire una forma di collisione ad un nodo "
+"CollisionPolygon2D serve a fornire una forma di collisione a un nodo "
"derivato di CollisionObject2D. Si prega di utilizzarlo solamente come figlio "
"di Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. in modo da "
"dargli una forma."
@@ -12698,13 +12729,14 @@ msgstr ""
"costruzione \"Segmenti\"."
#: scene/2d/collision_shape_2d.cpp
+#, fuzzy
msgid ""
"CollisionShape2D only serves to provide a collision shape to a "
"CollisionObject2D derived node. Please only use it as a child of Area2D, "
"StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."
msgstr ""
-"CollisionShape2D serve a fornire una forma di collisione ad un nodo derivato "
-"di CollisionObject2D. Si prega di utilizzarlo solamente come figlio di "
+"CollisionShape2D serve a fornire una forma di collisione a un nodo derivato "
+"da CollisionObject2D. Si prega di utilizzarlo solamente come figlio di "
"Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. in modo da dargli "
"una forma."
@@ -12840,9 +12872,9 @@ msgstr ""
"Modifica invece la dimensione nelle forme di collisione figlie."
#: scene/2d/remote_transform_2d.cpp
+#, fuzzy
msgid "Path property must point to a valid Node2D node to work."
-msgstr ""
-"La proprietà path deve puntare ad un nodo Node2D valido per funzionare."
+msgstr "La proprietà path deve puntare a un nodo Node2D valido per funzionare."
#: scene/2d/skeleton_2d.cpp
msgid "This Bone2D chain should end at a Skeleton2D node."
@@ -12888,11 +12920,12 @@ msgid "ARVRController must have an ARVROrigin node as its parent."
msgstr "ARVRController deve avere un nodo ARVROrigin come genitore."
#: scene/3d/arvr_nodes.cpp
+#, fuzzy
msgid ""
"The controller ID must not be 0 or this controller won't be bound to an "
"actual controller."
msgstr ""
-"L'id del controller non deve essere 0 o non verrà associato ad un controller "
+"L'id del controller non deve essere 0 o non verrà associato a un controller "
"attuale."
#: scene/3d/arvr_nodes.cpp
@@ -12900,11 +12933,12 @@ msgid "ARVRAnchor must have an ARVROrigin node as its parent."
msgstr "ARVRAnchor deve avere un nodo ARVROrigin come genitore."
#: scene/3d/arvr_nodes.cpp
+#, fuzzy
msgid ""
"The anchor ID must not be 0 or this anchor won't be bound to an actual "
"anchor."
msgstr ""
-"L'ID dell'ancora non deve essere 0 oppure non verrà associato ad un'ancora "
+"L'ID dell'ancora non deve essere 0 oppure non verrà associato a un'ancora "
"attuale."
#: scene/3d/arvr_nodes.cpp
@@ -12947,28 +12981,29 @@ msgstr ""
"definire la sua forma."
#: scene/3d/collision_polygon.cpp
+#, fuzzy
msgid ""
"CollisionPolygon only serves to provide a collision shape to a "
"CollisionObject derived node. Please only use it as a child of Area, "
"StaticBody, RigidBody, KinematicBody, etc. to give them a shape."
msgstr ""
-"CollisionPolygon serve solamente a fornire una forma di collisione ad un "
-"nodo derivato di CollisionObject. Si prega di usarlo solamente come figlio "
-"di Area, StaticBody, RigidBody, KinematicBody, etc. in modo da dargli una "
-"forma."
+"CollisionPolygon serve solamente a fornire una forma di collisione a un nodo "
+"derivato da CollisionObject. Si prega di usarlo solamente come figlio di "
+"Area, StaticBody, RigidBody, KinematicBody, etc. in modo da dargli una forma."
#: scene/3d/collision_polygon.cpp
msgid "An empty CollisionPolygon has no effect on collision."
msgstr "Un CollisionPolygon vuoto non ha effetti in collisione."
#: scene/3d/collision_shape.cpp
+#, fuzzy
msgid ""
"CollisionShape only serves to provide a collision shape to a CollisionObject "
"derived node. Please only use it as a child of Area, StaticBody, RigidBody, "
"KinematicBody, etc. to give them a shape."
msgstr ""
-"CollisionShape serve a fornire una forma di collisione ad un nodo derivato "
-"di CollisionObject. Si prega di utilizzarlo solamente come figlio di Area, "
+"CollisionShape serve a fornire una forma di collisione a un nodo derivato da "
+"CollisionObject. Si prega di utilizzarlo solamente come figlio di Area, "
"StaticBody, RigidBody, KinematicBody, etc. in modo da dargli una forma."
#: scene/3d/collision_shape.cpp
@@ -13288,13 +13323,14 @@ msgid "If \"Exp Edit\" is enabled, \"Min Value\" must be greater than 0."
msgstr "Se \"Exp Edit\" è abilitato, \"Min Value\" deve essere maggiore di 0."
#: scene/gui/scroll_container.cpp
+#, fuzzy
msgid ""
"ScrollContainer is intended to work with a single child control.\n"
"Use a container as child (VBox, HBox, etc.), or a Control and set the custom "
"minimum size manually."
msgstr ""
"ScrollContainer è inteso per funzionare con un singolo figlio di controllo.\n"
-"Usa un container come figlio (VBox, HBox, ect.), oppure un nodo Control ed "
+"Usa un container come figlio (VBox, HBox, ect.), oppure un nodo Control e "
"imposta la dimensione minima personalizzata manualmente."
#: scene/gui/tree.cpp
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 1fd770fe13..45977a890f 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -5214,9 +5214,10 @@ msgstr ""
"シーンを保存してから再度行ってください。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"ベイクするメッシュがありません。メッシュに UV2チャンネルが含まれてお"
"り、'Bake Light' フラグがオンになっていることを確認してください。"
diff --git a/editor/translations/ka.po b/editor/translations/ka.po
index 587624651a..7a108d6f95 100644
--- a/editor/translations/ka.po
+++ b/editor/translations/ka.po
@@ -5176,8 +5176,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/km.po b/editor/translations/km.po
index fe396cf590..33e9b00daf 100644
--- a/editor/translations/km.po
+++ b/editor/translations/km.po
@@ -4986,8 +4986,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index ec9fed24ca..877f572f48 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -27,7 +27,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-20 13:35+0000\n"
+"PO-Revision-Date: 2021-07-16 05:47+0000\n"
"Last-Translator: Myeongjin Lee <aranet100@gmail.com>\n"
"Language-Team: Korean <https://hosted.weblate.org/projects/godot-engine/"
"godot/ko/>\n"
@@ -36,7 +36,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.7\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -5182,9 +5182,10 @@ msgstr ""
"당신의 씬을 저장하고 다시 시도하세요."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"라이트맵을 구울 메시가 없습니다. 메시가 UV2 채널을 갖고 있고 'Bake Light' 플"
"래그가 켜져 있는지 확인해주세요."
diff --git a/editor/translations/lt.po b/editor/translations/lt.po
index 6df1f44cfb..f4043f1de2 100644
--- a/editor/translations/lt.po
+++ b/editor/translations/lt.po
@@ -5145,8 +5145,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/lv.po b/editor/translations/lv.po
index 8c8a0011c7..a4c8d10715 100644
--- a/editor/translations/lv.po
+++ b/editor/translations/lv.po
@@ -5038,8 +5038,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/mi.po b/editor/translations/mi.po
index 36a93be0ee..5a847e6594 100644
--- a/editor/translations/mi.po
+++ b/editor/translations/mi.po
@@ -4978,8 +4978,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/mk.po b/editor/translations/mk.po
index 7e5aa06f3c..001542b888 100644
--- a/editor/translations/mk.po
+++ b/editor/translations/mk.po
@@ -4985,8 +4985,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/ml.po b/editor/translations/ml.po
index 3919011ade..f7bc8349bc 100644
--- a/editor/translations/ml.po
+++ b/editor/translations/ml.po
@@ -4993,8 +4993,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/mr.po b/editor/translations/mr.po
index 4d81595cb1..66157f77d1 100644
--- a/editor/translations/mr.po
+++ b/editor/translations/mr.po
@@ -4985,8 +4985,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/ms.po b/editor/translations/ms.po
index 6226d644a3..d8714d6196 100644
--- a/editor/translations/ms.po
+++ b/editor/translations/ms.po
@@ -14,7 +14,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-05-29 13:49+0000\n"
+"PO-Revision-Date: 2021-07-23 12:59+0000\n"
"Last-Translator: Keviindran Ramachandran <keviinx@yahoo.com>\n"
"Language-Team: Malay <https://hosted.weblate.org/projects/godot-engine/godot/"
"ms/>\n"
@@ -23,7 +23,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -459,7 +459,7 @@ msgstr "Kunci Gerak Anim"
#: editor/animation_track_editor.cpp
#: modules/visual_script/visual_script_editor.cpp
msgid "Clipboard is empty!"
-msgstr ""
+msgstr "Papan klip kosong!"
#: editor/animation_track_editor.cpp
msgid "Paste Tracks"
@@ -1122,7 +1122,7 @@ msgstr "Terima kasih dari komuniti Godot!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Klik untuk salin."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -1624,16 +1624,15 @@ msgstr ""
"GLES3. Aktifkan 'Import Etc 2' atau 'Import Pvrtc' dalam Tetapan Projek."
#: editor/editor_export.cpp
-#, fuzzy
msgid ""
"Target platform requires 'PVRTC' texture compression for the driver fallback "
"to GLES2.\n"
"Enable 'Import Pvrtc' in Project Settings, or disable 'Driver Fallback "
"Enabled'."
msgstr ""
-"Platform sasaran memerlukan pemampatan tekstur 'ETC' untuk sandaran pemandu "
+"Platform sasaran memerlukan pemampatan tekstur 'PVRTC' untuk sandaran driver "
"ke GLES2.\n"
-"Aktifkan 'Import Etc' dalam Tetapan Projek, atau nyahaktifkan 'Driver "
+"Aktifkan 'Import Pvrtc' dalam Tetapan Projek, atau nyahaktifkan 'Driver "
"Fallback Enabled'."
#: editor/editor_export.cpp platform/android/export/export.cpp
@@ -2335,9 +2334,8 @@ msgid "Layout name not found!"
msgstr "Nama susun atur tidak dijumpai!"
#: editor/editor_node.cpp
-#, fuzzy
msgid "Restored the Default layout to its base settings."
-msgstr "Tata letak lalai telah dipulihkan ke tetapan asas."
+msgstr "Susun atur lalai telah dipulihkan ke tetapan asas."
#: editor/editor_node.cpp
msgid ""
@@ -4501,34 +4499,34 @@ msgstr "Tetapkan kedudukan pengadunan dalam ruang"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Select and move points, create points with RMB."
-msgstr ""
+msgstr "Pilih dan pindahkan titik-titik, cipta titik-titik dengan RMB."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp scene/gui/graph_edit.cpp
msgid "Enable snap and show grid."
-msgstr ""
+msgstr "Aktifkan snap dan tunjukkan grid."
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Point"
-msgstr ""
+msgstr "Titik"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
msgid "Open Editor"
-msgstr ""
+msgstr "Buka Editor"
#: editor/plugins/animation_blend_space_1d_editor.cpp
#: editor/plugins/animation_blend_space_2d_editor.cpp
#: editor/plugins/animation_blend_tree_editor_plugin.cpp
#: editor/plugins/animation_state_machine_editor.cpp
msgid "Open Animation Node"
-msgstr ""
+msgstr "Buka Nod Animasi"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Triangle already exists."
-msgstr ""
+msgstr "Segi tiga sudah wujud."
#: editor/plugins/animation_blend_space_2d_editor.cpp
#, fuzzy
@@ -4537,39 +4535,40 @@ msgstr "Anim Tambah Trek"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Change BlendSpace2D Limits"
-msgstr ""
+msgstr "Tukar Had-had BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Change BlendSpace2D Labels"
-msgstr ""
+msgstr "Tukar Label-label BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Remove BlendSpace2D Point"
-msgstr ""
+msgstr "Keluarkan Titik BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Remove BlendSpace2D Triangle"
-msgstr ""
+msgstr "Keluarkan Segi tiga BlendSpace2D"
#: editor/plugins/animation_blend_space_2d_editor.cpp
+#, fuzzy
msgid "BlendSpace2D does not belong to an AnimationTree node."
-msgstr ""
+msgstr "BlendSpace2D bukan milik nod AnimationTree."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "No triangles exist, so no blending can take place."
-msgstr ""
+msgstr "Tiada segi tiga-segi tiga wujud, jadi tiada pengadunan boleh berlaku."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Toggle Auto Triangles"
-msgstr ""
+msgstr "Togol Segi Tiga Auto"
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Create triangles by connecting points."
-msgstr ""
+msgstr "Cipta segi tiga dengan menhubungkan titik-titik."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Erase points and triangles."
-msgstr ""
+msgstr "Padamkan titik-titik dan segi tiga-segi tiga."
#: editor/plugins/animation_blend_space_2d_editor.cpp
msgid "Generate blend triangles automatically (instead of manually)"
@@ -5334,8 +5333,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index 042ee8d26f..c36274abba 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -5427,8 +5427,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index 2410cd5ad0..296291e435 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -46,12 +46,13 @@
# T-rex08 <ipadtriceratops@gmail.com>, 2021.
# Dwarffish <hoogvlietjohan@gmail.com>, 2021.
# Arthur de Roos <arthur.de.roos@gmail.com>, 2021.
+# Vancha March <tjipkevdh@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-06-05 08:32+0000\n"
-"Last-Translator: Stijn Hinlopen <f.a.hinlopen@gmail.com>\n"
+"PO-Revision-Date: 2021-07-26 14:18+0000\n"
+"Last-Translator: Vancha March <tjipkevdh@gmail.com>\n"
"Language-Team: Dutch <https://hosted.weblate.org/projects/godot-engine/godot/"
"nl/>\n"
"Language: nl\n"
@@ -59,7 +60,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.7-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -1162,7 +1163,7 @@ msgstr "Bedankt van de Godot gemeenschap!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
-msgstr ""
+msgstr "Klik om te kopiëren."
#: editor/editor_about.cpp
msgid "Godot Engine contributors"
@@ -5243,9 +5244,10 @@ msgstr ""
"Sla uw scène op en probeer opnieuw."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Geen meshes om te bakken. Zorg ervoor dat ze een UV2 kanaal bevatten en dat "
"'Bake Light' vlag aan staat."
diff --git a/editor/translations/or.po b/editor/translations/or.po
index 87528cdac5..c1d191a4a5 100644
--- a/editor/translations/or.po
+++ b/editor/translations/or.po
@@ -4984,8 +4984,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index 3c51593e02..d933e8f92b 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -52,8 +52,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-07-05 14:32+0000\n"
-"Last-Translator: Rafal Brozio <rafal.brozio@gmail.com>\n"
+"PO-Revision-Date: 2021-07-16 05:47+0000\n"
+"Last-Translator: Tomek <kobewi4e@gmail.com>\n"
"Language-Team: Polish <https://hosted.weblate.org/projects/godot-engine/"
"godot/pl/>\n"
"Language: pl\n"
@@ -62,7 +62,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2;\n"
-"X-Generator: Weblate 4.8-dev\n"
+"X-Generator: Weblate 4.7.2-dev\n"
#: core/math/expression.cpp modules/gdscript/gdscript_functions.cpp
#: modules/visual_script/visual_script_builtin_funcs.cpp
@@ -5229,9 +5229,10 @@ msgstr ""
"Zapisz scenę i spróbuj ponownie."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Brak siatek do cieniowania. Upewnij się, że zawierają kanał UV2 i że flaga "
"\"Bake Light\" jest ustawiona."
@@ -5760,7 +5761,7 @@ msgstr "Powiększ do zaznaczenia"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Preview Canvas Scale"
-msgstr "Skala płótna podglądu"
+msgstr "Podejrzyj skalę płótna"
#: editor/plugins/canvas_item_editor_plugin.cpp
msgid "Translation mask for inserting keys."
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index 675c9cf506..9b586ad756 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -5153,8 +5153,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/pt.po b/editor/translations/pt.po
index 17b1861821..6eb24001a5 100644
--- a/editor/translations/pt.po
+++ b/editor/translations/pt.po
@@ -5209,9 +5209,10 @@ msgstr ""
"Guarde a sua cena e tente novamente."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Não há malhas para consolidar. Assegure-se que contêm um canal UV2 e que a "
"referência 'Bake Light' flag está on."
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index e79dd0fa19..01f6220bbd 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -5320,9 +5320,10 @@ msgstr ""
"Salve sua cena e tente novamente."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Não há malhas para preparar. Certifique-se de que elas possuem um canal UV2 "
"e que a propriedade \"Preparar Luz\" está habilitada."
diff --git a/editor/translations/ro.po b/editor/translations/ro.po
index 7ac06fc1b1..3b5af5fe1a 100644
--- a/editor/translations/ro.po
+++ b/editor/translations/ro.po
@@ -5218,9 +5218,10 @@ msgstr ""
"cale de salvare din proprietățile BakedLightmap."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Nicio structură pentru procesare. Asigură-te că acestea conțin un canal UV2 "
"și că opțiunea 'Procesează Lumina' este pornită."
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index 4b56d21383..e02b70b16d 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -97,12 +97,13 @@
# Bualma Show <appleaidar6@gmail.com>, 2021.
# enderlorde <madel.laboratories@gmail.com>, 2021.
# Олег Довгер <oleg.a.dovger@gmail.com>, 2021.
+# Anna Malinovskaia <tacitcoast@gmail.com>, 2021.
msgid ""
msgstr ""
"Project-Id-Version: Godot Engine editor\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2021-07-13 06:13+0000\n"
-"Last-Translator: Danil Alexeev <danil@alexeev.xyz>\n"
+"PO-Revision-Date: 2021-07-19 09:34+0000\n"
+"Last-Translator: Anna Malinovskaia <tacitcoast@gmail.com>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/godot-engine/"
"godot/ru/>\n"
"Language: ru\n"
@@ -5286,9 +5287,10 @@ msgstr ""
"Сохраните сцену и попробуйте ещё раз."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Нет полисеток для запекания. Убедитесь, что они содержат канал UV2 и что "
"флаг «Запекание света» включён."
diff --git a/editor/translations/si.po b/editor/translations/si.po
index a5586af274..36abdd4774 100644
--- a/editor/translations/si.po
+++ b/editor/translations/si.po
@@ -5024,8 +5024,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index d97e1321ef..cb56bb037e 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -5183,9 +5183,10 @@ msgstr ""
"na uloženie so BakedLightmap vlastností."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Žiadne mesh-e na bake. Uistite sa že obsahujú UV2 channel a je na ňom 'Bake "
"Light' vlajka."
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index 07bd33c389..42f0bfc2cb 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -5419,9 +5419,10 @@ msgstr ""
"shranitev iz lastnosti Zapečene Svetlobne karte."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Brez modelov za peko. Poskrbi, da vsebujejo kanal UV2 in da je vključena "
"oznaka 'Zapeči Svetlobo'."
diff --git a/editor/translations/sq.po b/editor/translations/sq.po
index 49a42b5553..f054de99bd 100644
--- a/editor/translations/sq.po
+++ b/editor/translations/sq.po
@@ -5273,8 +5273,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/sr_Cyrl.po b/editor/translations/sr_Cyrl.po
index 53fb04b3e4..5d4f6cab1b 100644
--- a/editor/translations/sr_Cyrl.po
+++ b/editor/translations/sr_Cyrl.po
@@ -5682,8 +5682,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Нема мрежа за печење. Провери да ли садрже UV2 канал и да је опција 'Изпеци "
"Светла' укључена."
diff --git a/editor/translations/sr_Latn.po b/editor/translations/sr_Latn.po
index 0a90379b41..49f7cd7f3e 100644
--- a/editor/translations/sr_Latn.po
+++ b/editor/translations/sr_Latn.po
@@ -5048,8 +5048,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/sv.po b/editor/translations/sv.po
index 0c5db25a9a..79c1c4a1b9 100644
--- a/editor/translations/sv.po
+++ b/editor/translations/sv.po
@@ -5277,8 +5277,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/ta.po b/editor/translations/ta.po
index 0c9022b097..45eef9a8f6 100644
--- a/editor/translations/ta.po
+++ b/editor/translations/ta.po
@@ -5033,8 +5033,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/te.po b/editor/translations/te.po
index 8274d5520f..47338f3f28 100644
--- a/editor/translations/te.po
+++ b/editor/translations/te.po
@@ -4987,8 +4987,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/th.po b/editor/translations/th.po
index e9c2a80a49..fc38c35df9 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -5125,9 +5125,10 @@ msgstr ""
"ลองบันทึกฉากของคุณแล้วลองอีกครั้ง"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"ไม่มีพื้นผิวให้สร้าง lightmap กรุณาตรวจสอบว่าพื้นผิวมี UV2 และได้เปิดใช้งาน 'Bake Light'"
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index 578d7b48d0..4f3eb3ff60 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -5250,9 +5250,10 @@ msgstr ""
"Sahneyi kaydedip tekrar deneyin."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Pişirilecek örüntüler yok. Örüntülerin UV2 kanalı içerdiğinden ve 'Bake "
"Light' bayrağınının açık olduğundan emin olun."
diff --git a/editor/translations/tt.po b/editor/translations/tt.po
index 3e63f2369d..d5d41b7879 100644
--- a/editor/translations/tt.po
+++ b/editor/translations/tt.po
@@ -4987,8 +4987,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/tzm.po b/editor/translations/tzm.po
index 0b0ce7d01e..fdb092c6a4 100644
--- a/editor/translations/tzm.po
+++ b/editor/translations/tzm.po
@@ -4985,8 +4985,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/uk.po b/editor/translations/uk.po
index 50508c5df3..66c69938f6 100644
--- a/editor/translations/uk.po
+++ b/editor/translations/uk.po
@@ -5222,9 +5222,10 @@ msgstr ""
"Збережіть вашу сцену і повторіть спробу."
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"Немає полісеток для запікання. Переконайтеся, що вони містять канал UV2 і що "
"прапор 'Запікання світла' включений."
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index 0a213a2bdf..5476915ea5 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -5091,8 +5091,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/vi.po b/editor/translations/vi.po
index 0104d05502..4267f19def 100644
--- a/editor/translations/vi.po
+++ b/editor/translations/vi.po
@@ -5156,8 +5156,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index 4393cb4e08..c5b0c34c74 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -83,7 +83,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Chinese (Simplified) (Godot Engine)\n"
"POT-Creation-Date: 2018-01-20 12:15+0200\n"
-"PO-Revision-Date: 2021-07-13 06:13+0000\n"
+"PO-Revision-Date: 2021-07-23 12:59+0000\n"
"Last-Translator: Haoyu Qiu <timothyqiu32@gmail.com>\n"
"Language-Team: Chinese (Simplified) <https://hosted.weblate.org/projects/"
"godot-engine/godot/zh_Hans/>\n"
@@ -1172,7 +1172,7 @@ msgstr "改变字典值"
#: editor/editor_about.cpp
msgid "Thanks from the Godot community!"
-msgstr "Godot 社区感谢你!"
+msgstr "Godot 社区感谢大家!"
#: editor/editor_about.cpp editor/editor_node.cpp editor/project_manager.cpp
msgid "Click to copy."
@@ -5171,9 +5171,10 @@ msgstr ""
"BakedLightmap 属性。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr "没有可烘焙的网格。请确保网格包含 UV2 通道并且勾选 “Bake Light” 选项。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
@@ -7338,7 +7339,7 @@ msgstr "顶视图。"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom View."
-msgstr "仰视图。"
+msgstr "底视图。"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom"
@@ -7547,11 +7548,11 @@ msgstr "使用吸附"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Bottom View"
-msgstr "仰视图"
+msgstr "底视图"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Top View"
-msgstr "俯视图"
+msgstr "顶视图"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Rear View"
@@ -7559,7 +7560,7 @@ msgstr "后视图"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Front View"
-msgstr "正视图"
+msgstr "前视图"
#: editor/plugins/spatial_editor_plugin.cpp
msgid "Left View"
@@ -8240,7 +8241,7 @@ msgstr "新建自动图块"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "New Atlas"
-msgstr "新建合集"
+msgstr "新建图集"
#: editor/plugins/tile_set_editor_plugin.cpp
msgid "Next Coordinate"
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index 28a69ee289..69a8998437 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -5380,8 +5380,8 @@ msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
#: editor/plugins/baked_lightmap_editor_plugin.cpp
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index f65d628d63..2d04a07157 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -5118,9 +5118,10 @@ msgstr ""
"請保存場景並重試。"
#: editor/plugins/baked_lightmap_editor_plugin.cpp
+#, fuzzy
msgid ""
-"No meshes to bake. Make sure they contain an UV2 channel and that the 'Bake "
-"Light' flag is on."
+"No meshes to bake. Make sure they contain an UV2 channel and that the 'Use "
+"In Baked Light' and 'Generate Lightmap' flags are on."
msgstr ""
"無可烘焙之網格。請確保這些網格包含 UV2 通道並已開啟「Bake Light」旗標。"
diff --git a/main/main.cpp b/main/main.cpp
index 1e5445fd93..02c3dffd11 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1080,7 +1080,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
#else
const String error_msg = "Error: Couldn't load project data at path \"" + project_path + "\". Is the .pck file missing?\nIf you've renamed the executable, the associated .pck file should also be renamed to match the executable's name (without the extension).\n";
OS::get_singleton()->print("%s", error_msg.ascii().get_data());
- DisplayServer::get_singleton()->alert(error_msg);
+ OS::get_singleton()->alert(error_msg);
goto error;
#endif
@@ -1089,6 +1089,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// Initialize user data dir.
OS::get_singleton()->ensure_user_data_dir();
+ ResourceUID::get_singleton()->load_from_cache(); // load UUIDs from cache.
+
GLOBAL_DEF("memory/limits/multithreaded_server/rid_pool_prealloc", 60);
ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/multithreaded_server/rid_pool_prealloc",
PropertyInfo(Variant::INT,
@@ -2015,6 +2017,7 @@ bool Main::start() {
// Let's throw an error gently. The code leading to this is pretty brittle so
// this might end up triggered by valid usage, in which case we'll have to
// fine-tune further.
+ OS::get_singleton()->alert("Couldn't detect whether to run the editor, the project manager or a specific project. Aborting.");
ERR_FAIL_V_MSG(false, "Couldn't detect whether to run the editor, the project manager or a specific project. Aborting.");
}
#endif
@@ -2044,9 +2047,8 @@ bool Main::start() {
if (obj) {
memdelete(obj);
}
- ERR_FAIL_V_MSG(false,
- vformat("Can't load the script \"%s\" as it doesn't inherit from SceneTree or MainLoop.",
- script));
+ OS::get_singleton()->alert(vformat("Can't load the script \"%s\" as it doesn't inherit from SceneTree or MainLoop.", script));
+ ERR_FAIL_V_MSG(false, vformat("Can't load the script \"%s\" as it doesn't inherit from SceneTree or MainLoop.", script));
}
script_loop->set_initialize_script(script_res);
@@ -2065,7 +2067,7 @@ bool Main::start() {
if (obj) {
memdelete(obj);
}
- DisplayServer::get_singleton()->alert("Error: Invalid MainLoop script base type: " + script_base);
+ OS::get_singleton()->alert("Error: Invalid MainLoop script base type: " + script_base);
ERR_FAIL_V_MSG(false, vformat("The global class %s does not inherit from SceneTree or MainLoop.", main_loop_type));
}
script_loop->set_initialize_script(script_res);
@@ -2079,7 +2081,7 @@ bool Main::start() {
if (!main_loop) {
if (!ClassDB::class_exists(main_loop_type)) {
- DisplayServer::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type);
+ OS::get_singleton()->alert("Error: MainLoop type doesn't exist: " + main_loop_type);
return false;
} else {
Object *ml = ClassDB::instantiate(main_loop_type);
@@ -2169,8 +2171,8 @@ bool Main::start() {
}
}
- for (List<Node *>::Element *E = to_add.front(); E; E = E->next()) {
- sml->get_root()->add_child(E->get());
+ for (Node *E : to_add) {
+ sml->get_root()->add_child(E);
}
}
}
diff --git a/main/main_timer_sync.cpp b/main/main_timer_sync.cpp
index 93448d0904..94e62bea97 100644
--- a/main/main_timer_sync.cpp
+++ b/main/main_timer_sync.cpp
@@ -30,7 +30,7 @@
#include "main_timer_sync.h"
-void MainFrameTime::clamp_process_step(float min_process_step, float max_process_step) {
+void MainFrameTime::clamp_process_step(double min_process_step, double max_process_step) {
if (process_step < min_process_step) {
process_step = min_process_step;
} else if (process_step > max_process_step) {
@@ -43,25 +43,25 @@ void MainFrameTime::clamp_process_step(float min_process_step, float max_process
// returns the fraction of p_physics_step required for the timer to overshoot
// before advance_core considers changing the physics_steps return from
// the typical values as defined by typical_physics_steps
-float MainTimerSync::get_physics_jitter_fix() {
+double MainTimerSync::get_physics_jitter_fix() {
return Engine::get_singleton()->get_physics_jitter_fix();
}
// gets our best bet for the average number of physics steps per render frame
// return value: number of frames back this data is consistent
-int MainTimerSync::get_average_physics_steps(float &p_min, float &p_max) {
+int MainTimerSync::get_average_physics_steps(double &p_min, double &p_max) {
p_min = typical_physics_steps[0];
p_max = p_min + 1;
for (int i = 1; i < CONTROL_STEPS; ++i) {
- const float typical_lower = typical_physics_steps[i];
- const float current_min = typical_lower / (i + 1);
+ const double typical_lower = typical_physics_steps[i];
+ const double current_min = typical_lower / (i + 1);
if (current_min > p_max) {
return i; // bail out of further restrictions would void the interval
} else if (current_min > p_min) {
p_min = current_min;
}
- const float current_max = (typical_lower + 1) / (i + 1);
+ const double current_max = (typical_lower + 1) / (i + 1);
if (current_max < p_min) {
return i;
} else if (current_max < p_max) {
@@ -73,7 +73,7 @@ int MainTimerSync::get_average_physics_steps(float &p_min, float &p_max) {
}
// advance physics clock by p_process_step, return appropriate number of steps to simulate
-MainFrameTime MainTimerSync::advance_core(float p_physics_step, int p_physics_fps, float p_process_step) {
+MainFrameTime MainTimerSync::advance_core(double p_physics_step, int p_physics_fps, double p_process_step) {
MainFrameTime ret;
ret.process_step = p_process_step;
@@ -146,7 +146,7 @@ MainFrameTime MainTimerSync::advance_core(float p_physics_step, int p_physics_fp
}
// calls advance_core, keeps track of deficit it adds to animaption_step, make sure the deficit sum stays close to zero
-MainFrameTime MainTimerSync::advance_checked(float p_physics_step, int p_physics_fps, float p_process_step) {
+MainFrameTime MainTimerSync::advance_checked(double p_physics_step, int p_physics_fps, double p_process_step) {
if (fixed_fps != -1) {
p_process_step = 1.0 / fixed_fps;
}
@@ -163,7 +163,7 @@ MainFrameTime MainTimerSync::advance_checked(float p_physics_step, int p_physics
// first, least important clamping: keep ret.process_step consistent with typical_physics_steps.
// this smoothes out the process steps and culls small but quick variations.
{
- float min_average_physics_steps, max_average_physics_steps;
+ double min_average_physics_steps, max_average_physics_steps;
int consistent_steps = get_average_physics_steps(min_average_physics_steps, max_average_physics_steps);
if (consistent_steps > 3) {
ret.clamp_process_step(min_average_physics_steps * p_physics_step, max_average_physics_steps * p_physics_step);
@@ -171,7 +171,7 @@ MainFrameTime MainTimerSync::advance_checked(float p_physics_step, int p_physics
}
// second clamping: keep abs(time_deficit) < jitter_fix * frame_slise
- float max_clock_deviation = get_physics_jitter_fix() * p_physics_step;
+ double max_clock_deviation = get_physics_jitter_fix() * p_physics_step;
ret.clamp_process_step(p_process_step - max_clock_deviation, p_process_step + max_clock_deviation);
// last clamping: make sure time_accum is between 0 and p_physics_step for consistency between physics and process
@@ -191,7 +191,7 @@ MainFrameTime MainTimerSync::advance_checked(float p_physics_step, int p_physics
}
// determine wall clock step since last iteration
-float MainTimerSync::get_cpu_process_step() {
+double MainTimerSync::get_cpu_process_step() {
uint64_t cpu_ticks_elapsed = current_cpu_ticks_usec - last_cpu_ticks_usec;
last_cpu_ticks_usec = current_cpu_ticks_usec;
@@ -220,8 +220,8 @@ void MainTimerSync::set_fixed_fps(int p_fixed_fps) {
}
// advance one physics frame, return timesteps to take
-MainFrameTime MainTimerSync::advance(float p_physics_step, int p_physics_fps) {
- float cpu_process_step = get_cpu_process_step();
+MainFrameTime MainTimerSync::advance(double p_physics_step, int p_physics_fps) {
+ double cpu_process_step = get_cpu_process_step();
return advance_checked(p_physics_step, p_physics_fps, cpu_process_step);
}
diff --git a/main/main_timer_sync.h b/main/main_timer_sync.h
index 884978bf96..abdec18f6d 100644
--- a/main/main_timer_sync.h
+++ b/main/main_timer_sync.h
@@ -34,11 +34,11 @@
#include "core/config/engine.h"
struct MainFrameTime {
- float process_step; // delta time to advance during process()
+ double process_step; // delta time to advance during process()
int physics_steps; // number of times to iterate the physics engine
- float interpolation_fraction; // fraction through the current physics tick
+ double interpolation_fraction; // fraction through the current physics tick
- void clamp_process_step(float min_process_step, float max_process_step);
+ void clamp_process_step(double min_process_step, double max_process_step);
};
class MainTimerSync {
@@ -47,10 +47,10 @@ class MainTimerSync {
uint64_t current_cpu_ticks_usec = 0;
// logical game time since last physics timestep
- float time_accum = 0;
+ double time_accum = 0;
// current difference between wall clock time and reported sum of process_steps
- float time_deficit = 0;
+ double time_deficit = 0;
// number of frames back for keeping accumulated physics steps roughly constant.
// value of 12 chosen because that is what is required to make 144 Hz monitors
@@ -70,20 +70,20 @@ protected:
// returns the fraction of p_physics_step required for the timer to overshoot
// before advance_core considers changing the physics_steps return from
// the typical values as defined by typical_physics_steps
- float get_physics_jitter_fix();
+ double get_physics_jitter_fix();
// gets our best bet for the average number of physics steps per render frame
// return value: number of frames back this data is consistent
- int get_average_physics_steps(float &p_min, float &p_max);
+ int get_average_physics_steps(double &p_min, double &p_max);
// advance physics clock by p_process_step, return appropriate number of steps to simulate
- MainFrameTime advance_core(float p_physics_step, int p_physics_fps, float p_process_step);
+ MainFrameTime advance_core(double p_physics_step, int p_physics_fps, double p_process_step);
// calls advance_core, keeps track of deficit it adds to animaption_step, make sure the deficit sum stays close to zero
- MainFrameTime advance_checked(float p_physics_step, int p_physics_fps, float p_process_step);
+ MainFrameTime advance_checked(double p_physics_step, int p_physics_fps, double p_process_step);
// determine wall clock step since last iteration
- float get_cpu_process_step();
+ double get_cpu_process_step();
public:
MainTimerSync();
@@ -96,7 +96,7 @@ public:
void set_fixed_fps(int p_fixed_fps);
// advance one frame, return timesteps to take
- MainFrameTime advance(float p_physics_step, int p_physics_fps);
+ MainFrameTime advance(double p_physics_step, int p_physics_fps);
};
#endif // MAIN_TIMER_SYNC_H
diff --git a/main/performance.cpp b/main/performance.cpp
index 9f5be7b8c4..f9ff34c05d 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -77,7 +77,7 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(MONITOR_MAX);
}
-float Performance::_get_node_count() const {
+int Performance::_get_node_count() const {
MainLoop *ml = OS::get_singleton()->get_main_loop();
SceneTree *sml = Object::cast_to<SceneTree>(ml);
if (!sml) {
@@ -118,7 +118,7 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
return names[p_monitor];
}
-float Performance::get_monitor(Monitor p_monitor) const {
+double Performance::get_monitor(Monitor p_monitor) const {
switch (p_monitor) {
case TIME_FPS:
return Engine::get_singleton()->get_frames_per_second();
@@ -207,11 +207,11 @@ Performance::MonitorType Performance::get_monitor_type(Monitor p_monitor) const
return types[p_monitor];
}
-void Performance::set_process_time(float p_pt) {
+void Performance::set_process_time(double p_pt) {
_process_time = p_pt;
}
-void Performance::set_physics_process_time(float p_pt) {
+void Performance::set_physics_process_time(double p_pt) {
_physics_process_time = p_pt;
}
diff --git a/main/performance.h b/main/performance.h
index 174b3500d1..4653051ebb 100644
--- a/main/performance.h
+++ b/main/performance.h
@@ -43,10 +43,10 @@ class Performance : public Object {
static Performance *singleton;
static void _bind_methods();
- float _get_node_count() const;
+ int _get_node_count() const;
- float _process_time;
- float _physics_process_time;
+ double _process_time;
+ double _physics_process_time;
class MonitorCall {
Callable _callable;
@@ -96,13 +96,13 @@ public:
MONITOR_TYPE_TIME
};
- float get_monitor(Monitor p_monitor) const;
+ double get_monitor(Monitor p_monitor) const;
String get_monitor_name(Monitor p_monitor) const;
MonitorType get_monitor_type(Monitor p_monitor) const;
- void set_process_time(float p_pt);
- void set_physics_process_time(float p_pt);
+ void set_process_time(double p_pt);
+ void set_physics_process_time(double p_pt);
void add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args);
void remove_custom_monitor(const StringName &p_id);
diff --git a/misc/dist/windows/modpath.pas b/misc/dist/windows/modpath.pas
index c55ec60163..ab09f18254 100644
--- a/misc/dist/windows/modpath.pas
+++ b/misc/dist/windows/modpath.pas
@@ -144,7 +144,7 @@ begin
end;
end;
-// Split a string into an array using passed delimeter
+// Split a string into an array using passed delimiter.
procedure MPExplode(var Dest: TArrayOfString; Text: String; Separator: String);
var
i: Integer;
diff --git a/modules/camera/camera_osx.h b/modules/camera/camera_osx.h
index 964b7c1edc..84274f0bf6 100644
--- a/modules/camera/camera_osx.h
+++ b/modules/camera/camera_osx.h
@@ -32,7 +32,7 @@
#define CAMERAOSX_H
///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!!
-// If you fix something here, make sure you fix it there as wel!
+// If you fix something here, make sure you fix it there as well!
#include "servers/camera_server.h"
diff --git a/modules/camera/camera_osx.mm b/modules/camera/camera_osx.mm
index 6bc56add20..4875eb578a 100644
--- a/modules/camera/camera_osx.mm
+++ b/modules/camera/camera_osx.mm
@@ -29,7 +29,7 @@
/*************************************************************************/
///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!!
-// If you fix something here, make sure you fix it there as wel!
+// If you fix something here, make sure you fix it there as well!
#include "camera_osx.h"
#include "servers/camera/camera_feed.h"
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 5a37486568..cb82b65307 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -42,7 +42,7 @@ inline static bool is_snapable(const Vector3 &p_point1, const Vector3 &p_point2,
inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2], const Vector2 p_uvs[2], const Vector2 &p_interpolation_point) {
float segment_length = (p_segement_points[1] - p_segement_points[0]).length();
- if (segment_length < CMP_EPSILON) {
+ if (p_segement_points[0].is_equal_approx(p_segement_points[1])) {
return p_uvs[0];
}
@@ -53,13 +53,13 @@ inline static Vector2 interpolate_segment_uv(const Vector2 p_segement_points[2],
}
inline static Vector2 interpolate_triangle_uv(const Vector2 p_vertices[3], const Vector2 p_uvs[3], const Vector2 &p_interpolation_point) {
- if (p_interpolation_point.distance_squared_to(p_vertices[0]) < CMP_EPSILON2) {
+ if (p_interpolation_point.is_equal_approx(p_vertices[0])) {
return p_uvs[0];
}
- if (p_interpolation_point.distance_squared_to(p_vertices[1]) < CMP_EPSILON2) {
+ if (p_interpolation_point.is_equal_approx(p_vertices[1])) {
return p_uvs[1];
}
- if (p_interpolation_point.distance_squared_to(p_vertices[2]) < CMP_EPSILON2) {
+ if (p_interpolation_point.is_equal_approx(p_vertices[2])) {
return p_uvs[2];
}
@@ -530,8 +530,8 @@ void CSGBrushOperation::MeshMerge::_add_distance(List<real_t> &r_intersectionsA,
List<real_t> &intersections = p_from_B ? r_intersectionsB : r_intersectionsA;
// Check if distance exists.
- for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) {
- if (Math::is_equal_approx(**E, p_distance)) {
+ for (const real_t E : intersections) {
+ if (Math::is_equal_approx(E, p_distance)) {
return;
}
}
@@ -589,7 +589,7 @@ bool CSGBrushOperation::MeshMerge::_bvh_inside(FaceBVH *facebvhptr, int p_max_de
Vector3 intersection_point;
// Check if faces are co-planar.
- if ((current_normal - face_normal).length_squared() < CMP_EPSILON2 &&
+ if (current_normal.is_equal_approx(face_normal) &&
is_point_in_triangle(face_center, current_points)) {
// Only add an intersection if not a B face.
if (!face.from_b) {
diff --git a/modules/csg/csg_gizmos.cpp b/modules/csg/csg_gizmos.cpp
index 37a7d96de5..fc84c029ec 100644
--- a/modules/csg/csg_gizmos.cpp
+++ b/modules/csg/csg_gizmos.cpp
@@ -29,6 +29,8 @@
/*************************************************************************/
#include "csg_gizmos.h"
+#include "editor/plugins/node_3d_editor_plugin.h"
+#include "scene/3d/camera_3d.h"
///////////
@@ -48,7 +50,7 @@ CSGShape3DGizmoPlugin::CSGShape3DGizmoPlugin() {
create_handle_material("handles");
}
-String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const {
+String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
if (Object::cast_to<CSGSphere3D>(cs)) {
@@ -60,17 +62,17 @@ String CSGShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo,
}
if (Object::cast_to<CSGCylinder3D>(cs)) {
- return p_idx == 0 ? "Radius" : "Height";
+ return p_id == 0 ? "Radius" : "Height";
}
if (Object::cast_to<CSGTorus3D>(cs)) {
- return p_idx == 0 ? "InnerRadius" : "OuterRadius";
+ return p_id == 0 ? "InnerRadius" : "OuterRadius";
}
return "";
}
-Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const {
+Variant CSGShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
if (Object::cast_to<CSGSphere3D>(cs)) {
@@ -85,18 +87,18 @@ Variant CSGShape3DGizmoPlugin::get_handle_value(EditorNode3DGizmo *p_gizmo, int
if (Object::cast_to<CSGCylinder3D>(cs)) {
CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
- return p_idx == 0 ? s->get_radius() : s->get_height();
+ return p_id == 0 ? s->get_radius() : s->get_height();
}
if (Object::cast_to<CSGTorus3D>(cs)) {
CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs);
- return p_idx == 0 ? s->get_inner_radius() : s->get_outer_radius();
+ return p_id == 0 ? s->get_inner_radius() : s->get_outer_radius();
}
return Variant();
}
-void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) {
+void CSGShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
Transform3D gt = cs->get_global_transform();
@@ -129,10 +131,10 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
CSGBox3D *s = Object::cast_to<CSGBox3D>(cs);
Vector3 axis;
- axis[p_idx] = 1.0;
+ axis[p_id] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
- float d = ra[p_idx];
+ float d = ra[p_id];
if (Node3DEditor::get_singleton()->is_snap_enabled()) {
d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap());
}
@@ -142,7 +144,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
}
Vector3 h = s->get_size();
- h[p_idx] = d * 2;
+ h[p_id] = d * 2;
s->set_size(h);
}
@@ -150,7 +152,7 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
Vector3 axis;
- axis[p_idx == 0 ? 0 : 1] = 1.0;
+ axis[p_id == 0 ? 0 : 1] = 1.0;
Vector3 ra, rb;
Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb);
float d = axis.dot(ra);
@@ -162,9 +164,9 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
d = 0.001;
}
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_radius(d);
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
s->set_height(d * 2.0);
}
}
@@ -185,15 +187,15 @@ void CSGShape3DGizmoPlugin::set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Ca
d = 0.001;
}
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_inner_radius(d);
- } else if (p_idx == 1) {
+ } else if (p_id == 1) {
s->set_outer_radius(d);
}
}
}
-void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) {
+void CSGShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const {
CSGShape3D *cs = Object::cast_to<CSGShape3D>(p_gizmo->get_spatial_node());
if (Object::cast_to<CSGSphere3D>(cs)) {
@@ -227,7 +229,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
if (Object::cast_to<CSGCylinder3D>(cs)) {
CSGCylinder3D *s = Object::cast_to<CSGCylinder3D>(cs);
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_radius(p_restore);
} else {
s->set_height(p_restore);
@@ -236,7 +238,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
}
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx == 0) {
+ if (p_id == 0) {
ur->create_action(TTR("Change Cylinder Radius"));
ur->add_do_method(s, "set_radius", s->get_radius());
ur->add_undo_method(s, "set_radius", p_restore);
@@ -252,7 +254,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
if (Object::cast_to<CSGTorus3D>(cs)) {
CSGTorus3D *s = Object::cast_to<CSGTorus3D>(cs);
if (p_cancel) {
- if (p_idx == 0) {
+ if (p_id == 0) {
s->set_inner_radius(p_restore);
} else {
s->set_outer_radius(p_restore);
@@ -261,7 +263,7 @@ void CSGShape3DGizmoPlugin::commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx,
}
UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo();
- if (p_idx == 0) {
+ if (p_id == 0) {
ur->create_action(TTR("Change Torus Inner Radius"));
ur->add_do_method(s, "set_inner_radius", s->get_inner_radius());
ur->add_undo_method(s, "set_inner_radius", p_restore);
@@ -356,7 +358,7 @@ void CSGShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
break;
}
- p_gizmo->add_mesh(mesh, false, Ref<SkinReference>(), solid_material);
+ p_gizmo->add_mesh(mesh, solid_material);
}
if (Object::cast_to<CSGSphere3D>(cs)) {
diff --git a/modules/csg/csg_gizmos.h b/modules/csg/csg_gizmos.h
index 8f7da35de3..847313c0b4 100644
--- a/modules/csg/csg_gizmos.h
+++ b/modules/csg/csg_gizmos.h
@@ -33,22 +33,22 @@
#include "csg_shape.h"
#include "editor/editor_plugin.h"
-#include "editor/node_3d_editor_gizmos.h"
+#include "editor/plugins/node_3d_editor_gizmos.h"
class CSGShape3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(CSGShape3DGizmoPlugin, EditorNode3DGizmoPlugin);
public:
- bool has_gizmo(Node3D *p_spatial) override;
- String get_gizmo_name() const override;
- int get_priority() const override;
- bool is_selectable_when_hidden() const override;
- void redraw(EditorNode3DGizmo *p_gizmo) override;
-
- String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- Variant get_handle_value(EditorNode3DGizmo *p_gizmo, int p_idx) const override;
- void set_handle(EditorNode3DGizmo *p_gizmo, int p_idx, Camera3D *p_camera, const Point2 &p_point) override;
- void commit_handle(EditorNode3DGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) override;
+ virtual bool has_gizmo(Node3D *p_spatial) override;
+ virtual String get_gizmo_name() const override;
+ virtual int get_priority() const override;
+ virtual bool is_selectable_when_hidden() const override;
+ virtual void redraw(EditorNode3DGizmo *p_gizmo) override;
+
+ virtual String get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ virtual Variant get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const override;
+ virtual void set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) const override;
+ virtual void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) const override;
CSGShape3DGizmoPlugin();
};
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 53424f2cfd..b47fa35f1a 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -548,7 +548,7 @@ void CSGShape3D::_notification(int p_what) {
void CSGShape3D::set_operation(Operation p_operation) {
operation = p_operation;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
CSGShape3D::Operation CSGShape3D::get_operation() const {
@@ -778,7 +778,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
}
}
- bool flat = normal[0].distance_to(normal[1]) < CMP_EPSILON && normal[0].distance_to(normal[2]) < CMP_EPSILON;
+ bool flat = normal[0].is_equal_approx(normal[1]) && normal[0].is_equal_approx(normal[2]);
vw[as + j + 0] = vertex[0];
vw[as + j + 1] = vertex[1];
@@ -820,7 +820,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
}
}
- bool flat = normal[0].distance_to(normal[1]) < CMP_EPSILON && normal[0].distance_to(normal[2]) < CMP_EPSILON;
+ bool flat = normal[0].is_equal_approx(normal[1]) && normal[0].is_equal_approx(normal[2]);
vw[as + j + 0] = vertex[0];
vw[as + j + 1] = vertex[1];
@@ -845,7 +845,7 @@ CSGBrush *CSGMesh3D::_build_brush() {
void CSGMesh3D::_mesh_changed() {
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
void CSGMesh3D::set_material(const Ref<Material> &p_material) {
@@ -923,36 +923,40 @@ CSGBrush *CSGSphere3D::_build_brush() {
Ref<Material> *materialsw = materials.ptrw();
bool *invertw = invert.ptrw();
- const double lat_step = 1.0 / rings;
- const double lon_step = 1.0 / radial_segments;
+ // We want to follow an order that's convenient for UVs.
+ // For latitude step we start at the top and move down like in an image.
+ const double latitude_step = -Math_PI / rings;
+ const double longitude_step = Math_TAU / radial_segments;
int face = 0;
- for (int i = 1; i <= rings; i++) {
- double lat0 = Math_PI * (0.5 - (i - 1) * lat_step);
- double c0 = Math::cos(lat0);
- double s0 = Math::sin(lat0);
- double v0 = double(i - 1) / rings;
-
- double lat1 = Math_PI * (0.5 - i * lat_step);
- double c1 = Math::cos(lat1);
- double s1 = Math::sin(lat1);
- double v1 = double(i) / rings;
-
- for (int j = 1; j <= radial_segments; j++) {
- double lng0 = Math_TAU * (0.5 - (j - 1) * lon_step);
- double x0 = Math::cos(lng0);
- double y0 = Math::sin(lng0);
- double u0 = double(j - 1) / radial_segments;
-
- double lng1 = Math_TAU * (0.5 - j * lon_step);
- double x1 = Math::cos(lng1);
- double y1 = Math::sin(lng1);
- double u1 = double(j) / radial_segments;
+ for (int i = 0; i < rings; i++) {
+ double latitude0 = latitude_step * i + Math_TAU / 4;
+ double cos0 = Math::cos(latitude0);
+ double sin0 = Math::sin(latitude0);
+ double v0 = double(i) / rings;
+
+ double latitude1 = latitude_step * (i + 1) + Math_TAU / 4;
+ double cos1 = Math::cos(latitude1);
+ double sin1 = Math::sin(latitude1);
+ double v1 = double(i + 1) / rings;
+
+ for (int j = 0; j < radial_segments; j++) {
+ double longitude0 = longitude_step * j;
+ // We give sin to X and cos to Z on purpose.
+ // This allows UVs to be CCW on +X so it maps to images well.
+ double x0 = Math::sin(longitude0);
+ double z0 = Math::cos(longitude0);
+ double u0 = double(j) / radial_segments;
+
+ double longitude1 = longitude_step * (j + 1);
+ double x1 = Math::sin(longitude1);
+ double z1 = Math::cos(longitude1);
+ double u1 = double(j + 1) / radial_segments;
Vector3 v[4] = {
- Vector3(x0 * c0, s0, y0 * c0) * radius,
- Vector3(x1 * c0, s0, y1 * c0) * radius,
- Vector3(x1 * c1, s1, y1 * c1) * radius,
- Vector3(x0 * c1, s1, y0 * c1) * radius,
+ Vector3(x0 * cos0, sin0, z0 * cos0) * radius,
+ Vector3(x1 * cos0, sin0, z1 * cos0) * radius,
+ Vector3(x1 * cos1, sin1, z1 * cos1) * radius,
+ Vector3(x0 * cos1, sin1, z0 * cos1) * radius,
};
Vector2 u[4] = {
@@ -962,8 +966,8 @@ CSGBrush *CSGSphere3D::_build_brush() {
Vector2(u0, v1),
};
- if (i < rings) {
- //face 1
+ // Draw the first face, but skip this at the north pole (i == 0).
+ if (i > 0) {
facesw[face * 3 + 0] = v[0];
facesw[face * 3 + 1] = v[1];
facesw[face * 3 + 2] = v[2];
@@ -979,8 +983,8 @@ CSGBrush *CSGSphere3D::_build_brush() {
face++;
}
- if (i > 1) {
- //face 2
+ // Draw the second face, but skip this at the south pole (i == rings - 1).
+ if (i < rings - 1) {
facesw[face * 3 + 0] = v[2];
facesw[face * 3 + 1] = v[3];
facesw[face * 3 + 2] = v[0];
@@ -1034,7 +1038,7 @@ void CSGSphere3D::set_radius(const float p_radius) {
ERR_FAIL_COND(p_radius <= 0);
radius = p_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGSphere3D::get_radius() const {
@@ -1044,7 +1048,7 @@ float CSGSphere3D::get_radius() const {
void CSGSphere3D::set_radial_segments(const int p_radial_segments) {
radial_segments = p_radial_segments > 4 ? p_radial_segments : 4;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGSphere3D::get_radial_segments() const {
@@ -1054,7 +1058,7 @@ int CSGSphere3D::get_radial_segments() const {
void CSGSphere3D::set_rings(const int p_rings) {
rings = p_rings > 1 ? p_rings : 1;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGSphere3D::get_rings() const {
@@ -1203,7 +1207,7 @@ void CSGBox3D::_bind_methods() {
void CSGBox3D::set_size(const Vector3 &p_size) {
size = p_size;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
Vector3 CSGBox3D::get_size() const {
@@ -1213,7 +1217,7 @@ Vector3 CSGBox3D::get_size() const {
void CSGBox3D::set_material(const Ref<Material> &p_material) {
material = p_material;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
Ref<Material> CSGBox3D::get_material() const {
@@ -1384,7 +1388,7 @@ void CSGCylinder3D::_bind_methods() {
void CSGCylinder3D::set_radius(const float p_radius) {
radius = p_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGCylinder3D::get_radius() const {
@@ -1394,7 +1398,7 @@ float CSGCylinder3D::get_radius() const {
void CSGCylinder3D::set_height(const float p_height) {
height = p_height;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGCylinder3D::get_height() const {
@@ -1405,7 +1409,7 @@ void CSGCylinder3D::set_sides(const int p_sides) {
ERR_FAIL_COND(p_sides < 3);
sides = p_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGCylinder3D::get_sides() const {
@@ -1415,7 +1419,7 @@ int CSGCylinder3D::get_sides() const {
void CSGCylinder3D::set_cone(const bool p_cone) {
cone = p_cone;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
bool CSGCylinder3D::is_cone() const {
@@ -1603,7 +1607,7 @@ void CSGTorus3D::_bind_methods() {
void CSGTorus3D::set_inner_radius(const float p_inner_radius) {
inner_radius = p_inner_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGTorus3D::get_inner_radius() const {
@@ -1613,7 +1617,7 @@ float CSGTorus3D::get_inner_radius() const {
void CSGTorus3D::set_outer_radius(const float p_outer_radius) {
outer_radius = p_outer_radius;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGTorus3D::get_outer_radius() const {
@@ -1624,7 +1628,7 @@ void CSGTorus3D::set_sides(const int p_sides) {
ERR_FAIL_COND(p_sides < 3);
sides = p_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGTorus3D::get_sides() const {
@@ -1635,7 +1639,7 @@ void CSGTorus3D::set_ring_sides(const int p_ring_sides) {
ERR_FAIL_COND(p_ring_sides < 3);
ring_sides = p_ring_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGTorus3D::get_ring_sides() const {
@@ -2172,7 +2176,7 @@ void CSGPolygon3D::_validate_property(PropertyInfo &property) const {
void CSGPolygon3D::_path_changed() {
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
void CSGPolygon3D::_path_exited() {
@@ -2248,7 +2252,7 @@ void CSGPolygon3D::_bind_methods() {
void CSGPolygon3D::set_polygon(const Vector<Vector2> &p_polygon) {
polygon = p_polygon;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
Vector<Vector2> CSGPolygon3D::get_polygon() const {
@@ -2258,7 +2262,7 @@ Vector<Vector2> CSGPolygon3D::get_polygon() const {
void CSGPolygon3D::set_mode(Mode p_mode) {
mode = p_mode;
_make_dirty();
- update_gizmo();
+ update_gizmos();
notify_property_list_changed();
}
@@ -2270,7 +2274,7 @@ void CSGPolygon3D::set_depth(const float p_depth) {
ERR_FAIL_COND(p_depth < 0.001);
depth = p_depth;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGPolygon3D::get_depth() const {
@@ -2290,7 +2294,7 @@ void CSGPolygon3D::set_spin_degrees(const float p_spin_degrees) {
ERR_FAIL_COND(p_spin_degrees < 0.01 || p_spin_degrees > 360);
spin_degrees = p_spin_degrees;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGPolygon3D::get_spin_degrees() const {
@@ -2301,7 +2305,7 @@ void CSGPolygon3D::set_spin_sides(const int p_spin_sides) {
ERR_FAIL_COND(p_spin_sides < 3);
spin_sides = p_spin_sides;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int CSGPolygon3D::get_spin_sides() const {
@@ -2311,7 +2315,7 @@ int CSGPolygon3D::get_spin_sides() const {
void CSGPolygon3D::set_path_node(const NodePath &p_path) {
path_node = p_path;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
NodePath CSGPolygon3D::get_path_node() const {
@@ -2322,7 +2326,7 @@ void CSGPolygon3D::set_path_interval(float p_interval) {
ERR_FAIL_COND_MSG(p_interval < 0.001, "Path interval cannot be smaller than 0.001.");
path_interval = p_interval;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
float CSGPolygon3D::get_path_interval() const {
@@ -2332,7 +2336,7 @@ float CSGPolygon3D::get_path_interval() const {
void CSGPolygon3D::set_path_rotation(PathRotation p_rotation) {
path_rotation = p_rotation;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
CSGPolygon3D::PathRotation CSGPolygon3D::get_path_rotation() const {
@@ -2342,7 +2346,7 @@ CSGPolygon3D::PathRotation CSGPolygon3D::get_path_rotation() const {
void CSGPolygon3D::set_path_local(bool p_enable) {
path_local = p_enable;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
bool CSGPolygon3D::is_path_local() const {
@@ -2352,7 +2356,7 @@ bool CSGPolygon3D::is_path_local() const {
void CSGPolygon3D::set_path_joined(bool p_enable) {
path_joined = p_enable;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
bool CSGPolygon3D::is_path_joined() const {
diff --git a/modules/fbx/data/fbx_mesh_data.cpp b/modules/fbx/data/fbx_mesh_data.cpp
index 0d33b8e7c6..8b4b1e08b3 100644
--- a/modules/fbx/data/fbx_mesh_data.cpp
+++ b/modules/fbx/data/fbx_mesh_data.cpp
@@ -525,7 +525,7 @@ void FBXMeshData::reorganize_vertices(
}
const Vector3 vert_poly_normal = *nrml_arr->getptr(*pid);
- if ((this_vert_poly_normal - vert_poly_normal).length_squared() > CMP_EPSILON) {
+ if (!vert_poly_normal.is_equal_approx(this_vert_poly_normal)) {
// Yes this polygon need duplication.
need_duplication = true;
break;
@@ -586,7 +586,7 @@ void FBXMeshData::reorganize_vertices(
continue;
}
const Vector2 vert_poly_uv = *uvs->getptr(*pid);
- if (((*this_vert_poly_uv) - vert_poly_uv).length_squared() > CMP_EPSILON) {
+ if (!vert_poly_uv.is_equal_approx(*this_vert_poly_uv)) {
// Yes this polygon need duplication.
need_duplication = true;
break;
diff --git a/modules/fbx/fbx_parser/ByteSwapper.h b/modules/fbx/fbx_parser/ByteSwapper.h
index 5c16383974..08d38147d5 100644
--- a/modules/fbx/fbx_parser/ByteSwapper.h
+++ b/modules/fbx/fbx_parser/ByteSwapper.h
@@ -70,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
-/** @file Helper class tp perform various byte oder swappings
+/** @file Helper class tp perform various byte order swappings
(e.g. little to big endian) */
#ifndef BYTE_SWAPPER_H
#define BYTE_SWAPPER_H
diff --git a/modules/fbx/fbx_parser/FBXDocument.cpp b/modules/fbx/fbx_parser/FBXDocument.cpp
index 89c69d2ee8..92c62e68b5 100644
--- a/modules/fbx/fbx_parser/FBXDocument.cpp
+++ b/modules/fbx/fbx_parser/FBXDocument.cpp
@@ -198,7 +198,7 @@ ObjectPtr LazyObject::LoadObject() {
object.reset(new ModelLimbNode(id, element, doc, name));
} else if (strcmp(classtag.c_str(), "IKEffector") && strcmp(classtag.c_str(), "FKEffector")) {
- // FK and IK effectors are not supporte
+ // FK and IK effectors are not supported.
object.reset(new Model(id, element, doc, name));
}
} else if (!strncmp(obtype, "Material", length)) {
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 1ff591a87f..9445fac1c6 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -129,9 +129,7 @@ void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
config_file->get_section_keys("entry", &entry_key_list);
}
- for (List<String>::Element *E = entry_key_list.front(); E; E = E->next()) {
- String key = E->get();
-
+ for (const String &key : entry_key_list) {
PropertyInfo prop;
prop.type = Variant::STRING;
@@ -147,9 +145,7 @@ void GDNativeLibrary::_get_property_list(List<PropertyInfo> *p_list) const {
config_file->get_section_keys("dependencies", &dependency_key_list);
}
- for (List<String>::Element *E = dependency_key_list.front(); E; E = E->next()) {
- String key = E->get();
-
+ for (const String &key : dependency_key_list) {
PropertyInfo prop;
prop.type = Variant::STRING;
@@ -175,9 +171,7 @@ void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) {
p_config_file->get_section_keys("entry", &entry_keys);
}
- for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) {
- String key = E->get();
-
+ for (const String &key : entry_keys) {
Vector<String> tags = key.split(".");
bool skip = false;
@@ -207,9 +201,7 @@ void GDNativeLibrary::set_config_file(Ref<ConfigFile> p_config_file) {
p_config_file->get_section_keys("dependencies", &dependency_keys);
}
- for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) {
- String key = E->get();
-
+ for (const String &key : dependency_keys) {
Vector<String> tags = key.split(".");
bool skip = false;
diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index cfb57137bb..1d75ea206c 100644
--- a/modules/gdnative/gdnative/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -915,8 +915,8 @@ void GDAPI godot_variant_get_builtin_method_list(godot_variant_type p_type, godo
List<StringName> list;
Variant::get_builtin_method_list((Variant::Type)p_type, &list);
int i = 0;
- for (const List<StringName>::Element *E = list.front(); E; E = E->next()) {
- memnew_placement_custom(&r_list[i], StringName, StringName(E->get()));
+ for (const StringName &E : list) {
+ memnew_placement_custom(&r_list[i], StringName, StringName(E));
}
}
@@ -970,8 +970,8 @@ void GDAPI godot_variant_get_member_list(godot_variant_type p_type, godot_string
List<StringName> members;
Variant::get_member_list((Variant::Type)p_type, &members);
int i = 0;
- for (const List<StringName>::Element *E = members.front(); E; E = E->next()) {
- memnew_placement_custom(&r_list[i++], StringName, StringName(E->get()));
+ for (const StringName &E : members) {
+ memnew_placement_custom(&r_list[i++], StringName, StringName(E));
}
}
@@ -1075,8 +1075,8 @@ void GDAPI godot_variant_get_constants_list(godot_variant_type p_type, godot_str
List<StringName> constants;
int i = 0;
Variant::get_constants_for_type((Variant::Type)p_type, &constants);
- for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- memnew_placement_custom(&r_list[i++], StringName, StringName(E->get()));
+ for (const StringName &E : constants) {
+ memnew_placement_custom(&r_list[i++], StringName, StringName(E));
}
}
@@ -1227,8 +1227,8 @@ void GDAPI godot_variant_get_utility_function_list(godot_string_name *r_function
godot_string_name *func = r_functions;
Variant::get_utility_function_list(&functions);
- for (const List<StringName>::Element *E = functions.front(); E; E = E->next()) {
- memnew_placement_custom(func++, StringName, StringName(E->get()));
+ for (const StringName &E : functions) {
+ memnew_placement_custom(func++, StringName, StringName(E));
}
}
diff --git a/modules/gdnative/include/net/godot_webrtc.h b/modules/gdnative/include/net/godot_webrtc.h
index 25aa72dae1..52006e56ec 100644
--- a/modules/gdnative/include/net/godot_webrtc.h
+++ b/modules/gdnative/include/net/godot_webrtc.h
@@ -37,8 +37,8 @@
extern "C" {
#endif
-#define GODOT_NET_WEBRTC_API_MAJOR 3
-#define GODOT_NET_WEBRTC_API_MINOR 2
+#define GODOT_NET_WEBRTC_API_MAJOR 4
+#define GODOT_NET_WEBRTC_API_MINOR 0
/* Library Interface (used to set default GDNative WebRTC implementation */
typedef struct {
@@ -101,6 +101,7 @@ typedef struct {
int (*get_max_retransmits)(const void *);
const char *(*get_protocol)(const void *);
bool (*is_negotiated)(const void *);
+ int (*get_buffered_amount)(const void *);
godot_error (*poll)(void *);
void (*close)(void *);
diff --git a/modules/gdnative/nativescript/api_generator.cpp b/modules/gdnative/nativescript/api_generator.cpp
index 477bc9f74d..df0f29277e 100644
--- a/modules/gdnative/nativescript/api_generator.cpp
+++ b/modules/gdnative/nativescript/api_generator.cpp
@@ -425,11 +425,11 @@ List<ClassAPI> generate_c_api_classes() {
List<EnumAPI> enums;
List<StringName> enum_names;
ClassDB::get_enum_list(class_name, &enum_names, true);
- for (List<StringName>::Element *E = enum_names.front(); E; E = E->next()) {
+ for (const StringName &E : enum_names) {
List<StringName> value_names;
EnumAPI enum_api;
- enum_api.name = E->get();
- ClassDB::get_enum_constants(class_name, E->get(), &value_names, true);
+ enum_api.name = E;
+ ClassDB::get_enum_constants(class_name, E, &value_names, true);
for (List<StringName>::Element *val_e = value_names.front(); val_e; val_e = val_e->next()) {
int int_val = ClassDB::get_integer_constant(class_name, val_e->get(), nullptr);
enum_api.values.push_back(Pair<int, String>(int_val, val_e->get()));
@@ -459,8 +459,8 @@ List<ClassAPI> generate_c_builtin_api_types() {
List<StringName> utility_functions;
Variant::get_utility_function_list(&utility_functions);
- for (const List<StringName>::Element *E = utility_functions.front(); E; E = E->next()) {
- const StringName &function_name = E->get();
+ for (const StringName &E : utility_functions) {
+ const StringName &function_name = E;
MethodAPI function_api;
function_api.method_name = function_name;
@@ -521,8 +521,8 @@ List<ClassAPI> generate_c_builtin_api_types() {
List<StringName> methods;
Variant::get_builtin_method_list(type, &methods);
- for (const List<StringName>::Element *E = methods.front(); E; E = E->next()) {
- const StringName &method_name = E->get();
+ for (const StringName &E : methods) {
+ const StringName &method_name = E;
MethodAPI method_api;
@@ -578,8 +578,8 @@ List<ClassAPI> generate_c_builtin_api_types() {
List<StringName> constants;
Variant::get_constants_for_type(type, &constants);
- for (const List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- const StringName &constant_name = E->get();
+ for (const StringName &E : constants) {
+ const StringName &constant_name = E;
ConstantAPI constant_api;
constant_api.constant_name = constant_name;
@@ -593,8 +593,8 @@ List<ClassAPI> generate_c_builtin_api_types() {
List<StringName> members;
Variant::get_member_list(type, &members);
- for (const List<StringName>::Element *E = members.front(); E; E = E->next()) {
- const StringName &member_name = E->get();
+ for (const StringName &E : members) {
+ const StringName &member_name = E;
PropertyAPI member_api;
member_api.name = member_name;
diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp
index d7943827c2..f3a0e9603f 100644
--- a/modules/gdnative/nativescript/nativescript.cpp
+++ b/modules/gdnative/nativescript/nativescript.cpp
@@ -98,10 +98,10 @@ void NativeScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder)
List<PropertyInfo> info;
get_script_property_list(&info);
Map<StringName, Variant> values;
- for (List<PropertyInfo>::Element *E = info.front(); E; E = E->next()) {
+ for (const PropertyInfo &E : info) {
Variant value;
- get_property_default_value(E->get().name, value);
- values[E->get().name] = value;
+ get_property_default_value(E.name, value);
+ values[E.name] = value;
}
p_placeholder->update(info, values);
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index 8e5ae29ed9..a41c4f7b19 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -79,9 +79,7 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
List<String> entry_keys;
config->get_section_keys("entry", &entry_keys);
- for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) {
- String key = E->get();
-
+ for (const String &key : entry_keys) {
Vector<String> tags = key.split(".");
bool skip = false;
@@ -112,9 +110,7 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
List<String> dependency_keys;
config->get_section_keys("dependencies", &dependency_keys);
- for (List<String>::Element *E = dependency_keys.front(); E; E = E->next()) {
- String key = E->get();
-
+ for (const String &key : dependency_keys) {
Vector<String> tags = key.split(".");
bool skip = false;
@@ -149,9 +145,7 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty
List<String> entry_keys;
config->get_section_keys("entry", &entry_keys);
- for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) {
- String key = E->get();
-
+ for (const String &key : entry_keys) {
Vector<String> tags = key.split(".");
bool skip = false;
diff --git a/modules/gdnative/tests/test_variant.h b/modules/gdnative/tests/test_variant.h
index 2850036604..c506882283 100644
--- a/modules/gdnative/tests/test_variant.h
+++ b/modules/gdnative/tests/test_variant.h
@@ -191,8 +191,8 @@ TEST_CASE("[GDNative Variant] Get utility function list") {
godot_string_name *cur = c_list;
- for (const List<StringName>::Element *E = cpp_list.front(); E; E = E->next()) {
- const StringName &cpp_name = E->get();
+ for (const StringName &E : cpp_list) {
+ const StringName &cpp_name = E;
StringName *c_name = (StringName *)cur++;
CHECK(*c_name == cpp_name);
diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml
index 839aa6b3c6..e68deb070d 100644
--- a/modules/gdscript/doc_classes/@GDScript.xml
+++ b/modules/gdscript/doc_classes/@GDScript.xml
@@ -241,16 +241,18 @@
</methods>
<constants>
<constant name="PI" value="3.14159265358979">
- Constant that represents how many times the diameter of a circle fits around its perimeter. This is equivalent to [code]TAU / 2[/code].
+ Constant that represents how many times the diameter of a circle fits around its perimeter. This is equivalent to [code]TAU / 2[/code], or 180 degrees in rotations.
</constant>
<constant name="TAU" value="6.28318530717959">
- The circle constant, the circumference of the unit circle in radians.
+ The circle constant, the circumference of the unit circle in radians. This is equivalent to [code]PI * 2[/code], or 360 degrees in rotations.
</constant>
<constant name="INF" value="inf">
- Positive infinity. For negative infinity, use -INF.
+ Positive floating-point infinity. This is the result of floating-point division when the divisor is [code]0.0[/code]. For negative infinity, use [code]-INF[/code]. Dividing by [code]-0.0[/code] will result in negative infinity if the numerator is positive, so dividing by [code]0.0[/code] is not the same as dividing by [code]-0.0[/code] (despite [code]0.0 == -0.0[/code] returning [code]true[/code]).
+ [b]Note:[/b] Numeric infinity is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer number by [code]0[/code] will not result in [constant INF] and will result in a run-time error instead.
</constant>
<constant name="NAN" value="nan">
- "Not a Number", an invalid value. [code]NaN[/code] has special properties, including that it is not equal to itself. It is output by some invalid operations, such as dividing zero by zero.
+ "Not a Number", an invalid floating-point value. [constant NAN] has special properties, including that it is not equal to itself ([code]NAN == NAN[/code] returns [code]false[/code]). It is output by some invalid operations, such as dividing floating-point [code]0.0[/code] by [code]0.0[/code].
+ [b]Note:[/b] "Not a Number" is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer [code]0[/code] by [code]0[/code] will not result in [constant NAN] and will result in a run-time error instead.
</constant>
</constants>
</class>
diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp
index 9a4c22f49f..ed8b0a4690 100644
--- a/modules/gdscript/editor/gdscript_highlighter.cpp
+++ b/modules/gdscript/editor/gdscript_highlighter.cpp
@@ -458,8 +458,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const Color types_color = EDITOR_GET("text_editor/highlighting/engine_type_color");
List<StringName> types;
ClassDB::get_class_list(&types);
- for (List<StringName>::Element *E = types.front(); E; E = E->next()) {
- String n = E->get();
+ for (const StringName &E : types) {
+ String n = E;
if (n.begins_with("_")) {
n = n.substr(1, n.length());
}
@@ -470,8 +470,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color");
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
- for (List<StringName>::Element *E = global_classes.front(); E; E = E->next()) {
- keywords[String(E->get())] = usertype_color;
+ for (const StringName &E : global_classes) {
+ keywords[String(E)] = usertype_color;
}
/* Autoloads. */
@@ -489,8 +489,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color");
List<String> core_types;
gdscript->get_core_type_words(&core_types);
- for (List<String>::Element *E = core_types.front(); E; E = E->next()) {
- keywords[E->get()] = basetype_color;
+ for (const String &E : core_types) {
+ keywords[E] = basetype_color;
}
/* Reserved words. */
@@ -498,11 +498,11 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color");
List<String> keyword_list;
gdscript->get_reserved_words(&keyword_list);
- for (List<String>::Element *E = keyword_list.front(); E; E = E->next()) {
- if (gdscript->is_control_flow_keyword(E->get())) {
- keywords[E->get()] = control_flow_keyword_color;
+ for (const String &E : keyword_list) {
+ if (gdscript->is_control_flow_keyword(E)) {
+ keywords[E] = control_flow_keyword_color;
} else {
- keywords[E->get()] = keyword_color;
+ keywords[E] = keyword_color;
}
}
@@ -510,8 +510,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color");
List<String> comments;
gdscript->get_comment_delimiters(&comments);
- for (List<String>::Element *E = comments.front(); E; E = E->next()) {
- String comment = E->get();
+ for (const String &comment : comments) {
String beg = comment.get_slice(" ", 0);
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
add_color_region(beg, end, comment_color, end == "");
@@ -521,8 +520,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
const Color string_color = EDITOR_GET("text_editor/highlighting/string_color");
List<String> strings;
gdscript->get_string_delimiters(&strings);
- for (List<String>::Element *E = strings.front(); E; E = E->next()) {
- String string = E->get();
+ for (const String &string : strings) {
String beg = string.get_slice(" ", 0);
String end = string.get_slice_count(" ") > 1 ? string.get_slice(" ", 1) : String();
add_color_region(beg, end, string_color, end == "");
@@ -536,9 +534,9 @@ void GDScriptSyntaxHighlighter::_update_cache() {
if (instance_base != StringName()) {
List<PropertyInfo> plist;
ClassDB::get_property_list(instance_base, &plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- String name = E->get().name;
- if (E->get().usage & PROPERTY_USAGE_CATEGORY || E->get().usage & PROPERTY_USAGE_GROUP || E->get().usage & PROPERTY_USAGE_SUBGROUP) {
+ for (const PropertyInfo &E : plist) {
+ String name = E.name;
+ if (E.usage & PROPERTY_USAGE_CATEGORY || E.usage & PROPERTY_USAGE_GROUP || E.usage & PROPERTY_USAGE_SUBGROUP) {
continue;
}
if (name.find("/") != -1) {
@@ -549,8 +547,8 @@ void GDScriptSyntaxHighlighter::_update_cache() {
List<String> clist;
ClassDB::get_integer_constant_list(instance_base, &clist);
- for (List<String>::Element *E = clist.front(); E; E = E->next()) {
- member_keywords[E->get()] = member_variable_color;
+ for (const String &E : clist) {
+ member_keywords[E] = member_variable_color;
}
}
}
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index d0b7722847..8957b00a1b 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -291,8 +291,8 @@ void GDScript::_get_script_property_list(List<PropertyInfo> *r_list, bool p_incl
sptr = sptr->_base;
}
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- r_list->push_back(E->get());
+ for (const PropertyInfo &E : props) {
+ r_list->push_back(E);
}
}
@@ -401,8 +401,8 @@ void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<Pro
values[E->key()] = E->get();
}
- for (List<PropertyInfo>::Element *E = members_cache.front(); E; E = E->next()) {
- propnames.push_back(E->get());
+ for (const PropertyInfo &E : members_cache) {
+ propnames.push_back(E);
}
}
@@ -861,8 +861,7 @@ Error GDScript::reload(bool p_keep_state) {
}
}
#ifdef DEBUG_ENABLED
- for (const List<GDScriptWarning>::Element *E = parser.get_warnings().front(); E; E = E->next()) {
- const GDScriptWarning &warning = E->get();
+ for (const GDScriptWarning &warning : parser.get_warnings()) {
if (EngineDebugger::is_active()) {
Vector<ScriptLanguage::StackInfo> si;
EngineDebugger::get_script_debugger()->send_error("", get_path(), warning.start_line, warning.get_name(), warning.get_message(), ERR_HANDLER_WARNING, si);
@@ -1445,8 +1444,8 @@ void GDScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const
sptr = sptr->_base;
}
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- p_properties->push_back(E->get());
+ for (const PropertyInfo &E : props) {
+ p_properties->push_back(E);
}
}
@@ -1637,33 +1636,32 @@ void GDScriptLanguage::init() {
_add_global(StaticCString::create("PI"), Math_PI);
_add_global(StaticCString::create("TAU"), Math_TAU);
- _add_global(StaticCString::create("INF"), Math_INF);
- _add_global(StaticCString::create("NAN"), Math_NAN);
+ _add_global(StaticCString::create("INF"), INFINITY);
+ _add_global(StaticCString::create("NAN"), NAN);
//populate native classes
List<StringName> class_list;
ClassDB::get_class_list(&class_list);
- for (List<StringName>::Element *E = class_list.front(); E; E = E->next()) {
- StringName n = E->get();
+ for (const StringName &n : class_list) {
String s = String(n);
if (s.begins_with("_")) {
- n = s.substr(1, s.length());
+ s = s.substr(1, s.length());
}
- if (globals.has(n)) {
+ if (globals.has(s)) {
continue;
}
- Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(E->get()));
- _add_global(n, nc);
+ Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(n));
+ _add_global(s, nc);
}
//populate singletons
List<Engine::Singleton> singletons;
Engine::get_singleton()->get_singletons(&singletons);
- for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
- _add_global(E->get().name, E->get().ptr);
+ for (const Engine::Singleton &E : singletons) {
+ _add_global(E.name, E.ptr);
}
#ifdef TESTS_ENABLED
@@ -1806,10 +1804,10 @@ void GDScriptLanguage::reload_all_scripts() {
scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order
- for (List<Ref<GDScript>>::Element *E = scripts.front(); E; E = E->next()) {
- print_verbose("GDScript: Reloading: " + E->get()->get_path());
- E->get()->load_source_code(E->get()->get_path());
- E->get()->reload(true);
+ for (Ref<GDScript> &script : scripts) {
+ print_verbose("GDScript: Reloading: " + script->get_path());
+ script->load_source_code(script->get_path());
+ script->reload(true);
}
#endif
}
@@ -1838,21 +1836,21 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
scripts.sort_custom<GDScriptDepSort>(); //update in inheritance dependency order
- for (List<Ref<GDScript>>::Element *E = scripts.front(); E; E = E->next()) {
- bool reload = E->get() == p_script || to_reload.has(E->get()->get_base());
+ for (Ref<GDScript> &script : scripts) {
+ bool reload = script == p_script || to_reload.has(script->get_base());
if (!reload) {
continue;
}
- to_reload.insert(E->get(), Map<ObjectID, List<Pair<StringName, Variant>>>());
+ to_reload.insert(script, Map<ObjectID, List<Pair<StringName, Variant>>>());
if (!p_soft_reload) {
//save state and remove script from instances
- Map<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[E->get()];
+ Map<ObjectID, List<Pair<StringName, Variant>>> &map = to_reload[script];
- while (E->get()->instances.front()) {
- Object *obj = E->get()->instances.front()->get();
+ while (script->instances.front()) {
+ Object *obj = script->instances.front()->get();
//save instance info
List<Pair<StringName, Variant>> state;
if (obj->get_script_instance()) {
@@ -1865,8 +1863,8 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
//same thing for placeholders
#ifdef TOOLS_ENABLED
- while (E->get()->placeholders.size()) {
- Object *obj = E->get()->placeholders.front()->get()->get_owner();
+ while (script->placeholders.size()) {
+ Object *obj = script->placeholders.front()->get()->get_owner();
//save instance info
if (obj->get_script_instance()) {
@@ -1876,13 +1874,13 @@ void GDScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_so
obj->set_script(Variant());
} else {
// no instance found. Let's remove it so we don't loop forever
- E->get()->placeholders.erase(E->get()->placeholders.front()->get());
+ script->placeholders.erase(script->placeholders.front()->get());
}
}
#endif
- for (Map<ObjectID, List<Pair<StringName, Variant>>>::Element *F = E->get()->pending_reload_state.front(); F; F = F->next()) {
+ for (Map<ObjectID, List<Pair<StringName, Variant>>>::Element *F = script->pending_reload_state.front(); F; F = F->next()) {
map[F->key()] = F->get(); //pending to reload, use this one instead
}
}
@@ -2025,8 +2023,8 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
List<StringName> functions;
GDScriptUtilityFunctions::get_function_list(&functions);
- for (const List<StringName>::Element *E = functions.front(); E; E = E->next()) {
- p_words->push_back(String(E->get()));
+ for (const StringName &E : functions) {
+ p_words->push_back(String(E));
}
}
@@ -2296,8 +2294,8 @@ void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<S
return;
}
- for (const List<String>::Element *E = parser.get_dependencies().front(); E; E = E->next()) {
- p_dependencies->push_back(E->get());
+ for (const String &E : parser.get_dependencies()) {
+ p_dependencies->push_back(E);
}
}
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index e7fb33a6a7..ab37e54cf1 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -115,8 +115,8 @@ static GDScriptParser::DataType make_native_enum_type(const StringName &p_native
StringName real_native_name = GDScriptParser::get_real_class_name(p_native_class);
ClassDB::get_enum_constants(real_native_name, p_enum_name, &enum_values);
- for (const List<StringName>::Element *E = enum_values.front(); E != nullptr; E = E->next()) {
- type.enum_values[E->get()] = ClassDB::get_integer_constant(real_native_name, E->get());
+ for (const StringName &E : enum_values) {
+ type.enum_values[E] = ClassDB::get_integer_constant(real_native_name, E);
}
return type;
@@ -573,8 +573,8 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
member.variable->set_datatype(datatype);
// Apply annotations.
- for (List<GDScriptParser::AnnotationNode *>::Element *E = member.variable->annotations.front(); E; E = E->next()) {
- E->get()->apply(parser, member.variable);
+ for (GDScriptParser::AnnotationNode *&E : member.variable->annotations) {
+ E->apply(parser, member.variable);
}
} break;
case GDScriptParser::ClassNode::Member::CONSTANT: {
@@ -622,8 +622,8 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
member.constant->set_datatype(datatype);
// Apply annotations.
- for (List<GDScriptParser::AnnotationNode *>::Element *E = member.constant->annotations.front(); E; E = E->next()) {
- E->get()->apply(parser, member.constant);
+ for (GDScriptParser::AnnotationNode *&E : member.constant->annotations) {
+ E->apply(parser, member.constant);
}
} break;
case GDScriptParser::ClassNode::Member::SIGNAL: {
@@ -641,8 +641,8 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
member.signal->set_datatype(signal_type);
// Apply annotations.
- for (List<GDScriptParser::AnnotationNode *>::Element *E = member.signal->annotations.front(); E; E = E->next()) {
- E->get()->apply(parser, member.signal);
+ for (GDScriptParser::AnnotationNode *&E : member.signal->annotations) {
+ E->apply(parser, member.signal);
}
} break;
case GDScriptParser::ClassNode::Member::ENUM: {
@@ -688,8 +688,8 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
member.m_enum->set_datatype(enum_type);
// Apply annotations.
- for (List<GDScriptParser::AnnotationNode *>::Element *E = member.m_enum->annotations.front(); E; E = E->next()) {
- E->get()->apply(parser, member.m_enum);
+ for (GDScriptParser::AnnotationNode *&E : member.m_enum->annotations) {
+ E->apply(parser, member.m_enum);
}
} break;
case GDScriptParser::ClassNode::Member::FUNCTION:
@@ -761,8 +761,8 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) {
resolve_function_body(member.function);
// Apply annotations.
- for (List<GDScriptParser::AnnotationNode *>::Element *E = member.function->annotations.front(); E; E = E->next()) {
- E->get()->apply(parser, member.function);
+ for (GDScriptParser::AnnotationNode *&E : member.function->annotations) {
+ E->apply(parser, member.function);
}
}
@@ -1927,9 +1927,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool is_awa
Variant::get_constructor_list(builtin_type, &constructors);
bool match = false;
- for (const List<MethodInfo>::Element *E = constructors.front(); E != nullptr; E = E->next()) {
- const MethodInfo &info = E->get();
-
+ for (const MethodInfo &info : constructors) {
if (p_call->arguments.size() < info.arguments.size() - info.default_arguments.size()) {
continue;
}
@@ -2326,8 +2324,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
Variant::construct(base.builtin_type, dummy, nullptr, 0, temp);
List<PropertyInfo> properties;
dummy.get_property_list(&properties);
- for (const List<PropertyInfo>::Element *E = properties.front(); E != nullptr; E = E->next()) {
- const PropertyInfo &prop = E->get();
+ for (const PropertyInfo &prop : properties) {
if (prop.name == name) {
p_identifier->set_datatype(type_from_property(prop));
return;
@@ -3125,8 +3122,8 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
GDScriptParser::ClassNode *found = ref->get_parser()->head;
// It should be okay to assume this exists, since we have a complete script already.
- for (const List<StringName>::Element *E = class_chain.front(); E; E = E->next()) {
- found = found->get_member(E->get()).m_class;
+ for (const StringName &E : class_chain) {
+ found = found->get_member(E).m_class;
}
result.class_type = found;
@@ -3222,9 +3219,9 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, GD
List<MethodInfo> methods;
dummy.get_method_list(&methods);
- for (const List<MethodInfo>::Element *E = methods.front(); E != nullptr; E = E->next()) {
- if (E->get().name == p_function) {
- return function_signature_from_info(E->get(), r_return_type, r_par_types, r_default_arg_count, r_static, r_vararg);
+ for (const MethodInfo &E : methods) {
+ if (E.name == p_function) {
+ return function_signature_from_info(E, r_return_type, r_par_types, r_default_arg_count, r_static, r_vararg);
}
}
@@ -3321,8 +3318,8 @@ bool GDScriptAnalyzer::function_signature_from_info(const MethodInfo &p_info, GD
r_default_arg_count = p_info.default_arguments.size();
r_vararg = (p_info.flags & METHOD_FLAG_VARARG) != 0;
- for (const List<PropertyInfo>::Element *E = p_info.arguments.front(); E != nullptr; E = E->next()) {
- r_par_types.push_back(type_from_property(E->get()));
+ for (const PropertyInfo &E : p_info.arguments) {
+ r_par_types.push_back(type_from_property(E));
}
return true;
}
@@ -3330,8 +3327,8 @@ bool GDScriptAnalyzer::function_signature_from_info(const MethodInfo &p_info, GD
bool GDScriptAnalyzer::validate_call_arg(const MethodInfo &p_method, const GDScriptParser::CallNode *p_call) {
List<GDScriptParser::DataType> arg_types;
- for (const List<PropertyInfo>::Element *E = p_method.arguments.front(); E != nullptr; E = E->next()) {
- arg_types.push_back(type_from_property(E->get()));
+ for (const PropertyInfo &E : p_method.arguments) {
+ arg_types.push_back(type_from_property(E));
}
return validate_call_arg(arg_types, p_method.default_arguments.size(), (p_method.flags & METHOD_FLAG_VARARG) != 0, p_call);
@@ -3658,11 +3655,11 @@ Error GDScriptAnalyzer::resolve_program() {
List<String> parser_keys;
depended_parsers.get_key_list(&parser_keys);
- for (const List<String>::Element *E = parser_keys.front(); E != nullptr; E = E->next()) {
- if (depended_parsers[E->get()].is_null()) {
+ for (const String &E : parser_keys) {
+ if (depended_parsers[E].is_null()) {
return ERR_PARSE_ERROR;
}
- depended_parsers[E->get()]->raise_status(GDScriptParserRef::FULLY_SOLVED);
+ depended_parsers[E]->raise_status(GDScriptParserRef::FULLY_SOLVED);
}
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
}
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 9ff5a342ec..5958326315 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -1459,8 +1459,8 @@ void GDScriptByteCodeGenerator::write_endfor() {
}
// Patch break statements.
- for (const List<int>::Element *E = current_breaks_to_patch.back()->get().front(); E; E = E->next()) {
- patch_jump(E->get());
+ for (const int &E : current_breaks_to_patch.back()->get()) {
+ patch_jump(E);
}
current_breaks_to_patch.pop_back();
@@ -1494,8 +1494,8 @@ void GDScriptByteCodeGenerator::write_endwhile() {
while_jmp_addrs.pop_back();
// Patch break statements.
- for (const List<int>::Element *E = current_breaks_to_patch.back()->get().front(); E; E = E->next()) {
- patch_jump(E->get());
+ for (const int &E : current_breaks_to_patch.back()->get()) {
+ patch_jump(E);
}
current_breaks_to_patch.pop_back();
}
@@ -1506,8 +1506,8 @@ void GDScriptByteCodeGenerator::start_match() {
void GDScriptByteCodeGenerator::start_match_branch() {
// Patch continue statements.
- for (const List<int>::Element *E = match_continues_to_patch.back()->get().front(); E; E = E->next()) {
- patch_jump(E->get());
+ for (const int &E : match_continues_to_patch.back()->get()) {
+ patch_jump(E);
}
match_continues_to_patch.pop_back();
// Start a new list for next branch.
@@ -1516,8 +1516,8 @@ void GDScriptByteCodeGenerator::start_match_branch() {
void GDScriptByteCodeGenerator::end_match() {
// Patch continue statements.
- for (const List<int>::Element *E = match_continues_to_patch.back()->get().front(); E; E = E->next()) {
- patch_jump(E->get());
+ for (const int &E : match_continues_to_patch.back()->get()) {
+ patch_jump(E);
}
match_continues_to_patch.pop_back();
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index fbe791a109..7c9d08b782 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -981,8 +981,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
assigned = prev_base;
// Set back the values into their bases.
- for (List<ChainInfo>::Element *E = set_chain.front(); E; E = E->next()) {
- const ChainInfo &info = E->get();
+ for (const ChainInfo &info : set_chain) {
if (!info.is_named) {
gen->write_set(info.base, info.key, assigned);
if (info.key.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index c1a7bedbc8..2a93bb620b 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -141,8 +141,8 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li
}
#ifdef DEBUG_ENABLED
if (r_warnings) {
- for (const List<GDScriptWarning>::Element *E = parser.get_warnings().front(); E; E = E->next()) {
- const GDScriptWarning &warn = E->get();
+ for (const GDScriptWarning &E : parser.get_warnings()) {
+ const GDScriptWarning &warn = E;
ScriptLanguage::Warning w;
w.start_line = warn.start_line;
w.end_line = warn.end_line;
@@ -157,8 +157,8 @@ bool GDScriptLanguage::validate(const String &p_script, const String &p_path, Li
#endif
if (err) {
if (r_errors) {
- for (const List<GDScriptParser::ParserError>::Element *E = parser.get_errors().front(); E; E = E->next()) {
- const GDScriptParser::ParserError &pe = E->get();
+ for (const GDScriptParser::ParserError &E : parser.get_errors()) {
+ const GDScriptParser::ParserError &pe = E;
ScriptLanguage::ScriptError e;
e.line = pe.line;
e.column = pe.column;
@@ -319,9 +319,9 @@ void GDScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p
List<Pair<StringName, int>> locals;
f->debug_get_stack_member_state(*_call_stack[l].line, &locals);
- for (List<Pair<StringName, int>>::Element *E = locals.front(); E; E = E->next()) {
- p_locals->push_back(E->get().first);
- p_values->push_back(_call_stack[l].stack[E->get().second]);
+ for (const Pair<StringName, int> &E : locals) {
+ p_locals->push_back(E.first);
+ p_values->push_back(_call_stack[l].stack[E.second]);
}
}
@@ -421,8 +421,8 @@ void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const
List<StringName> functions;
GDScriptUtilityFunctions::get_function_list(&functions);
- for (const List<StringName>::Element *E = functions.front(); E; E = E->next()) {
- p_functions->push_back(GDScriptUtilityFunctions::get_function_info(E->get()));
+ for (const StringName &E : functions) {
+ p_functions->push_back(GDScriptUtilityFunctions::get_function_info(E));
}
// Not really "functions", but show in documentation.
@@ -457,12 +457,12 @@ void GDScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_const
Pair<String, Variant> infinity;
infinity.first = "INF";
- infinity.second = Math_INF;
+ infinity.second = INFINITY;
p_constants->push_back(infinity);
Pair<String, Variant> nan;
nan.first = "NAN";
- nan.second = Math_NAN;
+ nan.second = NAN;
p_constants->push_back(nan);
}
@@ -548,7 +548,7 @@ static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx, bool
int def_args = p_info.arguments.size() - p_info.default_arguments.size();
int i = 0;
- for (const List<PropertyInfo>::Element *E = p_info.arguments.front(); E; E = E->next()) {
+ for (const PropertyInfo &E : p_info.arguments) {
if (i > 0) {
arghint += ", ";
}
@@ -556,7 +556,7 @@ static String _make_arguments_hint(const MethodInfo &p_info, int p_arg_idx, bool
if (i == p_arg_idx) {
arghint += String::chr(0xFFFF);
}
- arghint += E->get().name + ": " + _get_visual_datatype(E->get(), true);
+ arghint += E.name + ": " + _get_visual_datatype(E, true);
if (i - def_args >= 0) {
arghint += String(" = ") + p_info.default_arguments[i - def_args].get_construct_string();
@@ -662,11 +662,11 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
r_result.insert(node.display, node);
List<StringName> node_types;
ClassDB::get_inheriters_from_class("Node", &node_types);
- for (const List<StringName>::Element *E = node_types.front(); E != nullptr; E = E->next()) {
- if (!ClassDB::is_class_exposed(E->get())) {
+ for (const StringName &E : node_types) {
+ if (!ClassDB::is_class_exposed(E)) {
continue;
}
- ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CLASS);
+ ScriptCodeCompletionOption option(E, ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
}
@@ -675,9 +675,9 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
static void _list_available_types(bool p_inherit_only, GDScriptParser::CompletionContext &p_context, Map<String, ScriptCodeCompletionOption> &r_result) {
List<StringName> native_types;
ClassDB::get_class_list(&native_types);
- for (const List<StringName>::Element *E = native_types.front(); E != nullptr; E = E->next()) {
- if (ClassDB::is_class_exposed(E->get()) && !Engine::get_singleton()->has_singleton(E->get())) {
- ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CLASS);
+ for (const StringName &E : native_types) {
+ if (ClassDB::is_class_exposed(E) && !Engine::get_singleton()->has_singleton(E)) {
+ ScriptCodeCompletionOption option(E, ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
}
@@ -687,8 +687,8 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
// Native enums from base class
List<StringName> enums;
ClassDB::get_enum_list(p_context.current_class->base_type.native_type, &enums);
- for (const List<StringName>::Element *E = enums.front(); E != nullptr; E = E->next()) {
- ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_ENUM);
+ for (const StringName &E : enums) {
+ ScriptCodeCompletionOption option(E, ScriptCodeCompletionOption::KIND_ENUM);
r_result.insert(option.display, option);
}
}
@@ -725,8 +725,8 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
// Global scripts
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
- for (const List<StringName>::Element *E = global_classes.front(); E != nullptr; E = E->next()) {
- ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CLASS);
+ for (const StringName &E : global_classes) {
+ ScriptCodeCompletionOption option(E, ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
@@ -865,8 +865,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (!_static) {
List<PropertyInfo> members;
scr->get_script_property_list(&members);
- for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ for (const PropertyInfo &E : members) {
+ ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
@@ -879,20 +879,20 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
List<MethodInfo> signals;
scr->get_script_signal_list(&signals);
- for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_SIGNAL);
+ for (const MethodInfo &E : signals) {
+ ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_SIGNAL);
r_result.insert(option.display, option);
}
}
List<MethodInfo> methods;
scr->get_script_method_list(&methods);
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name.begins_with("@")) {
+ for (const MethodInfo &E : methods) {
+ if (E.name.begins_with("@")) {
continue;
}
- ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
- if (E->get().arguments.size()) {
+ ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_FUNCTION);
+ if (E.arguments.size()) {
option.insert_text += "(";
} else {
option.insert_text += "()";
@@ -920,22 +920,22 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (!p_only_functions) {
List<String> constants;
ClassDB::get_integer_constant_list(type, &constants);
- for (List<String>::Element *E = constants.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ for (const String &E : constants) {
+ ScriptCodeCompletionOption option(E, ScriptCodeCompletionOption::KIND_CONSTANT);
r_result.insert(option.display, option);
}
if (!_static || Engine::get_singleton()->has_singleton(type)) {
List<PropertyInfo> pinfo;
ClassDB::get_property_list(type, &pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) {
+ for (const PropertyInfo &E : pinfo) {
+ if (E.usage & (PROPERTY_USAGE_GROUP | PROPERTY_USAGE_CATEGORY)) {
continue;
}
- if (E->get().name.find("/") != -1) {
+ if (E.name.find("/") != -1) {
continue;
}
- ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
@@ -945,12 +945,12 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
List<MethodInfo> methods;
bool is_autocompleting_getters = GLOBAL_GET("debug/gdscript/completion/autocomplete_setters_and_getters").booleanize();
ClassDB::get_method_list(type, &methods, false, !is_autocompleting_getters);
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name.begins_with("_")) {
+ for (const MethodInfo &E : methods) {
+ if (E.name.begins_with("_")) {
continue;
}
- ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
- if (E->get().arguments.size()) {
+ ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_FUNCTION);
+ if (E.arguments.size()) {
option.insert_text += "(";
} else {
option.insert_text += "()";
@@ -977,9 +977,9 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
tmp.get_property_list(&members);
}
- for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
- if (String(E->get().name).find("/") == -1) {
- ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
+ for (const PropertyInfo &E : members) {
+ if (String(E.name).find("/") == -1) {
+ ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
@@ -987,9 +987,9 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
List<MethodInfo> methods;
tmp.get_method_list(&methods);
- for (const List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
- if (E->get().arguments.size()) {
+ for (const MethodInfo &E : methods) {
+ ScriptCodeCompletionOption option(E.name, ScriptCodeCompletionOption::KIND_FUNCTION);
+ if (E.arguments.size()) {
option.insert_text += "(";
} else {
option.insert_text += "()";
@@ -1019,9 +1019,9 @@ static void _find_identifiers(GDScriptParser::CompletionContext &p_context, bool
List<StringName> functions;
GDScriptUtilityFunctions::get_function_list(&functions);
- for (const List<StringName>::Element *E = functions.front(); E; E = E->next()) {
- MethodInfo function = GDScriptUtilityFunctions::get_function_info(E->get());
- ScriptCodeCompletionOption option(String(E->get()), ScriptCodeCompletionOption::KIND_FUNCTION);
+ for (const StringName &E : functions) {
+ MethodInfo function = GDScriptUtilityFunctions::get_function_info(E);
+ ScriptCodeCompletionOption option(String(E), ScriptCodeCompletionOption::KIND_FUNCTION);
if (function.arguments.size() || (function.flags & METHOD_FLAG_VARARG)) {
option.insert_text += "(";
} else {
@@ -1768,9 +1768,9 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
StringName real_native = GDScriptParser::get_real_class_name(base_type.native_type);
MethodInfo info;
if (ClassDB::get_method_info(real_native, p_context.current_function->identifier->name, &info)) {
- for (const List<PropertyInfo>::Element *E = info.arguments.front(); E; E = E->next()) {
- if (E->get().name == p_identifier) {
- r_type = _type_from_property(E->get());
+ for (const PropertyInfo &E : info.arguments) {
+ if (E.name == p_identifier) {
+ r_type = _type_from_property(E);
return true;
}
}
@@ -1932,8 +1932,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
if (!is_static) {
List<PropertyInfo> members;
scr->get_script_property_list(&members);
- for (const List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
- const PropertyInfo &prop = E->get();
+ for (const PropertyInfo &prop : members) {
if (prop.name == p_identifier) {
r_type = _type_from_property(prop);
return true;
@@ -2096,8 +2095,7 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
if (scr.is_valid()) {
List<MethodInfo> methods;
scr->get_script_method_list(&methods);
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- MethodInfo &mi = E->get();
+ for (const MethodInfo &mi : methods) {
if (mi.name == p_method) {
r_type = _type_from_property(mi.return_val);
return true;
@@ -2137,8 +2135,7 @@ static bool _guess_method_return_type_from_base(GDScriptParser::CompletionContex
List<MethodInfo> methods;
tmp.get_method_list(&methods);
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- MethodInfo &mi = E->get();
+ for (const MethodInfo &mi : methods) {
if (mi.name == p_method) {
r_type = _type_from_property(mi.return_val);
return true;
@@ -2183,8 +2180,8 @@ static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_co
List<StringName> enum_constants;
ClassDB::get_enum_constants(class_name, enum_name, &enum_constants);
- for (List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
- String candidate = class_name + "." + E->get();
+ for (const StringName &E : enum_constants) {
+ String candidate = class_name + "." + E;
ScriptCodeCompletionOption option(candidate, ScriptCodeCompletionOption::KIND_ENUM);
r_result.insert(option.display, option);
}
@@ -2228,8 +2225,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
if (obj) {
List<String> options;
obj->get_argument_options(p_method, p_argidx, &options);
- for (List<String>::Element *F = options.front(); F; F = F->next()) {
- ScriptCodeCompletionOption option(F->get(), ScriptCodeCompletionOption::KIND_FUNCTION);
+ for (const String &F : options) {
+ ScriptCodeCompletionOption option(F, ScriptCodeCompletionOption::KIND_FUNCTION);
r_result.insert(option.display, option);
}
}
@@ -2250,8 +2247,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- String s = E->get().name;
+ for (const PropertyInfo &E : props) {
+ String s = E.name;
if (!s.begins_with("autoload/")) {
continue;
}
@@ -2266,8 +2263,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
// Get input actions
List<PropertyInfo> props;
ProjectSettings::get_singleton()->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- String s = E->get().name;
+ for (const PropertyInfo &E : props) {
+ String s = E.name;
if (!s.begins_with("input/")) {
continue;
}
@@ -2291,9 +2288,9 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
List<MethodInfo> methods;
base.get_method_list(&methods);
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name == p_method) {
- r_arghint = _make_arguments_hint(E->get(), p_argidx);
+ for (const MethodInfo &E : methods) {
+ if (E.name == p_method) {
+ r_arghint = _make_arguments_hint(E, p_argidx);
return;
}
}
@@ -2340,14 +2337,14 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
Variant::get_constructor_list(GDScriptParser::get_builtin_type(call->function_name), &constructors);
int i = 0;
- for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) {
- if (p_argidx >= E->get().arguments.size()) {
+ for (const MethodInfo &E : constructors) {
+ if (p_argidx >= E.arguments.size()) {
continue;
}
if (i > 0) {
r_arghint += "\n";
}
- r_arghint += _make_arguments_hint(E->get(), p_argidx);
+ r_arghint += _make_arguments_hint(E, p_argidx);
i++;
}
return;
@@ -2406,9 +2403,9 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
case GDScriptParser::COMPLETION_ANNOTATION: {
List<MethodInfo> annotations;
parser.get_annotation_list(&annotations);
- for (const List<MethodInfo>::Element *E = annotations.front(); E != nullptr; E = E->next()) {
- ScriptCodeCompletionOption option(E->get().name.substr(1), ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
- if (E->get().arguments.size() > 0) {
+ for (const MethodInfo &E : annotations) {
+ ScriptCodeCompletionOption option(E.name.substr(1), ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
+ if (E.arguments.size() > 0) {
option.insert_text += "(";
}
options.insert(option.display, option);
@@ -2426,10 +2423,10 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
case GDScriptParser::COMPLETION_BUILT_IN_TYPE_CONSTANT: {
List<StringName> constants;
Variant::get_constants_for_type(completion_context.builtin_type, &constants);
- for (const List<StringName>::Element *E = constants.front(); E != nullptr; E = E->next()) {
- ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CONSTANT);
+ for (const StringName &E : constants) {
+ ScriptCodeCompletionOption option(E, ScriptCodeCompletionOption::KIND_CONSTANT);
bool valid = false;
- Variant default_value = Variant::get_constant_value(completion_context.builtin_type, E->get(), &valid);
+ Variant default_value = Variant::get_constant_value(completion_context.builtin_type, E, &valid);
if (valid) {
option.default_value = default_value;
}
@@ -2606,8 +2603,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
List<MethodInfo> virtual_methods;
ClassDB::get_virtual_methods(class_name, &virtual_methods);
- for (List<MethodInfo>::Element *E = virtual_methods.front(); E; E = E->next()) {
- MethodInfo &mi = E->get();
+ for (const MethodInfo &mi : virtual_methods) {
String method_hint = mi.name;
if (method_hint.find(":") != -1) {
method_hint = method_hint.get_slice(":", 0);
@@ -2656,8 +2652,8 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
List<String> opts;
p_owner->get_argument_options("get_node", 0, &opts);
- for (List<String>::Element *E = opts.front(); E; E = E->next()) {
- String opt = E->get().strip_edges();
+ for (const String &E : opts) {
+ String opt = E.strip_edges();
if (opt.is_quoted()) {
r_forced = true;
String idopt = opt.unquote();
@@ -2841,8 +2837,8 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
List<MethodInfo> virtual_methods;
ClassDB::get_virtual_methods(class_name, &virtual_methods, true);
- for (List<MethodInfo>::Element *E = virtual_methods.front(); E; E = E->next()) {
- if (E->get().name == p_symbol) {
+ for (const MethodInfo &E : virtual_methods) {
+ if (E.name == p_symbol) {
r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_METHOD;
r_result.class_name = base_type.native_type;
r_result.class_member = p_symbol;
@@ -2860,8 +2856,8 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co
List<String> constants;
ClassDB::get_integer_constant_list(class_name, &constants, true);
- for (List<String>::Element *E = constants.front(); E; E = E->next()) {
- if (E->get() == p_symbol) {
+ for (const String &E : constants) {
+ if (E == p_symbol) {
r_result.type = ScriptLanguage::LookupResult::RESULT_CLASS_CONSTANT;
r_result.class_name = base_type.native_type;
r_result.class_member = p_symbol;
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index f300d5a2c9..876c508689 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -94,8 +94,7 @@ struct _GDFKCS {
void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const {
int oc = 0;
Map<StringName, _GDFKC> sdmap;
- for (const List<StackDebug>::Element *E = stack_debug.front(); E; E = E->next()) {
- const StackDebug &sd = E->get();
+ for (const StackDebug &sd : stack_debug) {
if (sd.line > p_line) {
break;
}
@@ -131,10 +130,10 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String
stackpositions.sort();
- for (List<_GDFKCS>::Element *E = stackpositions.front(); E; E = E->next()) {
+ for (_GDFKCS &E : stackpositions) {
Pair<StringName, int> p;
- p.first = E->get().id;
- p.second = E->get().pos;
+ p.first = E.id;
+ p.second = E.pos;
r_stackvars->push_back(p);
}
}
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index df36afc0f0..466ddb4b10 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -136,8 +136,8 @@ void GDScriptParser::cleanup() {
void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const {
List<StringName> keys;
valid_annotations.get_key_list(&keys);
- for (const List<StringName>::Element *E = keys.front(); E != nullptr; E = E->next()) {
- r_annotations->push_back(valid_annotations[E->get()].info);
+ for (const StringName &E : keys) {
+ r_annotations->push_back(valid_annotations[E].info);
}
}
@@ -248,7 +248,7 @@ void GDScriptParser::push_warning(const Node *p_source, GDScriptWarning::Code p_
warning.rightmost_column = p_source->rightmost_column;
List<GDScriptWarning>::Element *before = nullptr;
- for (List<GDScriptWarning>::Element *E = warnings.front(); E != nullptr; E = E->next()) {
+ for (List<GDScriptWarning>::Element *E = warnings.front(); E; E = E->next()) {
if (E->get().start_line > warning.start_line) {
break;
}
@@ -1332,8 +1332,7 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali
}
void GDScriptParser::clear_unused_annotations() {
- for (const List<AnnotationNode *>::Element *E = annotation_stack.front(); E != nullptr; E = E->next()) {
- AnnotationNode *annotation = E->get();
+ for (const AnnotationNode *annotation : annotation_stack) {
push_error(vformat(R"(Annotation "%s" does not precedes a valid target, so it will have no effect.)", annotation->name), annotation);
}
@@ -1796,8 +1795,8 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
List<StringName> binds;
branch->patterns[0]->binds.get_key_list(&binds);
- for (List<StringName>::Element *E = binds.front(); E != nullptr; E = E->next()) {
- SuiteNode::Local local(branch->patterns[0]->binds[E->get()], current_function);
+ for (const StringName &E : binds) {
+ SuiteNode::Local local(branch->patterns[0]->binds[E], current_function);
suite->add_local(local);
}
}
@@ -2123,10 +2122,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_builtin_constant(Expressio
constant->value = Math_TAU;
break;
case GDScriptTokenizer::Token::CONST_INF:
- constant->value = Math_INF;
+ constant->value = INFINITY;
break;
case GDScriptTokenizer::Token::CONST_NAN:
- constant->value = Math_NAN;
+ constant->value = NAN;
break;
default:
return nullptr; // Unreachable.
@@ -3618,7 +3617,7 @@ void GDScriptParser::TreePrinter::push_text(const String &p_text) {
printed += p_text;
}
-void GDScriptParser::TreePrinter::print_annotation(AnnotationNode *p_annotation) {
+void GDScriptParser::TreePrinter::print_annotation(const AnnotationNode *p_annotation) {
push_text(p_annotation->name);
push_text(" (");
for (int i = 0; i < p_annotation->arguments.size(); i++) {
@@ -3993,8 +3992,8 @@ void GDScriptParser::TreePrinter::print_for(ForNode *p_for) {
}
void GDScriptParser::TreePrinter::print_function(FunctionNode *p_function, const String &p_context) {
- for (const List<AnnotationNode *>::Element *E = p_function->annotations.front(); E != nullptr; E = E->next()) {
- print_annotation(E->get());
+ for (const AnnotationNode *E : p_function->annotations) {
+ print_annotation(E);
}
push_text(p_context);
push_text(" ");
@@ -4333,8 +4332,8 @@ void GDScriptParser::TreePrinter::print_unary_op(UnaryOpNode *p_unary_op) {
}
void GDScriptParser::TreePrinter::print_variable(VariableNode *p_variable) {
- for (const List<AnnotationNode *>::Element *E = p_variable->annotations.front(); E != nullptr; E = E->next()) {
- print_annotation(E->get());
+ for (const AnnotationNode *E : p_variable->annotations) {
+ print_annotation(E);
}
push_text("Variable ");
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 043d87c705..6a227a55e5 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -1431,7 +1431,7 @@ public:
void push_line(const String &p_line = String());
void push_text(const String &p_text);
- void print_annotation(AnnotationNode *p_annotation);
+ void print_annotation(const AnnotationNode *p_annotation);
void print_array(ArrayNode *p_array);
void print_assert(AssertNode *p_assert);
void print_assignment(AssignmentNode *p_assignment);
diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp
index 64c629662c..62531473c3 100644
--- a/modules/gdscript/gdscript_utility_functions.cpp
+++ b/modules/gdscript/gdscript_utility_functions.cpp
@@ -706,8 +706,8 @@ bool GDScriptUtilityFunctions::function_exists(const StringName &p_function) {
}
void GDScriptUtilityFunctions::get_function_list(List<StringName> *r_functions) {
- for (const List<StringName>::Element *E = utility_function_name_table.front(); E; E = E->next()) {
- r_functions->push_back(E->get());
+ for (const StringName &E : utility_function_name_table) {
+ r_functions->push_back(E);
}
}
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index e9a7bf3830..d106b3b541 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -39,8 +39,7 @@ void ExtendGDScriptParser::update_diagnostics() {
diagnostics.clear();
const List<ParserError> &errors = get_errors();
- for (const List<ParserError>::Element *E = errors.front(); E != nullptr; E = E->next()) {
- const ParserError &error = E->get();
+ for (const ParserError &error : errors) {
lsp::Diagnostic diagnostic;
diagnostic.severity = lsp::DiagnosticSeverity::Error;
diagnostic.message = error.message;
@@ -61,8 +60,7 @@ void ExtendGDScriptParser::update_diagnostics() {
}
const List<GDScriptWarning> &warnings = get_warnings();
- for (const List<GDScriptWarning>::Element *E = warnings.front(); E; E = E->next()) {
- const GDScriptWarning &warning = E->get();
+ for (const GDScriptWarning &warning : warnings) {
lsp::Diagnostic diagnostic;
diagnostic.severity = lsp::DiagnosticSeverity::Warning;
diagnostic.message = "(" + warning.get_name() + "): " + warning.get_message();
@@ -152,9 +150,9 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
}
r_symbol.kind = lsp::SymbolKind::Class;
r_symbol.deprecated = false;
- r_symbol.range.start.line = LINE_NUMBER_TO_INDEX(p_class->start_line);
- r_symbol.range.start.character = LINE_NUMBER_TO_INDEX(p_class->start_column);
- r_symbol.range.end.line = LINE_NUMBER_TO_INDEX(p_class->end_line);
+ r_symbol.range.start.line = p_class->start_line;
+ r_symbol.range.start.character = p_class->start_column;
+ r_symbol.range.end.line = lines.size();
r_symbol.selectionRange.start.line = r_symbol.range.start.line;
r_symbol.detail = "class " + r_symbol.name;
bool is_root_class = &r_symbol == &class_symbol;
@@ -167,7 +165,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
case ClassNode::Member::VARIABLE: {
lsp::DocumentSymbol symbol;
symbol.name = m.variable->identifier->name;
- symbol.kind = lsp::SymbolKind::Variable;
+ symbol.kind = m.variable->property == VariableNode::PropertyStyle::PROP_NONE ? lsp::SymbolKind::Variable : lsp::SymbolKind::Property;
symbol.deprecated = false;
symbol.range.start.line = LINE_NUMBER_TO_INDEX(m.variable->start_line);
symbol.range.start.character = LINE_NUMBER_TO_INDEX(m.variable->start_column);
@@ -319,7 +317,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN
const String uri = get_uri();
r_symbol.name = p_func->identifier->name;
- r_symbol.kind = lsp::SymbolKind::Function;
+ r_symbol.kind = p_func->is_static ? lsp::SymbolKind::Function : lsp::SymbolKind::Method;
r_symbol.detail = "func " + String(p_func->identifier->name) + "(";
r_symbol.deprecated = false;
r_symbol.range.start.line = LINE_NUMBER_TO_INDEX(p_func->start_line);
@@ -467,8 +465,8 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) {
}
String doc;
- for (List<String>::Element *E = doc_lines.front(); E; E = E->next()) {
- doc += E->get() + "\n";
+ for (const String &E : doc_lines) {
+ doc += E + "\n";
}
return doc;
}
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 55aff618aa..69ddbe5d1e 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -157,8 +157,7 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
int i = 0;
arr.resize(options.size());
- for (const List<ScriptCodeCompletionOption>::Element *E = options.front(); E; E = E->next()) {
- const ScriptCodeCompletionOption &option = E->get();
+ for (const ScriptCodeCompletionOption &option : options) {
lsp::CompletionItem item;
item.label = option.display;
item.data = request_data;
@@ -294,8 +293,8 @@ Array GDScriptTextDocument::documentLink(const Dictionary &p_params) {
List<lsp::DocumentLink> links;
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_document_links(params.textDocument.uri, links);
- for (const List<lsp::DocumentLink>::Element *E = links.front(); E; E = E->next()) {
- ret.push_back(E->get().to_json());
+ for (const lsp::DocumentLink &E : links) {
+ ret.push_back(E.to_json());
}
return ret;
}
@@ -322,8 +321,8 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
Array contents;
List<const lsp::DocumentSymbol *> list;
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(params, list);
- for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
- if (const lsp::DocumentSymbol *s = E->get()) {
+ for (const lsp::DocumentSymbol *&E : list) {
+ if (const lsp::DocumentSymbol *s = E) {
contents.push_back(s->render().value);
}
}
@@ -430,8 +429,8 @@ Array GDScriptTextDocument::find_symbols(const lsp::TextDocumentPositionParams &
} else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
List<const lsp::DocumentSymbol *> list;
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(p_location, list);
- for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
- if (const lsp::DocumentSymbol *s = E->get()) {
+ for (const lsp::DocumentSymbol *&E : list) {
+ if (const lsp::DocumentSymbol *s = E) {
if (!s->uri.is_empty()) {
lsp::Location location;
location.uri = s->uri;
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 1915c92cbf..e6c819b22f 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -119,8 +119,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_
void GDScriptWorkspace::reload_all_workspace_scripts() {
List<String> paths;
list_script_files("res://", paths);
- for (List<String>::Element *E = paths.front(); E; E = E->next()) {
- const String &path = E->get();
+ for (const String &path : paths) {
Error err;
String content = FileAccess::get_file_as_string(path, &err);
ERR_CONTINUE(err != OK);
@@ -559,8 +558,8 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::N
void GDScriptWorkspace::resolve_document_links(const String &p_uri, List<lsp::DocumentLink> &r_list) {
if (const ExtendGDScriptParser *parser = get_parse_successed_script(get_file_path(p_uri))) {
const List<lsp::DocumentLink> &links = parser->get_document_links();
- for (const List<lsp::DocumentLink>::Element *E = links.front(); E; E = E->next()) {
- r_list.push_back(E->get());
+ for (const lsp::DocumentLink &E : links) {
+ r_list.push_back(E);
}
}
}
@@ -587,8 +586,7 @@ Error GDScriptWorkspace::resolve_signature(const lsp::TextDocumentPositionParams
GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(text_pos, symbols);
}
- for (List<const lsp::DocumentSymbol *>::Element *E = symbols.front(); E; E = E->next()) {
- const lsp::DocumentSymbol *symbol = E->get();
+ for (const lsp::DocumentSymbol *const &symbol : symbols) {
if (symbol->kind == lsp::SymbolKind::Method || symbol->kind == lsp::SymbolKind::Function) {
lsp::SignatureInformation signature_info;
signature_info.label = symbol->detail;
diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp
index a7dcfdb22d..0138f132ad 100644
--- a/modules/gdscript/language_server/lsp.hpp
+++ b/modules/gdscript/language_server/lsp.hpp
@@ -1018,32 +1018,32 @@ struct CompletionList {
* A symbol kind.
*/
namespace SymbolKind {
-static const int File = 0;
-static const int Module = 1;
-static const int Namespace = 2;
-static const int Package = 3;
-static const int Class = 4;
-static const int Method = 5;
-static const int Property = 6;
-static const int Field = 7;
-static const int Constructor = 8;
-static const int Enum = 9;
-static const int Interface = 10;
-static const int Function = 11;
-static const int Variable = 12;
-static const int Constant = 13;
-static const int String = 14;
-static const int Number = 15;
-static const int Boolean = 16;
-static const int Array = 17;
-static const int Object = 18;
-static const int Key = 19;
-static const int Null = 20;
-static const int EnumMember = 21;
-static const int Struct = 22;
-static const int Event = 23;
-static const int Operator = 24;
-static const int TypeParameter = 25;
+static const int File = 1;
+static const int Module = 2;
+static const int Namespace = 3;
+static const int Package = 4;
+static const int Class = 5;
+static const int Method = 6;
+static const int Property = 7;
+static const int Field = 8;
+static const int Constructor = 9;
+static const int Enum = 10;
+static const int Interface = 11;
+static const int Function = 12;
+static const int Variable = 13;
+static const int Constant = 14;
+static const int String = 15;
+static const int Number = 16;
+static const int Boolean = 17;
+static const int Array = 18;
+static const int Object = 19;
+static const int Key = 20;
+static const int Null = 21;
+static const int EnumMember = 22;
+static const int Struct = 23;
+static const int Event = 24;
+static const int Operator = 25;
+static const int TypeParameter = 26;
}; // namespace SymbolKind
/**
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index b7faebb4ef..03a48bf071 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -295,7 +295,7 @@ void GDScriptTestRunner::handle_cmdline() {
String test_cmd = "--gdscript-test";
String gen_cmd = "--gdscript-generate-tests";
- for (List<String>::Element *E = cmdline_args.front(); E != nullptr; E = E->next()) {
+ for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) {
String &cmd = E->get();
if (cmd == test_cmd || cmd == gen_cmd) {
if (E->next() == nullptr) {
@@ -440,8 +440,8 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
result.output = get_text_for_status(result.status) + "\n";
const List<GDScriptParser::ParserError> &errors = parser.get_errors();
- for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E; E = E->next()) {
- result.output += E->get().message + "\n"; // TODO: line, column?
+ for (const GDScriptParser::ParserError &E : errors) {
+ result.output += E.message + "\n"; // TODO: line, column?
break; // Only the first error since the following might be cascading.
}
if (!p_is_generating) {
@@ -459,8 +459,8 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
result.output = get_text_for_status(result.status) + "\n";
const List<GDScriptParser::ParserError> &errors = parser.get_errors();
- for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E; E = E->next()) {
- result.output += E->get().message + "\n"; // TODO: line, column?
+ for (const GDScriptParser::ParserError &E : errors) {
+ result.output += E.message + "\n"; // TODO: line, column?
break; // Only the first error since the following might be cascading.
}
if (!p_is_generating) {
@@ -470,8 +470,8 @@ GDScriptTest::TestResult GDScriptTest::execute_test_code(bool p_is_generating) {
}
StringBuilder warning_string;
- for (const List<GDScriptWarning>::Element *E = parser.get_warnings().front(); E != nullptr; E = E->next()) {
- const GDScriptWarning warning = E->get();
+ for (const GDScriptWarning &E : parser.get_warnings()) {
+ const GDScriptWarning warning = E;
warning_string.append(">> WARNING");
warning_string.append("\n>> Line: ");
warning_string.append(itos(warning.start_line));
diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp
index 7aa5895981..52e9d92223 100644
--- a/modules/gdscript/tests/test_gdscript.cpp
+++ b/modules/gdscript/tests/test_gdscript.cpp
@@ -113,8 +113,7 @@ static void test_parser(const String &p_code, const String &p_script_path, const
if (err != OK) {
const List<GDScriptParser::ParserError> &errors = parser.get_errors();
- for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E != nullptr; E = E->next()) {
- const GDScriptParser::ParserError &error = E->get();
+ for (const GDScriptParser::ParserError &error : errors) {
print_line(vformat("%02d:%02d: %s", error.line, error.column, error.message));
}
}
@@ -124,8 +123,7 @@ static void test_parser(const String &p_code, const String &p_script_path, const
if (err != OK) {
const List<GDScriptParser::ParserError> &errors = parser.get_errors();
- for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E != nullptr; E = E->next()) {
- const GDScriptParser::ParserError &error = E->get();
+ for (const GDScriptParser::ParserError &error : errors) {
print_line(vformat("%02d:%02d: %s", error.line, error.column, error.message));
}
}
@@ -143,8 +141,7 @@ static void test_compiler(const String &p_code, const String &p_script_path, con
if (err != OK) {
print_line("Error in parser:");
const List<GDScriptParser::ParserError> &errors = parser.get_errors();
- for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E != nullptr; E = E->next()) {
- const GDScriptParser::ParserError &error = E->get();
+ for (const GDScriptParser::ParserError &error : errors) {
print_line(vformat("%02d:%02d: %s", error.line, error.column, error.message));
}
return;
@@ -156,8 +153,7 @@ static void test_compiler(const String &p_code, const String &p_script_path, con
if (err != OK) {
print_line("Error in analyzer:");
const List<GDScriptParser::ParserError> &errors = parser.get_errors();
- for (const List<GDScriptParser::ParserError>::Element *E = errors.front(); E != nullptr; E = E->next()) {
- const GDScriptParser::ParserError &error = E->get();
+ for (const GDScriptParser::ParserError &error : errors) {
print_line(vformat("%02d:%02d: %s", error.line, error.column, error.message));
}
return;
diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp
index 730c6b89f7..dd545ff431 100644
--- a/modules/glslang/register_types.cpp
+++ b/modules/glslang/register_types.cpp
@@ -193,7 +193,7 @@ void preregister_glslang_types() {
// initialize in case it's not initialized. This is done once per thread
// and it's safe to call multiple times
glslang::InitializeProcess();
- RenderingDevice::shader_set_compile_function(_compile_shader_glsl);
+ RenderingDevice::shader_set_compile_to_spirv_function(_compile_shader_glsl);
RenderingDevice::shader_set_get_cache_key_function(_get_cache_key_function_glsl);
}
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index 71a9b3667f..30d023606f 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -2796,7 +2796,7 @@ Error GLTFDocument::_parse_meshes(Ref<GLTFState> state) {
mat = mat3d;
}
- import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat);
+ import_mesh->add_surface(primitive, array, morphs, Dictionary(), mat, mat.is_valid() ? mat->get_name() : String());
}
Vector<float> blend_weights;
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index 0cd41133f1..fea513c820 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -519,14 +519,14 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
RS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid());
int idx = 0;
- for (List<Pair<Transform3D, IndexKey>>::Element *F = E->get().front(); F; F = F->next()) {
- RS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first);
+ for (const Pair<Transform3D, IndexKey> &F : E->get()) {
+ RS::get_singleton()->multimesh_instance_set_transform(mm, idx, F.first);
#ifdef TOOLS_ENABLED
Octant::MultimeshInstance::Item it;
it.index = idx;
- it.transform = F->get().first;
- it.key = F->get().second;
+ it.transform = F.first;
+ it.key = F.second;
mmi.items.push_back(it);
#endif
diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp
index 046f8c0adb..989c2d295c 100644
--- a/modules/gridmap/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/grid_map_editor_plugin.cpp
@@ -497,8 +497,8 @@ void GridMapEditor::_fill_selection() {
}
void GridMapEditor::_clear_clipboard_data() {
- for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) {
- RenderingServer::get_singleton()->free(E->get().instance);
+ for (const ClipboardItem &E : clipboard_items) {
+ RenderingServer::get_singleton()->free(E.instance);
}
clipboard_items.clear();
@@ -552,9 +552,7 @@ void GridMapEditor::_update_paste_indicator() {
RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf);
- for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) {
- ClipboardItem &item = E->get();
-
+ for (const ClipboardItem &item : clipboard_items) {
xf = Transform3D();
xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size();
xf.basis = rot * xf.basis;
@@ -578,9 +576,7 @@ void GridMapEditor::_do_paste() {
Vector3 ofs = paste_indicator.current - paste_indicator.click;
undo_redo->create_action(TTR("GridMap Paste Selection"));
- for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) {
- ClipboardItem &item = E->get();
-
+ for (const ClipboardItem &item : clipboard_items) {
Vector3 position = rot.xform(item.grid_offset) + paste_indicator.begin + ofs;
Basis orm;
@@ -663,8 +659,7 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In
if ((mb->get_button_index() == MOUSE_BUTTON_RIGHT && input_action == INPUT_ERASE) || (mb->get_button_index() == MOUSE_BUTTON_LEFT && input_action == INPUT_PAINT)) {
if (set_items.size()) {
undo_redo->create_action(TTR("GridMap Paint"));
- for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) {
- const SetItem &si = E->get();
+ for (const SetItem &si : set_items) {
undo_redo->add_do_method(node, "set_cell_item", si.position, si.new_value, si.new_orientation);
}
for (List<SetItem>::Element *E = set_items.back(); E; E = E->prev()) {
@@ -869,8 +864,8 @@ void GridMapEditor::update_palette() {
int item = 0;
- for (List<_CGMEItemSort>::Element *E = il.front(); E; E = E->next()) {
- int id = E->get().id;
+ for (_CGMEItemSort &E : il) {
+ int id = E.id;
String name = mesh_library->get_item_name(id);
Ref<Texture2D> preview = mesh_library->get_item_preview(id);
diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp
index b75cf6502e..fe941e25e7 100644
--- a/modules/lightmapper_rd/lightmapper_rd.cpp
+++ b/modules/lightmapper_rd/lightmapper_rd.cpp
@@ -794,7 +794,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
}
ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
- RID rasterize_shader = rd->shader_create_from_bytecode(raster_shader->get_bytecode());
+ RID rasterize_shader = rd->shader_create_from_spirv(raster_shader->get_spirv_stages());
ERR_FAIL_COND_V(rasterize_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //this is a bug check, though, should not happen
@@ -945,27 +945,27 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
// Unoccluder
- RID compute_shader_unocclude = rd->shader_create_from_bytecode(compute_shader->get_bytecode("unocclude"));
+ RID compute_shader_unocclude = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("unocclude"));
ERR_FAIL_COND_V(compute_shader_unocclude.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen
RID compute_shader_unocclude_pipeline = rd->compute_pipeline_create(compute_shader_unocclude);
// Direct light
- RID compute_shader_primary = rd->shader_create_from_bytecode(compute_shader->get_bytecode("primary"));
+ RID compute_shader_primary = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("primary"));
ERR_FAIL_COND_V(compute_shader_primary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen
RID compute_shader_primary_pipeline = rd->compute_pipeline_create(compute_shader_primary);
// Indirect light
- RID compute_shader_secondary = rd->shader_create_from_bytecode(compute_shader->get_bytecode("secondary"));
+ RID compute_shader_secondary = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("secondary"));
ERR_FAIL_COND_V(compute_shader_secondary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen
RID compute_shader_secondary_pipeline = rd->compute_pipeline_create(compute_shader_secondary);
// Dilate
- RID compute_shader_dilate = rd->shader_create_from_bytecode(compute_shader->get_bytecode("dilate"));
+ RID compute_shader_dilate = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("dilate"));
ERR_FAIL_COND_V(compute_shader_dilate.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen
RID compute_shader_dilate_pipeline = rd->compute_pipeline_create(compute_shader_dilate);
// Light probes
- RID compute_shader_light_probes = rd->shader_create_from_bytecode(compute_shader->get_bytecode("light_probes"));
+ RID compute_shader_light_probes = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("light_probes"));
ERR_FAIL_COND_V(compute_shader_light_probes.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen
RID compute_shader_light_probes_pipeline = rd->compute_pipeline_create(compute_shader_light_probes);
@@ -1506,11 +1506,11 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d
}
ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
- RID blendseams_line_raster_shader = rd->shader_create_from_bytecode(blendseams_shader->get_bytecode("lines"));
+ RID blendseams_line_raster_shader = rd->shader_create_from_spirv(blendseams_shader->get_spirv_stages("lines"));
ERR_FAIL_COND_V(blendseams_line_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
- RID blendseams_triangle_raster_shader = rd->shader_create_from_bytecode(blendseams_shader->get_bytecode("triangles"));
+ RID blendseams_triangle_raster_shader = rd->shader_create_from_spirv(blendseams_shader->get_spirv_stages("triangles"));
ERR_FAIL_COND_V(blendseams_triangle_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);
diff --git a/modules/mono/.editorconfig b/modules/mono/.editorconfig
new file mode 100644
index 0000000000..c9dcd7724e
--- /dev/null
+++ b/modules/mono/.editorconfig
@@ -0,0 +1,14 @@
+[*.sln]
+indent_style = tab
+
+[*.{csproj,props,targets,nuspec,resx}]
+indent_style = space
+indent_size = 2
+
+[*.cs]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+max_line_length = 120
+csharp_indent_case_contents_when_block = false
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
index 25193a1352..0da06131af 100644
--- a/modules/mono/class_db_api_json.cpp
+++ b/modules/mono/class_db_api_json.cpp
@@ -50,8 +50,8 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
//must be alphabetically sorted for hash to compute
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- ClassDB::ClassInfo *t = ClassDB::classes.getptr(E->get());
+ for (const StringName &E : names) {
+ ClassDB::ClassInfo *t = ClassDB::classes.getptr(E);
ERR_FAIL_COND(!t);
if (t->api != p_api || !t->exposed) {
continue;
@@ -84,11 +84,11 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array methods;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary method_dict;
methods.push_back(method_dict);
- MethodBind *mb = t->method_map[F->get()];
+ MethodBind *mb = t->method_map[F];
method_dict["name"] = mb->get_name();
method_dict["argument_count"] = mb->get_argument_count();
method_dict["return_type"] = mb->get_argument_type(-1);
@@ -141,12 +141,12 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array constants;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary constant_dict;
constants.push_back(constant_dict);
- constant_dict["name"] = F->get();
- constant_dict["value"] = t->constant_map[F->get()];
+ constant_dict["name"] = F;
+ constant_dict["value"] = t->constant_map[F];
}
if (!constants.is_empty()) {
@@ -168,12 +168,12 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array signals;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary signal_dict;
signals.push_back(signal_dict);
- MethodInfo &mi = t->signal_map[F->get()];
- signal_dict["name"] = F->get();
+ MethodInfo &mi = t->signal_map[F];
+ signal_dict["name"] = F;
Array arguments;
signal_dict["arguments"] = arguments;
@@ -203,13 +203,13 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array properties;
- for (List<StringName>::Element *F = snames.front(); F; F = F->next()) {
+ for (const StringName &F : snames) {
Dictionary property_dict;
properties.push_back(property_dict);
- ClassDB::PropertySetGet *psg = t->property_setget.getptr(F->get());
+ ClassDB::PropertySetGet *psg = t->property_setget.getptr(F);
- property_dict["name"] = F->get();
+ property_dict["name"] = F;
property_dict["setter"] = psg->setter;
property_dict["getter"] = psg->getter;
}
@@ -222,15 +222,15 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Array property_list;
//property list
- for (List<PropertyInfo>::Element *F = t->property_list.front(); F; F = F->next()) {
+ for (const PropertyInfo &F : t->property_list) {
Dictionary property_dict;
property_list.push_back(property_dict);
- property_dict["name"] = F->get().name;
- property_dict["type"] = F->get().type;
- property_dict["hint"] = F->get().hint;
- property_dict["hint_string"] = F->get().hint_string;
- property_dict["usage"] = F->get().usage;
+ property_dict["name"] = F.name;
+ property_dict["type"] = F.type;
+ property_dict["hint"] = F.hint;
+ property_dict["hint_string"] = F.hint_string;
+ property_dict["usage"] = F.usage;
}
if (!property_list.is_empty()) {
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 80675feb3b..15a5807370 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -145,8 +145,8 @@ void CSharpLanguage::finalize() {
finalizing = true;
// Make sure all script binding gchandles are released before finalizing GDMono
- for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
- CSharpScriptBinding &script_binding = E->value();
+ for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
+ CSharpScriptBinding &script_binding = E.value;
if (!script_binding.gchandle.is_released()) {
script_binding.gchandle.release();
@@ -163,8 +163,8 @@ void CSharpLanguage::finalize() {
script_bindings.clear();
#ifdef DEBUG_ENABLED
- for (Map<ObjectID, int>::Element *E = unsafe_object_references.front(); E; E = E->next()) {
- const ObjectID &id = E->key();
+ for (const KeyValue<ObjectID, int> &E : unsafe_object_references) {
+ const ObjectID &id = E.key;
Object *obj = ObjectDB::get_instance(id);
if (obj) {
@@ -864,8 +864,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// We need to keep reference instances alive during reloading
List<Ref<RefCounted>> rc_instances;
- for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
- CSharpScriptBinding &script_binding = E->value();
+ for (const KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
+ const CSharpScriptBinding &script_binding = E.value;
RefCounted *rc = Object::cast_to<RefCounted>(script_binding.owner);
if (rc) {
rc_instances.push_back(Ref<RefCounted>(rc));
@@ -874,9 +874,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// As scripts are going to be reloaded, must proceed without locking here
- for (List<Ref<CSharpScript>>::Element *E = scripts.front(); E; E = E->next()) {
- Ref<CSharpScript> &script = E->get();
-
+ for (Ref<CSharpScript> &script : scripts) {
to_reload.push_back(script);
if (script->get_path().is_empty()) {
@@ -887,8 +885,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Script::instances are deleted during managed object disposal, which happens on domain finalize.
// Only placeholders are kept. Therefore we need to keep a copy before that happens.
- for (Set<Object *>::Element *F = script->instances.front(); F; F = F->next()) {
- Object *obj = F->get();
+ for (Object *&obj : script->instances) {
script->pending_reload_instances.insert(obj->get_instance_id());
RefCounted *rc = Object::cast_to<RefCounted>(obj);
@@ -898,8 +895,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
#ifdef TOOLS_ENABLED
- for (Set<PlaceHolderScriptInstance *>::Element *F = script->placeholders.front(); F; F = F->next()) {
- Object *obj = F->get()->get_owner();
+ for (PlaceHolderScriptInstance *&script_instance : script->placeholders) {
+ Object *obj = script_instance->get_owner();
script->pending_reload_instances.insert(obj->get_instance_id());
RefCounted *rc = Object::cast_to<RefCounted>(obj);
@@ -912,9 +909,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Save state and remove script from instances
Map<ObjectID, CSharpScript::StateBackup> &owners_map = script->pending_reload_state;
- for (Set<Object *>::Element *F = script->instances.front(); F; F = F->next()) {
- Object *obj = F->get();
-
+ for (Object *&obj : script->instances) {
ERR_CONTINUE(!obj->get_script_instance());
CSharpInstance *csi = static_cast<CSharpInstance *>(obj->get_script_instance());
@@ -936,9 +931,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
}
// After the state of all instances is saved, clear scripts and script instances
- for (List<Ref<CSharpScript>>::Element *E = scripts.front(); E; E = E->next()) {
- Ref<CSharpScript> &script = E->get();
-
+ for (Ref<CSharpScript> &script : scripts) {
while (script->instances.front()) {
Object *obj = script->instances.front()->get();
obj->set_script(REF()); // Remove script and existing script instances (placeholder are not removed before domain reload)
@@ -951,11 +944,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
if (gdmono->reload_scripts_domain() != OK) {
// Failed to reload the scripts domain
// Make sure to add the scripts back to their owners before returning
- for (List<Ref<CSharpScript>>::Element *E = to_reload.front(); E; E = E->next()) {
- Ref<CSharpScript> scr = E->get();
-
- for (const Map<ObjectID, CSharpScript::StateBackup>::Element *F = scr->pending_reload_state.front(); F; F = F->next()) {
- Object *obj = ObjectDB::get_instance(F->key());
+ for (Ref<CSharpScript> &scr : to_reload) {
+ for (const KeyValue<ObjectID, CSharpScript::StateBackup> &F : scr->pending_reload_state) {
+ Object *obj = ObjectDB::get_instance(F.key);
if (!obj) {
continue;
@@ -975,8 +966,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
#endif
// Restore Variant properties state, it will be kept by the placeholder until the next script reloading
- for (List<Pair<StringName, Variant>>::Element *G = scr->pending_reload_state[obj_id].properties.front(); G; G = G->next()) {
- placeholder->property_set_fallback(G->get().first, G->get().second, nullptr);
+ for (const Pair<StringName, Variant> &G : scr->pending_reload_state[obj_id].properties) {
+ placeholder->property_set_fallback(G.first, G.second, nullptr);
}
scr->pending_reload_state.erase(obj_id);
@@ -988,9 +979,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
List<Ref<CSharpScript>> to_reload_state;
- for (List<Ref<CSharpScript>>::Element *E = to_reload.front(); E; E = E->next()) {
- Ref<CSharpScript> script = E->get();
-
+ for (Ref<CSharpScript> &script : to_reload) {
#ifdef TOOLS_ENABLED
script->exports_invalidated = true;
#endif
@@ -1043,8 +1032,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
StringName native_name = NATIVE_GDMONOCLASS_NAME(script->native);
{
- for (Set<ObjectID>::Element *F = script->pending_reload_instances.front(); F; F = F->next()) {
- ObjectID obj_id = F->get();
+ for (const ObjectID &obj_id : script->pending_reload_instances) {
Object *obj = ObjectDB::get_instance(obj_id);
if (!obj) {
@@ -1095,11 +1083,8 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
to_reload_state.push_back(script);
}
- for (List<Ref<CSharpScript>>::Element *E = to_reload_state.front(); E; E = E->next()) {
- Ref<CSharpScript> script = E->get();
-
- for (Set<ObjectID>::Element *F = script->pending_reload_instances.front(); F; F = F->next()) {
- ObjectID obj_id = F->get();
+ for (Ref<CSharpScript> &script : to_reload_state) {
+ for (const ObjectID &obj_id : script->pending_reload_instances) {
Object *obj = ObjectDB::get_instance(obj_id);
if (!obj) {
@@ -1113,16 +1098,16 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
CSharpScript::StateBackup &state_backup = script->pending_reload_state[obj_id];
- for (List<Pair<StringName, Variant>>::Element *G = state_backup.properties.front(); G; G = G->next()) {
- obj->get_script_instance()->set(G->get().first, G->get().second);
+ for (const Pair<StringName, Variant> &G : state_backup.properties) {
+ obj->get_script_instance()->set(G.first, G.second);
}
CSharpInstance *csi = CAST_CSHARP_INSTANCE(obj->get_script_instance());
if (csi) {
- for (List<Pair<StringName, Array>>::Element *G = state_backup.event_signals.front(); G; G = G->next()) {
- const StringName &name = G->get().first;
- const Array &serialized_data = G->get().second;
+ for (const Pair<StringName, Array> &G : state_backup.event_signals) {
+ const StringName &name = G.first;
+ const Array &serialized_data = G.second;
Map<StringName, CSharpScript::EventSignal>::Element *match = script->event_signals.find(name);
@@ -1166,9 +1151,9 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
{
MutexLock lock(ManagedCallable::instances_mutex);
- for (Map<ManagedCallable *, Array>::Element *elem = ManagedCallable::instances_pending_reload.front(); elem; elem = elem->next()) {
- ManagedCallable *managed_callable = elem->key();
- const Array &serialized_data = elem->value();
+ for (const KeyValue<ManagedCallable *, Array> &elem : ManagedCallable::instances_pending_reload) {
+ ManagedCallable *managed_callable = elem.key;
+ const Array &serialized_data = elem.value;
MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data);
MonoDelegate *delegate = nullptr;
@@ -1312,8 +1297,8 @@ bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
}
void CSharpLanguage::_on_scripts_domain_unloaded() {
- for (Map<Object *, CSharpScriptBinding>::Element *E = script_bindings.front(); E; E = E->next()) {
- CSharpScriptBinding &script_binding = E->value();
+ for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
+ CSharpScriptBinding &script_binding = E.value;
script_binding.gchandle.release();
script_binding.inited = false;
}
@@ -1738,12 +1723,12 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
}
void CSharpInstance::get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state) {
- List<PropertyInfo> pinfo;
- get_property_list(&pinfo);
+ List<PropertyInfo> property_list;
+ get_property_list(&property_list);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+ for (const PropertyInfo &prop_info : property_list) {
Pair<StringName, Variant> state_pair;
- state_pair.first = E->get().name;
+ state_pair.first = prop_info.name;
ManagedType managedType;
@@ -1766,8 +1751,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
MonoObject *owner_managed = get_mono_object();
ERR_FAIL_NULL(owner_managed);
- for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) {
- const CSharpScript::EventSignal &event_signal = E->value();
+ for (const KeyValue<StringName, CSharpScript::EventSignal> &E : script->event_signals) {
+ const CSharpScript::EventSignal &event_signal = E.value;
MonoDelegate *delegate_field_value = (MonoDelegate *)event_signal.field->get_value(owner_managed);
if (!delegate_field_value) {
@@ -1794,8 +1779,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
}
void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
- for (Map<StringName, PropertyInfo>::Element *E = script->member_info.front(); E; E = E->next()) {
- p_properties->push_back(E->value());
+ for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
+ p_properties->push_back(E.value);
}
// Call _get_property_list
@@ -2034,8 +2019,8 @@ void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_f
}
void CSharpInstance::connect_event_signals() {
- for (const Map<StringName, CSharpScript::EventSignal>::Element *E = script->event_signals.front(); E; E = E->next()) {
- const CSharpScript::EventSignal &event_signal = E->value();
+ for (const KeyValue<StringName, CSharpScript::EventSignal> &E : script->event_signals) {
+ const CSharpScript::EventSignal &event_signal = E.value;
StringName signal_name = event_signal.field->get_name();
@@ -2049,8 +2034,7 @@ void CSharpInstance::connect_event_signals() {
}
void CSharpInstance::disconnect_event_signals() {
- for (const List<Callable>::Element *E = connected_event_signals.front(); E; E = E->next()) {
- const Callable &callable = E->get();
+ for (const Callable &callable : connected_event_signals) {
const EventSignalCallable *event_signal_callable = static_cast<const EventSignalCallable *>(callable.get_custom());
owner->disconnect(event_signal_callable->get_signal(), callable);
}
@@ -2320,12 +2304,12 @@ void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List
base_cache->_update_exports_values(values, propnames);
}
- for (Map<StringName, Variant>::Element *E = exported_members_defval_cache.front(); E; E = E->next()) {
- values[E->key()] = E->get();
+ for (const KeyValue<StringName, Variant> &E : exported_members_defval_cache) {
+ values[E.key] = E.value;
}
- for (List<PropertyInfo>::Element *E = exported_members_cache.front(); E; E = E->next()) {
- propnames.push_back(E->get());
+ for (const PropertyInfo &prop_info : exported_members_cache) {
+ propnames.push_back(prop_info);
}
}
@@ -2556,8 +2540,8 @@ bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_upda
_update_exports_values(values, propnames);
if (changed) {
- for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
- E->get()->update(propnames, values);
+ for (PlaceHolderScriptInstance *&script_instance : placeholders) {
+ script_instance->update(propnames, values);
}
} else {
p_instance_to_update->update(propnames, values);
@@ -3389,11 +3373,11 @@ bool CSharpScript::has_script_signal(const StringName &p_signal) const {
}
void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
- for (const Map<StringName, Vector<SignalParameter>>::Element *E = _signals.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, Vector<SignalParameter>> &E : _signals) {
MethodInfo mi;
- mi.name = E->key();
+ mi.name = E.key;
- const Vector<SignalParameter> &params = E->value();
+ const Vector<SignalParameter> &params = E.value;
for (int i = 0; i < params.size(); i++) {
const SignalParameter &param = params[i];
@@ -3408,11 +3392,11 @@ void CSharpScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
r_signals->push_back(mi);
}
- for (const Map<StringName, EventSignal>::Element *E = event_signals.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, EventSignal> &E : event_signals) {
MethodInfo mi;
- mi.name = E->key();
+ mi.name = E.key;
- const EventSignal &event_signal = E->value();
+ const EventSignal &event_signal = E.value;
const Vector<SignalParameter> &params = event_signal.parameters;
for (int i = 0; i < params.size(); i++) {
const SignalParameter &param = params[i];
@@ -3452,8 +3436,8 @@ Ref<Script> CSharpScript::get_base_script() const {
}
void CSharpScript::get_script_property_list(List<PropertyInfo> *p_list) const {
- for (Map<StringName, PropertyInfo>::Element *E = member_info.front(); E; E = E->next()) {
- p_list->push_back(E->value());
+ for (const KeyValue<StringName, PropertyInfo> &E : member_info) {
+ p_list->push_back(E.value);
}
}
@@ -3536,8 +3520,8 @@ CSharpScript::~CSharpScript() {
void CSharpScript::get_members(Set<StringName> *p_members) {
#if defined(TOOLS_ENABLED) || defined(DEBUG_ENABLED)
if (p_members) {
- for (Set<StringName>::Element *E = exported_members_names.front(); E; E = E->next()) {
- p_members->insert(E->get());
+ for (const StringName &member_name : exported_members_names) {
+ p_members->insert(member_name);
}
}
#endif
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
index 224d7e5b5a..11d8e0f72b 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
@@ -15,8 +15,9 @@
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
- <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <!-- Generates a package at build -->
- <IncludeBuildOutput>false</IncludeBuildOutput> <!-- Do not include the generator as a lib dependency -->
+ <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+ <!-- Do not include the generator as a lib dependency -->
+ <IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" PrivateAssets="all" />
diff --git a/modules/mono/editor/GodotTools/.gitignore b/modules/mono/editor/GodotTools/.gitignore
index 48e2f914d8..a41d1c89b5 100644
--- a/modules/mono/editor/GodotTools/.gitignore
+++ b/modules/mono/editor/GodotTools/.gitignore
@@ -353,4 +353,3 @@ healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
-
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs
index 4db71500da..450c4bf0cb 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/Program.cs
@@ -113,8 +113,7 @@ namespace GodotTools.IdeMessaging.CLI
}
}
- ExitMainLoop:
-
+ ExitMainLoop:
await forwarder.WriteLineToOutput("Event=Quit");
}
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
index cc0da44a13..284e94810a 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
@@ -150,8 +150,8 @@ EndProject";
{"Tools|Any CPU", "ExportRelease|Any CPU"}
};
- var regex = new Regex(string.Join("|",dict.Keys.Select(Regex.Escape)));
- var result = regex.Replace(input,m => dict[m.Value]);
+ var regex = new Regex(string.Join("|", dict.Keys.Select(Regex.Escape)));
+ var result = regex.Replace(input, m => dict[m.Value]);
if (result != input)
{
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
index 5bb8d444c2..f69307104f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs
@@ -577,27 +577,27 @@ MONO_AOT_MODE_LAST = 1000,
{
case OS.Platforms.Windows:
case OS.Platforms.UWP:
- {
- string arch = bits == "64" ? "x86_64" : "i686";
- return $"windows-{arch}";
- }
+ {
+ string arch = bits == "64" ? "x86_64" : "i686";
+ return $"windows-{arch}";
+ }
case OS.Platforms.MacOS:
- {
- Debug.Assert(bits == null || bits == "64");
- string arch = "x86_64";
- return $"{platform}-{arch}";
- }
+ {
+ Debug.Assert(bits == null || bits == "64");
+ string arch = "x86_64";
+ return $"{platform}-{arch}";
+ }
case OS.Platforms.LinuxBSD:
case OS.Platforms.Server:
- {
- string arch = bits == "64" ? "x86_64" : "i686";
- return $"linux-{arch}";
- }
+ {
+ string arch = bits == "64" ? "x86_64" : "i686";
+ return $"linux-{arch}";
+ }
case OS.Platforms.Haiku:
- {
- string arch = bits == "64" ? "x86_64" : "i686";
- return $"{platform}-{arch}";
- }
+ {
+ string arch = bits == "64" ? "x86_64" : "i686";
+ return $"{platform}-{arch}";
+ }
default:
throw new NotSupportedException($"Platform not supported: {platform}");
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index 270be8b6bf..0b5aa72a81 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -76,9 +76,9 @@ namespace GodotTools.Export
GlobalDef("mono/export/aot/use_interpreter", true);
// --aot or --aot=opt1,opt2 (use 'mono --aot=help AuxAssembly.dll' to list AOT options)
- GlobalDef("mono/export/aot/extra_aot_options", new string[] { });
+ GlobalDef("mono/export/aot/extra_aot_options", Array.Empty<string>());
// --optimize/-O=opt1,opt2 (use 'mono --list-opt'' to list optimize options)
- GlobalDef("mono/export/aot/extra_optimizer_options", new string[] { });
+ GlobalDef("mono/export/aot/extra_optimizer_options", Array.Empty<string>());
GlobalDef("mono/export/aot/android_toolchain_path", "");
}
@@ -188,7 +188,7 @@ namespace GodotTools.Export
// However, at least in the case of 'WebAssembly.Net.Http' for some reason the BCL assemblies
// reference a different version even though the assembly is the same, for some weird reason.
- var wasmFrameworkAssemblies = new[] {"WebAssembly.Bindings", "WebAssembly.Net.WebSockets"};
+ var wasmFrameworkAssemblies = new[] { "WebAssembly.Bindings", "WebAssembly.Net.WebSockets" };
foreach (string thisWasmFrameworkAssemblyName in wasmFrameworkAssemblies)
{
@@ -298,8 +298,8 @@ namespace GodotTools.Export
LLVMOutputPath = "",
FullAot = platform == OS.Platforms.iOS || (bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false),
UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"),
- ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? new string[] { },
- ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? new string[] { },
+ ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? Array.Empty<string>(),
+ ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? Array.Empty<string>(),
ToolchainPath = aotToolchainPath
};
@@ -381,7 +381,7 @@ namespace GodotTools.Export
private static bool PlatformHasTemplateDir(string platform)
{
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
- return !new[] {OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform);
+ return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform);
}
private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform)
@@ -430,7 +430,7 @@ namespace GodotTools.Export
/// </summary>
private static bool PlatformRequiresCustomBcl(string platform)
{
- if (new[] {OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5}.Contains(platform))
+ if (new[] { OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform))
return true;
// The 'net_4_x' BCL is not compatible between Windows and the other platforms.
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index 3f14629b11..b9aa760f4d 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -3,7 +3,8 @@
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
<TargetFramework>net472</TargetFramework>
<LangVersion>7.2</LangVersion>
- <GodotApiConfiguration>Debug</GodotApiConfiguration> <!-- The Godot editor uses the Debug Godot API assemblies -->
+ <!-- The Godot editor uses the Debug Godot API assemblies -->
+ <GodotApiConfiguration>Debug</GodotApiConfiguration>
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
<GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
<GodotApiAssembliesDir>$(GodotOutputDataDir)/Api/$(GodotApiConfiguration)</GodotApiAssembliesDir>
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
index 94fc5da425..821532f759 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
@@ -47,7 +47,7 @@ namespace GodotTools.Ides.Rider
GD.PushWarning(e.Message);
}
- return new RiderInfo[0];
+ return Array.Empty<RiderInfo>();
}
private static RiderInfo[] CollectAllRiderPathsLinux()
@@ -249,7 +249,7 @@ namespace GodotTools.Ides.Rider
bool isMac)
{
if (!Directory.Exists(toolboxRiderRootPath))
- return new string[0];
+ return Array.Empty<string>();
var channelDirs = Directory.GetDirectories(toolboxRiderRootPath);
var paths = channelDirs.SelectMany(channelDir =>
@@ -295,7 +295,7 @@ namespace GodotTools.Ides.Rider
Logger.Warn($"Failed to get RiderPath from {channelDir}", e);
}
- return new string[0];
+ return Array.Empty<string>();
})
.Where(c => !string.IsNullOrEmpty(c))
.ToArray();
@@ -306,7 +306,7 @@ namespace GodotTools.Ides.Rider
{
var folder = new DirectoryInfo(Path.Combine(buildDir, dirName));
if (!folder.Exists)
- return new string[0];
+ return Array.Empty<string>();
if (!isMac)
return new[] { Path.Combine(folder.FullName, searchPattern) }.Where(File.Exists).ToArray();
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
index ed25cdaa63..60dd565ef2 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
@@ -57,7 +57,7 @@ namespace GodotTools.Ides.Rider
public static bool IsExternalEditorSetToRider(EditorSettings editorSettings)
{
- return editorSettings.HasSetting(EditorPathSettingName) && IsRider((string) editorSettings.GetSetting(EditorPathSettingName));
+ return editorSettings.HasSetting(EditorPathSettingName) && IsRider((string)editorSettings.GetSetting(EditorPathSettingName));
}
public static bool IsRider(string path)
diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
index e745966435..4624439665 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
@@ -74,10 +74,10 @@ namespace GodotTools.Utils
}
private static readonly IEnumerable<string> LinuxBSDPlatforms =
- new[] {Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD};
+ new[] { Names.Linux, Names.FreeBSD, Names.NetBSD, Names.BSD };
private static readonly IEnumerable<string> UnixLikePlatforms =
- new[] {Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS}
+ new[] { Names.MacOS, Names.Server, Names.Haiku, Names.Android, Names.iOS }
.Concat(LinuxBSDPlatforms).ToArray();
private static readonly Lazy<bool> _isWindows = new Lazy<bool>(() => IsOS(Names.Windows));
@@ -111,13 +111,22 @@ namespace GodotTools.Utils
private static string PathWhichWindows([NotNull] string name)
{
- string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? new string[] { };
+ string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>();
string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep);
+ char[] invalidPathChars = Path.GetInvalidPathChars();
var searchDirs = new List<string>();
if (pathDirs != null)
- searchDirs.AddRange(pathDirs);
+ {
+ foreach (var pathDir in pathDirs)
+ {
+ if (pathDir.IndexOfAny(invalidPathChars) != -1)
+ continue;
+
+ searchDirs.Add(pathDir);
+ }
+ }
string nameExt = Path.GetExtension(name);
bool hasPathExt = !string.IsNullOrEmpty(nameExt) && windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase);
@@ -128,20 +137,29 @@ namespace GodotTools.Utils
return searchDirs.Select(dir => Path.Combine(dir, name)).FirstOrDefault(File.Exists);
return (from dir in searchDirs
- select Path.Combine(dir, name)
+ select Path.Combine(dir, name)
into path
- from ext in windowsExts
- select path + ext).FirstOrDefault(File.Exists);
+ from ext in windowsExts
+ select path + ext).FirstOrDefault(File.Exists);
}
private static string PathWhichUnix([NotNull] string name)
{
string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep);
+ char[] invalidPathChars = Path.GetInvalidPathChars();
var searchDirs = new List<string>();
if (pathDirs != null)
- searchDirs.AddRange(pathDirs);
+ {
+ foreach (var pathDir in pathDirs)
+ {
+ if (pathDir.IndexOfAny(invalidPathChars) != -1)
+ continue;
+
+ searchDirs.Add(pathDir);
+ }
+ }
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
@@ -196,7 +214,7 @@ namespace GodotTools.Utils
startInfo.UseShellExecute = false;
- using (var process = new Process {StartInfo = startInfo})
+ using (var process = new Process { StartInfo = startInfo })
{
process.Start();
process.WaitForExit();
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 620b031ddb..632f7d61cc 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -416,8 +416,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
// Try to find as global enum constant
const EnumInterface *target_ienum = nullptr;
- for (const List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
- target_ienum = &E->get();
+ for (const EnumInterface &ienum : global_enums) {
+ target_ienum = &ienum;
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
if (target_iconst) {
break;
@@ -455,8 +455,8 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf
// Try to find as enum constant in the current class
const EnumInterface *target_ienum = nullptr;
- for (const List<EnumInterface>::Element *E = target_itype->enums.front(); E; E = E->next()) {
- target_ienum = &E->get();
+ for (const EnumInterface &ienum : target_itype->enums) {
+ target_ienum = &ienum;
target_iconst = find_constant_by_name(target_name, target_ienum->constants);
if (target_iconst) {
break;
@@ -655,9 +655,7 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
return 0;
}
- for (const List<ConstantInterface>::Element *E = p_ienum.constants.front()->next(); E; E = E->next()) {
- const ConstantInterface &iconstant = E->get();
-
+ for (const ConstantInterface &iconstant : p_ienum.constants) {
Vector<String> parts = iconstant.name.split("_", /* p_allow_empty: */ true);
int i;
@@ -682,12 +680,10 @@ int BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumInterface &p_ienum, int p_prefix_length) {
if (p_prefix_length > 0) {
- for (List<ConstantInterface>::Element *E = p_ienum.constants.front(); E; E = E->next()) {
+ for (ConstantInterface &iconstant : p_ienum.constants) {
int curr_prefix_length = p_prefix_length;
- ConstantInterface &curr_const = E->get();
-
- String constant_name = curr_const.name;
+ String constant_name = iconstant.name;
Vector<String> parts = constant_name.split("_", /* p_allow_empty: */ true);
@@ -713,15 +709,13 @@ void BindingsGenerator::_apply_prefix_to_enum_constants(BindingsGenerator::EnumI
constant_name += parts[i];
}
- curr_const.proxy_name = snake_to_pascal_case(constant_name, true);
+ iconstant.proxy_name = snake_to_pascal_case(constant_name, true);
}
}
}
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
- for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
- const MethodInterface &imethod = E->get();
-
+ for (const MethodInterface &imethod : p_itype.methods) {
if (imethod.is_virtual) {
continue;
}
@@ -735,8 +729,8 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
// Get arguments information
int i = 0;
- for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
- const TypeInterface *arg_type = _get_type_or_placeholder(F->get().type);
+ for (const ArgumentInterface &iarg : imethod.arguments) {
+ const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
im_sig += ", ";
im_sig += arg_type->im_type_in;
@@ -776,10 +770,10 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
if (p_itype.api_type != ClassDB::API_EDITOR) {
match->get().editor_only = false;
}
- method_icalls_map.insert(&E->get(), &match->get());
+ method_icalls_map.insert(&imethod, &match->get());
} else {
List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
- method_icalls_map.insert(&E->get(), &added->get());
+ method_icalls_map.insert(&imethod, &added->get());
}
}
}
@@ -859,9 +853,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
p_output.append(INDENT1 "public static partial class " BINDINGS_GLOBAL_SCOPE_CLASS "\n" INDENT1 "{");
- for (const List<ConstantInterface>::Element *E = global_constants.front(); E; E = E->next()) {
- const ConstantInterface &iconstant = E->get();
-
+ for (const ConstantInterface &iconstant : global_constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -894,9 +886,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
// Enums
- for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
- const EnumInterface &ienum = E->get();
-
+ for (const EnumInterface &ienum : global_enums) {
CRASH_COND(ienum.constants.is_empty());
String enum_proxy_name = ienum.cname.operator String();
@@ -921,9 +911,8 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append(enum_proxy_name);
p_output.append("\n" INDENT1 OPEN_BLOCK);
- for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
- const ConstantInterface &iconstant = F->get();
-
+ const ConstantInterface &last = ienum.constants.back()->get();
+ for (const ConstantInterface &iconstant : ienum.constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), nullptr);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -945,7 +934,7 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
p_output.append(iconstant.proxy_name);
p_output.append(" = ");
p_output.append(itos(iconstant.value));
- p_output.append(F != ienum.constants.back() ? ",\n" : "\n");
+ p_output.append(&iconstant != &last ? ",\n" : "\n");
}
p_output.append(INDENT1 CLOSE_BLOCK);
@@ -1053,11 +1042,11 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
- for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : core_custom_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : method_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
#undef ADD_INTERNAL_CALL
@@ -1161,11 +1150,11 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
cs_icalls_content.append(m_icall.im_sig + ");\n"); \
}
- for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : editor_custom_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
- ADD_INTERNAL_CALL(E->get());
+ for (const InternalCall &internal_call : method_icalls) {
+ ADD_INTERNAL_CALL(internal_call);
}
#undef ADD_INTERNAL_CALL
@@ -1327,9 +1316,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add constants
- for (const List<ConstantInterface>::Element *E = itype.constants.front(); E; E = E->next()) {
- const ConstantInterface &iconstant = E->get();
-
+ for (const ConstantInterface &iconstant : itype.constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -1360,18 +1347,15 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add enums
- for (const List<EnumInterface>::Element *E = itype.enums.front(); E; E = E->next()) {
- const EnumInterface &ienum = E->get();
-
+ for (const EnumInterface &ienum : itype.enums) {
ERR_FAIL_COND_V(ienum.constants.is_empty(), ERR_BUG);
output.append(MEMBER_BEGIN "public enum ");
output.append(ienum.cname.operator String());
output.append(MEMBER_BEGIN OPEN_BLOCK);
- for (const List<ConstantInterface>::Element *F = ienum.constants.front(); F; F = F->next()) {
- const ConstantInterface &iconstant = F->get();
-
+ const ConstantInterface &last = ienum.constants.back()->get();
+ for (const ConstantInterface &iconstant : ienum.constants) {
if (iconstant.const_doc && iconstant.const_doc->description.size()) {
String xml_summary = bbcode_to_xml(fix_doc_description(iconstant.const_doc->description), &itype);
Vector<String> summary_lines = xml_summary.length() ? xml_summary.split("\n") : Vector<String>();
@@ -1393,7 +1377,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.append(iconstant.proxy_name);
output.append(" = ");
output.append(itos(iconstant.value));
- output.append(F != ienum.constants.back() ? ",\n" : "\n");
+ output.append(&iconstant != &last ? ",\n" : "\n");
}
output.append(INDENT2 CLOSE_BLOCK);
@@ -1401,8 +1385,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add properties
- for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) {
- const PropertyInterface &iprop = E->get();
+ for (const PropertyInterface &iprop : itype.properties) {
Error prop_err = _generate_cs_property(itype, iprop, output);
ERR_FAIL_COND_V_MSG(prop_err != OK, prop_err,
"Failed to generate property '" + iprop.cname.operator String() +
@@ -1463,15 +1446,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
int method_bind_count = 0;
- for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
- const MethodInterface &imethod = E->get();
+ for (const MethodInterface &imethod : itype.methods) {
Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'.");
}
- for (const List<SignalInterface>::Element *E = itype.signals_.front(); E; E = E->next()) {
- const SignalInterface &isignal = E->get();
+ for (const SignalInterface &isignal : itype.signals_) {
Error method_err = _generate_cs_signal(itype, isignal, output);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate signal '" + isignal.name + "' for class '" + itype.name + "'.");
@@ -1678,8 +1659,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
StringBuilder default_args_doc;
// Retrieve information from the arguments
- for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
+ const ArgumentInterface &first = p_imethod.arguments.front()->get();
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
@@ -1699,7 +1680,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Add the current arguments to the signature
// If the argument has a default value which is not a constant, we will make it Nullable
{
- if (F != p_imethod.arguments.front()) {
+ if (&iarg != &first) {
arguments_sig += ", ";
}
@@ -1754,7 +1735,12 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
cs_in_statements += " : ";
}
- String def_arg = sformat(iarg.default_argument, arg_type->cs_type);
+ String cs_type = arg_type->cs_type;
+ if (cs_type.ends_with("[]")) {
+ cs_type = cs_type.substr(0, cs_type.length() - 2);
+ }
+
+ String def_arg = sformat(iarg.default_argument, cs_type);
cs_in_statements += def_arg;
cs_in_statements += ";\n" INDENT3;
@@ -1763,8 +1749,10 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Apparently the name attribute must not include the @
String param_tag_name = iarg.name.begins_with("@") ? iarg.name.substr(1, iarg.name.length()) : iarg.name;
+ // Escape < and > in the attribute default value
+ String param_def_arg = def_arg.replacen("<", "&lt;").replacen(">", "&gt;");
- default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + def_arg + "</param>");
+ default_args_doc.append(MEMBER_BEGIN "/// <param name=\"" + param_tag_name + "\">If the parameter is null, then the default value is " + param_def_arg + "</param>");
} else {
icall_params += arg_type->cs_in.is_empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
}
@@ -1855,9 +1843,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
p_output.append(p_imethod.name);
p_output.append("\"");
- for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
p_output.append(", ");
- p_output.append(F->get().name);
+ p_output.append(iarg.name);
}
p_output.append(");\n" CLOSE_BLOCK_L2);
@@ -1899,8 +1887,8 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
String arguments_sig;
// Retrieve information from the arguments
- for (const List<ArgumentInterface>::Element *F = p_isignal.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
+ const ArgumentInterface &first = p_isignal.arguments.front()->get();
+ for (const ArgumentInterface &iarg : p_isignal.arguments) {
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
ERR_FAIL_COND_V_MSG(arg_type->is_singleton, ERR_BUG,
@@ -1914,7 +1902,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf
// Add the current arguments to the signature
- if (F != p_isignal.arguments.front()) {
+ if (&iarg != &first) {
arguments_sig += ", ";
}
@@ -2042,8 +2030,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
- for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
- const MethodInterface &imethod = E->get();
+ for (const MethodInterface &imethod : itype.methods) {
Error method_err = _generate_glue_method(itype, imethod, output);
ERR_FAIL_COND_V_MSG(method_err != OK, method_err,
"Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'.");
@@ -2114,20 +2101,20 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
}
bool tools_sequence = false;
- for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) {
+ for (const InternalCall &internal_call : core_custom_icalls) {
if (tools_sequence) {
- if (!E->get().editor_only) {
+ if (!internal_call.editor_only) {
tools_sequence = false;
output.append("#endif\n");
}
} else {
- if (E->get().editor_only) {
+ if (internal_call.editor_only) {
output.append("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ ADD_INTERNAL_CALL_REGISTRATION(internal_call);
}
if (tools_sequence) {
@@ -2136,24 +2123,24 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
}
output.append("#ifdef TOOLS_ENABLED\n");
- for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ for (const InternalCall &internal_call : editor_custom_icalls)
+ ADD_INTERNAL_CALL_REGISTRATION(internal_call);
output.append("#endif // TOOLS_ENABLED\n");
- for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
+ for (const InternalCall &internal_call : method_icalls) {
if (tools_sequence) {
- if (!E->get().editor_only) {
+ if (!internal_call.editor_only) {
tools_sequence = false;
output.append("#endif\n");
}
} else {
- if (E->get().editor_only) {
+ if (internal_call.editor_only) {
output.append("#ifdef TOOLS_ENABLED\n");
tools_sequence = true;
}
}
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ ADD_INTERNAL_CALL_REGISTRATION(internal_call);
}
if (tools_sequence) {
@@ -2209,8 +2196,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
// Get arguments information
int i = 0;
- for (const List<ArgumentInterface>::Element *F = p_imethod.arguments.front(); F; F = F->next()) {
- const ArgumentInterface &iarg = F->get();
+ for (const ArgumentInterface &iarg : p_imethod.arguments) {
const TypeInterface *arg_type = _get_type_or_placeholder(iarg.type);
String c_param_name = "arg" + itos(i + 1);
@@ -2623,9 +2609,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
Map<StringName, StringName> accessor_methods;
- for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- const PropertyInfo &property = E->get();
-
+ for (const PropertyInfo &property : property_list) {
if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY) {
continue;
}
@@ -2684,9 +2668,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
ClassDB::get_method_list(type_cname, &method_list, true);
method_list.sort();
- for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
- const MethodInfo &method_info = E->get();
-
+ for (const MethodInfo &method_info : method_list) {
int argc = method_info.arguments.size();
if (method_info.name.is_empty()) {
@@ -2840,9 +2822,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
// Classes starting with an underscore are ignored unless they're used as a property setter or getter
if (!imethod.is_virtual && imethod.name[0] == '_') {
- for (const List<PropertyInterface>::Element *F = itype.properties.front(); F; F = F->next()) {
- const PropertyInterface &iprop = F->get();
-
+ for (const PropertyInterface &iprop : itype.properties) {
if (iprop.setter == imethod.name || iprop.getter == imethod.name) {
imethod.is_internal = true;
itype.methods.push_back(imethod);
@@ -2952,8 +2932,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
}
EnumInterface ienum(enum_proxy_cname);
const List<StringName> &enum_constants = enum_map.get(*k);
- for (const List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
- const StringName &constant_cname = E->get();
+ for (const StringName &constant_cname : enum_constants) {
String constant_name = constant_cname.operator String();
int *value = class_info->constant_map.getptr(constant_cname);
ERR_FAIL_NULL_V(value, false);
@@ -2989,9 +2968,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
enum_types.insert(enum_itype.cname, enum_itype);
}
- for (const List<String>::Element *E = constants.front(); E; E = E->next()) {
- const String &constant_name = E->get();
- int *value = class_info->constant_map.getptr(StringName(E->get()));
+ for (const String &constant_name : constants) {
+ int *value = class_info->constant_map.getptr(StringName(constant_name));
ERR_FAIL_NULL_V(value, false);
ConstantInterface iconstant(constant_name, snake_to_pascal_case(constant_name, true), *value);
@@ -3099,6 +3077,9 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
r_iarg.default_argument = "null";
break;
case Variant::ARRAY:
+ r_iarg.default_argument = "new %s { }";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+ break;
case Variant::PACKED_BYTE_ARRAY:
case Variant::PACKED_INT32_ARRAY:
case Variant::PACKED_INT64_ARRAY:
@@ -3108,7 +3089,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
case Variant::PACKED_VECTOR2_ARRAY:
case Variant::PACKED_VECTOR3_ARRAY:
case Variant::PACKED_COLOR_ARRAY:
- r_iarg.default_argument = "new %s {}";
+ r_iarg.default_argument = "Array.Empty<%s>()";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
break;
case Variant::TRANSFORM2D: {
@@ -3539,9 +3520,7 @@ void BindingsGenerator::_populate_global_constants() {
}
}
- for (List<EnumInterface>::Element *E = global_enums.front(); E; E = E->next()) {
- EnumInterface &ienum = E->get();
-
+ for (EnumInterface &ienum : global_enums) {
TypeInterface enum_itype;
enum_itype.is_enum = true;
enum_itype.name = ienum.cname.operator String();
@@ -3571,13 +3550,13 @@ void BindingsGenerator::_populate_global_constants() {
hardcoded_enums.push_back("Vector2i.Axis");
hardcoded_enums.push_back("Vector3.Axis");
hardcoded_enums.push_back("Vector3i.Axis");
- for (List<StringName>::Element *E = hardcoded_enums.front(); E; E = E->next()) {
+ for (const StringName &enum_cname : hardcoded_enums) {
// These enums are not generated and must be written manually (e.g.: Vector3.Axis)
// Here, we assume core types do not begin with underscore
TypeInterface enum_itype;
enum_itype.is_enum = true;
- enum_itype.name = E->get().operator String();
- enum_itype.cname = E->get();
+ enum_itype.name = enum_cname.operator String();
+ enum_itype.cname = enum_cname;
enum_itype.proxy_name = enum_itype.name;
TypeInterface::postsetup_enum_type(enum_itype);
enum_types.insert(enum_itype.cname, enum_itype);
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 48c0e02723..a649181b20 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -357,9 +357,9 @@ class BindingsGenerator {
List<SignalInterface> signals_;
const MethodInterface *find_method_by_name(const StringName &p_cname) const {
- for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().cname == p_cname) {
- return &E->get();
+ for (const MethodInterface &E : methods) {
+ if (E.cname == p_cname) {
+ return &E;
}
}
@@ -367,9 +367,9 @@ class BindingsGenerator {
}
const PropertyInterface *find_property_by_name(const StringName &p_cname) const {
- for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().cname == p_cname) {
- return &E->get();
+ for (const PropertyInterface &E : properties) {
+ if (E.cname == p_cname) {
+ return &E;
}
}
@@ -377,9 +377,9 @@ class BindingsGenerator {
}
const PropertyInterface *find_property_by_proxy_name(const String &p_proxy_name) const {
- for (const List<PropertyInterface>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().proxy_name == p_proxy_name) {
- return &E->get();
+ for (const PropertyInterface &E : properties) {
+ if (E.proxy_name == p_proxy_name) {
+ return &E;
}
}
@@ -387,9 +387,9 @@ class BindingsGenerator {
}
const MethodInterface *find_method_by_proxy_name(const String &p_proxy_name) const {
- for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().proxy_name == p_proxy_name) {
- return &E->get();
+ for (const MethodInterface &E : methods) {
+ if (E.proxy_name == p_proxy_name) {
+ return &E;
}
}
@@ -613,9 +613,9 @@ class BindingsGenerator {
}
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
- for (const List<ConstantInterface>::Element *E = p_constants.front(); E; E = E->next()) {
- if (E->get().name == p_name) {
- return &E->get();
+ for (const ConstantInterface &E : p_constants) {
+ if (E.name == p_name) {
+ return &E;
}
}
diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp
index bbfba83e6f..b7b36a92d8 100644
--- a/modules/mono/editor/code_completion.cpp
+++ b/modules/mono/editor/code_completion.cpp
@@ -109,9 +109,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<PropertyInfo> project_props;
ProjectSettings::get_singleton()->get_property_list(&project_props);
- for (List<PropertyInfo>::Element *E = project_props.front(); E; E = E->next()) {
- const PropertyInfo &prop = E->get();
-
+ for (const PropertyInfo &prop : project_props) {
if (!prop.name.begins_with("input/")) {
continue;
}
@@ -125,8 +123,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
// AutoLoads
Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
- for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) {
- const ProjectSettings::AutoloadInfo &info = E->value();
+ for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : autoloads) {
+ const ProjectSettings::AutoloadInfo &info = E.value;
suggestions.push_back(quoted("/root/" + String(info.name)));
}
}
@@ -187,8 +185,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
ClassDB::get_signal_list(native, &signals, /* p_no_inheritance: */ false);
}
- for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
- const String &signal = E->get().name;
+ for (const MethodInfo &E : signals) {
+ const String &signal = E.name;
suggestions.push_back(quoted(signal));
}
} break;
@@ -199,8 +197,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_color_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -211,8 +209,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_constant_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -223,8 +221,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_font_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -235,8 +233,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_font_size_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
@@ -247,8 +245,8 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
List<StringName> sn;
Theme::get_default()->get_stylebox_list(base->get_class(), &sn);
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- suggestions.push_back(quoted(E->get()));
+ for (const StringName &E : sn) {
+ suggestions.push_back(quoted(E));
}
}
} break;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
index 2b641a8937..061c572c32 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs
@@ -1,16 +1,10 @@
-// file: core/math/aabb.h
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/math/aabb.cpp
-// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
-// file: core/variant_call.cpp
-// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
index ce613f7ef9..f52a767018 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs
@@ -25,16 +25,30 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Wrapper around Godot's Array class, an array of Variant
+ /// typed elements allocated in the engine in C++. Useful when
+ /// interfacing with the engine. Otherwise prefer .NET collections
+ /// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
+ /// </summary>
public class Array : IList, IDisposable
{
ArraySafeHandle safeHandle;
bool disposed = false;
+ /// <summary>
+ /// Constructs a new empty <see cref="Array"/>.
+ /// </summary>
public Array()
{
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
}
+ /// <summary>
+ /// Constructs a new <see cref="Array"/> from the given collection's elements.
+ /// </summary>
+ /// <param name="collection">The collection of elements to construct from.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(IEnumerable collection) : this()
{
if (collection == null)
@@ -44,6 +58,11 @@ namespace Godot.Collections
Add(element);
}
+ /// <summary>
+ /// Constructs a new <see cref="Array"/> from the given objects.
+ /// </summary>
+ /// <param name="array">The objects to put in the new array.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(params object[] array) : this()
{
if (array == null)
@@ -71,21 +90,40 @@ namespace Godot.Collections
return safeHandle.DangerousGetHandle();
}
+ /// <summary>
+ /// Duplicates this <see cref="Array"/>.
+ /// </summary>
+ /// <param name="deep">If true, performs a deep copy.</param>
+ /// <returns>A new Godot Array.</returns>
public Array Duplicate(bool deep = false)
{
return new Array(godot_icall_Array_Duplicate(GetPtr(), deep));
}
+ /// <summary>
+ /// Resizes this <see cref="Array"/> to the given size.
+ /// </summary>
+ /// <param name="newSize">The new size of the array.</param>
+ /// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
public Error Resize(int newSize)
{
return godot_icall_Array_Resize(GetPtr(), newSize);
}
+ /// <summary>
+ /// Shuffles the contents of this <see cref="Array"/> into a random order.
+ /// </summary>
public void Shuffle()
{
godot_icall_Array_Shuffle(GetPtr());
}
+ /// <summary>
+ /// Concatenates these two <see cref="Array"/>s.
+ /// </summary>
+ /// <param name="left">The first array.</param>
+ /// <param name="right">The second array.</param>
+ /// <returns>A new Godot Array with the contents of both arrays.</returns>
public static Array operator +(Array left, Array right)
{
return new Array(godot_icall_Array_Concatenate(left.GetPtr(), right.GetPtr()));
@@ -93,6 +131,9 @@ namespace Godot.Collections
// IDisposable
+ /// <summary>
+ /// Disposes of this <see cref="Array"/>.
+ /// </summary>
public void Dispose()
{
if (disposed)
@@ -109,38 +150,90 @@ namespace Godot.Collections
// IList
- public bool IsReadOnly => false;
+ bool IList.IsReadOnly => false;
- public bool IsFixedSize => false;
+ bool IList.IsFixedSize => false;
+ /// <summary>
+ /// Returns the object at the given index.
+ /// </summary>
+ /// <value>The object at the given index.</value>
public object this[int index]
{
get => godot_icall_Array_At(GetPtr(), index);
set => godot_icall_Array_SetAt(GetPtr(), index, value);
}
+ /// <summary>
+ /// Adds an object to the end of this <see cref="Array"/>.
+ /// This is the same as `append` or `push_back` in GDScript.
+ /// </summary>
+ /// <param name="value">The object to add.</param>
+ /// <returns>The new size after adding the object.</returns>
public int Add(object value) => godot_icall_Array_Add(GetPtr(), value);
+ /// <summary>
+ /// Checks if this <see cref="Array"/> contains the given object.
+ /// </summary>
+ /// <param name="value">The item to look for.</param>
+ /// <returns>Whether or not this array contains the given object.</returns>
public bool Contains(object value) => godot_icall_Array_Contains(GetPtr(), value);
+ /// <summary>
+ /// Erases all items from this <see cref="Array"/>.
+ /// </summary>
public void Clear() => godot_icall_Array_Clear(GetPtr());
+ /// <summary>
+ /// Searches this <see cref="Array"/> for an object
+ /// and returns its index or -1 if not found.
+ /// </summary>
+ /// <param name="value">The object to search for.</param>
+ /// <returns>The index of the object, or -1 if not found.</returns>
public int IndexOf(object value) => godot_icall_Array_IndexOf(GetPtr(), value);
+ /// <summary>
+ /// Inserts a new object at a given position in the array.
+ /// The position must be a valid position of an existing item,
+ /// or the position at the end of the array.
+ /// Existing items will be moved to the right.
+ /// </summary>
+ /// <param name="index">The index to insert at.</param>
+ /// <param name="value">The object to insert.</param>
public void Insert(int index, object value) => godot_icall_Array_Insert(GetPtr(), index, value);
+ /// <summary>
+ /// Removes the first occurrence of the specified value
+ /// from this <see cref="Array"/>.
+ /// </summary>
+ /// <param name="value">The value to remove.</param>
public void Remove(object value) => godot_icall_Array_Remove(GetPtr(), value);
+ /// <summary>
+ /// Removes an element from this <see cref="Array"/> by index.
+ /// </summary>
+ /// <param name="index">The index of the element to remove.</param>
public void RemoveAt(int index) => godot_icall_Array_RemoveAt(GetPtr(), index);
// ICollection
+ /// <summary>
+ /// Returns the number of elements in this <see cref="Array"/>.
+ /// This is also known as the size or length of the array.
+ /// </summary>
+ /// <returns>The number of elements.</returns>
public int Count => godot_icall_Array_Count(GetPtr());
- public object SyncRoot => this;
+ object ICollection.SyncRoot => this;
- public bool IsSynchronized => false;
+ bool ICollection.IsSynchronized => false;
+ /// <summary>
+ /// Copies the elements of this <see cref="Array"/> to the given
+ /// untyped C# array, starting at the given index.
+ /// </summary>
+ /// <param name="array">The array to copy to.</param>
+ /// <param name="index">The index to start at.</param>
public void CopyTo(System.Array array, int index)
{
if (array == null)
@@ -155,6 +248,10 @@ namespace Godot.Collections
// IEnumerable
+ /// <summary>
+ /// Gets an enumerator for this <see cref="Array"/>.
+ /// </summary>
+ /// <returns>An enumerator.</returns>
public IEnumerator GetEnumerator()
{
int count = Count;
@@ -165,6 +262,10 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Converts this <see cref="Array"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this array.</returns>
public override string ToString()
{
return godot_icall_Array_ToString(GetPtr());
@@ -234,6 +335,13 @@ namespace Godot.Collections
internal extern static string godot_icall_Array_ToString(IntPtr ptr);
}
+ /// <summary>
+ /// Typed wrapper around Godot's Array class, an array of Variant
+ /// typed elements allocated in the engine in C++. Useful when
+ /// interfacing with the engine. Otherwise prefer .NET collections
+ /// such as arrays or <see cref="List{T}"/>.
+ /// </summary>
+ /// <typeparam name="T">The type of the array.</typeparam>
public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
{
Array objectArray;
@@ -246,11 +354,19 @@ namespace Godot.Collections
Array.godot_icall_Array_Generic_GetElementTypeInfo(typeof(T), out elemTypeEncoding, out elemTypeClass);
}
+ /// <summary>
+ /// Constructs a new empty <see cref="Array{T}"/>.
+ /// </summary>
public Array()
{
objectArray = new Array();
}
+ /// <summary>
+ /// Constructs a new <see cref="Array{T}"/> from the given collection's elements.
+ /// </summary>
+ /// <param name="collection">The collection of elements to construct from.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(IEnumerable<T> collection)
{
if (collection == null)
@@ -259,6 +375,11 @@ namespace Godot.Collections
objectArray = new Array(collection);
}
+ /// <summary>
+ /// Constructs a new <see cref="Array{T}"/> from the given items.
+ /// </summary>
+ /// <param name="array">The items to put in the new array.</param>
+ /// <returns>A new Godot Array.</returns>
public Array(params T[] array) : this()
{
if (array == null)
@@ -268,6 +389,10 @@ namespace Godot.Collections
objectArray = new Array(array);
}
+ /// <summary>
+ /// Constructs a typed <see cref="Array{T}"/> from an untyped <see cref="Array"/>.
+ /// </summary>
+ /// <param name="array">The untyped array to construct from.</param>
public Array(Array array)
{
objectArray = array;
@@ -288,26 +413,49 @@ namespace Godot.Collections
return objectArray.GetPtr();
}
+ /// <summary>
+ /// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>.
+ /// </summary>
+ /// <param name="from">The typed array to convert.</param>
public static explicit operator Array(Array<T> from)
{
return from.objectArray;
}
+ /// <summary>
+ /// Duplicates this <see cref="Array{T}"/>.
+ /// </summary>
+ /// <param name="deep">If true, performs a deep copy.</param>
+ /// <returns>A new Godot Array.</returns>
public Array<T> Duplicate(bool deep = false)
{
return new Array<T>(objectArray.Duplicate(deep));
}
+ /// <summary>
+ /// Resizes this <see cref="Array{T}"/> to the given size.
+ /// </summary>
+ /// <param name="newSize">The new size of the array.</param>
+ /// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
public Error Resize(int newSize)
{
return objectArray.Resize(newSize);
}
+ /// <summary>
+ /// Shuffles the contents of this <see cref="Array{T}"/> into a random order.
+ /// </summary>
public void Shuffle()
{
objectArray.Shuffle();
}
+ /// <summary>
+ /// Concatenates these two <see cref="Array{T}"/>s.
+ /// </summary>
+ /// <param name="left">The first array.</param>
+ /// <param name="right">The second array.</param>
+ /// <returns>A new Godot Array with the contents of both arrays.</returns>
public static Array<T> operator +(Array<T> left, Array<T> right)
{
return new Array<T>(left.objectArray + right.objectArray);
@@ -315,22 +463,44 @@ namespace Godot.Collections
// IList<T>
+ /// <summary>
+ /// Returns the value at the given index.
+ /// </summary>
+ /// <value>The value at the given index.</value>
public T this[int index]
{
get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); }
set { objectArray[index] = value; }
}
+ /// <summary>
+ /// Searches this <see cref="Array{T}"/> for an item
+ /// and returns its index or -1 if not found.
+ /// </summary>
+ /// <param name="item">The item to search for.</param>
+ /// <returns>The index of the item, or -1 if not found.</returns>
public int IndexOf(T item)
{
return objectArray.IndexOf(item);
}
+ /// <summary>
+ /// Inserts a new item at a given position in the <see cref="Array{T}"/>.
+ /// The position must be a valid position of an existing item,
+ /// or the position at the end of the array.
+ /// Existing items will be moved to the right.
+ /// </summary>
+ /// <param name="index">The index to insert at.</param>
+ /// <param name="item">The item to insert.</param>
public void Insert(int index, T item)
{
objectArray.Insert(index, item);
}
+ /// <summary>
+ /// Removes an element from this <see cref="Array{T}"/> by index.
+ /// </summary>
+ /// <param name="index">The index of the element to remove.</param>
public void RemoveAt(int index)
{
objectArray.RemoveAt(index);
@@ -338,31 +508,53 @@ namespace Godot.Collections
// ICollection<T>
+ /// <summary>
+ /// Returns the number of elements in this <see cref="Array{T}"/>.
+ /// This is also known as the size or length of the array.
+ /// </summary>
+ /// <returns>The number of elements.</returns>
public int Count
{
get { return objectArray.Count; }
}
- public bool IsReadOnly
- {
- get { return objectArray.IsReadOnly; }
- }
+ bool ICollection<T>.IsReadOnly => false;
+ /// <summary>
+ /// Adds an item to the end of this <see cref="Array{T}"/>.
+ /// This is the same as `append` or `push_back` in GDScript.
+ /// </summary>
+ /// <param name="item">The item to add.</param>
+ /// <returns>The new size after adding the item.</returns>
public void Add(T item)
{
objectArray.Add(item);
}
+ /// <summary>
+ /// Erases all items from this <see cref="Array{T}"/>.
+ /// </summary>
public void Clear()
{
objectArray.Clear();
}
+ /// <summary>
+ /// Checks if this <see cref="Array{T}"/> contains the given item.
+ /// </summary>
+ /// <param name="item">The item to look for.</param>
+ /// <returns>Whether or not this array contains the given item.</returns>
public bool Contains(T item)
{
return objectArray.Contains(item);
}
+ /// <summary>
+ /// Copies the elements of this <see cref="Array{T}"/> to the given
+ /// C# array, starting at the given index.
+ /// </summary>
+ /// <param name="array">The C# array to copy to.</param>
+ /// <param name="arrayIndex">The index to start at.</param>
public void CopyTo(T[] array, int arrayIndex)
{
if (array == null)
@@ -386,6 +578,12 @@ namespace Godot.Collections
}
}
+ /// <summary>
+ /// Removes the first occurrence of the specified value
+ /// from this <see cref="Array{T}"/>.
+ /// </summary>
+ /// <param name="item">The value to remove.</param>
+ /// <returns>A bool indicating success or failure.</returns>
public bool Remove(T item)
{
return Array.godot_icall_Array_Remove(GetPtr(), item);
@@ -393,6 +591,10 @@ namespace Godot.Collections
// IEnumerable<T>
+ /// <summary>
+ /// Gets an enumerator for this <see cref="Array{T}"/>.
+ /// </summary>
+ /// <returns>An enumerator.</returns>
public IEnumerator<T> GetEnumerator()
{
int count = objectArray.Count;
@@ -408,6 +610,10 @@ namespace Godot.Collections
return GetEnumerator();
}
+ /// <summary>
+ /// Converts this <see cref="Array{T}"/> to a string.
+ /// </summary>
+ /// <returns>A string representation of this array.</returns>
public override string ToString() => objectArray.ToString();
}
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index 5dbf5d5657..cef343e152 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
index 4bb727bd35..d64c8b563e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
namespace Godot
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
index 785e87a043..1dca9e6ea7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs
@@ -61,7 +61,7 @@ namespace Godot
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
- writer.Write((ulong) TargetKind.Static);
+ writer.Write((ulong)TargetKind.Static);
SerializeType(writer, @delegate.GetType());
@@ -77,8 +77,8 @@ namespace Godot
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
- writer.Write((ulong) TargetKind.GodotObject);
- writer.Write((ulong) godotObject.GetInstanceId());
+ writer.Write((ulong)TargetKind.GodotObject);
+ writer.Write((ulong)godotObject.GetInstanceId());
SerializeType(writer, @delegate.GetType());
@@ -100,7 +100,7 @@ namespace Godot
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
- writer.Write((ulong) TargetKind.CompilerGenerated);
+ writer.Write((ulong)TargetKind.CompilerGenerated);
SerializeType(writer, targetType);
SerializeType(writer, @delegate.GetType());
@@ -149,14 +149,14 @@ namespace Godot
int flags = 0;
if (methodInfo.IsPublic)
- flags |= (int) BindingFlags.Public;
+ flags |= (int)BindingFlags.Public;
else
- flags |= (int) BindingFlags.NonPublic;
+ flags |= (int)BindingFlags.NonPublic;
if (methodInfo.IsStatic)
- flags |= (int) BindingFlags.Static;
+ flags |= (int)BindingFlags.Static;
else
- flags |= (int) BindingFlags.Instance;
+ flags |= (int)BindingFlags.Instance;
writer.Write(flags);
@@ -238,7 +238,7 @@ namespace Godot
}
else
{
- if (TryDeserializeSingleDelegate((byte[]) elem, out Delegate oneDelegate))
+ if (TryDeserializeSingleDelegate((byte[])elem, out Delegate oneDelegate))
delegates.Add(oneDelegate);
}
}
@@ -257,7 +257,7 @@ namespace Godot
using (var stream = new MemoryStream(buffer, writable: false))
using (var reader = new BinaryReader(stream))
{
- var targetKind = (TargetKind) reader.ReadUInt64();
+ var targetKind = (TargetKind)reader.ReadUInt64();
switch (targetKind)
{
@@ -353,11 +353,11 @@ namespace Godot
parameterTypes[i] = parameterType;
}
- methodInfo = declaringType.GetMethod(methodName, (BindingFlags) flags, null, parameterTypes, null);
+ methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags, null, parameterTypes, null);
return methodInfo != null && methodInfo.ReturnType == returnType;
}
- methodInfo = declaringType.GetMethod(methodName, (BindingFlags) flags);
+ methodInfo = declaringType.GetMethod(methodName, (BindingFlags)flags);
return methodInfo != null && methodInfo.ReturnType == returnType;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs
index c4c911b863..0c21bcaa3f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DynamicObject.cs
@@ -1,4 +1,3 @@
-
using System;
using System.Collections.Generic;
using System.Dynamic;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
index 6699c5992c..e7d4c40034 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs
@@ -1,12 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
-
#endif
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
// TODO: Add comments describing what this class does. It is not obvious.
@@ -26,7 +25,7 @@ namespace Godot
public static real_t Db2Linear(real_t db)
{
- return (real_t) Math.Exp(db * 0.11512925464970228420089957273422);
+ return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
}
public static real_t DecTime(real_t value, real_t amount, real_t step)
@@ -51,7 +50,7 @@ namespace Godot
public static real_t Linear2Db(real_t linear)
{
- return (real_t) (Math.Log(linear) * 8.6858896380650365530225783783321);
+ return (real_t)(Math.Log(linear) * 8.6858896380650365530225783783321);
}
public static Resource Load(string path)
@@ -76,7 +75,7 @@ namespace Godot
public static void Print(params object[] what)
{
- godot_icall_GD_print(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_print(Array.ConvertAll(what ?? new object[] { "null" }, x => x != null ? x.ToString() : "null"));
}
public static void PrintStack()
@@ -86,22 +85,22 @@ namespace Godot
public static void PrintErr(params object[] what)
{
- godot_icall_GD_printerr(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_printerr(Array.ConvertAll(what ?? new object[] { "null" }, x => x != null ? x.ToString() : "null"));
}
public static void PrintRaw(params object[] what)
{
- godot_icall_GD_printraw(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_printraw(Array.ConvertAll(what ?? new object[] { "null" }, x => x != null ? x.ToString() : "null"));
}
public static void PrintS(params object[] what)
{
- godot_icall_GD_prints(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_prints(Array.ConvertAll(what ?? new object[] { "null" }, x => x != null ? x.ToString() : "null"));
}
public static void PrintT(params object[] what)
{
- godot_icall_GD_printt(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null"));
+ godot_icall_GD_printt(Array.ConvertAll(what ?? new object[] { "null" }, x => x != null ? x.ToString() : "null"));
}
public static float Randf()
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs
index f1a00ae0fa..a566b53659 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs
@@ -1,4 +1,3 @@
-using System;
using System.Diagnostics;
namespace Godot
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs
index 702a6c76ba..729529d093 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
index c59d083080..f508211f68 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MarshalUtils.cs
@@ -1,12 +1,8 @@
using System;
-using System.Collections;
using System.Collections.Generic;
namespace Godot
{
- using Array = Godot.Collections.Array;
- using Dictionary = Godot.Collections.Dictionary;
-
static class MarshalUtils
{
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
index c3f372d415..213f84ad73 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs
@@ -1,9 +1,9 @@
-using System;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
namespace Godot
{
@@ -14,13 +14,15 @@ namespace Godot
/// <summary>
/// The circle constant, the circumference of the unit circle in radians.
/// </summary>
- public const real_t Tau = (real_t) 6.2831853071795864769252867666M; // 6.2831855f and 6.28318530717959
+ // 6.2831855f and 6.28318530717959
+ public const real_t Tau = (real_t)6.2831853071795864769252867666M;
/// <summary>
/// Constant that represents how many times the diameter of a circle
/// fits around its perimeter. This is equivalent to `Mathf.Tau / 2`.
/// </summary>
- public const real_t Pi = (real_t) 3.1415926535897932384626433833M; // 3.1415927f and 3.14159265358979
+ // 3.1415927f and 3.14159265358979
+ public const real_t Pi = (real_t)3.1415926535897932384626433833M;
/// <summary>
/// Positive infinity. For negative infinity, use `-Mathf.Inf`.
@@ -34,8 +36,10 @@ namespace Godot
/// </summary>
public const real_t NaN = real_t.NaN;
- private const real_t Deg2RadConst = (real_t) 0.0174532925199432957692369077M; // 0.0174532924f and 0.0174532925199433
- private const real_t Rad2DegConst = (real_t) 57.295779513082320876798154814M; // 57.29578f and 57.2957795130823
+ // 0.0174532924f and 0.0174532925199433
+ private const real_t Deg2RadConst = (real_t)0.0174532925199432957692369077M;
+ // 57.29578f and 57.2957795130823
+ private const real_t Rad2DegConst = (real_t)57.295779513082320876798154814M;
/// <summary>
/// Returns the absolute value of `s` (i.e. positive value).
@@ -515,7 +519,8 @@ namespace Godot
/// <returns>One of three possible values: `1`, `-1`, or `0`.</returns>
public static int Sign(int s)
{
- if (s == 0) return 0;
+ if (s == 0)
+ return 0;
return s < 0 ? -1 : 1;
}
@@ -526,7 +531,8 @@ namespace Godot
/// <returns>One of three possible values: `1`, `-1`, or `0`.</returns>
public static int Sign(real_t s)
{
- if (s == 0) return 0;
+ if (s == 0)
+ return 0;
return s < 0 ? -1 : 1;
}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
index c2f4701b5f..0888e33090 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/MathfEx.cs
@@ -1,10 +1,9 @@
-using System;
-
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
namespace Godot
{
@@ -15,12 +14,12 @@ namespace Godot
/// <summary>
/// The natural number `e`.
/// </summary>
- public const real_t E = (real_t) 2.7182818284590452353602874714M; // 2.7182817f and 2.718281828459045
+ public const real_t E = (real_t)2.7182818284590452353602874714M; // 2.7182817f and 2.718281828459045
/// <summary>
/// The square root of 2.
/// </summary>
- public const real_t Sqrt2 = (real_t) 1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095
+ public const real_t Sqrt2 = (real_t)1.4142135623730950488016887242M; // 1.4142136f and 1.414213562373095
/// <summary>
/// A very small number used for float comparison with error tolerance.
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
index ad6ca51e8b..1278fb53c2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
@@ -177,7 +177,7 @@ namespace Godot
return null;
}
- return from + dir * -dist;
+ return from - (dir * dist);
}
/// <summary>
@@ -206,7 +206,7 @@ namespace Godot
return null;
}
- return begin + segment * -dist;
+ return begin - (segment * dist);
}
/// <summary>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
index 817103994a..35f8217432 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
index 612fb64a3d..1053baaa26 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index 98efa89ef0..b182f1f15e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -61,9 +61,9 @@ namespace Godot
return string.Empty;
}
- // <summary>
- // If the string is a path to a file, return the path to the file without the extension.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file, return the path to the file without the extension.
+ /// </summary>
public static string BaseName(this string instance)
{
int index = instance.LastIndexOf('.');
@@ -74,17 +74,17 @@ namespace Godot
return instance;
}
- // <summary>
- // Return true if the strings begins with the given string.
- // </summary>
+ /// <summary>
+ /// Return <see langword="true"/> if the strings begins with the given string.
+ /// </summary>
public static bool BeginsWith(this string instance, string text)
{
return instance.StartsWith(text);
}
- // <summary>
- // Return the bigrams (pairs of consecutive letters) of this string.
- // </summary>
+ /// <summary>
+ /// Return the bigrams (pairs of consecutive letters) of this string.
+ /// </summary>
public static string[] Bigrams(this string instance)
{
var b = new string[instance.Length - 1];
@@ -124,12 +124,12 @@ namespace Godot
instance = instance.Substring(2);
}
- return sign * Convert.ToInt32(instance, 2);;
+ return sign * Convert.ToInt32(instance, 2);
}
- // <summary>
- // Return the amount of substrings in string.
- // </summary>
+ /// <summary>
+ /// Return the amount of substrings in string.
+ /// </summary>
public static int Count(this string instance, string what, bool caseSensitive = true, int from = 0, int to = 0)
{
if (what.Length == 0)
@@ -187,9 +187,9 @@ namespace Godot
return c;
}
- // <summary>
- // Return a copy of the string with special characters escaped using the C language standard.
- // </summary>
+ /// <summary>
+ /// Return a copy of the string with special characters escaped using the C language standard.
+ /// </summary>
public static string CEscape(this string instance)
{
var sb = new StringBuilder(string.Copy(instance));
@@ -209,9 +209,10 @@ namespace Godot
return sb.ToString();
}
- // <summary>
- // Return a copy of the string with escaped characters replaced by their meanings according to the C language standard.
- // </summary>
+ /// <summary>
+ /// Return a copy of the string with escaped characters replaced by their meanings
+ /// according to the C language standard.
+ /// </summary>
public static string CUnescape(this string instance)
{
var sb = new StringBuilder(string.Copy(instance));
@@ -231,9 +232,12 @@ namespace Godot
return sb.ToString();
}
- // <summary>
- // Change the case of some letters. Replace underscores with spaces, convert all letters to lowercase then capitalize first and every letter following the space character. For [code]capitalize camelCase mixed_with_underscores[/code] it will return [code]Capitalize Camelcase Mixed With Underscores[/code].
- // </summary>
+ /// <summary>
+ /// Change the case of some letters. Replace underscores with spaces, convert all letters
+ /// to lowercase then capitalize first and every letter following the space character.
+ /// For <c>capitalize camelCase mixed_with_underscores</c> it will return
+ /// <c>Capitalize Camelcase Mixed With Underscores</c>.
+ /// </summary>
public static string Capitalize(this string instance)
{
string aux = instance.Replace("_", " ").ToLower();
@@ -254,17 +258,17 @@ namespace Godot
return cap;
}
- // <summary>
- // Perform a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
- // </summary>
+ /// <summary>
+ /// Perform a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// </summary>
public static int CasecmpTo(this string instance, string to)
{
return instance.CompareTo(to, caseSensitive: true);
}
- // <summary>
- // Perform a comparison to another string, return -1 if less, 0 if equal and +1 if greater.
- // </summary>
+ /// <summary>
+ /// Perform a comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// </summary>
public static int CompareTo(this string instance, string to, bool caseSensitive = true)
{
if (string.IsNullOrEmpty(instance))
@@ -316,25 +320,25 @@ namespace Godot
}
}
- // <summary>
- // Return true if the strings ends with the given string.
- // </summary>
+ /// <summary>
+ /// Return <see langword="true"/> if the strings ends with the given string.
+ /// </summary>
public static bool EndsWith(this string instance, string text)
{
return instance.EndsWith(text);
}
- // <summary>
- // Erase [code]chars[/code] characters from the string starting from [code]pos[/code].
- // </summary>
+ /// <summary>
+ /// Erase <paramref name="chars"/> characters from the string starting from <paramref name="pos"/>.
+ /// </summary>
public static void Erase(this StringBuilder instance, int pos, int chars)
{
instance.Remove(pos, chars);
}
- // <summary>
- // If the string is a path to a file, return the extension.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file, return the extension.
+ /// </summary>
public static string Extension(this string instance)
{
int pos = instance.FindLast(".");
@@ -345,14 +349,18 @@ namespace Godot
return instance.Substring(pos + 1);
}
- /// <summary>Find the first occurrence of a substring. Optionally, the search starting position can be passed.</summary>
+ /// <summary>
+ /// Find the first occurrence of a substring. Optionally, the search starting position can be passed.
+ /// </summary>
/// <returns>The starting position of the substring, or -1 if not found.</returns>
public static int Find(this string instance, string what, int from = 0, bool caseSensitive = true)
{
return instance.IndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
- /// <summary>Find the first occurrence of a char. Optionally, the search starting position can be passed.</summary>
+ /// <summary>
+ /// Find the first occurrence of a char. Optionally, the search starting position can be passed.
+ /// </summary>
/// <returns>The first instance of the char, or -1 if not found.</returns>
public static int Find(this string instance, char what, int from = 0, bool caseSensitive = true)
{
@@ -375,16 +383,19 @@ namespace Godot
return instance.LastIndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
- /// <summary>Find the first occurrence of a substring but search as case-insensitive. Optionally, the search starting position can be passed.</summary>
+ /// <summary>
+ /// Find the first occurrence of a substring but search as case-insensitive.
+ /// Optionally, the search starting position can be passed.
+ /// </summary>
/// <returns>The starting position of the substring, or -1 if not found.</returns>
public static int FindN(this string instance, string what, int from = 0)
{
return instance.IndexOf(what, from, StringComparison.OrdinalIgnoreCase);
}
- // <summary>
- // If the string is a path to a file, return the base directory.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file, return the base directory.
+ /// </summary>
public static string GetBaseDir(this string instance)
{
int basepos = instance.Find("://");
@@ -419,9 +430,9 @@ namespace Godot
return @base + rs.Substr(0, sep);
}
- // <summary>
- // If the string is a path to a file, return the file and ignore the base directory.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file, return the file and ignore the base directory.
+ /// </summary>
public static string GetFile(this string instance)
{
int sep = Mathf.Max(instance.FindLast("/"), instance.FindLast("\\"));
@@ -461,14 +472,14 @@ namespace Godot
return Encoding.UTF8.GetString(bytes);
}
- // <summary>
- // Hash the string and return a 32 bits unsigned integer.
- // </summary>
+ /// <summary>
+ /// Hash the string and return a 32 bits unsigned integer.
+ /// </summary>
public static uint Hash(this string instance)
{
uint hash = 5381;
- foreach(uint c in instance)
+ foreach (uint c in instance)
{
hash = (hash << 5) + hash + c; // hash * 33 + c
}
@@ -553,17 +564,17 @@ namespace Godot
return sign * int.Parse(instance, NumberStyles.HexNumber);
}
- // <summary>
- // Insert a substring at a given position.
- // </summary>
+ /// <summary>
+ /// Insert a substring at a given position.
+ /// </summary>
public static string Insert(this string instance, int pos, string what)
{
return instance.Insert(pos, what);
}
- // <summary>
- // If the string is a path to a file or directory, return true if the path is absolute.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file or directory, return <see langword="true"/> if the path is absolute.
+ /// </summary>
public static bool IsAbsPath(this string instance)
{
if (string.IsNullOrEmpty(instance))
@@ -574,17 +585,17 @@ namespace Godot
return instance[0] == '/' || instance[0] == '\\';
}
- // <summary>
- // If the string is a path to a file or directory, return true if the path is relative.
- // </summary>
+ /// <summary>
+ /// If the string is a path to a file or directory, return <see langword="true"/> if the path is relative.
+ /// </summary>
public static bool IsRelPath(this string instance)
{
return !IsAbsPath(instance);
}
- // <summary>
- // Check whether this string is a subsequence of the given string.
- // </summary>
+ /// <summary>
+ /// Check whether this string is a subsequence of the given string.
+ /// </summary>
public static bool IsSubsequenceOf(this string instance, string text, bool caseSensitive = true)
{
int len = instance.Length;
@@ -625,34 +636,36 @@ namespace Godot
return false;
}
- // <summary>
- // Check whether this string is a subsequence of the given string, ignoring case differences.
- // </summary>
+ /// <summary>
+ /// Check whether this string is a subsequence of the given string, ignoring case differences.
+ /// </summary>
public static bool IsSubsequenceOfI(this string instance, string text)
{
return instance.IsSubsequenceOf(text, caseSensitive: false);
}
- // <summary>
- // Check whether the string contains a valid float.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid <see langword="float"/>.
+ /// </summary>
public static bool IsValidFloat(this string instance)
{
float f;
return float.TryParse(instance, out f);
}
- // <summary>
- // Check whether the string contains a valid color in HTML notation.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid color in HTML notation.
+ /// </summary>
public static bool IsValidHtmlColor(this string instance)
{
return Color.HtmlIsValid(instance);
}
- // <summary>
- // Check whether the string is a valid identifier. As is common in programming languages, a valid identifier may contain only letters, digits and underscores (_) and the first character may not be a digit.
- // </summary>
+ /// <summary>
+ /// Check whether the string is a valid identifier. As is common in
+ /// programming languages, a valid identifier may contain only letters,
+ /// digits and underscores (_) and the first character may not be a digit.
+ /// </summary>
public static bool IsValidIdentifier(this string instance)
{
int len = instance.Length;
@@ -680,18 +693,18 @@ namespace Godot
return true;
}
- // <summary>
- // Check whether the string contains a valid integer.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid integer.
+ /// </summary>
public static bool IsValidInteger(this string instance)
{
int f;
return int.TryParse(instance, out f);
}
- // <summary>
- // Check whether the string contains a valid IP address.
- // </summary>
+ /// <summary>
+ /// Check whether the string contains a valid IP address.
+ /// </summary>
public static bool IsValidIPAddress(this string instance)
{
// TODO: Support IPv6 addresses
@@ -714,9 +727,9 @@ namespace Godot
return true;
}
- // <summary>
- // Return a copy of the string with special characters escaped using the JSON standard.
- // </summary>
+ /// <summary>
+ /// Return a copy of the string with special characters escaped using the JSON standard.
+ /// </summary>
public static string JSONEscape(this string instance)
{
var sb = new StringBuilder(string.Copy(instance));
@@ -733,9 +746,9 @@ namespace Godot
return sb.ToString();
}
- // <summary>
- // Return an amount of characters from the left of the string.
- // </summary>
+ /// <summary>
+ /// Return an amount of characters from the left of the string.
+ /// </summary>
public static string Left(this string instance, int pos)
{
if (pos <= 0)
@@ -783,7 +796,8 @@ namespace Godot
}
/// <summary>
- /// Do a simple expression match, where '*' matches zero or more arbitrary characters and '?' matches any single character except '.'.
+ /// Do a simple expression match, where '*' matches zero or more
+ /// arbitrary characters and '?' matches any single character except '.'.
/// </summary>
private static bool ExprMatch(this string instance, string expr, bool caseSensitive)
{
@@ -798,13 +812,17 @@ namespace Godot
case '?':
return instance.Length > 0 && instance[0] != '.' && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
default:
- if (instance.Length == 0) return false;
- return (caseSensitive ? instance[0] == expr[0] : char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
+ if (instance.Length == 0)
+ return false;
+ if (caseSensitive)
+ return instance[0] == expr[0];
+ return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
}
}
/// <summary>
- /// Do a simple case sensitive expression match, using ? and * wildcards (see [method expr_match]).
+ /// Do a simple case sensitive expression match, using ? and * wildcards
+ /// (see <see cref="ExprMatch(string, string, bool)"/>).
/// </summary>
public static bool Match(this string instance, string expr, bool caseSensitive = true)
{
@@ -815,7 +833,8 @@ namespace Godot
}
/// <summary>
- /// Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]).
+ /// Do a simple case insensitive expression match, using ? and * wildcards
+ /// (see <see cref="ExprMatch(string, string, bool)"/>).
/// </summary>
public static bool MatchN(this string instance, string expr)
{
@@ -825,9 +844,9 @@ namespace Godot
return instance.ExprMatch(expr, caseSensitive: false);
}
- // <summary>
- // Return the MD5 hash of the string as an array of bytes.
- // </summary>
+ /// <summary>
+ /// Return the MD5 hash of the string as an array of bytes.
+ /// </summary>
public static byte[] MD5Buffer(this string instance)
{
return godot_icall_String_md5_buffer(instance);
@@ -836,9 +855,9 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static byte[] godot_icall_String_md5_buffer(string str);
- // <summary>
- // Return the MD5 hash of the string as a string.
- // </summary>
+ /// <summary>
+ /// Return the MD5 hash of the string as a string.
+ /// </summary>
public static string MD5Text(this string instance)
{
return godot_icall_String_md5_text(instance);
@@ -847,25 +866,25 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static string godot_icall_String_md5_text(string str);
- // <summary>
- // Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
- // </summary>
+ /// <summary>
+ /// Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// </summary>
public static int NocasecmpTo(this string instance, string to)
{
return instance.CompareTo(to, caseSensitive: false);
}
- // <summary>
- // Return the character code at position [code]at[/code].
- // </summary>
+ /// <summary>
+ /// Return the character code at position <paramref name="at"/>.
+ /// </summary>
public static int OrdAt(this string instance, int at)
{
return instance[at];
}
- // <summary>
- // Format a number to have an exact number of [code]digits[/code] after the decimal point.
- // </summary>
+ /// <summary>
+ /// Format a number to have an exact number of <paramref name="digits"/> after the decimal point.
+ /// </summary>
public static string PadDecimals(this string instance, int digits)
{
int c = instance.Find(".");
@@ -899,9 +918,9 @@ namespace Godot
return instance;
}
- // <summary>
- // Format a number to have an exact number of [code]digits[/code] before the decimal point.
- // </summary>
+ /// <summary>
+ /// Format a number to have an exact number of <paramref name="digits"/> before the decimal point.
+ /// </summary>
public static string PadZeros(this string instance, int digits)
{
string s = instance;
@@ -932,9 +951,10 @@ namespace Godot
return s;
}
- // <summary>
- // If the string is a path, this concatenates [code]file[/code] at the end of the string as a subpath. E.g. [code]"this/is".plus_file("path") == "this/is/path"[/code].
- // </summary>
+ /// <summary>
+ /// If the string is a path, this concatenates <paramref name="file"/> at the end of the string as a subpath.
+ /// E.g. <c>"this/is".PlusFile("path") == "this/is/path"</c>.
+ /// </summary>
public static string PlusFile(this string instance, string file)
{
if (instance.Length > 0 && instance[instance.Length - 1] == '/')
@@ -942,25 +962,25 @@ namespace Godot
return instance + "/" + file;
}
- // <summary>
- // Replace occurrences of a substring for different ones inside the string.
- // </summary>
+ /// <summary>
+ /// Replace occurrences of a substring for different ones inside the string.
+ /// </summary>
public static string Replace(this string instance, string what, string forwhat)
{
return instance.Replace(what, forwhat);
}
- // <summary>
- // Replace occurrences of a substring for different ones inside the string, but search case-insensitive.
- // </summary>
+ /// <summary>
+ /// Replace occurrences of a substring for different ones inside the string, but search case-insensitive.
+ /// </summary>
public static string ReplaceN(this string instance, string what, string forwhat)
{
return Regex.Replace(instance, what, forwhat, RegexOptions.IgnoreCase);
}
- // <summary>
- // Perform a search for a substring, but start from the end of the string instead of the beginning.
- // </summary>
+ /// <summary>
+ /// Perform a search for a substring, but start from the end of the string instead of the beginning.
+ /// </summary>
public static int RFind(this string instance, string what, int from = -1)
{
return godot_icall_String_rfind(instance, what, from);
@@ -969,9 +989,10 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static int godot_icall_String_rfind(string str, string what, int from);
- // <summary>
- // Perform a search for a substring, but start from the end of the string instead of the beginning. Also search case-insensitive.
- // </summary>
+ /// <summary>
+ /// Perform a search for a substring, but start from the end of the string instead of the beginning.
+ /// Also search case-insensitive.
+ /// </summary>
public static int RFindN(this string instance, string what, int from = -1)
{
return godot_icall_String_rfindn(instance, what, from);
@@ -980,9 +1001,9 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static int godot_icall_String_rfindn(string str, string what, int from);
- // <summary>
- // Return the right side of the string from a given position.
- // </summary>
+ /// <summary>
+ /// Return the right side of the string from a given position.
+ /// </summary>
public static string Right(this string instance, int pos)
{
if (pos >= instance.Length)
@@ -1029,9 +1050,9 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static byte[] godot_icall_String_sha256_buffer(string str);
- // <summary>
- // Return the SHA-256 hash of the string as a string.
- // </summary>
+ /// <summary>
+ /// Return the SHA-256 hash of the string as a string.
+ /// </summary>
public static string SHA256Text(this string instance)
{
return godot_icall_String_sha256_text(instance);
@@ -1040,9 +1061,10 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static string godot_icall_String_sha256_text(string str);
- // <summary>
- // Return the similarity index of the text compared to this string. 1 means totally similar and 0 means totally dissimilar.
- // </summary>
+ /// <summary>
+ /// Return the similarity index of the text compared to this string.
+ /// 1 means totally similar and 0 means totally dissimilar.
+ /// </summary>
public static float Similarity(this string instance, string text)
{
if (instance == text)
@@ -1080,17 +1102,19 @@ namespace Godot
return 2.0f * inter / sum;
}
- // <summary>
- // Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
- // </summary>
+ /// <summary>
+ /// Split the string by a divisor string, return an array of the substrings.
+ /// Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
+ /// </summary>
public static string[] Split(this string instance, string divisor, bool allowEmpty = true)
{
return instance.Split(new[] { divisor }, StringSplitOptions.RemoveEmptyEntries);
}
- // <summary>
- // Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",".
- // </summary>
+ /// <summary>
+ /// Split the string in floats by using a divisor string, return an array of the substrings.
+ /// Example "1,2.5,3" will return [1,2.5,3] if split by ",".
+ /// </summary>
public static float[] SplitFloats(this string instance, string divisor, bool allowEmpty = true)
{
var ret = new List<float>();
@@ -1122,9 +1146,10 @@ namespace Godot
(char)30, (char)31, (char)32
};
- // <summary>
- // Return a copy of the string stripped of any non-printable character at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively.
- // </summary>
+ /// <summary>
+ /// Return a copy of the string stripped of any non-printable character at the beginning and the end.
+ /// The optional arguments are used to toggle stripping on the left and right edges respectively.
+ /// </summary>
public static string StripEdges(this string instance, bool left = true, bool right = true)
{
if (left)
@@ -1137,58 +1162,62 @@ namespace Godot
return instance.TrimEnd(_nonPrintable);
}
- // <summary>
- // Return part of the string from the position [code]from[/code], with length [code]len[/code].
- // </summary>
+ /// <summary>
+ /// Return part of the string from the position <paramref name="from"/>, with length <paramref name="len"/>.
+ /// </summary>
public static string Substr(this string instance, int from, int len)
{
int max = instance.Length - from;
return instance.Substring(from, len > max ? max : len);
}
- // <summary>
- // Convert the String (which is a character array) to PackedByteArray (which is an array of bytes). The conversion is speeded up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters.
- // </summary>
+ /// <summary>
+ /// Convert the String (which is a character array) to PackedByteArray (which is an array of bytes).
+ /// The conversion is speeded up in comparison to <see cref="ToUTF8(string)"/> with the assumption
+ /// that all the characters the String contains are only ASCII characters.
+ /// </summary>
public static byte[] ToAscii(this string instance)
{
return Encoding.ASCII.GetBytes(instance);
}
- // <summary>
- // Convert a string, containing a decimal number, into a [code]float[/code].
- // </summary>
+ /// <summary>
+ /// Convert a string, containing a decimal number, into a <see langword="float" />.
+ /// </summary>
public static float ToFloat(this string instance)
{
return float.Parse(instance);
}
- // <summary>
- // Convert a string, containing an integer number, into an [code]int[/code].
- // </summary>
+ /// <summary>
+ /// Convert a string, containing an integer number, into an <see langword="int" />.
+ /// </summary>
public static int ToInt(this string instance)
{
return int.Parse(instance);
}
- // <summary>
- // Return the string converted to lowercase.
- // </summary>
+ /// <summary>
+ /// Return the string converted to lowercase.
+ /// </summary>
public static string ToLower(this string instance)
{
return instance.ToLower();
}
- // <summary>
- // Return the string converted to uppercase.
- // </summary>
+ /// <summary>
+ /// Return the string converted to uppercase.
+ /// </summary>
public static string ToUpper(this string instance)
{
return instance.ToUpper();
}
- // <summary>
- // Convert the String (which is an array of characters) to PackedByteArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii().
- // </summary>
+ /// <summary>
+ /// Convert the String (which is an array of characters) to PackedByteArray (which is an array of bytes).
+ /// The conversion is a bit slower than <see cref="ToAscii(string)"/>, but supports all UTF-8 characters.
+ /// Therefore, you should prefer this function over <see cref="ToAscii(string)"/>.
+ /// </summary>
public static byte[] ToUTF8(this string instance)
{
return Encoding.UTF8.GetBytes(instance);
@@ -1221,17 +1250,18 @@ namespace Godot
return Uri.EscapeDataString(instance);
}
- // <summary>
- // Return a copy of the string with special characters escaped using the XML standard.
- // </summary>
+ /// <summary>
+ /// Return a copy of the string with special characters escaped using the XML standard.
+ /// </summary>
public static string XMLEscape(this string instance)
{
return SecurityElement.Escape(instance);
}
- // <summary>
- // Return a copy of the string with escaped characters replaced by their meanings according to the XML standard.
- // </summary>
+ /// <summary>
+ /// Return a copy of the string with escaped characters replaced by their meanings
+ /// according to the XML standard.
+ /// </summary>
public static string XMLUnescape(this string instance)
{
return SecurityElement.FromString(instance).Text;
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index fe93592667..c135eb137f 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index 26b1a9e8b2..5c57203ca7 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
index af053bd263..a0948d8b10 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs
@@ -1,16 +1,10 @@
-// file: core/math/math_2d.h
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/math/math_2d.cpp
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/variant_call.cpp
-// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
index 9068593fd8..b4c631608e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs
@@ -1,11 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
-
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index 31a9af2d9e..a02a0d2dd9 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -1,16 +1,10 @@
-// file: core/math/vector3.h
-// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
-// file: core/math/vector3.cpp
-// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
-// file: core/variant_call.cpp
-// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
-using System;
-using System.Runtime.InteropServices;
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
index e727afa3ff..80bad061b2 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs
@@ -1,11 +1,10 @@
-using System;
-using System.Runtime.InteropServices;
-
#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
+using System;
+using System.Runtime.InteropServices;
namespace Godot
{
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 2d04cedb9b..a99dff8432 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -177,8 +177,8 @@ MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
MonoArray *result = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), property_list.size());
int i = 0;
- for (List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E->get().name);
+ for (const PropertyInfo &E : property_list) {
+ MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E.name);
mono_array_setref(result, i, boxed);
i++;
}
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 02d875f669..299344bb93 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -100,8 +100,8 @@ void gd_mono_setup_runtime_main_args() {
main_args.write[0] = execpath.ptrw();
int i = 1;
- for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) {
- CharString &stored = cmdline_args_utf8.push_back(E->get().utf8())->get();
+ for (const String &E : cmdline_args) {
+ CharString &stored = cmdline_args_utf8.push_back(E.utf8())->get();
main_args.write[i] = stored.ptrw();
i++;
}
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index 67d6f3ef29..67f38bf127 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -330,8 +330,8 @@ no_pdb:
void GDMonoAssembly::unload() {
ERR_FAIL_NULL(image); // Should not be called if already unloaded
- for (Map<MonoClass *, GDMonoClass *>::Element *E = cached_raw.front(); E; E = E->next()) {
- memdelete(E->value());
+ for (const KeyValue<MonoClass *, GDMonoClass *> &E : cached_raw) {
+ memdelete(E.value);
}
cached_classes.clear();
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index f9fddd931b..27b4ac7fa7 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -522,12 +522,12 @@ GDMonoClass::~GDMonoClass() {
mono_custom_attrs_free(attributes);
}
- for (Map<StringName, GDMonoField *>::Element *E = fields.front(); E; E = E->next()) {
- memdelete(E->value());
+ for (const KeyValue<StringName, GDMonoField *> &E : fields) {
+ memdelete(E.value);
}
- for (Map<StringName, GDMonoProperty *>::Element *E = properties.front(); E; E = E->next()) {
- memdelete(E->value());
+ for (const KeyValue<StringName, GDMonoProperty *> &E : properties) {
+ memdelete(E.value);
}
{
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 41306f0687..3150ca0bc8 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -734,7 +734,7 @@ void NavMap::dispatch_callbacks() {
void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const {
Vector3 from = path[path.size() - 1];
- if (from.distance_to(p_to_point) < CMP_EPSILON) {
+ if (from.is_equal_approx(p_to_point)) {
return;
}
Plane cut_plane;
@@ -752,10 +752,10 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys
ERR_FAIL_COND(from_poly->back_navigation_poly_id == -1);
from_poly = &p_navigation_polys[from_poly->back_navigation_poly_id];
- if (pathway_start.distance_to(pathway_end) > CMP_EPSILON) {
+ if (!pathway_start.is_equal_approx(pathway_end)) {
Vector3 inters;
if (cut_plane.intersects_segment(pathway_start, pathway_end, &inters)) {
- if (inters.distance_to(p_to_point) > CMP_EPSILON && inters.distance_to(path[path.size() - 1]) > CMP_EPSILON) {
+ if (!inters.is_equal_approx(p_to_point) && !inters.is_equal_approx(path[path.size() - 1])) {
path.push_back(inters);
}
}
diff --git a/modules/navigation/navigation_mesh_editor_plugin.cpp b/modules/navigation/navigation_mesh_editor_plugin.cpp
index 8f4203e260..587e56f593 100644
--- a/modules/navigation/navigation_mesh_editor_plugin.cpp
+++ b/modules/navigation/navigation_mesh_editor_plugin.cpp
@@ -65,7 +65,7 @@ void NavigationMeshEditor::_bake_pressed() {
NavigationMeshGenerator::get_singleton()->clear(node->get_navigation_mesh());
NavigationMeshGenerator::get_singleton()->bake(node->get_navigation_mesh(), node);
- node->update_gizmo();
+ node->update_gizmos();
}
void NavigationMeshEditor::_clear_pressed() {
@@ -77,7 +77,7 @@ void NavigationMeshEditor::_clear_pressed() {
bake_info->set_text("");
if (node) {
- node->update_gizmo();
+ node->update_gizmos();
}
}
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index 7aeb9e1858..41cd75fd22 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -514,11 +514,11 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
}
Transform3D navmesh_xform = Object::cast_to<Node3D>(p_node)->get_transform().affine_inverse();
- for (const List<Node *>::Element *E = parse_nodes.front(); E; E = E->next()) {
+ for (Node *E : parse_nodes) {
int geometry_type = p_nav_mesh->get_parsed_geometry_type();
uint32_t collision_mask = p_nav_mesh->get_collision_mask();
bool recurse_children = p_nav_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
- _parse_geometry(navmesh_xform, E->get(), vertices, indices, geometry_type, collision_mask, recurse_children);
+ _parse_geometry(navmesh_xform, E, vertices, indices, geometry_type, collision_mask, recurse_children);
}
if (vertices.size() > 0 && indices.size() > 0) {
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 2513039e8e..fa4888f843 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -927,14 +927,14 @@ void TextServerAdvanced::font_set_oversampling(float p_oversampling) {
oversampling = p_oversampling;
List<RID> fonts;
font_owner.get_owned_list(&fonts);
- for (List<RID>::Element *E = fonts.front(); E; E = E->next()) {
- font_owner.getornull(E->get())->clear_cache();
+ for (const RID &E : fonts) {
+ font_owner.getornull(E)->clear_cache();
}
List<RID> text_bufs;
shaped_owner.get_owned_list(&text_bufs);
- for (List<RID>::Element *E = text_bufs.front(); E; E = E->next()) {
- invalidate(shaped_owner.getornull(E->get()));
+ for (const RID &E : text_bufs) {
+ invalidate(shaped_owner.getornull(E));
}
}
}
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 9ad7dabbcc..004cbc2bb3 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -473,8 +473,8 @@ void TextServerFallback::font_set_oversampling(float p_oversampling) {
oversampling = p_oversampling;
List<RID> fonts;
font_owner.get_owned_list(&fonts);
- for (List<RID>::Element *E = fonts.front(); E; E = E->next()) {
- font_owner.getornull(E->get())->clear_cache();
+ for (const RID &E : fonts) {
+ font_owner.getornull(E)->clear_cache();
}
}
}
diff --git a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
index 1c23b58507..ba4eba26fd 100644
--- a/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
+++ b/modules/visual_script/doc_classes/VisualScriptCustomNode.xml
@@ -30,6 +30,24 @@
Return the count of input value ports.
</description>
</method>
+ <method name="_get_input_value_port_hint" qualifiers="virtual">
+ <return type="int">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Return the specified input port's hint. See the [enum @GlobalScope.PropertyHint] hints.
+ </description>
+ </method>
+ <method name="_get_input_value_port_hint_string" qualifiers="virtual">
+ <return type="String">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Return the specified input port's hint string.
+ </description>
+ </method>
<method name="_get_input_value_port_name" qualifiers="virtual">
<return type="String">
</return>
@@ -71,13 +89,31 @@
Return the amount of output value ports.
</description>
</method>
+ <method name="_get_output_value_port_hint" qualifiers="virtual">
+ <return type="int">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Return the specified output port's hint. See the [enum @GlobalScope.PropertyHint] hints.
+ </description>
+ </method>
+ <method name="_get_output_value_port_hint_string" qualifiers="virtual">
+ <return type="String">
+ </return>
+ <argument index="0" name="idx" type="int">
+ </argument>
+ <description>
+ Return the specified output port's hint string.
+ </description>
+ </method>
<method name="_get_output_value_port_name" qualifiers="virtual">
<return type="String">
</return>
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return the specified output's name.
+ Return the specified output port's name.
</description>
</method>
<method name="_get_output_value_port_type" qualifiers="virtual">
@@ -86,7 +122,7 @@
<argument index="0" name="idx" type="int">
</argument>
<description>
- Return the specified output's type. See the [enum Variant.Type] values.
+ Return the specified output port's type. See the [enum Variant.Type] values.
</description>
</method>
<method name="_get_text" qualifiers="virtual">
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index 0de39512ae..7a2404fd80 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -588,14 +588,14 @@ void VisualScript::rename_variable(const StringName &p_name, const StringName &p
variables.erase(p_name);
List<int> ids;
get_node_list(&ids);
- for (List<int>::Element *E = ids.front(); E; E = E->next()) {
- Ref<VisualScriptVariableGet> nodeget = get_node(E->get());
+ for (int &E : ids) {
+ Ref<VisualScriptVariableGet> nodeget = get_node(E);
if (nodeget.is_valid()) {
if (nodeget->get_variable() == p_name) {
nodeget->set_variable(p_new_name);
}
} else {
- Ref<VisualScriptVariableSet> nodeset = get_node(E->get());
+ Ref<VisualScriptVariableSet> nodeset = get_node(E);
if (nodeset.is_valid()) {
if (nodeset->get_variable() == p_name) {
nodeset->set_variable(p_new_name);
@@ -715,9 +715,9 @@ int VisualScript::get_available_id() const {
List<int> nds;
nodes.get_key_list(&nds);
int max = -1;
- for (const List<int>::Element *E = nds.front(); E; E = E->next()) {
- if (E->get() > max) {
- max = E->get();
+ for (const int &E : nds) {
+ if (E > max) {
+ max = E;
}
}
return (max + 1);
@@ -752,15 +752,15 @@ void VisualScript::_update_placeholders() {
List<StringName> keys;
variables.get_key_list(&keys);
- for (List<StringName>::Element *E = keys.front(); E; E = E->next()) {
- if (!variables[E->get()]._export) {
+ for (const StringName &E : keys) {
+ if (!variables[E]._export) {
continue;
}
- PropertyInfo p = variables[E->get()].info;
- p.name = String(E->get());
+ PropertyInfo p = variables[E].info;
+ p.name = String(E);
pinfo.push_back(p);
- values[p.name] = variables[E->get()].default_value;
+ values[p.name] = variables[E].default_value;
}
for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
@@ -783,15 +783,15 @@ ScriptInstance *VisualScript::instance_create(Object *p_this) {
List<StringName> keys;
variables.get_key_list(&keys);
- for (const List<StringName>::Element *E = keys.front(); E; E = E->next()) {
- if (!variables[E->get()]._export) {
+ for (const StringName &E : keys) {
+ if (!variables[E]._export) {
continue;
}
- PropertyInfo p = variables[E->get()].info;
- p.name = String(E->get());
+ PropertyInfo p = variables[E].info;
+ p.name = String(E);
pinfo.push_back(p);
- values[p.name] = variables[E->get()].default_value;
+ values[p.name] = variables[E].default_value;
}
sins->update(pinfo, values);
@@ -874,11 +874,11 @@ void VisualScript::get_script_method_list(List<MethodInfo> *p_list) const {
List<StringName> funcs;
functions.get_key_list(&funcs);
- for (List<StringName>::Element *E = funcs.front(); E; E = E->next()) {
+ for (const StringName &E : funcs) {
MethodInfo mi;
- mi.name = E->get();
- if (functions[E->get()].func_id >= 0) {
- Ref<VisualScriptFunction> func = nodes[functions[E->get()].func_id].node;
+ mi.name = E;
+ if (functions[E].func_id >= 0) {
+ Ref<VisualScriptFunction> func = nodes[functions[E].func_id].node;
if (func.is_valid()) {
for (int i = 0; i < func->get_argument_count(); i++) {
PropertyInfo arg;
@@ -928,10 +928,10 @@ void VisualScript::get_script_property_list(List<PropertyInfo> *p_list) const {
List<StringName> vars;
get_variable_list(&vars);
- for (List<StringName>::Element *E = vars.front(); E; E = E->next()) {
- //if (!variables[E->get()]._export)
+ for (const StringName &E : vars) {
+ //if (!variables[E]._export)
// continue;
- PropertyInfo pi = variables[E->get()].info;
+ PropertyInfo pi = variables[E].info;
pi.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
p_list->push_back(pi);
}
@@ -945,8 +945,8 @@ int VisualScript::get_member_line(const StringName &p_member) const {
bool VisualScript::are_subnodes_edited() const {
List<int> keys;
nodes.get_key_list(&keys);
- for (const List<int>::Element *F = keys.front(); F; F = F->next()) {
- if (nodes[F->get()].node->is_edited()) {
+ for (const int &F : keys) {
+ if (nodes[F].node->is_edited()) {
return true;
}
}
@@ -1017,13 +1017,13 @@ void VisualScript::_set_data(const Dictionary &p_data) {
rpc_functions.clear();
List<StringName> fns;
functions.get_key_list(&fns);
- for (const List<StringName>::Element *E = fns.front(); E; E = E->next()) {
- if (functions[E->get()].func_id >= 0 && nodes.has(functions[E->get()].func_id)) {
- Ref<VisualScriptFunction> vsf = nodes[functions[E->get()].func_id].node;
+ for (const StringName &E : fns) {
+ if (functions[E].func_id >= 0 && nodes.has(functions[E].func_id)) {
+ Ref<VisualScriptFunction> vsf = nodes[functions[E].func_id].node;
if (vsf.is_valid()) {
if (vsf->get_rpc_mode() != MultiplayerAPI::RPC_MODE_DISABLED) {
MultiplayerAPI::RPCConfig nd;
- nd.name = E->get();
+ nd.name = E;
nd.rpc_mode = vsf->get_rpc_mode();
nd.transfer_mode = MultiplayerPeer::TRANSFER_MODE_RELIABLE; // TODO
if (rpc_functions.find(nd) == -1) {
@@ -1045,11 +1045,11 @@ Dictionary VisualScript::_get_data() const {
Array vars;
List<StringName> var_names;
variables.get_key_list(&var_names);
- for (const List<StringName>::Element *E = var_names.front(); E; E = E->next()) {
- Dictionary var = _get_variable_info(E->get());
- var["name"] = E->get(); // Make sure it's the right one.
- var["default_value"] = variables[E->get()].default_value;
- var["export"] = variables[E->get()]._export;
+ for (const StringName &E : var_names) {
+ Dictionary var = _get_variable_info(E);
+ var["name"] = E; // Make sure it's the right one.
+ var["default_value"] = variables[E].default_value;
+ var["export"] = variables[E]._export;
vars.push_back(var);
}
d["variables"] = vars;
@@ -1073,10 +1073,10 @@ Dictionary VisualScript::_get_data() const {
Array funcs;
List<StringName> func_names;
functions.get_key_list(&func_names);
- for (const List<StringName>::Element *E = func_names.front(); E; E = E->next()) {
+ for (const StringName &E : func_names) {
Dictionary func;
- func["name"] = E->get();
- func["function_id"] = functions[E->get()].func_id;
+ func["name"] = E;
+ func["function_id"] = functions[E].func_id;
funcs.push_back(func);
}
d["functions"] = funcs;
@@ -1084,10 +1084,10 @@ Dictionary VisualScript::_get_data() const {
Array nds;
List<int> node_ids;
nodes.get_key_list(&node_ids);
- for (const List<int>::Element *F = node_ids.front(); F; F = F->next()) {
- nds.push_back(F->get());
- nds.push_back(nodes[F->get()].pos);
- nds.push_back(nodes[F->get()].node);
+ for (const int &F : node_ids) {
+ nds.push_back(F);
+ nds.push_back(nodes[F].pos);
+ nds.push_back(nodes[F].node);
}
d["nodes"] = nds;
@@ -1202,8 +1202,8 @@ VisualScript::~VisualScript() {
// Remove all nodes and stuff that hold data refs.
List<int> nds;
nodes.get_key_list(&nds);
- for (const List<int>::Element *E = nds.front(); E; E = E->next()) {
- remove_node(E->get());
+ for (const int &E : nds) {
+ remove_node(E);
}
}
@@ -1233,12 +1233,12 @@ bool VisualScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
void VisualScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
List<StringName> vars;
script->variables.get_key_list(&vars);
- for (const List<StringName>::Element *E = vars.front(); E; E = E->next()) {
- if (!script->variables[E->get()]._export) {
+ for (const StringName &E : vars) {
+ if (!script->variables[E]._export) {
continue;
}
- PropertyInfo p = script->variables[E->get()].info;
- p.name = String(E->get());
+ PropertyInfo p = script->variables[E].info;
+ p.name = String(E);
p.usage |= PROPERTY_USAGE_SCRIPT_VARIABLE;
p_properties->push_back(p);
}
@@ -1262,11 +1262,11 @@ Variant::Type VisualScriptInstance::get_property_type(const StringName &p_name,
void VisualScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
List<StringName> fns;
script->functions.get_key_list(&fns);
- for (const List<StringName>::Element *E = fns.front(); E; E = E->next()) {
+ for (const StringName &E : fns) {
MethodInfo mi;
- mi.name = E->get();
- if (script->functions[E->get()].func_id >= 0 && script->nodes.has(script->functions[E->get()].func_id)) {
- Ref<VisualScriptFunction> vsf = script->nodes[script->functions[E->get()].func_id].node;
+ mi.name = E;
+ if (script->functions[E].func_id >= 0 && script->nodes.has(script->functions[E].func_id)) {
+ Ref<VisualScriptFunction> vsf = script->nodes[script->functions[E].func_id].node;
if (vsf.is_valid()) {
for (int i = 0; i < vsf->get_argument_count(); i++) {
PropertyInfo arg;
@@ -1868,8 +1868,8 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
{
List<StringName> keys;
script->variables.get_key_list(&keys);
- for (const List<StringName>::Element *E = keys.front(); E; E = E->next()) {
- variables[E->get()] = script->variables[E->get()].default_value;
+ for (const StringName &E : keys) {
+ variables[E] = script->variables[E].default_value;
}
}
@@ -1877,8 +1877,8 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
{
List<StringName> keys;
script->functions.get_key_list(&keys);
- for (const List<StringName>::Element *E = keys.front(); E; E = E->next()) {
- const VisualScript::Function vsfn = p_script->functions[E->get()];
+ for (const StringName &E : keys) {
+ const VisualScript::Function vsfn = p_script->functions[E];
Function function;
function.node = vsfn.func_id;
function.max_stack = 0;
@@ -1889,7 +1889,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
Map<StringName, int> local_var_indices;
if (function.node < 0) {
- VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E->get()));
+ VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No start node in function: " + String(E));
ERR_CONTINUE(function.node < 0);
}
@@ -1897,7 +1897,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
Ref<VisualScriptFunction> func_node = script->get_node(vsfn.func_id);
if (func_node.is_null()) {
- VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E->get()));
+ VisualScriptLanguage::singleton->debug_break_parse(get_script()->get_path(), 0, "No VisualScriptFunction typed start node in function: " + String(E));
}
ERR_CONTINUE(!func_node.is_valid());
@@ -1938,12 +1938,12 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
while (!nd_queue.is_empty()) {
int ky = nd_queue.front()->get();
dc_lut[ky].get_key_list(&dc_keys);
- for (const List<int>::Element *F = dc_keys.front(); F; F = F->next()) {
+ for (const int &F : dc_keys) {
VisualScript::DataConnection dc;
- dc.from_node = dc_lut[ky][F->get()].first;
- dc.from_port = dc_lut[ky][F->get()].second;
+ dc.from_node = dc_lut[ky][F].first;
+ dc.from_port = dc_lut[ky][F].second;
dc.to_node = ky;
- dc.to_port = F->get();
+ dc.to_port = F;
dataconns.insert(dc);
nd_queue.push_back(dc.from_node);
node_ids.insert(dc.from_node);
@@ -2093,7 +2093,7 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
}
}
- functions[E->get()] = function;
+ functions[E] = function;
}
}
}
@@ -2467,10 +2467,10 @@ void VisualScriptLanguage::debug_get_stack_level_members(int p_level, List<Strin
List<StringName> vars;
vs->get_variable_list(&vars);
- for (List<StringName>::Element *E = vars.front(); E; E = E->next()) {
+ for (const StringName &E : vars) {
Variant v;
- if (_call_stack[l].instance->get_variable(E->get(), &v)) {
- p_members->push_back("variables/" + E->get());
+ if (_call_stack[l].instance->get_variable(E, &v)) {
+ p_members->push_back("variables/" + E);
p_values->push_back(v);
}
}
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 2e0eb4757a..fca7985b74 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -561,18 +561,16 @@ void VisualScriptEditor::_update_graph_connections() {
List<VisualScript::SequenceConnection> sequence_conns;
script->get_sequence_connection_list(&sequence_conns);
- for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) {
- graph->connect_node(itos(E->get().from_node), E->get().from_output, itos(E->get().to_node), 0);
+ for (const VisualScript::SequenceConnection &E : sequence_conns) {
+ graph->connect_node(itos(E.from_node), E.from_output, itos(E.to_node), 0);
}
List<VisualScript::DataConnection> data_conns;
script->get_data_connection_list(&data_conns);
- for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) {
- VisualScript::DataConnection dc = E->get();
-
- Ref<VisualScriptNode> from_node = script->get_node(E->get().from_node);
- Ref<VisualScriptNode> to_node = script->get_node(E->get().to_node);
+ for (VisualScript::DataConnection &dc : data_conns) {
+ Ref<VisualScriptNode> from_node = script->get_node(dc.from_node);
+ Ref<VisualScriptNode> to_node = script->get_node(dc.to_node);
if (to_node->has_input_sequence_port()) {
dc.to_port++;
@@ -580,7 +578,7 @@ void VisualScriptEditor::_update_graph_connections() {
dc.from_port += from_node->get_output_sequence_port_count();
- graph->connect_node(itos(E->get().from_node), dc.from_port, itos(E->get().to_node), dc.to_port);
+ graph->connect_node(itos(dc.from_node), dc.from_port, itos(dc.to_node), dc.to_port);
}
}
@@ -656,27 +654,27 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
script->get_node_list(&ids);
StringName editor_icons = "EditorIcons";
- for (List<int>::Element *E = ids.front(); E; E = E->next()) {
- if (p_only_id >= 0 && p_only_id != E->get()) {
+ for (int &E : ids) {
+ if (p_only_id >= 0 && p_only_id != E) {
continue;
}
- Ref<VisualScriptNode> node = script->get_node(E->get());
- Vector2 pos = script->get_node_position(E->get());
+ Ref<VisualScriptNode> node = script->get_node(E);
+ Vector2 pos = script->get_node_position(E);
GraphNode *gnode = memnew(GraphNode);
gnode->set_title(node->get_caption());
gnode->set_position_offset(pos * EDSCALE);
- if (error_line == E->get()) {
+ if (error_line == E) {
gnode->set_overlay(GraphNode::OVERLAY_POSITION);
} else if (node->is_breakpoint()) {
gnode->set_overlay(GraphNode::OVERLAY_BREAKPOINT);
}
gnode->set_meta("__vnode", node);
- gnode->set_name(itos(E->get()));
- gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved), varray(E->get()));
- gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node), varray(E->get()), CONNECT_DEFERRED);
+ gnode->set_name(itos(E));
+ gnode->connect("dragged", callable_mp(this, &VisualScriptEditor::_node_moved), varray(E));
+ gnode->connect("close_request", callable_mp(this, &VisualScriptEditor::_remove_node), varray(E), CONNECT_DEFERRED);
{
Ref<VisualScriptFunction> v = node;
@@ -696,7 +694,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Input Port"));
hbnc->add_child(btn);
- btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port), varray(E->get()), CONNECT_DEFERRED);
+ btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_input_port), varray(E), CONNECT_DEFERRED);
}
if (nd_list->is_output_port_editable()) {
if (nd_list->is_input_port_editable()) {
@@ -706,7 +704,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *btn = memnew(Button);
btn->set_text(TTR("Add Output Port"));
hbnc->add_child(btn);
- btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port), varray(E->get()), CONNECT_DEFERRED);
+ btn->connect("pressed", callable_mp(this, &VisualScriptEditor::_add_output_port), varray(E), CONNECT_DEFERRED);
}
gnode->add_child(hbnc);
} else if (Object::cast_to<VisualScriptExpression>(node.ptr())) {
@@ -716,7 +714,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
line_edit->set_expand_to_text_length_enabled(true);
line_edit->add_theme_font_override("font", get_theme_font(SNAME("source"), SNAME("EditorFonts")));
gnode->add_child(line_edit);
- line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E->get()));
+ line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E));
} else {
String text = node->get_text();
if (!text.is_empty()) {
@@ -732,7 +730,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
gnode->set_comment(true);
gnode->set_resizable(true);
gnode->set_custom_minimum_size(vsc->get_size() * EDSCALE);
- gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized), varray(E->get()));
+ gnode->connect("resize_request", callable_mp(this, &VisualScriptEditor::_comment_node_resized), varray(E));
}
if (node_styles.has(node->get_category())) {
@@ -835,8 +833,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0));
name_box->set_text(left_name);
name_box->set_expand_to_text_length_enabled(true);
- name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E->get()));
- name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E->get(), i, true));
+ name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E));
+ name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E, i, true));
} else {
hbc->add_child(memnew(Label(left_name)));
}
@@ -849,18 +847,18 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
opbtn->select(left_type);
opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
hbc->add_child(opbtn);
- opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E->get(), i, true), CONNECT_DEFERRED);
+ opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E, i, true), CONNECT_DEFERRED);
}
Button *rmbtn = memnew(Button);
rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbc->add_child(rmbtn);
- rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E->get(), i), CONNECT_DEFERRED);
+ rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_input_port), varray(E, i), CONNECT_DEFERRED);
} else {
hbc->add_child(memnew(Label(left_name)));
}
- if (left_type != Variant::NIL && !script->is_input_value_port_connected(E->get(), i)) {
+ if (left_type != Variant::NIL && !script->is_input_value_port_connected(E, i)) {
PropertyInfo pi = node->get_input_value_port_info(i);
Button *button = memnew(Button);
Variant value = node->get_default_input_value(i);
@@ -887,7 +885,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
} else {
button->set_text(value);
}
- button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited), varray(button, E->get(), i));
+ button->connect("pressed", callable_mp(this, &VisualScriptEditor::_default_value_edited), varray(button, E, i));
hbc2->add_child(button);
}
} else {
@@ -911,7 +909,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
Button *rmbtn = memnew(Button);
rmbtn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
hbc->add_child(rmbtn);
- rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E->get(), i), CONNECT_DEFERRED);
+ rmbtn->connect("pressed", callable_mp(this, &VisualScriptEditor::_remove_output_port), varray(E, i), CONNECT_DEFERRED);
if (nd_list->is_output_port_type_editable()) {
OptionButton *opbtn = memnew(OptionButton);
@@ -921,7 +919,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
opbtn->select(right_type);
opbtn->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
hbc->add_child(opbtn);
- opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E->get(), i, false), CONNECT_DEFERRED);
+ opbtn->connect("item_selected", callable_mp(this, &VisualScriptEditor::_change_port_type), varray(E, i, false), CONNECT_DEFERRED);
}
if (nd_list->is_output_port_name_editable()) {
@@ -930,8 +928,8 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
name_box->set_custom_minimum_size(Size2(60 * EDSCALE, 0));
name_box->set_text(right_name);
name_box->set_expand_to_text_length_enabled(true);
- name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E->get()));
- name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E->get(), i, false));
+ name_box->connect("resized", callable_mp(this, &VisualScriptEditor::_update_node_size), varray(E));
+ name_box->connect("focus_exited", callable_mp(this, &VisualScriptEditor::_port_name_focus_out), varray(name_box, E, i, false));
} else {
hbc->add_child(memnew(Label(right_name)));
}
@@ -1047,13 +1045,13 @@ void VisualScriptEditor::_update_members() {
List<StringName> func_names;
script->get_function_list(&func_names);
func_names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = func_names.front(); E; E = E->next()) {
+ for (const StringName &E : func_names) {
TreeItem *ti = members->create_item(functions);
- ti->set_text(0, E->get());
+ ti->set_text(0, E);
ti->set_selectable(0, true);
- ti->set_metadata(0, E->get());
+ ti->set_metadata(0, E);
ti->add_button(0, Control::get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")), 0);
- if (selected == E->get()) {
+ if (selected == E) {
ti->select(0);
}
}
@@ -1101,18 +1099,18 @@ void VisualScriptEditor::_update_members() {
List<StringName> var_names;
script->get_variable_list(&var_names);
- for (List<StringName>::Element *E = var_names.front(); E; E = E->next()) {
+ for (const StringName &E : var_names) {
TreeItem *ti = members->create_item(variables);
- ti->set_text(0, E->get());
+ ti->set_text(0, E);
- ti->set_suffix(0, "= " + _sanitized_variant_text(E->get()));
- ti->set_icon(0, type_icons[script->get_variable_info(E->get()).type]);
+ ti->set_suffix(0, "= " + _sanitized_variant_text(E));
+ ti->set_icon(0, type_icons[script->get_variable_info(E).type]);
ti->set_selectable(0, true);
ti->set_editable(0, true);
- ti->set_metadata(0, E->get());
- if (selected == E->get()) {
+ ti->set_metadata(0, E);
+ if (selected == E) {
ti->select(0);
}
}
@@ -1125,13 +1123,13 @@ void VisualScriptEditor::_update_members() {
List<StringName> signal_names;
script->get_custom_signal_list(&signal_names);
- for (List<StringName>::Element *E = signal_names.front(); E; E = E->next()) {
+ for (const StringName &E : signal_names) {
TreeItem *ti = members->create_item(_signals);
- ti->set_text(0, E->get());
+ ti->set_text(0, E);
ti->set_selectable(0, true);
ti->set_editable(0, true);
- ti->set_metadata(0, E->get());
- if (selected == E->get()) {
+ ti->set_metadata(0, E);
+ if (selected == E) {
ti->select(0);
}
}
@@ -1237,8 +1235,8 @@ void VisualScriptEditor::_member_edited() {
// Also fix all function calls.
List<int> lst;
script->get_node_list(&lst);
- for (List<int>::Element *F = lst.front(); F; F = F->next()) {
- Ref<VisualScriptFunctionCall> fncall = script->get_node(F->get());
+ for (int &F : lst) {
+ Ref<VisualScriptFunctionCall> fncall = script->get_node(F);
if (!fncall.is_valid()) {
continue;
}
@@ -1572,13 +1570,13 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) {
script->get_data_connection_list(&data_connections);
HashMap<int, Set<int>> conn_map;
- for (const List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_id && E->get().from_port == p_port) {
+ for (const VisualScript::DataConnection &E : data_connections) {
+ if (E.from_node == p_id && E.from_port == p_port) {
// Push into the connections map.
- if (!conn_map.has(E->get().to_node)) {
- conn_map.set(E->get().to_node, Set<int>());
+ if (!conn_map.has(E.to_node)) {
+ conn_map.set(E.to_node, Set<int>());
}
- conn_map[E->get().to_node].insert(E->get().to_port);
+ conn_map[E.to_node].insert(E.to_port);
}
}
@@ -1587,9 +1585,9 @@ void VisualScriptEditor::_remove_output_port(int p_id, int p_port) {
List<int> keys;
conn_map.get_key_list(&keys);
- for (const List<int>::Element *E = keys.front(); E; E = E->next()) {
- for (const Set<int>::Element *F = conn_map[E->get()].front(); F; F = F->next()) {
- undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E->get(), F->get());
+ for (const int &E : keys) {
+ for (const Set<int>::Element *F = conn_map[E].front(); F; F = F->next()) {
+ undo_redo->add_undo_method(script.ptr(), "data_connect", p_id, p_port, E, F);
}
}
@@ -1642,8 +1640,8 @@ Vector2 VisualScriptEditor::_get_available_pos(bool p_centered, Vector2 p_pos) c
bool exists = false;
List<int> existing;
script->get_node_list(&existing);
- for (List<int>::Element *E = existing.front(); E; E = E->next()) {
- Point2 pos = script->get_node_position(E->get());
+ for (int &E : existing) {
+ Point2 pos = script->get_node_position(E);
if (pos.distance_to(p_pos) < 50) {
p_pos += Vector2(graph->get_snap(), graph->get_snap());
exists = true;
@@ -1698,8 +1696,8 @@ void VisualScriptEditor::_on_nodes_delete() {
undo_redo->create_action(TTR("Remove VisualScript Nodes"));
- for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
- int cr_node = F->get();
+ for (int &F : to_erase) {
+ int cr_node = F;
undo_redo->add_do_method(script.ptr(), "remove_node", cr_node);
undo_redo->add_undo_method(script.ptr(), "add_node", cr_node, script->get_node(cr_node), script->get_node_position(cr_node));
@@ -1707,18 +1705,18 @@ void VisualScriptEditor::_on_nodes_delete() {
List<VisualScript::SequenceConnection> sequence_conns;
script->get_sequence_connection_list(&sequence_conns);
- for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) {
- if (E->get().from_node == cr_node || E->get().to_node == cr_node) {
- undo_redo->add_undo_method(script.ptr(), "sequence_connect", E->get().from_node, E->get().from_output, E->get().to_node);
+ for (const VisualScript::SequenceConnection &E : sequence_conns) {
+ if (E.from_node == cr_node || E.to_node == cr_node) {
+ undo_redo->add_undo_method(script.ptr(), "sequence_connect", E.from_node, E.from_output, E.to_node);
}
}
List<VisualScript::DataConnection> data_conns;
script->get_data_connection_list(&data_conns);
- for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) {
- if (E->get().from_node == F->get() || E->get().to_node == F->get()) {
- undo_redo->add_undo_method(script.ptr(), "data_connect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const VisualScript::DataConnection &E : data_conns) {
+ if (E.from_node == F || E.to_node == F) {
+ undo_redo->add_undo_method(script.ptr(), "data_connect", E.from_node, E.from_port, E.to_node, E.to_port);
}
}
}
@@ -1767,17 +1765,17 @@ void VisualScriptEditor::_on_nodes_duplicate() {
List<VisualScript::SequenceConnection> seqs;
script->get_sequence_connection_list(&seqs);
- for (List<VisualScript::SequenceConnection>::Element *E = seqs.front(); E; E = E->next()) {
- if (to_duplicate.has(E->get().from_node) && to_duplicate.has(E->get().to_node)) {
- undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E->get().from_node], E->get().from_output, remap[E->get().to_node]);
+ for (const VisualScript::SequenceConnection &E : seqs) {
+ if (to_duplicate.has(E.from_node) && to_duplicate.has(E.to_node)) {
+ undo_redo->add_do_method(script.ptr(), "sequence_connect", remap[E.from_node], E.from_output, remap[E.to_node]);
}
}
List<VisualScript::DataConnection> data;
script->get_data_connection_list(&data);
- for (List<VisualScript::DataConnection>::Element *E = data.front(); E; E = E->next()) {
- if (to_duplicate.has(E->get().from_node) && to_duplicate.has(E->get().to_node)) {
- undo_redo->add_do_method(script.ptr(), "data_connect", remap[E->get().from_node], E->get().from_port, remap[E->get().to_node], E->get().to_port);
+ for (const VisualScript::DataConnection &E : data) {
+ if (to_duplicate.has(E.from_node) && to_duplicate.has(E.to_node)) {
+ undo_redo->add_do_method(script.ptr(), "data_connect", remap[E.from_node], E.from_port, remap[E.to_node], E.to_port);
}
}
@@ -1903,8 +1901,8 @@ void VisualScriptEditor::_rename_function(const String &name, const String &new_
// Also fix all function calls.
List<int> lst;
script->get_node_list(&lst);
- for (List<int>::Element *F = lst.front(); F; F = F->next()) {
- Ref<VisualScriptFunctionCall> fncall = script->get_node(F->get());
+ for (int &F : lst) {
+ Ref<VisualScriptFunctionCall> fncall = script->get_node(F);
if (!fncall.is_valid()) {
continue;
}
@@ -2188,7 +2186,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
int new_id = script->get_available_id();
if (files.size()) {
- undo_redo->create_action(TTR("Add Preload Node"));
+ undo_redo->create_action(TTR("Add Node(s)"));
for (int i = 0; i < files.size(); i++) {
Ref<Resource> res = ResourceLoader::load(files[i]);
@@ -2221,8 +2219,8 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
undo_redo->commit_action();
}
- for (List<int>::Element *E = new_ids.front(); E; E = E->next()) {
- Node *node = graph->get_node(itos(E->get()));
+ for (int &E : new_ids) {
+ Node *node = graph->get_node(itos(E));
if (node) {
graph->set_selected(node);
_node_selected(node);
@@ -2251,41 +2249,35 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
undo_redo->create_action(TTR("Add Node(s) From Tree"));
int base_id = script->get_available_id();
- if (nodes.size() > 1) {
- use_node = true;
- }
-
- for (int i = 0; i < nodes.size(); i++) {
- NodePath np = nodes[i];
- Node *node = get_node(np);
- if (!node) {
- continue;
- }
+ if (use_node || nodes.size() > 1) {
+ for (int i = 0; i < nodes.size(); i++) {
+ NodePath np = nodes[i];
+ Node *node = get_node(np);
+ if (!node) {
+ continue;
+ }
- Ref<VisualScriptNode> n;
+ Ref<VisualScriptNode> n;
- if (use_node) {
Ref<VisualScriptSceneNode> scene_node;
scene_node.instantiate();
scene_node->set_node_path(sn->get_path_to(node));
n = scene_node;
- } else {
- // ! Doesn't work properly.
- Ref<VisualScriptFunctionCall> call;
- call.instantiate();
- call->set_call_mode(VisualScriptFunctionCall::CALL_MODE_NODE_PATH);
- call->set_base_path(sn->get_path_to(node));
- call->set_base_type(node->get_class());
- n = call;
- method_select->select_from_instance(node, "", true, node->get_class());
- selecting_method_id = base_id;
- }
- undo_redo->add_do_method(script.ptr(), "add_node", base_id, n, pos);
- undo_redo->add_undo_method(script.ptr(), "remove_node", base_id);
+ undo_redo->add_do_method(script.ptr(), "add_node", base_id, n, pos);
+ undo_redo->add_undo_method(script.ptr(), "remove_node", base_id);
+
+ base_id++;
+ pos += Vector2(25, 25);
+ }
- base_id++;
- pos += Vector2(25, 25);
+ } else {
+ NodePath np = nodes[0];
+ Node *node = get_node(np);
+ drop_position = pos;
+ drop_node = node;
+ drop_path = sn->get_path_to(node);
+ new_connect_node_select->select_from_instance(node, "", false, node->get_class());
}
undo_redo->add_do_method(this, "_update_graph");
undo_redo->add_undo_method(this, "_update_graph");
@@ -2404,14 +2396,6 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
}
}
-void VisualScriptEditor::_selected_method(const String &p_method, const String &p_type, const bool p_connecting) {
- Ref<VisualScriptFunctionCall> vsfc = script->get_node(selecting_method_id);
- if (!vsfc.is_valid()) {
- return;
- }
- vsfc->set_function(p_method);
-}
-
void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) {
Button *button = Object::cast_to<Button>(obj);
if (!button) {
@@ -2568,12 +2552,12 @@ void VisualScriptEditor::goto_line(int p_line, bool p_with_error) {
List<StringName> functions;
script->get_function_list(&functions);
- for (List<StringName>::Element *E = functions.front(); E; E = E->next()) {
+ for (const StringName &E : functions) {
if (script->has_node(p_line)) {
_update_graph();
_update_members();
- call_deferred(SNAME("call_deferred"), "_center_on_node", E->get(), p_line); //editor might be just created and size might not exist yet
+ call_deferred(SNAME("call_deferred"), "_center_on_node", E, p_line); //editor might be just created and size might not exist yet
return;
}
}
@@ -2614,13 +2598,13 @@ Array VisualScriptEditor::get_breakpoints() {
Array breakpoints;
List<StringName> functions;
script->get_function_list(&functions);
- for (List<StringName>::Element *E = functions.front(); E; E = E->next()) {
+ for (int i = 0; i < functions.size(); i++) {
List<int> nodes;
script->get_node_list(&nodes);
- for (List<int>::Element *F = nodes.front(); F; F = F->next()) {
- Ref<VisualScriptNode> vsn = script->get_node(F->get());
+ for (int &F : nodes) {
+ Ref<VisualScriptNode> vsn = script->get_node(F);
if (vsn->is_breakpoint()) {
- breakpoints.push_back(F->get() - 1); // Subtract 1 because breakpoints in text start from zero.
+ breakpoints.push_back(F - 1); // Subtract 1 because breakpoints in text start from zero.
}
}
}
@@ -2789,18 +2773,18 @@ void VisualScriptEditor::_remove_node(int p_id) {
List<VisualScript::SequenceConnection> sequence_conns;
script->get_sequence_connection_list(&sequence_conns);
- for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) {
- if (E->get().from_node == p_id || E->get().to_node == p_id) {
- undo_redo->add_undo_method(script.ptr(), "sequence_connect", E->get().from_node, E->get().from_output, E->get().to_node);
+ for (const VisualScript::SequenceConnection &E : sequence_conns) {
+ if (E.from_node == p_id || E.to_node == p_id) {
+ undo_redo->add_undo_method(script.ptr(), "sequence_connect", E.from_node, E.from_output, E.to_node);
}
}
List<VisualScript::DataConnection> data_conns;
script->get_data_connection_list(&data_conns);
- for (List<VisualScript::DataConnection>::Element *E = data_conns.front(); E; E = E->next()) {
- if (E->get().from_node == p_id || E->get().to_node == p_id) {
- undo_redo->add_undo_method(script.ptr(), "data_connect", E->get().from_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const VisualScript::DataConnection &E : data_conns) {
+ if (E.from_node == p_id || E.to_node == p_id) {
+ undo_redo->add_undo_method(script.ptr(), "data_connect", E.from_node, E.from_port, E.to_node, E.to_port);
}
}
@@ -2818,9 +2802,9 @@ bool VisualScriptEditor::node_has_sequence_connections(int p_id) {
List<VisualScript::SequenceConnection> sequence_conns;
script->get_sequence_connection_list(&sequence_conns);
- for (List<VisualScript::SequenceConnection>::Element *E = sequence_conns.front(); E; E = E->next()) {
- int from = E->get().from_node;
- int to = E->get().to_node;
+ for (const VisualScript::SequenceConnection &E : sequence_conns) {
+ int from = E.from_node;
+ int to = E.to_node;
if (to == p_id || from == p_id) {
return true;
@@ -3153,6 +3137,11 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
Set<int> vn;
+ if (drop_position != Vector2()) {
+ pos = drop_position;
+ }
+ drop_position = Vector2();
+
bool port_node_exists = true;
// if (func == StringName()) {
@@ -3206,18 +3195,62 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
if (p_category == String("method")) {
Ref<VisualScriptFunctionCall> n;
n.instantiate();
+ if (!drop_path.is_empty()) {
+ if (drop_path == ".") {
+ n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_SELF);
+ } else {
+ n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_NODE_PATH);
+ n->set_base_path(drop_path);
+ }
+ }
+ if (drop_node) {
+ n->set_base_type(drop_node->get_class());
+ if (drop_node->get_script_instance()) {
+ n->set_base_script(drop_node->get_script_instance()->get_script()->get_path());
+ }
+ }
vnode = n;
} else if (p_category == String("set")) {
Ref<VisualScriptPropertySet> n;
n.instantiate();
+ if (!drop_path.is_empty()) {
+ if (drop_path == ".") {
+ n->set_call_mode(VisualScriptPropertySet::CALL_MODE_SELF);
+ } else {
+ n->set_call_mode(VisualScriptPropertySet::CALL_MODE_NODE_PATH);
+ n->set_base_path(drop_path);
+ }
+ }
+ if (drop_node) {
+ n->set_base_type(drop_node->get_class());
+ if (drop_node->get_script_instance()) {
+ n->set_base_script(drop_node->get_script_instance()->get_script()->get_path());
+ }
+ }
vnode = n;
script_prop_set = n;
} else if (p_category == String("get")) {
Ref<VisualScriptPropertyGet> n;
n.instantiate();
n->set_property(p_text);
+ if (!drop_path.is_empty()) {
+ if (drop_path == ".") {
+ n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_SELF);
+ } else {
+ n->set_call_mode(VisualScriptPropertyGet::CALL_MODE_NODE_PATH);
+ n->set_base_path(drop_path);
+ }
+ }
+ if (drop_node) {
+ n->set_base_type(drop_node->get_class());
+ if (drop_node->get_script_instance()) {
+ n->set_base_script(drop_node->get_script_instance()->get_script()->get_path());
+ }
+ }
vnode = n;
}
+ drop_path = String();
+ drop_node = nullptr;
if (p_category == String("action")) {
if (p_text == "VisualScriptCondition") {
@@ -3427,9 +3460,9 @@ void VisualScriptEditor::_selected_new_virtual_method(const String &p_text, cons
List<MethodInfo> methods;
bool found = false;
ClassDB::get_virtual_methods(script->get_instance_base_type(), &methods);
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name == name) {
- minfo = E->get();
+ for (const MethodInfo &E : methods) {
+ if (E.name == name) {
+ minfo = E;
found = true;
}
}
@@ -3699,8 +3732,8 @@ void VisualScriptEditor::_menu_option(int p_what) {
_update_graph();
- for (List<String>::Element *E = reselect.front(); E; E = E->next()) {
- GraphNode *gn = Object::cast_to<GraphNode>(graph->get_node(E->get()));
+ for (const String &E : reselect) {
+ GraphNode *gn = Object::cast_to<GraphNode>(graph->get_node(E));
gn->set_selected(true);
}
@@ -3739,18 +3772,18 @@ void VisualScriptEditor::_menu_option(int p_what) {
List<VisualScript::SequenceConnection> sequence_connections;
script->get_sequence_connection_list(&sequence_connections);
- for (List<VisualScript::SequenceConnection>::Element *E = sequence_connections.front(); E; E = E->next()) {
- if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) {
- clipboard->sequence_connections.insert(E->get());
+ for (const VisualScript::SequenceConnection &E : sequence_connections) {
+ if (clipboard->nodes.has(E.from_node) && clipboard->nodes.has(E.to_node)) {
+ clipboard->sequence_connections.insert(E);
}
}
List<VisualScript::DataConnection> data_connections;
script->get_data_connection_list(&data_connections);
- for (List<VisualScript::DataConnection>::Element *E = data_connections.front(); E; E = E->next()) {
- if (clipboard->nodes.has(E->get().from_node) && clipboard->nodes.has(E->get().to_node)) {
- clipboard->data_connections.insert(E->get());
+ for (const VisualScript::DataConnection &E : data_connections) {
+ if (clipboard->nodes.has(E.from_node) && clipboard->nodes.has(E.to_node)) {
+ clipboard->data_connections.insert(E);
}
}
if (p_what == EDIT_CUT_NODES) {
@@ -3776,8 +3809,8 @@ void VisualScriptEditor::_menu_option(int p_what) {
{
List<int> nodes;
script->get_node_list(&nodes);
- for (List<int>::Element *E = nodes.front(); E; E = E->next()) {
- Vector2 pos = script->get_node_position(E->get()).snapped(Vector2(2, 2));
+ for (int &E : nodes) {
+ Vector2 pos = script->get_node_position(E).snapped(Vector2(2, 2));
existing_positions.insert(pos);
}
}
@@ -3900,22 +3933,22 @@ void VisualScriptEditor::_menu_option(int p_what) {
// Pick the node with input sequence.
Set<int> nodes_from;
Set<int> nodes_to;
- for (List<VisualScript::SequenceConnection>::Element *E = seqs.front(); E; E = E->next()) {
- if (nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) {
- seqmove.insert(E->get());
- nodes_from.insert(E->get().from_node);
- } else if (nodes.has(E->get().from_node) && !nodes.has(E->get().to_node)) {
- seqext.insert(E->get());
- } else if (!nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) {
+ for (const VisualScript::SequenceConnection &E : seqs) {
+ if (nodes.has(E.from_node) && nodes.has(E.to_node)) {
+ seqmove.insert(E);
+ nodes_from.insert(E.from_node);
+ } else if (nodes.has(E.from_node) && !nodes.has(E.to_node)) {
+ seqext.insert(E);
+ } else if (!nodes.has(E.from_node) && nodes.has(E.to_node)) {
if (start_node == -1) {
- seqext.insert(E->get());
- start_node = E->get().to_node;
+ seqext.insert(E);
+ start_node = E.to_node;
} else {
EditorNode::get_singleton()->show_warning(TTR("Try to only have one sequence input in selection."));
return;
}
}
- nodes_to.insert(E->get().to_node);
+ nodes_to.insert(E.to_node);
}
// To use to add return nodes.
@@ -3943,20 +3976,20 @@ void VisualScriptEditor::_menu_option(int p_what) {
{
List<VisualScript::DataConnection> dats;
script->get_data_connection_list(&dats);
- for (List<VisualScript::DataConnection>::Element *E = dats.front(); E; E = E->next()) {
- if (nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) {
- datamove.insert(E->get());
- } else if (!nodes.has(E->get().from_node) && nodes.has(E->get().to_node)) {
+ for (const VisualScript::DataConnection &E : dats) {
+ if (nodes.has(E.from_node) && nodes.has(E.to_node)) {
+ datamove.insert(E);
+ } else if (!nodes.has(E.from_node) && nodes.has(E.to_node)) {
// Add all these as inputs for the Function.
- Ref<VisualScriptNode> node = script->get_node(E->get().to_node);
+ Ref<VisualScriptNode> node = script->get_node(E.to_node);
if (node.is_valid()) {
- dataext.insert(E->get());
- PropertyInfo pi = node->get_input_value_port_info(E->get().to_port);
+ dataext.insert(E);
+ PropertyInfo pi = node->get_input_value_port_info(E.to_port);
inputs.push_back(pi.type);
- input_connections.push_back(Pair<int, int>(E->get().to_node, E->get().to_port));
+ input_connections.push_back(Pair<int, int>(E.to_node, E.to_port));
}
- } else if (nodes.has(E->get().from_node) && !nodes.has(E->get().to_node)) {
- dataext.insert(E->get());
+ } else if (nodes.has(E.from_node) && !nodes.has(E.to_node)) {
+ dataext.insert(E);
}
}
}
@@ -4057,9 +4090,9 @@ void VisualScriptEditor::_menu_option(int p_what) {
// but I hope that it will not be a problem considering that we won't be creating functions so frequently,
// and cyclic connections would be a problem but hopefully we won't let them get to this point.
void VisualScriptEditor::_get_ends(int p_node, const List<VisualScript::SequenceConnection> &p_seqs, const Set<int> &p_selected, Set<int> &r_end_nodes) {
- for (const List<VisualScript::SequenceConnection>::Element *E = p_seqs.front(); E; E = E->next()) {
- int from = E->get().from_node;
- int to = E->get().to_node;
+ for (const VisualScript::SequenceConnection &E : p_seqs) {
+ int from = E.from_node;
+ int to = E.to_node;
if (from == p_node && p_selected.has(to)) {
// This is an interior connection move forward to the to node.
@@ -4133,16 +4166,16 @@ void VisualScriptEditor::_member_option(int p_option) {
undo_redo->add_undo_method(script.ptr(), "add_node", fn_node, script->get_node(fn_node), script->get_node_position(fn_node));
List<VisualScript::SequenceConnection> seqcons;
script->get_sequence_connection_list(&seqcons);
- for (const List<VisualScript::SequenceConnection>::Element *E = seqcons.front(); E; E = E->next()) {
- if (E->get().from_node == fn_node) {
- undo_redo->add_undo_method(script.ptr(), "sequence_connect", fn_node, E->get().from_output, E->get().to_node);
+ for (const VisualScript::SequenceConnection &E : seqcons) {
+ if (E.from_node == fn_node) {
+ undo_redo->add_undo_method(script.ptr(), "sequence_connect", fn_node, E.from_output, E.to_node);
}
}
List<VisualScript::DataConnection> datcons;
script->get_data_connection_list(&datcons);
- for (const List<VisualScript::DataConnection>::Element *E = datcons.front(); E; E = E->next()) {
- if (E->get().from_node == fn_node) {
- undo_redo->add_undo_method(script.ptr(), "data_connect", fn_node, E->get().from_port, E->get().to_node, E->get().to_port);
+ for (const VisualScript::DataConnection &E : datcons) {
+ if (E.from_node == fn_node) {
+ undo_redo->add_undo_method(script.ptr(), "data_connect", fn_node, E.from_port, E.to_node, E.to_port);
}
}
undo_redo->add_do_method(this, "_update_members");
@@ -4446,11 +4479,6 @@ VisualScriptEditor::VisualScriptEditor() {
add_child(default_value_edit);
default_value_edit->connect("variant_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed));
- method_select = memnew(VisualScriptPropertySelector);
- add_child(method_select);
- method_select->connect("selected", callable_mp(this, &VisualScriptEditor::_selected_method));
- error_line = -1;
-
new_connect_node_select = memnew(VisualScriptPropertySelector);
add_child(new_connect_node_select);
new_connect_node_select->connect("selected", callable_mp(this, &VisualScriptEditor::_selected_connect_node));
diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h
index 1f0f087be7..3b7ed3dba6 100644
--- a/modules/visual_script/visual_script_editor.h
+++ b/modules/visual_script/visual_script_editor.h
@@ -179,6 +179,9 @@ class VisualScriptEditor : public ScriptEditorBase {
void connect_data(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode, int new_id);
+ NodePath drop_path;
+ Node *drop_node = nullptr;
+ Vector2 drop_position;
void _selected_connect_node(const String &p_text, const String &p_category, const bool p_connecting = true);
void connect_seq(Ref<VisualScriptNode> vnode_old, Ref<VisualScriptNode> vnode_new, int new_id);
@@ -270,9 +273,6 @@ class VisualScriptEditor : public ScriptEditorBase {
void _graph_ofs_changed(const Vector2 &p_ofs);
void _comment_node_resized(const Vector2 &p_new_size, int p_node);
- int selecting_method_id;
- void _selected_method(const String &p_method, const String &p_type, const bool p_connecting);
-
void _draw_color_over_button(Object *obj, Color p_color);
void _button_resource_previewed(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud);
diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp
index d63fbeb726..99b7275008 100644
--- a/modules/visual_script/visual_script_expression.cpp
+++ b/modules/visual_script/visual_script_expression.cpp
@@ -526,10 +526,10 @@ Error VisualScriptExpression::_get_token(Token &r_token) {
r_token.value = Math_TAU;
} else if (id == "INF") {
r_token.type = TK_CONSTANT;
- r_token.value = Math_INF;
+ r_token.value = INFINITY;
} else if (id == "NAN") {
r_token.type = TK_CONSTANT;
- r_token.value = Math_NAN;
+ r_token.value = NAN;
} else if (id == "not") {
r_token.type = TK_OP_NOT;
} else if (id == "or") {
diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp
index af86f90b25..62a4f465cb 100644
--- a/modules/visual_script/visual_script_flow_control.cpp
+++ b/modules/visual_script/visual_script_flow_control.cpp
@@ -852,11 +852,11 @@ void VisualScriptTypeCast::_bind_methods() {
}
String script_ext_hint;
- for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) {
+ for (const String &E : script_extensions) {
if (script_ext_hint != String()) {
script_ext_hint += ",";
}
- script_ext_hint += "*." + E->get();
+ script_ext_hint += "*." + E;
}
ADD_PROPERTY(PropertyInfo(Variant::STRING, "base_type", PROPERTY_HINT_TYPE_STRING, "Object"), "set_base_type", "get_base_type");
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 8f7b514881..6ba5ad4fd6 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -254,25 +254,32 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con
}
String VisualScriptFunctionCall::get_caption() const {
- if (call_mode == CALL_MODE_SELF) {
- return " " + String(function) + "()";
- }
- if (call_mode == CALL_MODE_SINGLETON) {
- return String(singleton) + ":" + String(function) + "()";
- } else if (call_mode == CALL_MODE_BASIC_TYPE) {
- return Variant::get_type_name(basic_type) + "." + String(function) + "()";
- } else if (call_mode == CALL_MODE_NODE_PATH) {
- return " [" + String(base_path.simplified()) + "]." + String(function) + "()";
- } else {
- return " " + base_type + "." + String(function) + "()";
- }
+ return " " + String(function) + "()";
}
String VisualScriptFunctionCall::get_text() const {
+ String text;
+
+ if (call_mode == CALL_MODE_BASIC_TYPE) {
+ text = String("On ") + Variant::get_type_name(basic_type);
+ } else if (call_mode == CALL_MODE_INSTANCE) {
+ text = String("On ") + base_type;
+ } else if (call_mode == CALL_MODE_NODE_PATH) {
+ text = "[" + String(base_path.simplified()) + "]";
+ } else if (call_mode == CALL_MODE_SELF) {
+ text = "On Self";
+ } else if (call_mode == CALL_MODE_SINGLETON) {
+ text = String(singleton) + ":" + String(function) + "()";
+ }
+
if (rpc_call_mode) {
- return "RPC";
+ text += " RPC";
+ if (rpc_call_mode == RPC_UNRELIABLE || rpc_call_mode == RPC_UNRELIABLE_TO_ID) {
+ text += " UNREL";
+ }
}
- return "";
+
+ return text;
}
void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) {
@@ -531,11 +538,11 @@ void VisualScriptFunctionCall::_validate_property(PropertyInfo &property) const
Engine::get_singleton()->get_singletons(&names);
property.hint = PROPERTY_HINT_ENUM;
String sl;
- for (List<Engine::Singleton>::Element *E = names.front(); E; E = E->next()) {
+ for (const Engine::Singleton &E : names) {
if (sl != String()) {
sl += ",";
}
- sl += E->get().name;
+ sl += E.name;
}
property.hint_string = sl;
}
@@ -676,11 +683,11 @@ void VisualScriptFunctionCall::_bind_methods() {
}
String script_ext_hint;
- for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) {
+ for (const String &E : script_extensions) {
if (script_ext_hint != String()) {
script_ext_hint += ",";
}
- script_ext_hint += "*." + E->get();
+ script_ext_hint += "*." + E;
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "call_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type,Singleton"), "set_call_mode", "get_call_mode");
@@ -901,11 +908,11 @@ static Ref<VisualScriptNode> create_function_call_node(const String &p_name) {
//////////////////////////////////////////
int VisualScriptPropertySet::get_output_sequence_port_count() const {
- return call_mode != CALL_MODE_BASIC_TYPE ? 1 : 0;
+ return 1;
}
bool VisualScriptPropertySet::has_input_sequence_port() const {
- return call_mode != CALL_MODE_BASIC_TYPE;
+ return 1;
}
Node *VisualScriptPropertySet::_get_base_node() const {
@@ -990,31 +997,33 @@ PropertyInfo VisualScriptPropertySet::get_input_value_port_info(int p_idx) const
if (p_idx == 0) {
PropertyInfo pi;
pi.type = (call_mode == CALL_MODE_INSTANCE ? Variant::OBJECT : basic_type);
- pi.name = (call_mode == CALL_MODE_INSTANCE ? String("instance") : Variant::get_type_name(basic_type).to_lower());
- _adjust_input_index(pi);
+ pi.name = "instance";
return pi;
}
}
List<PropertyInfo> props;
ClassDB::get_property_list(_get_base_type(), &props, false);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (E->get().name == property) {
- PropertyInfo pinfo = PropertyInfo(E->get().type, "value", PROPERTY_HINT_TYPE_STRING, E->get().hint_string);
+ for (const PropertyInfo &E : props) {
+ if (E.name == property) {
+ String detail_prop_name = property;
+ if (index != StringName()) {
+ detail_prop_name += "." + String(index);
+ }
+ PropertyInfo pinfo = PropertyInfo(E.type, detail_prop_name, PROPERTY_HINT_TYPE_STRING, E.hint_string);
_adjust_input_index(pinfo);
return pinfo;
}
}
PropertyInfo pinfo = type_cache;
- pinfo.name = "value";
_adjust_input_index(pinfo);
return pinfo;
}
PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) const {
if (call_mode == CALL_MODE_BASIC_TYPE) {
- return PropertyInfo(basic_type, "out");
+ return PropertyInfo(basic_type, "pass");
} else if (call_mode == CALL_MODE_INSTANCE) {
return PropertyInfo(Variant::OBJECT, "pass", PROPERTY_HINT_TYPE_STRING, get_base_type());
} else {
@@ -1036,17 +1045,18 @@ String VisualScriptPropertySet::get_caption() const {
}
String VisualScriptPropertySet::get_text() const {
+ if (!has_input_sequence_port()) {
+ return "";
+ }
if (call_mode == CALL_MODE_BASIC_TYPE) {
return String("On ") + Variant::get_type_name(basic_type);
+ } else if (call_mode == CALL_MODE_INSTANCE) {
+ return String("On ") + base_type;
+ } else if (call_mode == CALL_MODE_NODE_PATH) {
+ return " [" + String(base_path.simplified()) + "]";
+ } else {
+ return "On Self";
}
-
- static const char *cname[3] = {
- "Self",
- "Scene Node",
- "Instance"
- };
-
- return String("On ") + cname[call_mode];
}
void VisualScriptPropertySet::_update_base_type() {
@@ -1125,9 +1135,9 @@ void VisualScriptPropertySet::_update_cache() {
List<PropertyInfo> pinfo;
v.get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().name == property) {
- type_cache = E->get();
+ for (const PropertyInfo &E : pinfo) {
+ if (E.name == property) {
+ type_cache = E;
}
}
@@ -1176,9 +1186,9 @@ void VisualScriptPropertySet::_update_cache() {
script->get_script_property_list(&pinfo);
}
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().name == property) {
- type_cache = E->get();
+ for (const PropertyInfo &E : pinfo) {
+ if (E.name == property) {
+ type_cache = E;
return;
}
}
@@ -1344,8 +1354,8 @@ void VisualScriptPropertySet::_validate_property(PropertyInfo &property) const {
List<PropertyInfo> plist;
v.get_property_list(&plist);
String options = "";
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- options += "," + E->get().name;
+ for (const PropertyInfo &E : plist) {
+ options += "," + E.name;
}
property.hint = PROPERTY_HINT_ENUM;
@@ -1400,11 +1410,11 @@ void VisualScriptPropertySet::_bind_methods() {
}
String script_ext_hint;
- for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) {
+ for (const String &E : script_extensions) {
if (script_ext_hint != String()) {
script_ext_hint += ",";
}
- script_ext_hint += "*." + E->get();
+ script_ext_hint += "*." + E;
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode");
@@ -1707,7 +1717,9 @@ int VisualScriptPropertyGet::get_input_value_port_count() const {
}
int VisualScriptPropertyGet::get_output_value_port_count() const {
- return 1;
+ int pc = (call_mode == CALL_MODE_BASIC_TYPE || call_mode == CALL_MODE_INSTANCE) ? 2 : 1;
+
+ return pc;
}
String VisualScriptPropertyGet::get_output_sequence_port_text(int p_port) const {
@@ -1727,33 +1739,46 @@ PropertyInfo VisualScriptPropertyGet::get_input_value_port_info(int p_idx) const
}
PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) const {
- List<PropertyInfo> props;
- ClassDB::get_property_list(_get_base_type(), &props, false);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (E->get().name == property) {
- return PropertyInfo(E->get().type, "value." + String(index));
+ if (call_mode == CALL_MODE_BASIC_TYPE && p_idx == 0) {
+ return PropertyInfo(basic_type, "pass");
+ } else if (call_mode == CALL_MODE_INSTANCE && p_idx == 0) {
+ return PropertyInfo(Variant::OBJECT, "pass", PROPERTY_HINT_TYPE_STRING, get_base_type());
+ } else {
+ List<PropertyInfo> props;
+ ClassDB::get_property_list(_get_base_type(), &props, false);
+ for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
+ if (E->get().name == property) {
+ PropertyInfo pinfo = PropertyInfo(E->get().type, String(property) + "." + String(index), E->get().hint, E->get().hint_string);
+ _adjust_input_index(pinfo);
+ return pinfo;
+ }
}
}
- return PropertyInfo(type_cache, "value");
+ PropertyInfo pinfo = PropertyInfo(type_cache, "value");
+ _adjust_input_index(pinfo);
+ return pinfo;
}
String VisualScriptPropertyGet::get_caption() const {
- return String("Get ") + property;
+ String prop = String("Get ") + property;
+ if (index != StringName()) {
+ prop += "." + String(index);
+ }
+
+ return prop;
}
String VisualScriptPropertyGet::get_text() const {
if (call_mode == CALL_MODE_BASIC_TYPE) {
return String("On ") + Variant::get_type_name(basic_type);
+ } else if (call_mode == CALL_MODE_INSTANCE) {
+ return String("On ") + base_type;
+ } else if (call_mode == CALL_MODE_NODE_PATH) {
+ return " [" + String(base_path.simplified()) + "]";
+ } else {
+ return "On Self";
}
-
- static const char *cname[3] = {
- "Self",
- "Scene Node",
- "Instance"
- };
-
- return String("On ") + cname[call_mode];
}
void VisualScriptPropertyGet::set_base_type(const StringName &p_type) {
@@ -1795,9 +1820,9 @@ void VisualScriptPropertyGet::_update_cache() {
List<PropertyInfo> pinfo;
v.get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().name == property) {
- type_cache = E->get().type;
+ for (const PropertyInfo &E : pinfo) {
+ if (E.name == property) {
+ type_cache = E.type;
return;
}
}
@@ -1933,6 +1958,19 @@ Variant::Type VisualScriptPropertyGet::_get_type_cache() const {
return type_cache;
}
+void VisualScriptPropertyGet::_adjust_input_index(PropertyInfo &pinfo) const {
+ if (index != StringName()) {
+ Variant v;
+ Callable::CallError ce;
+ Variant::construct(pinfo.type, v, nullptr, 0, ce);
+ Variant i = v.get(index);
+ pinfo.type = i.get_type();
+ pinfo.name = String(property) + "." + index;
+ } else {
+ pinfo.name = String(property);
+ }
+}
+
void VisualScriptPropertyGet::set_index(const StringName &p_type) {
if (index == p_type) {
return;
@@ -2021,8 +2059,8 @@ void VisualScriptPropertyGet::_validate_property(PropertyInfo &property) const {
List<PropertyInfo> plist;
v.get_property_list(&plist);
String options = "";
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- options += "," + E->get().name;
+ for (const PropertyInfo &E : plist) {
+ options += "," + E.name;
}
property.hint = PROPERTY_HINT_ENUM;
@@ -2074,11 +2112,11 @@ void VisualScriptPropertyGet::_bind_methods() {
}
String script_ext_hint;
- for (List<String>::Element *E = script_extensions.front(); E; E = E->next()) {
+ for (const String &E : script_extensions) {
if (script_ext_hint != String()) {
script_ext_hint += ",";
}
- script_ext_hint += "." + E->get();
+ script_ext_hint += "." + E;
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "set_mode", PROPERTY_HINT_ENUM, "Self,Node Path,Instance,Basic Type"), "set_call_mode", "get_call_mode");
@@ -2159,15 +2197,17 @@ public:
bool valid;
Variant v = *p_inputs[0];
- *p_outputs[0] = v.get(property, &valid);
+ *p_outputs[1] = v.get(property, &valid);
if (index != StringName()) {
- *p_outputs[0] = p_outputs[0]->get_named(index, valid);
+ *p_outputs[1] = p_outputs[1]->get_named(index, valid);
}
if (!valid) {
r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
r_error_str = RTR("Invalid index property name.");
}
+
+ *p_outputs[0] = v;
};
}
@@ -2283,11 +2323,11 @@ void VisualScriptEmitSignal::_validate_property(PropertyInfo &property) const {
}
String ml;
- for (List<StringName>::Element *E = sigs.front(); E; E = E->next()) {
+ for (const StringName &E : sigs) {
if (ml != String()) {
ml += ",";
}
- ml += E->get();
+ ml += E;
}
property.hint_string = ml;
@@ -2378,8 +2418,8 @@ void register_visual_script_func_nodes() {
List<MethodInfo> ml;
vt.get_method_list(&ml);
- for (List<MethodInfo>::Element *E = ml.front(); E; E = E->next()) {
- VisualScriptLanguage::singleton->add_register_func("functions/by_type/" + type_name + "/" + E->get().name, create_basic_type_call_node);
+ for (const MethodInfo &E : ml) {
+ VisualScriptLanguage::singleton->add_register_func("functions/by_type/" + type_name + "/" + E.name, create_basic_type_call_node);
}
}
}
diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h
index eb17be1fbe..cca08455f9 100644
--- a/modules/visual_script/visual_script_func_nodes.h
+++ b/modules/visual_script/visual_script_func_nodes.h
@@ -272,6 +272,8 @@ private:
void _set_type_cache(Variant::Type p_type);
Variant::Type _get_type_cache() const;
+ void _adjust_input_index(PropertyInfo &pinfo) const;
+
protected:
virtual void _validate_property(PropertyInfo &property) const override;
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 2a46051ccf..c517d89aa5 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -1306,12 +1306,12 @@ void VisualScriptVariableGet::_validate_property(PropertyInfo &property) const {
vs->get_variable_list(&vars);
String vhint;
- for (List<StringName>::Element *E = vars.front(); E; E = E->next()) {
+ for (const StringName &E : vars) {
if (vhint != String()) {
vhint += ",";
}
- vhint += E->get().operator String();
+ vhint += E.operator String();
}
property.hint = PROPERTY_HINT_ENUM;
@@ -1416,12 +1416,12 @@ void VisualScriptVariableSet::_validate_property(PropertyInfo &property) const {
vs->get_variable_list(&vars);
String vhint;
- for (List<StringName>::Element *E = vars.front(); E; E = E->next()) {
+ for (const StringName &E : vars) {
if (vhint != String()) {
vhint += ",";
}
- vhint += E->get().operator String();
+ vhint += E.operator String();
}
property.hint = PROPERTY_HINT_ENUM;
@@ -1944,8 +1944,8 @@ void VisualScriptClassConstant::set_base_type(const StringName &p_which) {
ClassDB::get_integer_constant_list(base_type, &constants, true);
if (constants.size() > 0) {
bool found_name = false;
- for (List<String>::Element *E = constants.front(); E; E = E->next()) {
- if (E->get() == name) {
+ for (const String &E : constants) {
+ if (E == name) {
found_name = true;
break;
}
@@ -1993,11 +1993,11 @@ void VisualScriptClassConstant::_validate_property(PropertyInfo &property) const
ClassDB::get_integer_constant_list(base_type, &constants, true);
property.hint_string = "";
- for (List<String>::Element *E = constants.front(); E; E = E->next()) {
+ for (const String &E : constants) {
if (property.hint_string != String()) {
property.hint_string += ",";
}
- property.hint_string += E->get();
+ property.hint_string += E;
}
}
}
@@ -2078,8 +2078,8 @@ void VisualScriptBasicTypeConstant::set_basic_type(Variant::Type p_which) {
Variant::get_constants_for_type(type, &constants);
if (constants.size() > 0) {
bool found_name = false;
- for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
- if (E->get() == name) {
+ for (const StringName &E : constants) {
+ if (E == name) {
found_name = true;
break;
}
@@ -2131,11 +2131,11 @@ void VisualScriptBasicTypeConstant::_validate_property(PropertyInfo &property) c
return;
}
property.hint_string = "";
- for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
+ for (const StringName &E : constants) {
if (property.hint_string != String()) {
property.hint_string += ",";
}
- property.hint_string += String(E->get());
+ property.hint_string += String(E);
}
}
}
@@ -2182,8 +2182,8 @@ double VisualScriptMathConstant::const_value[MATH_CONSTANT_MAX] = {
Math_TAU,
2.71828182845904523536,
Math::sqrt(2.0),
- Math_INF,
- Math_NAN
+ INFINITY,
+ NAN
};
int VisualScriptMathConstant::get_output_sequence_port_count() const {
@@ -2358,15 +2358,15 @@ void VisualScriptEngineSingleton::_validate_property(PropertyInfo &property) con
Engine::get_singleton()->get_singletons(&singletons);
- for (List<Engine::Singleton>::Element *E = singletons.front(); E; E = E->next()) {
- if (E->get().name == "VS" || E->get().name == "PS" || E->get().name == "PS2D" || E->get().name == "AS" || E->get().name == "TS" || E->get().name == "SS" || E->get().name == "SS2D") {
+ for (const Engine::Singleton &E : singletons) {
+ if (E.name == "VS" || E.name == "PS" || E.name == "PS2D" || E.name == "AS" || E.name == "TS" || E.name == "SS" || E.name == "SS2D") {
continue; //skip these, too simple named
}
if (cc != String()) {
cc += ",";
}
- cc += E->get().name;
+ cc += E.name;
}
property.hint = PROPERTY_HINT_ENUM;
@@ -2868,6 +2868,12 @@ PropertyInfo VisualScriptCustomNode::get_input_value_port_info(int p_idx) const
if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_name")) {
info.name = get_script_instance()->call("_get_input_value_port_name", p_idx);
}
+ if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_hint")) {
+ info.hint = PropertyHint(int(get_script_instance()->call("_get_input_value_port_hint", p_idx)));
+ }
+ if (get_script_instance() && get_script_instance()->has_method("_get_input_value_port_hint_string")) {
+ info.hint_string = get_script_instance()->call("_get_input_value_port_hint_string", p_idx);
+ }
return info;
}
@@ -2879,9 +2885,31 @@ PropertyInfo VisualScriptCustomNode::get_output_value_port_info(int p_idx) const
if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_name")) {
info.name = get_script_instance()->call("_get_output_value_port_name", p_idx);
}
+ if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_hint")) {
+ info.hint = PropertyHint(int(get_script_instance()->call("_get_output_value_port_hint", p_idx)));
+ }
+ if (get_script_instance() && get_script_instance()->has_method("_get_output_value_port_hint_string")) {
+ info.hint_string = get_script_instance()->call("_get_output_value_port_hint_string", p_idx);
+ }
return info;
}
+VisualScriptCustomNode::TypeGuess VisualScriptCustomNode::guess_output_type(TypeGuess *p_inputs, int p_output) const {
+ TypeGuess tg;
+ PropertyInfo pi = VisualScriptCustomNode::get_output_value_port_info(p_output);
+ tg.type = pi.type;
+ if (pi.type == Variant::OBJECT) {
+ if (pi.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ if (pi.hint_string.is_resource_file()) {
+ tg.script = ResourceLoader::load(pi.hint_string);
+ } else if (ClassDB::class_exists(pi.hint_string)) {
+ tg.gdclass = pi.hint_string;
+ }
+ }
+ }
+ return tg;
+}
+
String VisualScriptCustomNode::get_caption() const {
if (get_script_instance() && get_script_instance()->has_method("_get_caption")) {
return get_script_instance()->call("_get_caption");
@@ -3003,9 +3031,13 @@ void VisualScriptCustomNode::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_input_value_port_type", PropertyInfo(Variant::INT, "idx")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_input_value_port_name", PropertyInfo(Variant::INT, "idx")));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_get_input_value_port_hint", PropertyInfo(Variant::INT, "idx")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_input_value_port_hint_string", PropertyInfo(Variant::INT, "idx")));
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_output_value_port_type", PropertyInfo(Variant::INT, "idx")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_output_value_port_name", PropertyInfo(Variant::INT, "idx")));
+ BIND_VMETHOD(MethodInfo(Variant::INT, "_get_output_value_port_hint", PropertyInfo(Variant::INT, "idx")));
+ BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_output_value_port_hint_string", PropertyInfo(Variant::INT, "idx")));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_caption"));
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_text"));
@@ -3717,9 +3749,7 @@ void VisualScriptInputAction::_validate_property(PropertyInfo &property) const {
ProjectSettings::get_singleton()->get_property_list(&pinfo);
Vector<String> al;
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- const PropertyInfo &pi = E->get();
-
+ for (const PropertyInfo &pi : pinfo) {
if (!pi.name.begins_with("input/")) {
continue;
}
@@ -3812,10 +3842,10 @@ void VisualScriptDeconstruct::_update_elements() {
List<PropertyInfo> pinfo;
v.get_property_list(&pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+ for (const PropertyInfo &E : pinfo) {
Element e;
- e.name = E->get().name;
- e.type = E->get().type;
+ e.name = E.name;
+ e.type = E.type;
elements.push_back(e);
}
}
@@ -3993,24 +4023,24 @@ void register_visual_script_nodes() {
List<MethodInfo> constructors;
Variant::get_constructor_list(Variant::Type(i), &constructors);
- for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) {
- if (E->get().arguments.size() > 0) {
+ for (const MethodInfo &E : constructors) {
+ if (E.arguments.size() > 0) {
String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "(";
- for (int j = 0; j < E->get().arguments.size(); j++) {
+ for (int j = 0; j < E.arguments.size(); j++) {
if (j > 0) {
name += ", ";
}
- if (E->get().arguments.size() == 1) {
- name += Variant::get_type_name(E->get().arguments[j].type);
+ if (E.arguments.size() == 1) {
+ name += Variant::get_type_name(E.arguments[j].type);
} else {
- name += E->get().arguments[j].name;
+ name += E.arguments[j].name;
}
}
name += ")";
VisualScriptLanguage::singleton->add_register_func(name, create_constructor_node);
Pair<Variant::Type, MethodInfo> pair;
pair.first = Variant::Type(i);
- pair.second = E->get();
+ pair.second = E;
constructor_map[name] = pair;
}
}
diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h
index b599b92b3a..2390e5c7bc 100644
--- a/modules/visual_script/visual_script_nodes.h
+++ b/modules/visual_script/visual_script_nodes.h
@@ -792,6 +792,8 @@ public:
virtual VisualScriptNodeInstance *instantiate(VisualScriptInstance *p_instance) override;
+ virtual TypeGuess guess_output_type(TypeGuess *p_inputs, int p_output) const override;
+
void _script_changed();
VisualScriptCustomNode();
diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp
index ccb2e2df75..8bf1c6cbfa 100644
--- a/modules/visual_script/visual_script_property_selector.cpp
+++ b/modules/visual_script/visual_script_property_selector.cpp
@@ -93,7 +93,7 @@ void VisualScriptPropertySelector::_update_search() {
base = ClassDB::get_parent_class_nocheck(base);
}
- for (List<StringName>::Element *E = base_list.front(); E; E = E->next()) {
+ for (const StringName &E : base_list) {
List<MethodInfo> methods;
List<PropertyInfo> props;
TreeItem *category = nullptr;
@@ -135,7 +135,7 @@ void VisualScriptPropertySelector::_update_search() {
vbc->get_theme_icon(SNAME("PackedColorArray"), SNAME("EditorIcons"))
};
{
- String b = String(E->get());
+ String b = String(E);
category = search_options->create_item(root);
if (category) {
category->set_text(0, b.replace_first("*", ""));
@@ -154,30 +154,30 @@ void VisualScriptPropertySelector::_update_search() {
if (Object::cast_to<Script>(obj)) {
Object::cast_to<Script>(obj)->get_script_property_list(&props);
} else {
- ClassDB::get_property_list(E->get(), &props, true);
+ ClassDB::get_property_list(E, &props, true);
}
}
- for (List<PropertyInfo>::Element *F = props.front(); F; F = F->next()) {
- if (!(F->get().usage & PROPERTY_USAGE_EDITOR) && !(F->get().usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) {
+ for (const PropertyInfo &F : props) {
+ if (!(F.usage & PROPERTY_USAGE_EDITOR) && !(F.usage & PROPERTY_USAGE_SCRIPT_VARIABLE)) {
continue;
}
- if (type_filter.size() && type_filter.find(F->get().type) == -1) {
+ if (type_filter.size() && type_filter.find(F.type) == -1) {
continue;
}
// capitalize() also converts underscore to space, we'll match again both possible styles
- String get_text_raw = String(vformat(TTR("Get %s"), F->get().name));
+ String get_text_raw = String(vformat(TTR("Get %s"), F.name));
String get_text = get_text_raw.capitalize();
- String set_text_raw = String(vformat(TTR("Set %s"), F->get().name));
+ String set_text_raw = String(vformat(TTR("Set %s"), F.name));
String set_text = set_text_raw.capitalize();
String input = search_box->get_text().capitalize();
if (input == String() || get_text_raw.findn(input) != -1 || get_text.findn(input) != -1) {
TreeItem *item = search_options->create_item(category ? category : root);
item->set_text(0, get_text);
- item->set_metadata(0, F->get().name);
- item->set_icon(0, type_icons[F->get().type]);
+ item->set_metadata(0, F.name);
+ item->set_icon(0, type_icons[F.type]);
item->set_metadata(1, "get");
item->set_collapsed(true);
item->set_selectable(0, true);
@@ -189,8 +189,8 @@ void VisualScriptPropertySelector::_update_search() {
if (input == String() || set_text_raw.findn(input) != -1 || set_text.findn(input) != -1) {
TreeItem *item = search_options->create_item(category ? category : root);
item->set_text(0, set_text);
- item->set_metadata(0, F->get().name);
- item->set_icon(0, type_icons[F->get().type]);
+ item->set_metadata(0, F.name);
+ item->set_icon(0, type_icons[F.type]);
item->set_metadata(1, "set");
item->set_selectable(0, true);
item->set_selectable(1, false);
@@ -211,7 +211,7 @@ void VisualScriptPropertySelector::_update_search() {
Object::cast_to<Script>(obj)->get_script_method_list(&methods);
}
- ClassDB::get_method_list(E->get(), &methods, true, true);
+ ClassDB::get_method_list(E, &methods, true, true);
}
}
for (List<MethodInfo>::Element *M = methods.front(); M; M = M->next()) {
@@ -340,11 +340,11 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
List<String> fnodes;
VisualScriptLanguage::singleton->get_registered_node_names(&fnodes);
- for (List<String>::Element *E = fnodes.front(); E; E = E->next()) {
- if (!E->get().begins_with(root_filter)) {
+ for (const String &E : fnodes) {
+ if (!E.begins_with(root_filter)) {
continue;
}
- Vector<String> path = E->get().split("/");
+ Vector<String> path = E.split("/");
// check if the name has the filter
bool in_filter = false;
@@ -355,7 +355,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
} else {
in_filter = false;
}
- if (E->get().findn(tx_filters[i]) != -1) {
+ if (E.findn(tx_filters[i]) != -1) {
in_filter = true;
break;
}
@@ -366,7 +366,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
bool in_modifier = p_modifiers.is_empty();
for (Set<String>::Element *F = p_modifiers.front(); F && in_modifier; F = F->next()) {
- if (E->get().findn(F->get()) != -1) {
+ if (E.findn(F->get()) != -1) {
in_modifier = true;
}
}
@@ -375,7 +375,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
}
TreeItem *item = search_options->create_item(root);
- Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(E->get());
+ Ref<VisualScriptNode> vnode = VisualScriptLanguage::singleton->create_node_from_name(E);
Ref<VisualScriptOperator> vnode_operator = vnode;
String type_name;
if (vnode_operator.is_valid()) {
@@ -409,7 +409,7 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt
item->set_text(0, type_name + String("").join(desc));
item->set_icon(0, vbc->get_theme_icon(SNAME("VisualScript"), SNAME("EditorIcons")));
item->set_selectable(0, true);
- item->set_metadata(0, E->get());
+ item->set_metadata(0, E);
item->set_selectable(0, true);
item->set_metadata(1, "visualscript");
item->set_selectable(1, false);
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index d8bc926a1d..9fa49b8a1d 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -438,21 +438,21 @@ void VisualScriptYieldSignal::_validate_property(PropertyInfo &property) const {
ClassDB::get_signal_list(_get_base_type(), &methods);
List<String> mstring;
- for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name.begins_with("_")) {
+ for (const MethodInfo &E : methods) {
+ if (E.name.begins_with("_")) {
continue;
}
- mstring.push_back(E->get().name.get_slice(":", 0));
+ mstring.push_back(E.name.get_slice(":", 0));
}
mstring.sort();
String ml;
- for (List<String>::Element *E = mstring.front(); E; E = E->next()) {
+ for (const String &E : mstring) {
if (ml != String()) {
ml += ",";
}
- ml += E->get();
+ ml += E;
}
property.hint_string = ml;
diff --git a/modules/webrtc/doc_classes/WebRTCDataChannel.xml b/modules/webrtc/doc_classes/WebRTCDataChannel.xml
index 5c90038b9a..3435dda982 100644
--- a/modules/webrtc/doc_classes/WebRTCDataChannel.xml
+++ b/modules/webrtc/doc_classes/WebRTCDataChannel.xml
@@ -14,6 +14,13 @@
Closes this data channel, notifying the other peer.
</description>
</method>
+ <method name="get_buffered_amount" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ Returns the number of bytes currently queued to be sent over this channel.
+ </description>
+ </method>
<method name="get_id" qualifiers="const">
<return type="int">
</return>
diff --git a/modules/webrtc/library_godot_webrtc.js b/modules/webrtc/library_godot_webrtc.js
index 5269117686..a0a6c21be3 100644
--- a/modules/webrtc/library_godot_webrtc.js
+++ b/modules/webrtc/library_godot_webrtc.js
@@ -166,6 +166,11 @@ const GodotRTCDataChannel = {
return GodotRTCDataChannel.get_prop(p_id, 'negotiated', 65535);
},
+ godot_js_rtc_datachannel_get_buffered_amount__sig: 'ii',
+ godot_js_rtc_datachannel_get_buffered_amount: function (p_id) {
+ return GodotRTCDataChannel.get_prop(p_id, 'bufferedAmount', 0);
+ },
+
godot_js_rtc_datachannel_label_get__sig: 'ii',
godot_js_rtc_datachannel_label_get: function (p_id) {
const ref = IDHandler.get(p_id);
diff --git a/modules/webrtc/webrtc_data_channel.cpp b/modules/webrtc/webrtc_data_channel.cpp
index 004112f992..ca520a733d 100644
--- a/modules/webrtc/webrtc_data_channel.cpp
+++ b/modules/webrtc/webrtc_data_channel.cpp
@@ -46,6 +46,7 @@ void WebRTCDataChannel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_max_retransmits"), &WebRTCDataChannel::get_max_retransmits);
ClassDB::bind_method(D_METHOD("get_protocol"), &WebRTCDataChannel::get_protocol);
ClassDB::bind_method(D_METHOD("is_negotiated"), &WebRTCDataChannel::is_negotiated);
+ ClassDB::bind_method(D_METHOD("get_buffered_amount"), &WebRTCDataChannel::get_buffered_amount);
ADD_PROPERTY(PropertyInfo(Variant::INT, "write_mode", PROPERTY_HINT_ENUM), "set_write_mode", "get_write_mode");
diff --git a/modules/webrtc/webrtc_data_channel.h b/modules/webrtc/webrtc_data_channel.h
index 20affc513f..809d35c6e3 100644
--- a/modules/webrtc/webrtc_data_channel.h
+++ b/modules/webrtc/webrtc_data_channel.h
@@ -70,6 +70,8 @@ public:
virtual String get_protocol() const = 0;
virtual bool is_negotiated() const = 0;
+ virtual int get_buffered_amount() const = 0;
+
virtual Error poll() = 0;
virtual void close() = 0;
diff --git a/modules/webrtc/webrtc_data_channel_gdnative.cpp b/modules/webrtc/webrtc_data_channel_gdnative.cpp
index f3009dde2f..10a3367557 100644
--- a/modules/webrtc/webrtc_data_channel_gdnative.cpp
+++ b/modules/webrtc/webrtc_data_channel_gdnative.cpp
@@ -111,6 +111,11 @@ bool WebRTCDataChannelGDNative::is_negotiated() const {
return interface->is_negotiated(interface->data);
}
+int WebRTCDataChannelGDNative::get_buffered_amount() const {
+ ERR_FAIL_COND_V(interface == NULL, 0);
+ return interface->get_buffered_amount(interface->data);
+}
+
Error WebRTCDataChannelGDNative::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {
ERR_FAIL_COND_V(interface == nullptr, ERR_UNCONFIGURED);
return (Error)interface->get_packet(interface->data, r_buffer, &r_buffer_size);
diff --git a/modules/webrtc/webrtc_data_channel_gdnative.h b/modules/webrtc/webrtc_data_channel_gdnative.h
index 7e02a32046..5c80edd48c 100644
--- a/modules/webrtc/webrtc_data_channel_gdnative.h
+++ b/modules/webrtc/webrtc_data_channel_gdnative.h
@@ -60,6 +60,7 @@ public:
virtual int get_max_retransmits() const override;
virtual String get_protocol() const override;
virtual bool is_negotiated() const override;
+ virtual int get_buffered_amount() const override;
virtual Error poll() override;
virtual void close() override;
diff --git a/modules/webrtc/webrtc_data_channel_js.cpp b/modules/webrtc/webrtc_data_channel_js.cpp
index dfbec80c86..31d6a0568c 100644
--- a/modules/webrtc/webrtc_data_channel_js.cpp
+++ b/modules/webrtc/webrtc_data_channel_js.cpp
@@ -46,6 +46,7 @@ extern int godot_js_rtc_datachannel_id_get(int p_id);
extern int godot_js_rtc_datachannel_max_packet_lifetime_get(int p_id);
extern int godot_js_rtc_datachannel_max_retransmits_get(int p_id);
extern int godot_js_rtc_datachannel_is_negotiated(int p_id);
+extern int godot_js_rtc_datachannel_get_buffered_amount(int p_id);
extern char *godot_js_rtc_datachannel_label_get(int p_id); // Must free the returned string.
extern char *godot_js_rtc_datachannel_protocol_get(int p_id); // Must free the returned string.
extern void godot_js_rtc_datachannel_destroy(int p_id);
@@ -181,6 +182,10 @@ bool WebRTCDataChannelJS::is_negotiated() const {
return godot_js_rtc_datachannel_is_negotiated(_js_id);
}
+int WebRTCDataChannelJS::get_buffered_amount() const {
+ return godot_js_rtc_datachannel_get_buffered_amount(_js_id);
+}
+
WebRTCDataChannelJS::WebRTCDataChannelJS() {
}
diff --git a/modules/webrtc/webrtc_data_channel_js.h b/modules/webrtc/webrtc_data_channel_js.h
index db58ebccff..5cd6a32ed9 100644
--- a/modules/webrtc/webrtc_data_channel_js.h
+++ b/modules/webrtc/webrtc_data_channel_js.h
@@ -72,6 +72,7 @@ public:
virtual int get_max_retransmits() const override;
virtual String get_protocol() const override;
virtual bool is_negotiated() const override;
+ virtual int get_buffered_amount() const override;
virtual Error poll() override;
virtual void close() override;
diff --git a/modules/webrtc/webrtc_multiplayer_peer.cpp b/modules/webrtc/webrtc_multiplayer_peer.cpp
index 51101e3124..9b08a26aed 100644
--- a/modules/webrtc/webrtc_multiplayer_peer.cpp
+++ b/modules/webrtc/webrtc_multiplayer_peer.cpp
@@ -112,22 +112,22 @@ void WebRTCMultiplayerPeer::poll() {
}
}
// Remove disconnected peers
- for (List<int>::Element *E = remove.front(); E; E = E->next()) {
- remove_peer(E->get());
- if (next_packet_peer == E->get()) {
+ for (int &E : remove) {
+ remove_peer(E);
+ if (next_packet_peer == E) {
next_packet_peer = 0;
}
}
// Signal newly connected peers
- for (List<int>::Element *E = add.front(); E; E = E->next()) {
+ for (int &E : add) {
// Already connected to server: simply notify new peer.
// NOTE: Mesh is always connected.
if (connection_status == CONNECTION_CONNECTED) {
- emit_signal(SNAME("peer_connected"), E->get());
+ emit_signal(SNAME("peer_connected"), E);
}
// Server emulation mode suppresses peer_conencted until server connects.
- if (server_compat && E->get() == TARGET_PEER_SERVER) {
+ if (server_compat && E == TARGET_PEER_SERVER) {
// Server connected.
connection_status = CONNECTION_CONNECTED;
emit_signal(SNAME("peer_connected"), TARGET_PEER_SERVER);
@@ -154,8 +154,8 @@ void WebRTCMultiplayerPeer::_find_next_peer() {
}
// After last.
while (E) {
- for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) {
- if (F->get()->get_available_packet_count()) {
+ for (const Ref<WebRTCDataChannel> &F : E->get()->channels) {
+ if (F->get_available_packet_count()) {
next_packet_peer = E->key();
return;
}
@@ -165,8 +165,8 @@ void WebRTCMultiplayerPeer::_find_next_peer() {
E = peer_map.front();
// Before last
while (E) {
- for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) {
- if (F->get()->get_available_packet_count()) {
+ for (const Ref<WebRTCDataChannel> &F : E->get()->channels) {
+ if (F->get_available_packet_count()) {
next_packet_peer = E->key();
return;
}
@@ -213,8 +213,8 @@ int WebRTCMultiplayerPeer::get_unique_id() const {
void WebRTCMultiplayerPeer::_peer_to_dict(Ref<ConnectedPeer> p_connected_peer, Dictionary &r_dict) {
Array channels;
- for (List<Ref<WebRTCDataChannel>>::Element *F = p_connected_peer->channels.front(); F; F = F->next()) {
- channels.push_back(F->get());
+ for (Ref<WebRTCDataChannel> &F : p_connected_peer->channels) {
+ channels.push_back(F);
}
r_dict["connection"] = p_connected_peer->connection;
r_dict["connected"] = p_connected_peer->connected;
@@ -297,9 +297,9 @@ Error WebRTCMultiplayerPeer::get_packet(const uint8_t **r_buffer, int &r_buffer_
_find_next_peer();
ERR_FAIL_V(ERR_UNAVAILABLE);
}
- for (List<Ref<WebRTCDataChannel>>::Element *E = peer_map[next_packet_peer]->channels.front(); E; E = E->next()) {
- if (E->get()->get_available_packet_count()) {
- Error err = E->get()->get_packet(r_buffer, r_buffer_size);
+ for (Ref<WebRTCDataChannel> &E : peer_map[next_packet_peer]->channels) {
+ if (E->get_available_packet_count()) {
+ Error err = E->get_packet(r_buffer, r_buffer_size);
_find_next_peer();
return err;
}
@@ -357,8 +357,8 @@ int WebRTCMultiplayerPeer::get_available_packet_count() const {
}
int size = 0;
for (Map<int, Ref<ConnectedPeer>>::Element *E = peer_map.front(); E; E = E->next()) {
- for (List<Ref<WebRTCDataChannel>>::Element *F = E->get()->channels.front(); F; F = F->next()) {
- size += F->get()->get_available_packet_count();
+ for (const Ref<WebRTCDataChannel> &F : E->get()->channels) {
+ size += F->get_available_packet_count();
}
}
return size;
diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp
index 744053b6e2..d3d0066c12 100644
--- a/modules/websocket/emws_client.cpp
+++ b/modules/websocket/emws_client.cpp
@@ -79,7 +79,7 @@ Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
String str = "ws://";
if (p_custom_headers.size()) {
- WARN_PRINT_ONCE("Custom headers are not supported in in HTML5 platform.");
+ WARN_PRINT_ONCE("Custom headers are not supported in HTML5 platform.");
}
if (p_ssl) {
str = "wss://";
diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp
index ddd8e190df..589bb8931a 100644
--- a/modules/websocket/websocket_multiplayer_peer.cpp
+++ b/modules/websocket/websocket_multiplayer_peer.cpp
@@ -65,9 +65,9 @@ void WebSocketMultiplayerPeer::_clear() {
memfree(_current_packet.data);
}
- for (List<Packet>::Element *E = _incoming_packets.front(); E; E = E->next()) {
- memfree(E->get().data);
- E->get().data = nullptr;
+ for (Packet &E : _incoming_packets) {
+ memfree(E.data);
+ E.data = nullptr;
}
_incoming_packets.clear();
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index 5f794415af..c6eb3d44b4 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -190,15 +190,15 @@ void WSLServer::poll() {
remove_ids.push_back(E->key());
}
}
- for (List<int>::Element *E = remove_ids.front(); E; E = E->next()) {
- _peer_map.erase(E->get());
+ for (int &E : remove_ids) {
+ _peer_map.erase(E);
}
remove_ids.clear();
List<Ref<PendingPeer>> remove_peers;
- for (List<Ref<PendingPeer>>::Element *E = _pending.front(); E; E = E->next()) {
+ for (const Ref<PendingPeer> &E : _pending) {
String resource_name;
- Ref<PendingPeer> ppeer = E->get();
+ Ref<PendingPeer> ppeer = E;
Error err = ppeer->do_handshake(_protocols, handshake_timeout, resource_name);
if (err == ERR_BUSY) {
continue;
@@ -224,8 +224,8 @@ void WSLServer::poll() {
remove_peers.push_back(ppeer);
_on_connect(id, ppeer->protocol, resource_name);
}
- for (List<Ref<PendingPeer>>::Element *E = remove_peers.front(); E; E = E->next()) {
- _pending.erase(E->get());
+ for (const Ref<PendingPeer> &E : remove_peers) {
+ _pending.erase(E);
}
remove_peers.clear();
diff --git a/modules/webxr/doc_classes/WebXRInterface.xml b/modules/webxr/doc_classes/WebXRInterface.xml
index 9b3a063ef5..67b2b866f3 100644
--- a/modules/webxr/doc_classes/WebXRInterface.xml
+++ b/modules/webxr/doc_classes/WebXRInterface.xml
@@ -88,7 +88,7 @@
- Using [XRController3D] nodes and their [signal XRController3D.button_pressed] and [signal XRController3D.button_released] signals. This is how controllers are typically handled in AR/VR apps in Godot, however, this will only work with advanced VR controllers like the Oculus Touch or Index controllers, for example. The buttons codes are defined by [url=https://immersive-web.github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping]Section 3.3 of the WebXR Gamepads Module[/url].
- Using [method Node._unhandled_input] and [InputEventJoypadButton] or [InputEventJoypadMotion]. This works the same as normal joypads, except the [member InputEvent.device] starts at 100, so the left controller is 100 and the right controller is 101, and the button codes are also defined by [url=https://immersive-web.github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping]Section 3.3 of the WebXR Gamepads Module[/url].
- Using the [signal select], [signal squeeze] and related signals. This method will work for both advanced VR controllers, and non-traditional "controllers" like a tap on the screen, a spoken voice command or a button press on the device itself. The [code]controller_id[/code] passed to these signals is the same id as used in [member XRController3D.controller_id].
- You can use one or all of these methods to allow your game or app to support a wider or narrower set of devices and input methods, or to allow more advanced interations with more advanced devices.
+ You can use one or all of these methods to allow your game or app to support a wider or narrower set of devices and input methods, or to allow more advanced interactions with more advanced devices.
</description>
<tutorials>
<link title="How to make a VR game for WebXR with Godot">https://www.snopekgames.com/blog/2020/how-make-vr-game-webxr-godot</link>
diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp
index 6957dea8c4..099e769303 100644
--- a/modules/webxr/webxr_interface_js.cpp
+++ b/modules/webxr/webxr_interface_js.cpp
@@ -35,6 +35,7 @@
#include "core/os/os.h"
#include "emscripten.h"
#include "godot_webxr.h"
+#include "servers/rendering/renderer_compositor.h"
#include <stdlib.h>
void _emwebxr_on_session_supported(char *p_session_mode, int p_supported) {
@@ -102,7 +103,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE void _emwebxr_on_input_event(char *p_signal_name
ERR_FAIL_COND(interface.is_null());
StringName signal_name = StringName(p_signal_name);
- interface->emit_signal(SNAME(signal_name), p_input_source + 1);
+ interface->emit_signal(signal_name, p_input_source + 1);
}
extern "C" EMSCRIPTEN_KEEPALIVE void _emwebxr_on_simple_event(char *p_signal_name) {
@@ -113,7 +114,7 @@ extern "C" EMSCRIPTEN_KEEPALIVE void _emwebxr_on_simple_event(char *p_signal_nam
ERR_FAIL_COND(interface.is_null());
StringName signal_name = StringName(p_signal_name);
- interface->emit_signal(SNAME(signal_name));
+ interface->emit_signal(signal_name);
}
void WebXRInterfaceJS::is_session_supported(const String &p_session_mode) {
@@ -376,6 +377,22 @@ void WebXRInterfaceJS::commit_for_eye(XRInterface::Eyes p_eye, RID p_render_targ
return;
}
godot_webxr_commit_for_eye(p_eye);
+}
+
+Vector<BlitToScreen> WebXRInterfaceJS::commit_views(RID p_render_target, const Rect2 &p_screen_rect) {
+ Vector<BlitToScreen> blit_to_screen;
+
+ if (!initialized) {
+ return blit_to_screen;
+ }
+
+ // @todo Refactor this to be based on "views" rather than "eyes".
+ godot_webxr_commit_for_eye(XRInterface::EYE_LEFT);
+ if (godot_webxr_get_view_count() > 1) {
+ godot_webxr_commit_for_eye(XRInterface::EYE_RIGHT);
+ }
+
+ return blit_to_screen;
};
void WebXRInterfaceJS::process() {
diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h
index 3b5509adeb..f9368582b7 100644
--- a/modules/webxr/webxr_interface_js.h
+++ b/modules/webxr/webxr_interface_js.h
@@ -89,6 +89,7 @@ public:
virtual CameraMatrix get_projection_for_view(uint32_t p_view, real_t p_aspect, real_t p_z_near, real_t p_z_far) override;
virtual unsigned int get_external_texture_for_eye(XRInterface::Eyes p_eye) override;
virtual void commit_for_eye(XRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) override;
+ virtual Vector<BlitToScreen> commit_views(RID p_render_target, const Rect2 &p_screen_rect) override;
virtual void process() override;
virtual void notification(int p_what) override;
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 1fcc3d4a5c..af8829324b 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -334,13 +334,6 @@ bool DisplayServerAndroid::can_any_window_draw() const {
return true;
}
-void DisplayServerAndroid::alert(const String &p_alert, const String &p_title) {
- GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
- ERR_FAIL_COND(!godot_java);
-
- godot_java->alert(p_alert, p_title);
-}
-
void DisplayServerAndroid::process_events() {
Input::get_singleton()->flush_accumulated_events();
}
@@ -361,7 +354,7 @@ Vector<String> DisplayServerAndroid::get_rendering_drivers_func() {
DisplayServer *DisplayServerAndroid::create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerAndroid(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
- ds->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver");
+ OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan versions.", "Unable to initialize Video driver");
}
return ds;
}
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index 46745f8030..9b9f5e99f6 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -204,8 +204,6 @@ public:
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
- virtual void alert(const String &p_alert, const String &p_title) override;
-
virtual void process_events() override;
void process_accelerometer(const Vector3 &p_accelerometer);
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 956b59ce80..e5d1c2020a 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -2068,6 +2068,8 @@ public:
if (!installed_android_build_template) {
r_missing_templates = !exists_export_template("android_source.zip", &err);
err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n";
+ } else {
+ r_missing_templates = false;
}
valid = installed_android_build_template && !r_missing_templates;
diff --git a/platform/android/java/app/gradle.properties b/platform/android/java/app/gradle.properties
new file mode 100644
index 0000000000..19587bd81f
--- /dev/null
+++ b/platform/android/java/app/gradle.properties
@@ -0,0 +1,25 @@
+# Godot custom build Gradle settings.
+# These properties apply when running custom build from the Godot editor.
+# NOTE: This should be kept in sync with 'godot/platform/android/java/gradle.properties' except
+# where otherwise specified.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+android.enableJetifier=true
+android.useAndroidX=true
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx4536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+org.gradle.warning.mode=all
+
+# Enable resource optimizations for release build.
+# NOTE: This is turned off for template release build in order to support the build legacy process.
+android.enableResourceOptimizations=true
diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle
index ee24a46d9f..87bb2ea218 100644
--- a/platform/android/java/build.gradle
+++ b/platform/android/java/build.gradle
@@ -115,7 +115,7 @@ task zipCustomBuild(type: Zip) {
doFirst {
logger.lifecycle("Generating Godot custom build template")
}
- from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradle.properties', 'gradlew', 'gradlew.bat', 'gradle/**']))
+ from(fileTree(dir: 'app', excludes: ['**/build/**', '**/.gradle/**', '**/*.iml']), fileTree(dir: '.', includes: ['gradlew', 'gradlew.bat', 'gradle/**']))
include '**/*'
archiveFileName = 'android_source.zip'
destinationDirectory = file(binDir)
diff --git a/platform/android/java/gradle.properties b/platform/android/java/gradle.properties
index 6b3b62a9da..b51a19a005 100644
--- a/platform/android/java/gradle.properties
+++ b/platform/android/java/gradle.properties
@@ -1,4 +1,6 @@
# Project-wide Gradle settings.
+# NOTE: This should be kept in sync with 'godot/platform/android/java/app/gradle.properties' except
+# where otherwise specified.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
@@ -20,3 +22,7 @@ org.gradle.jvmargs=-Xmx4536m
# org.gradle.parallel=true
org.gradle.warning.mode=all
+
+# Disable resource optimizations for template release build.
+# NOTE: This is turned on for custom build in order to improve the release build.
+android.enableResourceOptimizations=false
diff --git a/platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java b/platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java
index 008c150a8e..05b452d0c1 100644
--- a/platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java
+++ b/platform/android/java/lib/src/com/google/android/vending/licensing/Obfuscator.java
@@ -20,7 +20,7 @@ package com.google.android.vending.licensing;
* Interface used as part of a {@link Policy} to allow application authors to obfuscate
* licensing data that will be stored into a SharedPreferences file.
* <p>
- * Any transformation scheme must be reversable. Implementing classes may optionally implement an
+ * Any transformation scheme must be reversible. Implementing classes may optionally implement an
* integrity check to further prevent modification to preference data. Implementing classes
* should use device-specific information as a key in the obfuscation algorithm to prevent
* obfuscated preferences from being shared among devices.
diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp
index ed6b5c3e14..49891cd739 100644
--- a/platform/android/java_class_wrapper.cpp
+++ b/platform/android/java_class_wrapper.cpp
@@ -41,13 +41,13 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
ERR_FAIL_COND_V(env == nullptr, false);
MethodInfo *method = nullptr;
- for (List<MethodInfo>::Element *E = M->get().front(); E; E = E->next()) {
- if (!p_instance && !E->get()._static) {
+ for (MethodInfo &E : M->get()) {
+ if (!p_instance && !E._static) {
r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
continue;
}
- int pc = E->get().param_types.size();
+ int pc = E.param_types.size();
if (pc > p_argcount) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_error.argument = pc;
@@ -58,7 +58,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
r_error.argument = pc;
continue;
}
- uint32_t *ptypes = E->get().param_types.ptrw();
+ uint32_t *ptypes = E.param_types.ptrw();
bool valid = true;
for (int i = 0; i < pc; i++) {
@@ -107,7 +107,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
if (Object::cast_to<JavaObject>(ref.ptr())) {
Ref<JavaObject> jo = ref;
//could be faster
- jclass c = env->FindClass(E->get().param_sigs[i].operator String().utf8().get_data());
+ jclass c = env->FindClass(E.param_sigs[i].operator String().utf8().get_data());
if (!c || !env->IsInstanceOf(jo->instance, c)) {
arg_expected = Variant::OBJECT;
} else {
@@ -138,7 +138,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
if (!valid)
continue;
- method = &E->get();
+ method = &E;
break;
}
@@ -474,8 +474,8 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
} break;
}
- for (List<jobject>::Element *E = to_free.front(); E; E = E->next()) {
- env->DeleteLocalRef(E->get());
+ for (jobject &E : to_free) {
+ env->DeleteLocalRef(E);
}
return success;
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 222976d948..792a390e36 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -71,6 +71,13 @@ public:
virtual ~AndroidLogger() {}
};
+void OS_Android::alert(const String &p_alert, const String &p_title) {
+ GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
+ ERR_FAIL_COND(!godot_java);
+
+ godot_java->alert(p_alert, p_title);
+}
+
void OS_Android::initialize_core() {
OS_Unix::initialize_core();
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 1e89e9211d..38f0f3edc7 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -86,6 +86,8 @@ public:
virtual bool request_permissions() override;
virtual Vector<String> get_granted_permissions() const override;
+ virtual void alert(const String &p_alert, const String &p_title) override;
+
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
virtual String get_name() const override;
diff --git a/platform/iphone/display_server_iphone.h b/platform/iphone/display_server_iphone.h
index 6f64130b23..8ba7a69a4f 100644
--- a/platform/iphone/display_server_iphone.h
+++ b/platform/iphone/display_server_iphone.h
@@ -119,8 +119,6 @@ public:
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
-
virtual int get_screen_count() const override;
virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm
index bd95e2c703..b4f0a32027 100644
--- a/platform/iphone/display_server_iphone.mm
+++ b/platform/iphone/display_server_iphone.mm
@@ -320,12 +320,6 @@ String DisplayServerIPhone::get_name() const {
return "iPhone";
}
-void DisplayServerIPhone::alert(const String &p_alert, const String &p_title) {
- const CharString utf8_alert = p_alert.utf8();
- const CharString utf8_title = p_title.utf8();
- iOS::alert(utf8_alert.get_data(), utf8_title.get_data());
-}
-
int DisplayServerIPhone::get_screen_count() const {
return 1;
}
diff --git a/platform/iphone/godot_view_gesture_recognizer.h b/platform/iphone/godot_view_gesture_recognizer.h
index 48b2d5ffad..61438ef22f 100644
--- a/platform/iphone/godot_view_gesture_recognizer.h
+++ b/platform/iphone/godot_view_gesture_recognizer.h
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// GLViewGestureRecognizer allows iOS gestures to work currectly by
+// GLViewGestureRecognizer allows iOS gestures to work correctly by
// emulating UIScrollView's UIScrollViewDelayedTouchesBeganGestureRecognizer.
// It catches all gestures incoming to UIView and delays them for 150ms
// (the same value used by UIScrollViewDelayedTouchesBeganGestureRecognizer)
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index f4ff909adf..8abc3b7ed5 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -92,13 +92,12 @@ public:
void start();
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
virtual Error close_dynamic_library(void *p_library_handle) override;
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
- virtual void alert(const String &p_alert,
- const String &p_title = "ALERT!") override;
-
virtual String get_name() const override;
virtual String get_model_name() const override;
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index 1f08901082..b69996ccf0 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -114,6 +114,12 @@ OSIPhone::OSIPhone(String p_data_dir) {
OSIPhone::~OSIPhone() {}
+void OSIPhone::alert(const String &p_alert, const String &p_title) {
+ const CharString utf8_alert = p_alert.utf8();
+ const CharString utf8_title = p_title.utf8();
+ iOS::alert(utf8_alert.get_data(), utf8_title.get_data());
+}
+
void OSIPhone::initialize_core() {
OS_Unix::initialize_core();
@@ -221,12 +227,6 @@ Error OSIPhone::get_dynamic_library_symbol_handle(void *p_library_handle, const
return OS_Unix::get_dynamic_library_symbol_handle(p_library_handle, p_name, p_symbol_handle, p_optional);
}
-void OSIPhone::alert(const String &p_alert, const String &p_title) {
- const CharString utf8_alert = p_alert.utf8();
- const CharString utf8_title = p_title.utf8();
- iOS::alert(utf8_alert.get_data(), utf8_title.get_data());
-}
-
String OSIPhone::get_name() const {
return "iOS";
};
diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp
index 5e2b089c7f..8df81bb8cc 100644
--- a/platform/javascript/display_server_javascript.cpp
+++ b/platform/javascript/display_server_javascript.cpp
@@ -659,10 +659,6 @@ void DisplayServerJavaScript::send_window_event_callback(int p_notification) {
}
}
-void DisplayServerJavaScript::alert(const String &p_alert, const String &p_title) {
- godot_js_display_alert(p_alert.utf8().get_data());
-}
-
void DisplayServerJavaScript::set_icon(const Ref<Image> &p_icon) {
ERR_FAIL_COND(p_icon.is_null());
Ref<Image> icon = p_icon;
diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h
index f8acf30854..bf5e229c9a 100644
--- a/platform/javascript/display_server_javascript.h
+++ b/platform/javascript/display_server_javascript.h
@@ -109,7 +109,6 @@ public:
bool check_size_force_redraw();
// from DisplayServer
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
diff --git a/platform/javascript/js/libs/audio.worklet.js b/platform/javascript/js/libs/audio.worklet.js
index 6b3f80c6a9..866f845139 100644
--- a/platform/javascript/js/libs/audio.worklet.js
+++ b/platform/javascript/js/libs/audio.worklet.js
@@ -115,7 +115,7 @@ class GodotProcessor extends AudioWorkletProcessor {
this.input = new RingBuffer(p_data[1], avail_in);
this.output = new RingBuffer(p_data[2], avail_out);
} else if (p_cmd === 'stop') {
- this.runing = false;
+ this.running = false;
this.output = null;
this.input = null;
}
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 260bfad7a5..76102d941b 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -47,6 +47,10 @@
#include "godot_js.h"
+void OS_JavaScript::alert(const String &p_alert, const String &p_title) {
+ godot_js_display_alert(p_alert.utf8().get_data());
+}
+
// Lifecycle
void OS_JavaScript::initialize() {
OS_Unix::initialize_core();
@@ -111,8 +115,8 @@ Error OS_JavaScript::execute(const String &p_path, const List<String> &p_argumen
Error OS_JavaScript::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
Array args;
- for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- args.push_back(E->get());
+ for (const String &E : p_arguments) {
+ args.push_back(E);
}
String json_args = Variant(args).to_json_string();
int failed = godot_js_os_execute(json_args.utf8().get_data());
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 81bb9c5f3d..efac2dbca7 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -89,6 +89,9 @@ public:
String get_user_data_dir() const override;
bool is_userfs_persistent() const override;
+
+ void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+
Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) override;
void resume_audio();
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 8f0742041c..4a32dd9646 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -136,70 +136,6 @@ String DisplayServerX11::get_name() const {
return "X11";
}
-void DisplayServerX11::alert(const String &p_alert, const String &p_title) {
- const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
-
- String path = OS::get_singleton()->get_environment("PATH");
- Vector<String> path_elems = path.split(":", false);
- String program;
-
- for (int i = 0; i < path_elems.size(); i++) {
- for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
- String tested_path = path_elems[i].plus_file(message_programs[k]);
-
- if (FileAccess::exists(tested_path)) {
- program = tested_path;
- break;
- }
- }
-
- if (program.length()) {
- break;
- }
- }
-
- List<String> args;
-
- if (program.ends_with("zenity")) {
- args.push_back("--error");
- args.push_back("--width");
- args.push_back("500");
- args.push_back("--title");
- args.push_back(p_title);
- args.push_back("--text");
- args.push_back(p_alert);
- }
-
- if (program.ends_with("kdialog")) {
- args.push_back("--error");
- args.push_back(p_alert);
- args.push_back("--title");
- args.push_back(p_title);
- }
-
- if (program.ends_with("Xdialog")) {
- args.push_back("--title");
- args.push_back(p_title);
- args.push_back("--msgbox");
- args.push_back(p_alert);
- args.push_back("0");
- args.push_back("0");
- }
-
- if (program.ends_with("xmessage")) {
- args.push_back("-center");
- args.push_back("-title");
- args.push_back(p_title);
- args.push_back(p_alert);
- }
-
- if (program.length()) {
- OS::get_singleton()->execute(program, args);
- } else {
- print_line(p_alert);
- }
-}
-
void DisplayServerX11::_update_real_mouse_position(const WindowData &wd) {
Window root_return, child_return;
int root_x, root_y, win_x, win_y;
@@ -871,7 +807,9 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, V
void DisplayServerX11::show_window(WindowID p_id) {
_THREAD_SAFE_METHOD_
- WindowData &wd = windows[p_id];
+ const WindowData &wd = windows[p_id];
+
+ DEBUG_LOG_X11("show_window: %lu (%u) \n", wd.x11_window, p_id);
XMapWindow(x11_display, wd.x11_window);
}
@@ -1095,6 +1033,8 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
WindowID prev_parent = wd_window.transient_parent;
ERR_FAIL_COND(prev_parent == p_parent);
+ DEBUG_LOG_X11("window_set_transient: %lu (%u), prev_parent=%u, parent=%u\n", wd_window.x11_window, p_window, prev_parent, p_parent);
+
ERR_FAIL_COND_MSG(wd_window.on_top, "Windows with the 'on top' can't become transient.");
if (p_parent == INVALID_WINDOW_ID) {
//remove transient
@@ -1109,10 +1049,10 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
XSetTransientForHint(x11_display, wd_window.x11_window, None);
- // Set focus to parent sub window to avoid losing all focus with nested menus.
+ // Set focus to parent sub window to avoid losing all focus when closing a nested sub-menu.
// RevertToPointerRoot is used to make sure we don't lose all focus in case
// a subwindow and its parent are both destroyed.
- if (wd_window.menu_type && !wd_window.no_focus) {
+ if (wd_window.menu_type && !wd_window.no_focus && wd_window.focused) {
if (!wd_parent.no_focus) {
XSetInputFocus(x11_display, wd_parent.x11_window, RevertToPointerRoot, CurrentTime);
}
@@ -2227,7 +2167,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
// still works in half the cases. (won't handle deadkeys)
// For more complex input methods (deadkeys and more advanced)
// you have to use XmbLookupString (??).
- // So.. then you have to chosse which of both results
+ // So then you have to choose which of both results
// you want to keep.
// This is a real bizarreness and cpu waster.
@@ -3673,8 +3613,8 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
DisplayServer *DisplayServerX11::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerX11(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
- ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
+ OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
+ "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
"Unable to initialize Video driver");
}
return ds;
@@ -3972,8 +3912,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
if (!_refresh_device_info()) {
- alert("Your system does not support XInput 2.\n"
- "Please upgrade your distribution.",
+ OS::get_singleton()->alert("Your system does not support XInput 2.\n"
+ "Please upgrade your distribution.",
"Unable to initialize XInput");
r_error = ERR_UNAVAILABLE;
return;
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 29c15ca2ba..052c6d6b7b 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -280,8 +280,6 @@ public:
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
-
virtual void mouse_set_mode(MouseMode p_mode) override;
virtual MouseMode mouse_get_mode() const override;
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 8cd6ec43c6..08630be8b0 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -51,6 +51,70 @@
#include <sys/types.h>
#include <unistd.h>
+void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
+ const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
+
+ String path = get_environment("PATH");
+ Vector<String> path_elems = path.split(":", false);
+ String program;
+
+ for (int i = 0; i < path_elems.size(); i++) {
+ for (uint64_t k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
+ String tested_path = path_elems[i].plus_file(message_programs[k]);
+
+ if (FileAccess::exists(tested_path)) {
+ program = tested_path;
+ break;
+ }
+ }
+
+ if (program.length()) {
+ break;
+ }
+ }
+
+ List<String> args;
+
+ if (program.ends_with("zenity")) {
+ args.push_back("--error");
+ args.push_back("--width");
+ args.push_back("500");
+ args.push_back("--title");
+ args.push_back(p_title);
+ args.push_back("--text");
+ args.push_back(p_alert);
+ }
+
+ if (program.ends_with("kdialog")) {
+ args.push_back("--error");
+ args.push_back(p_alert);
+ args.push_back("--title");
+ args.push_back(p_title);
+ }
+
+ if (program.ends_with("Xdialog")) {
+ args.push_back("--title");
+ args.push_back(p_title);
+ args.push_back("--msgbox");
+ args.push_back(p_alert);
+ args.push_back("0");
+ args.push_back("0");
+ }
+
+ if (program.ends_with("xmessage")) {
+ args.push_back("-center");
+ args.push_back("-title");
+ args.push_back(p_title);
+ args.push_back(p_alert);
+ }
+
+ if (program.length()) {
+ execute(program, args);
+ } else {
+ print_line(p_alert);
+ }
+}
+
void OS_LinuxBSD::initialize() {
crash_handler.initialize();
@@ -387,7 +451,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = dir_access->make_dir_recursive(trash_path);
- // Issue an error if trash can is not created proprely.
+ // 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");
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index b6cf93c551..1e06587322 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -90,6 +90,8 @@ public:
virtual String get_unique_id() const override;
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+
virtual bool _check_internal_feature_support(const String &p_feature) override;
void run();
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 317e79d0ea..2393f2ea10 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -24,6 +24,7 @@ def get_opts():
return [
("osxcross_sdk", "OSXCross SDK version", "darwin16"),
("MACOS_SDK_PATH", "Path to the macOS SDK", ""),
+ ("VULKAN_SDK_PATH", "Path to the Vulkan SDK", ""),
BoolVariable(
"use_static_mvk",
"Link MoltenVK statically as Level-0 driver (better portability) or use Vulkan ICD loader (enables"
@@ -190,7 +191,7 @@ def configure(env):
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
env.Append(LINKFLAGS=["-framework", "Metal", "-framework", "QuartzCore", "-framework", "IOSurface"])
if env["use_static_mvk"]:
- env.Append(LINKFLAGS=["-framework", "MoltenVK"])
+ env.Append(LINKFLAGS=["-L$VULKAN_SDK_PATH/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/", "-lMoltenVK"])
env["builtin_vulkan"] = False
elif not env["builtin_vulkan"]:
env.Append(LIBS=["vulkan"])
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index c7b9e411b8..6b1b777224 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -60,6 +60,10 @@ class DisplayServerOSX : public DisplayServer {
_THREAD_SAFE_CLASS_
public:
+ void _send_event(NSEvent *p_event);
+ NSMenu *_get_dock_menu() const;
+ void _menu_callback(id p_sender);
+
#if defined(OPENGL_ENABLED)
ContextGL_OSX *context_gles2;
#endif
@@ -163,7 +167,6 @@ public:
String rendering_driver;
- id delegate;
id autoreleasePool;
CGEventSourceRef eventSource;
@@ -207,7 +210,6 @@ public:
virtual void global_menu_remove_item(const String &p_menu_root, int p_idx) override;
virtual void global_menu_clear(const String &p_menu_root) override;
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override;
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index dec6da42fe..73aa013701 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -105,46 +105,6 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
/*************************************************************************/
-/* GodotApplication */
-/*************************************************************************/
-
-@interface GodotApplication : NSApplication
-@end
-
-@implementation GodotApplication
-
-- (void)sendEvent:(NSEvent *)event {
- // special case handling of command-period, which is traditionally a special
- // shortcut in macOS and doesn't arrive at our regular keyDown handler.
- if ([event type] == NSEventTypeKeyDown) {
- if (([event modifierFlags] & NSEventModifierFlagCommand) && [event keyCode] == 0x2f) {
- Ref<InputEventKey> k;
- k.instantiate();
-
- _get_key_modifier_state([event modifierFlags], k);
- k->set_window_id(DisplayServerOSX::INVALID_WINDOW_ID);
- k->set_pressed(true);
- k->set_keycode(KEY_PERIOD);
- k->set_physical_keycode(KEY_PERIOD);
- k->set_echo([event isARepeat]);
-
- Input::get_singleton()->accumulate_input_event(k);
- }
- }
-
- // From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
- // This works around an AppKit bug, where key up events while holding
- // down the command key don't get sent to the key window.
- if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand)) {
- [[self keyWindow] sendEvent:event];
- } else {
- [super sendEvent:event];
- }
-}
-
-@end
-
-/*************************************************************************/
/* GlobalMenuItem */
/*************************************************************************/
@@ -161,121 +121,6 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
@end
/*************************************************************************/
-/* GodotApplicationDelegate */
-/*************************************************************************/
-
-@interface GodotApplicationDelegate : NSObject
-- (void)forceUnbundledWindowActivationHackStep1;
-- (void)forceUnbundledWindowActivationHackStep2;
-- (void)forceUnbundledWindowActivationHackStep3;
-@end
-
-@implementation GodotApplicationDelegate
-
-- (void)forceUnbundledWindowActivationHackStep1 {
- // Step1: Switch focus to macOS Dock.
- // Required to perform step 2, TransformProcessType will fail if app is already the in focus.
- for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
- [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
- break;
- }
- [self performSelector:@selector(forceUnbundledWindowActivationHackStep2) withObject:nil afterDelay:0.02];
-}
-
-- (void)forceUnbundledWindowActivationHackStep2 {
- // Step 2: Register app as foreground process.
- ProcessSerialNumber psn = { 0, kCurrentProcess };
- (void)TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- [self performSelector:@selector(forceUnbundledWindowActivationHackStep3) withObject:nil afterDelay:0.02];
-}
-
-- (void)forceUnbundledWindowActivationHackStep3 {
- // Step 3: Switch focus back to app window.
- [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
-}
-
-- (void)applicationDidFinishLaunching:(NSNotification *)notice {
- NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
- if (nsappname == nil) {
- // If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
- [self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
- }
-}
-
-- (void)applicationDidResignActive:(NSNotification *)notification {
- if (OS_OSX::get_singleton()->get_main_loop()) {
- OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
- }
-}
-
-- (void)applicationDidBecomeActive:(NSNotification *)notification {
- if (OS_OSX::get_singleton()->get_main_loop()) {
- OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
- }
-}
-
-- (void)globalMenuCallback:(id)sender {
- if (![sender representedObject]) {
- return;
- }
-
- GlobalMenuItem *value = [sender representedObject];
-
- if (value) {
- if (value->checkable) {
- if ([sender state] == NSControlStateValueOff) {
- [sender setState:NSControlStateValueOn];
- } else {
- [sender setState:NSControlStateValueOff];
- }
- }
-
- if (value->callback != Callable()) {
- Variant tag = value->meta;
- Variant *tagp = &tag;
- Variant ret;
- Callable::CallError ce;
- value->callback.call((const Variant **)&tagp, 1, ret, ce);
- }
- }
-}
-
-- (NSMenu *)applicationDockMenu:(NSApplication *)sender {
- return DS_OSX->dock_menu;
-}
-
-- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
- // Note: may be called called before main loop init!
- char *utfs = strdup([filename UTF8String]);
- ((OS_OSX *)(OS_OSX::get_singleton()))->open_with_filename.parse_utf8(utfs);
- free(utfs);
-
-#ifdef TOOLS_ENABLED
- // Open new instance
- if (OS_OSX::get_singleton()->get_main_loop()) {
- List<String> args;
- args.push_back(((OS_OSX *)(OS_OSX::get_singleton()))->open_with_filename);
- String exec = OS::get_singleton()->get_executable_path();
- OS::get_singleton()->create_process(exec, args);
- }
-#endif
- return YES;
-}
-
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
- DS_OSX->_send_window_event(DS_OSX->windows[DisplayServerOSX::MAIN_WINDOW_ID], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
- return NSTerminateCancel;
-}
-
-- (void)showAbout:(id)sender {
- if (OS_OSX::get_singleton()->get_main_loop()) {
- OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT);
- }
-}
-
-@end
-
-/*************************************************************************/
/* GodotWindowDelegate */
/*************************************************************************/
@@ -1983,26 +1828,6 @@ void DisplayServerOSX::global_menu_clear(const String &p_menu_root) {
}
}
-void DisplayServerOSX::alert(const String &p_alert, const String &p_title) {
- _THREAD_SAFE_METHOD_
-
- NSAlert *window = [[NSAlert alloc] init];
- NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];
- NSString *ns_alert = [NSString stringWithUTF8String:p_alert.utf8().get_data()];
-
- [window addButtonWithTitle:@"OK"];
- [window setMessageText:ns_title];
- [window setInformativeText:ns_alert];
- [window setAlertStyle:NSAlertStyleWarning];
-
- id key_window = [[NSApplication sharedApplication] keyWindow];
- [window runModal];
- [window release];
- if (key_window) {
- [key_window makeKeyAndOrderFront:nil];
- }
-}
-
Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
_THREAD_SAFE_METHOD_
@@ -3375,6 +3200,56 @@ void DisplayServerOSX::_release_pressed_events() {
}
}
+NSMenu *DisplayServerOSX::_get_dock_menu() const {
+ return dock_menu;
+}
+
+void DisplayServerOSX::_menu_callback(id p_sender) {
+ if (![p_sender representedObject]) {
+ return;
+ }
+
+ GlobalMenuItem *value = [p_sender representedObject];
+
+ if (value) {
+ if (value->checkable) {
+ if ([p_sender state] == NSControlStateValueOff) {
+ [p_sender setState:NSControlStateValueOn];
+ } else {
+ [p_sender setState:NSControlStateValueOff];
+ }
+ }
+
+ if (value->callback != Callable()) {
+ Variant tag = value->meta;
+ Variant *tagp = &tag;
+ Variant ret;
+ Callable::CallError ce;
+ value->callback.call((const Variant **)&tagp, 1, ret, ce);
+ }
+ }
+}
+
+void DisplayServerOSX::_send_event(NSEvent *p_event) {
+ // special case handling of command-period, which is traditionally a special
+ // shortcut in macOS and doesn't arrive at our regular keyDown handler.
+ if ([p_event type] == NSEventTypeKeyDown) {
+ if (([p_event modifierFlags] & NSEventModifierFlagCommand) && [p_event keyCode] == 0x2f) {
+ Ref<InputEventKey> k;
+ k.instantiate();
+
+ _get_key_modifier_state([p_event modifierFlags], k);
+ k->set_window_id(DisplayServerOSX::INVALID_WINDOW_ID);
+ k->set_pressed(true);
+ k->set_keycode(KEY_PERIOD);
+ k->set_physical_keycode(KEY_PERIOD);
+ k->set_echo([p_event isARepeat]);
+
+ Input::get_singleton()->accumulate_input_event(k);
+ }
+ }
+}
+
void DisplayServerOSX::_process_key_events() {
Ref<InputEventKey> k;
for (int i = 0; i < key_event_pos; i++) {
@@ -3615,7 +3490,7 @@ ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) co
DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
- ds->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver");
+ OS::get_singleton()->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver");
}
return ds;
}
@@ -3785,12 +3660,6 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
CGEventSourceSetLocalEventsSuppressionInterval(eventSource, 0.0);
- // Implicitly create shared NSApplication instance
- [GodotApplication sharedApplication];
-
- // In case we are unbundled, make us a proper UI application
- [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
-
keyboard_layout_dirty = true;
displays_arrangement_dirty = true;
displays_scale_dirty = true;
@@ -3804,9 +3673,6 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
// Register to be notified on displays arrangement changes
CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, nullptr);
- // Menu bar setup must go between sharedApplication above and
- // finishLaunching below, in order to properly emulate the behavior
- // of NSApplicationMain
NSMenuItem *menu_item;
NSString *title;
@@ -3846,32 +3712,10 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname];
[apple_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
- // Setup menu bar
- NSMenu *main_menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+ // Add items to the menu bar
+ NSMenu *main_menu = [NSApp mainMenu];
menu_item = [main_menu addItemWithTitle:@"" action:nil keyEquivalent:@""];
[main_menu setSubmenu:apple_menu forItem:menu_item];
- [NSApp setMainMenu:main_menu];
-
- [NSApp finishLaunching];
-
- delegate = [[GodotApplicationDelegate alloc] init];
- ERR_FAIL_COND(!delegate);
- [NSApp setDelegate:delegate];
-
- //process application:openFile: event
- while (true) {
- NSEvent *event = [NSApp
- nextEventMatchingMask:NSEventMaskAny
- untilDate:[NSDate distantPast]
- inMode:NSDefaultRunLoopMode
- dequeue:YES];
-
- if (event == nil) {
- break;
- }
-
- [NSApp sendEvent:event];
- }
//!!!!!!!!!!!!!!!!!!!!!!!!!!
//TODO - do Vulkan and GLES2 support checks, driver selection and fallback
@@ -3924,8 +3768,6 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
RendererCompositorRD::make_current();
}
#endif
-
- [NSApp activateIgnoringOtherApps:YES];
}
DisplayServerOSX::~DisplayServerOSX() {
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index ea34b8a24e..131c4b821e 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -178,6 +178,7 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/calendars"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/photos_library"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/apple_events"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/debugging"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/enabled"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_server"), false));
@@ -845,6 +846,10 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ent_f->store_line("<key>com.apple.security.automation.apple-events</key>");
ent_f->store_line("<true/>");
}
+ if ((bool)p_preset->get("codesign/entitlements/debugging")) {
+ ent_f->store_line("<key>com.apple.security.get-task-allow</key>");
+ ent_f->store_line("<true/>");
+ }
if ((bool)p_preset->get("codesign/entitlements/app_sandbox/enabled")) {
ent_f->store_line("<key>com.apple.security.app-sandbox</key>");
diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp
index 126ebc1908..d778271350 100644
--- a/platform/osx/joypad_osx.cpp
+++ b/platform/osx/joypad_osx.cpp
@@ -286,8 +286,9 @@ bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
}
if ((!refCF) || (!CFStringGetCString((CFStringRef)refCF, c_name, sizeof(c_name), kCFStringEncodingUTF8))) {
name = "Unidentified Joypad";
+ } else {
+ name = c_name;
}
- name = c_name;
int id = input->get_unused_joy_id();
ERR_FAIL_COND_V(id == -1, false);
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index d57940775d..37d30add78 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -72,6 +72,8 @@ protected:
public:
virtual String get_name() const override;
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
virtual MainLoop *get_main_loop() const override;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index b65d84d900..c458a0264a 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -41,6 +41,137 @@
#include <mach-o/dyld.h>
#include <os/log.h>
+#define DS_OSX ((DisplayServerOSX *)(DisplayServerOSX::get_singleton()))
+
+/*************************************************************************/
+/* GodotApplication */
+/*************************************************************************/
+
+@interface GodotApplication : NSApplication
+@end
+
+@implementation GodotApplication
+
+- (void)sendEvent:(NSEvent *)event {
+ if (DS_OSX) {
+ DS_OSX->_send_event(event);
+ }
+
+ // From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
+ // This works around an AppKit bug, where key up events while holding
+ // down the command key don't get sent to the key window.
+ if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand)) {
+ [[self keyWindow] sendEvent:event];
+ } else {
+ [super sendEvent:event];
+ }
+}
+
+@end
+
+/*************************************************************************/
+/* GodotApplicationDelegate */
+/*************************************************************************/
+
+@interface GodotApplicationDelegate : NSObject
+- (void)forceUnbundledWindowActivationHackStep1;
+- (void)forceUnbundledWindowActivationHackStep2;
+- (void)forceUnbundledWindowActivationHackStep3;
+@end
+
+@implementation GodotApplicationDelegate
+
+- (void)forceUnbundledWindowActivationHackStep1 {
+ // Step1: Switch focus to macOS Dock.
+ // Required to perform step 2, TransformProcessType will fail if app is already the in focus.
+ for (NSRunningApplication *app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
+ [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+ break;
+ }
+ [self performSelector:@selector(forceUnbundledWindowActivationHackStep2)
+ withObject:nil
+ afterDelay:0.02];
+}
+
+- (void)forceUnbundledWindowActivationHackStep2 {
+ // Step 2: Register app as foreground process.
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ (void)TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+ [self performSelector:@selector(forceUnbundledWindowActivationHackStep3) withObject:nil afterDelay:0.02];
+}
+
+- (void)forceUnbundledWindowActivationHackStep3 {
+ // Step 3: Switch focus back to app window.
+ [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notice {
+ NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
+ if (nsappname == nil) {
+ // If executable is not a bundled, macOS WindowServer won't register and activate app window correctly (menu and title bar are grayed out and input ignored).
+ [self performSelector:@selector(forceUnbundledWindowActivationHackStep1) withObject:nil afterDelay:0.02];
+ }
+}
+
+- (void)applicationDidResignActive:(NSNotification *)notification {
+ if (OS::get_singleton()->get_main_loop()) {
+ OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
+ }
+}
+
+- (void)applicationDidBecomeActive:(NSNotification *)notification {
+ if (OS::get_singleton()->get_main_loop()) {
+ OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
+ }
+}
+
+- (void)globalMenuCallback:(id)sender {
+ if (DS_OSX) {
+ return DS_OSX->_menu_callback(sender);
+ }
+}
+
+- (NSMenu *)applicationDockMenu:(NSApplication *)sender {
+ if (DS_OSX) {
+ return DS_OSX->_get_dock_menu();
+ } else {
+ return nullptr;
+ }
+}
+
+- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
+ // Note: may be called called before main loop init!
+ char *utfs = strdup([filename UTF8String]);
+ ((OS_OSX *)OS_OSX::get_singleton())->open_with_filename.parse_utf8(utfs);
+ free(utfs);
+
+#ifdef TOOLS_ENABLED
+ // Open new instance
+ if (OS_OSX::get_singleton()->get_main_loop()) {
+ List<String> args;
+ args.push_back(((OS_OSX *)OS_OSX::get_singleton())->open_with_filename);
+ String exec = OS_OSX::get_singleton()->get_executable_path();
+ OS_OSX::get_singleton()->create_process(exec, args);
+ }
+#endif
+ return YES;
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
+ if (DS_OSX) {
+ DS_OSX->_send_window_event(DS_OSX->windows[DisplayServerOSX::MAIN_WINDOW_ID], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ }
+ return NSTerminateCancel;
+}
+
+- (void)showAbout:(id)sender {
+ if (OS_OSX::get_singleton()->get_main_loop()) {
+ OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT);
+ }
+}
+
+@end
+
/*************************************************************************/
/* OSXTerminalLogger */
/*************************************************************************/
@@ -119,6 +250,24 @@ String OS_OSX::get_unique_id() const {
return serial_number;
}
+void OS_OSX::alert(const String &p_alert, const String &p_title) {
+ NSAlert *window = [[NSAlert alloc] init];
+ NSString *ns_title = [NSString stringWithUTF8String:p_title.utf8().get_data()];
+ NSString *ns_alert = [NSString stringWithUTF8String:p_alert.utf8().get_data()];
+
+ [window addButtonWithTitle:@"OK"];
+ [window setMessageText:ns_title];
+ [window setInformativeText:ns_alert];
+ [window setAlertStyle:NSAlertStyleWarning];
+
+ id key_window = [[NSApplication sharedApplication] keyWindow];
+ [window runModal];
+ [window release];
+ if (key_window) {
+ [key_window makeKeyAndOrderFront:nil];
+ }
+}
+
void OS_OSX::initialize_core() {
OS_Unix::initialize_core();
@@ -220,7 +369,7 @@ String OS_OSX::get_cache_path() const {
if (get_environment("XDG_CACHE_HOME").is_absolute_path()) {
return get_environment("XDG_CACHE_HOME");
} else {
- WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Libary/Caches` or `get_config_path()` per the XDG Base Directory specification.");
+ WARN_PRINT_ONCE("`XDG_CACHE_HOME` is a relative path. Ignoring its value and falling back to `$HOME/Library/Caches` or `get_config_path()` per the XDG Base Directory specification.");
}
}
if (has_environment("HOME")) {
@@ -372,6 +521,41 @@ OS_OSX::OS_OSX() {
#endif
DisplayServerOSX::register_osx_driver();
+
+ // Implicitly create shared NSApplication instance
+ [GodotApplication sharedApplication];
+
+ // In case we are unbundled, make us a proper UI application
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+ // Menu bar setup must go between sharedApplication above and
+ // finishLaunching below, in order to properly emulate the behavior
+ // of NSApplicationMain
+
+ NSMenu *main_menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+ [NSApp setMainMenu:main_menu];
+ [NSApp finishLaunching];
+
+ id delegate = [[GodotApplicationDelegate alloc] init];
+ ERR_FAIL_COND(!delegate);
+ [NSApp setDelegate:delegate];
+
+ //process application:openFile: event
+ while (true) {
+ NSEvent *event = [NSApp
+ nextEventMatchingMask:NSEventMaskAny
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+
+ if (event == nil) {
+ break;
+ }
+
+ [NSApp sendEvent:event];
+ }
+
+ [NSApp activateIgnoringOtherApps:YES];
}
bool OS_OSX::_check_internal_feature_support(const String &p_feature) {
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 7772ba2dbe..a94f38583c 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -171,7 +171,6 @@ def setup_mingw(env):
"""Set up env for use with mingw"""
# Nothing to do here
print("Using MinGW")
- pass
def configure_msvc(env, manual_msvc_config):
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 4f64809abc..e78b23c509 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -79,10 +79,6 @@ String DisplayServerWindows::get_name() const {
return "Windows";
}
-void DisplayServerWindows::alert(const String &p_alert, const String &p_title) {
- MessageBoxW(nullptr, (LPCWSTR)(p_alert.utf16().get_data()), (LPCWSTR)(p_title.utf16().get_data()), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
-}
-
void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) {
if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
// Mouse is grabbed (captured or confined).
@@ -3358,8 +3354,8 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() {
DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
- ds->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
+ OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan versions.\n"
+ "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
"Unable to initialize Video driver");
}
return ds;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index aa1d42d6ed..06014fbabe 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -442,8 +442,6 @@ public:
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
-
virtual void mouse_set_mode(MouseMode p_mode) override;
virtual MouseMode mouse_get_mode() const override;
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 56d673afc3..2c8afaf7de 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -165,6 +165,10 @@ BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) {
}
}
+void OS_Windows::alert(const String &p_alert, const String &p_title) {
+ MessageBoxW(nullptr, (LPCWSTR)(p_alert.utf16().get_data()), (LPCWSTR)(p_title.utf16().get_data()), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
+}
+
void OS_Windows::initialize_debugging() {
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
}
@@ -407,8 +411,8 @@ String OS_Windows::_quote_command_line_argument(const String &p_text) const {
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
String path = p_path.replace("/", "\\");
String command = _quote_command_line_argument(path);
- for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- command += " " + _quote_command_line_argument(E->get());
+ for (const String &E : p_arguments) {
+ command += " " + _quote_command_line_argument(E);
}
if (r_pipe) {
@@ -463,8 +467,8 @@ Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments,
Error OS_Windows::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
String path = p_path.replace("/", "\\");
String command = _quote_command_line_argument(path);
- for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- command += " " + _quote_command_line_argument(E->get());
+ for (const String &E : p_arguments) {
+ command += " " + _quote_command_line_argument(E);
}
ProcessInfo pi;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 8f9ef254f1..ea0c263b78 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -108,6 +108,8 @@ protected:
Map<ProcessID, ProcessInfo> *process_map;
public:
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false) override;
virtual Error close_dynamic_library(void *p_library_handle) override;
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp
index 9ee37670d1..da2ab6ada8 100644
--- a/scene/2d/animated_sprite_2d.cpp
+++ b/scene/2d/animated_sprite_2d.cpp
@@ -123,7 +123,7 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &property) const {
}
property.hint_string += String(E->get());
- if (animation == E->get()) {
+ if (animation == E) {
current_found = true;
}
}
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 5b12da8b57..9b4da2a77a 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -145,8 +145,7 @@ TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
List<RID> exceptions;
PhysicsServer2D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
Array ret;
- for (List<RID>::Element *E = exceptions.front(); E; E = E->next()) {
- RID body = E->get();
+ for (const RID &body : exceptions) {
ObjectID instance_id = PhysicsServer2D::get_singleton()->body_get_object_instance_id(body);
Object *obj = ObjectDB::get_instance(instance_id);
PhysicsBody2D *physics_body = Object::cast_to<PhysicsBody2D>(obj);
@@ -1188,9 +1187,6 @@ void CharacterBody2D::move_and_slide() {
}
void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
- on_floor = false;
- on_ceiling = false;
- on_wall = false;
if (up_direction == Vector2()) {
//all is a wall
on_wall = true;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 6d1e27bf1b..e9efa1cf84 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -58,7 +58,7 @@ void TileMapPattern::remove_cell(const Vector2i &p_coords, bool p_update_size) {
}
int TileMapPattern::get_cell_source_id(const Vector2i &p_coords) const {
- ERR_FAIL_COND_V(!pattern.has(p_coords), -1);
+ ERR_FAIL_COND_V(!pattern.has(p_coords), TileSet::INVALID_SOURCE);
return pattern[p_coords].source_id;
}
@@ -113,7 +113,7 @@ void TileMapPattern::clear() {
};
void TileMapPattern::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
+ ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell);
ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell);
ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id);
@@ -513,15 +513,15 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i
Vector2i atlas_coords = p_atlas_coords;
int alternative_tile = p_alternative_tile;
- if ((source_id == -1 || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) &&
- (source_id != -1 || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) {
+ if ((source_id == TileSet::INVALID_SOURCE || atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE) &&
+ (source_id != TileSet::INVALID_SOURCE || atlas_coords != TileSetSource::INVALID_ATLAS_COORDS || alternative_tile != TileSetSource::INVALID_TILE_ALTERNATIVE)) {
WARN_PRINT("Setting a cell a cell as empty requires both source_id, atlas_coord and alternative_tile to be set to their respective \"invalid\" values. Values were thus changes accordingly.");
- source_id = -1;
+ source_id = TileSet::INVALID_SOURCE;
atlas_coords = TileSetSource::INVALID_ATLAS_COORDS;
alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE;
}
- if (!E && source_id == -1) {
+ if (!E && source_id == TileSet::INVALID_SOURCE) {
return; // Nothing to do, the tile is already empty.
}
@@ -530,7 +530,7 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i
Map<Vector2i, TileMapQuadrant>::Element *Q = quadrant_map.find(qk);
- if (source_id == -1) {
+ if (source_id == TileSet::INVALID_SOURCE) {
// Erase existing cell in the tile map.
tile_map.erase(pk);
@@ -579,18 +579,23 @@ void TileMap::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i
}
}
-int TileMap::get_cell_source_id(const Vector2i &p_coords) const {
+int TileMap::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies) const {
// Get a cell source id from position
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
if (!E) {
- return -1;
+ return TileSet::INVALID_SOURCE;
+ }
+
+ if (p_use_proxies && tile_set.is_valid()) {
+ Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
+ return proxyed[0];
}
return E->get().source_id;
}
-Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords) const {
+Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies) const {
// Get a cell source id from position
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
@@ -598,10 +603,15 @@ Vector2i TileMap::get_cell_atlas_coords(const Vector2i &p_coords) const {
return TileSetSource::INVALID_ATLAS_COORDS;
}
+ if (p_use_proxies && tile_set.is_valid()) {
+ Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
+ return proxyed[1];
+ }
+
return E->get().get_atlas_coords();
}
-int TileMap::get_cell_alternative_tile(const Vector2i &p_coords) const {
+int TileMap::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies) const {
// Get a cell source id from position
const Map<Vector2i, TileMapCell>::Element *E = tile_map.find(p_coords);
@@ -609,6 +619,11 @@ int TileMap::get_cell_alternative_tile(const Vector2i &p_coords) const {
return TileSetSource::INVALID_TILE_ALTERNATIVE;
}
+ if (p_use_proxies && tile_set.is_valid()) {
+ Array proxyed = tile_set->map_tile_proxy(E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile);
+ return proxyed[2];
+ }
+
return E->get().alternative_tile;
}
@@ -697,11 +712,18 @@ void TileMap::set_pattern(Vector2i p_position, const TileMapPattern *p_pattern)
}
}
-TileMapCell TileMap::get_cell(const Vector2i &p_coords) const {
+TileMapCell TileMap::get_cell(const Vector2i &p_coords, bool p_use_proxies) const {
if (!tile_map.has(p_coords)) {
return TileMapCell();
} else {
- return tile_map.find(p_coords)->get();
+ TileMapCell c = tile_map.find(p_coords)->get();
+ if (p_use_proxies && tile_set.is_valid()) {
+ Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile);
+ c.source_id = proxyed[0];
+ c.set_atlas_coords(proxyed[1]);
+ c.alternative_tile = proxyed[2];
+ }
+ return c;
}
}
@@ -720,7 +742,7 @@ void TileMap::fix_invalid_tiles() {
}
}
for (Set<Vector2i>::Element *E = coords.front(); E; E = E->next()) {
- set_cell(E->get(), -1, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ set_cell(E->get(), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
}
@@ -773,6 +795,7 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
const int *r = p_data.ptr();
int offset = (format >= FORMAT_2) ? 3 : 2;
+ ERR_FAIL_COND_MSG(c % offset != 0, "Corrupted tile data.");
clear();
@@ -799,25 +822,28 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
SWAP(local[9], local[10]);
}
#endif
+ // Extracts position in TileMap.
int16_t x = decode_uint16(&local[0]);
int16_t y = decode_uint16(&local[2]);
if (format == FORMAT_3) {
uint16_t source_id = decode_uint16(&local[4]);
uint16_t atlas_coords_x = decode_uint16(&local[6]);
- uint16_t atlas_coords_y = decode_uint32(&local[8]);
+ uint16_t atlas_coords_y = decode_uint16(&local[8]);
uint16_t alternative_tile = decode_uint16(&local[10]);
set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile);
} else {
#ifndef DISABLE_DEPRECATED
- uint32_t v = decode_uint32(&local[4]);
- v &= (1 << 29) - 1;
+ // Previous decated format.
- // We generate an alternative tile number out of the the flags
- // An option should create the alternative in the tileset for compatibility
+ uint32_t v = decode_uint32(&local[4]);
+ // Extract the transform flags that used to be in the tilemap.
bool flip_h = v & (1 << 29);
bool flip_v = v & (1 << 30);
bool transpose = v & (1 << 31);
+ v &= (1 << 29) - 1;
+
+ // Extract autotile/atlas coords.
int16_t coord_x = 0;
int16_t coord_y = 0;
if (format == FORMAT_2) {
@@ -825,13 +851,17 @@ void TileMap::_set_tile_data(const Vector<int> &p_data) {
coord_y = decode_uint16(&local[10]);
}
- int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
-
if (tile_set.is_valid()) {
- v = tile_set->compatibility_get_source_for_tile_id(v);
+ Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose);
+ if (a.size() == 3) {
+ set_cell(Vector2i(x, y), a[0], a[1], a[2]);
+ } else {
+ ERR_PRINT(vformat("No valid tile in Tileset for: tile:%s coords:%s flip_h:%s flip_v:%s transpose:%s", v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose));
+ }
+ } else {
+ int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
+ set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
}
-
- set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
#endif
}
}
@@ -1567,8 +1597,8 @@ void TileMap::set_light_mask(int p_light_mask) {
// Occlusion: set light mask.
CanvasItem::set_light_mask(p_light_mask);
for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
- for (List<RID>::Element *F = E->get().canvas_items.front(); F; F = F->next()) {
- RenderingServer::get_singleton()->canvas_item_set_light_mask(F->get(), get_light_mask());
+ for (const RID &F : E->get().canvas_items) {
+ RenderingServer::get_singleton()->canvas_item_set_light_mask(F, get_light_mask());
}
}
}
@@ -1580,8 +1610,8 @@ void TileMap::set_material(const Ref<Material> &p_material) {
// Update material for the whole tilemap.
for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
TileMapQuadrant &q = E->get();
- for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
- RS::get_singleton()->canvas_item_set_use_parent_material(F->get(), get_use_parent_material() || get_material().is_valid());
+ for (const RID &F : q.canvas_items) {
+ RS::get_singleton()->canvas_item_set_use_parent_material(F, get_use_parent_material() || get_material().is_valid());
}
}
}
@@ -1593,8 +1623,8 @@ void TileMap::set_use_parent_material(bool p_use_parent_material) {
// Update use_parent_material for the whole tilemap.
for (Map<Vector2i, TileMapQuadrant>::Element *E = quadrant_map.front(); E; E = E->next()) {
TileMapQuadrant &q = E->get();
- for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
- RS::get_singleton()->canvas_item_set_use_parent_material(F->get(), get_use_parent_material() || get_material().is_valid());
+ for (const RID &F : q.canvas_items) {
+ RS::get_singleton()->canvas_item_set_use_parent_material(F, get_use_parent_material() || get_material().is_valid());
}
}
}
@@ -1604,8 +1634,8 @@ void TileMap::set_texture_filter(TextureFilter p_texture_filter) {
CanvasItem::set_texture_filter(p_texture_filter);
for (Map<Vector2i, TileMapQuadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
TileMapQuadrant &q = F->get();
- for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
- RenderingServer::get_singleton()->canvas_item_set_default_texture_filter(E->get(), RS::CanvasItemTextureFilter(p_texture_filter));
+ for (const RID &E : q.canvas_items) {
+ RenderingServer::get_singleton()->canvas_item_set_default_texture_filter(E, RS::CanvasItemTextureFilter(p_texture_filter));
_make_quadrant_dirty(F);
}
}
@@ -1616,8 +1646,8 @@ void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
CanvasItem::set_texture_repeat(p_texture_repeat);
for (Map<Vector2i, TileMapQuadrant>::Element *F = quadrant_map.front(); F; F = F->next()) {
TileMapQuadrant &q = F->get();
- for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
- RenderingServer::get_singleton()->canvas_item_set_default_texture_repeat(E->get(), RS::CanvasItemTextureRepeat(p_texture_repeat));
+ for (const RID &E : q.canvas_items) {
+ RenderingServer::get_singleton()->canvas_item_set_default_texture_repeat(E, RS::CanvasItemTextureRepeat(p_texture_repeat));
_make_quadrant_dirty(F);
}
}
@@ -1727,10 +1757,10 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_visibility_mode", "show_navigation"), &TileMap::set_navigation_visibility_mode);
ClassDB::bind_method(D_METHOD("get_navigation_visibility_mode"), &TileMap::get_navigation_visibility_mode);
- ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(-1), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
- ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMap::get_cell_source_id);
- ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMap::get_cell_atlas_coords);
- ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMap::get_cell_alternative_tile);
+ ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMap::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
+ ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords", "use_proxies"), &TileMap::get_cell_source_id);
+ ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords", "use_proxies"), &TileMap::get_cell_atlas_coords);
+ ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords", "use_proxies"), &TileMap::get_cell_alternative_tile);
ClassDB::bind_method(D_METHOD("fix_invalid_tiles"), &TileMap::fix_invalid_tiles);
ClassDB::bind_method(D_METHOD("get_surrounding_tiles", "coords"), &TileMap::get_surrounding_tiles);
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 3001e6b471..9e35e73ad8 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -265,16 +265,16 @@ public:
VisibilityMode get_navigation_visibility_mode();
void set_cell(const Vector2i &p_coords, int p_source_id = -1, const Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE);
- int get_cell_source_id(const Vector2i &p_coords) const;
- Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const;
- int get_cell_alternative_tile(const Vector2i &p_coords) const;
+ int get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies = false) const;
+ Vector2i get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies = false) const;
+ int get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies = false) const;
TileMapPattern *get_pattern(TypedArray<Vector2i> p_coords_array);
Vector2i map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, const TileMapPattern *p_pattern);
void set_pattern(Vector2i p_position, const TileMapPattern *p_pattern);
// Not exposed to users
- TileMapCell get_cell(const Vector2i &p_coords) const;
+ TileMapCell get_cell(const Vector2i &p_coords, bool p_use_proxies = false) const;
Map<Vector2i, TileMapQuadrant> &get_quadrant_map();
int get_effective_quadrant_size() const;
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index dd8cb1f20d..bb8f9f8ccb 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -794,7 +794,7 @@ uint32_t AudioStreamPlayer3D::get_area_mask() const {
void AudioStreamPlayer3D::set_emission_angle_enabled(bool p_enable) {
emission_angle_enabled = p_enable;
- update_gizmo();
+ update_gizmos();
}
bool AudioStreamPlayer3D::is_emission_angle_enabled() const {
@@ -804,7 +804,7 @@ bool AudioStreamPlayer3D::is_emission_angle_enabled() const {
void AudioStreamPlayer3D::set_emission_angle(float p_angle) {
ERR_FAIL_COND(p_angle < 0 || p_angle > 90);
emission_angle = p_angle;
- update_gizmo();
+ update_gizmos();
}
float AudioStreamPlayer3D::get_emission_angle() const {
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 0c38d85a6b..2e962b96c3 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -164,7 +164,7 @@ void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_f
mode = PROJECTION_PERSPECTIVE;
RenderingServer::get_singleton()->camera_set_perspective(camera, fov, near, far);
- update_gizmo();
+ update_gizmos();
force_change = false;
}
@@ -181,7 +181,7 @@ void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) {
force_change = false;
RenderingServer::get_singleton()->camera_set_orthogonal(camera, size, near, far);
- update_gizmo();
+ update_gizmos();
}
void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float p_z_far) {
@@ -198,7 +198,7 @@ void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float
force_change = false;
RenderingServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far);
- update_gizmo();
+ update_gizmos();
}
void Camera3D::set_projection(Camera3D::Projection p_mode) {
@@ -755,7 +755,7 @@ void ClippedCamera3D::_notification(int p_what) {
}
if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) {
- update_gizmo();
+ update_gizmos();
}
}
diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp
index 8a4f8b639b..42645f47d4 100644
--- a/scene/3d/collision_polygon_3d.cpp
+++ b/scene/3d/collision_polygon_3d.cpp
@@ -122,7 +122,7 @@ void CollisionPolygon3D::set_polygon(const Vector<Point2> &p_polygon) {
_build_polygon();
}
update_configuration_warnings();
- update_gizmo();
+ update_gizmos();
}
Vector<Point2> CollisionPolygon3D::get_polygon() const {
@@ -136,7 +136,7 @@ AABB CollisionPolygon3D::get_item_rect() const {
void CollisionPolygon3D::set_depth(real_t p_depth) {
depth = p_depth;
_build_polygon();
- update_gizmo();
+ update_gizmos();
}
real_t CollisionPolygon3D::get_depth() const {
@@ -145,7 +145,7 @@ real_t CollisionPolygon3D::get_depth() const {
void CollisionPolygon3D::set_disabled(bool p_disabled) {
disabled = p_disabled;
- update_gizmo();
+ update_gizmos();
if (parent) {
parent->shape_owner_set_disabled(owner_id, p_disabled);
diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp
index be3fde8013..9643d33c86 100644
--- a/scene/3d/collision_shape_3d.cpp
+++ b/scene/3d/collision_shape_3d.cpp
@@ -117,7 +117,7 @@ void CollisionShape3D::_notification(int p_what) {
}
void CollisionShape3D::resource_changed(RES res) {
- update_gizmo();
+ update_gizmos();
}
TypedArray<String> CollisionShape3D::get_configuration_warnings() const {
@@ -166,7 +166,7 @@ void CollisionShape3D::set_shape(const Ref<Shape3D> &p_shape) {
if (!shape.is_null()) {
shape->register_owner(this);
}
- update_gizmo();
+ update_gizmos();
if (parent) {
parent->shape_owner_clear_shapes(owner_id);
if (shape.is_valid()) {
@@ -187,7 +187,7 @@ Ref<Shape3D> CollisionShape3D::get_shape() const {
void CollisionShape3D::set_disabled(bool p_disabled) {
disabled = p_disabled;
- update_gizmo();
+ update_gizmos();
if (parent) {
parent->shape_owner_set_disabled(owner_id, p_disabled);
}
diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index 9e0bc9f3a1..60f8ad8f36 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -401,6 +401,22 @@ void CPUParticles3D::set_emission_colors(const Vector<Color> &p_colors) {
emission_colors = p_colors;
}
+void CPUParticles3D::set_emission_ring_axis(Vector3 p_axis) {
+ emission_ring_axis = p_axis;
+}
+
+void CPUParticles3D::set_emission_ring_height(float p_height) {
+ emission_ring_height = p_height;
+}
+
+void CPUParticles3D::set_emission_ring_radius(float p_radius) {
+ emission_ring_radius = p_radius;
+}
+
+void CPUParticles3D::set_emission_ring_inner_radius(float p_radius) {
+ emission_ring_inner_radius = p_radius;
+}
+
float CPUParticles3D::get_emission_sphere_radius() const {
return emission_sphere_radius;
}
@@ -421,6 +437,22 @@ Vector<Color> CPUParticles3D::get_emission_colors() const {
return emission_colors;
}
+Vector3 CPUParticles3D::get_emission_ring_axis() const {
+ return emission_ring_axis;
+}
+
+float CPUParticles3D::get_emission_ring_height() const {
+ return emission_ring_height;
+}
+
+float CPUParticles3D::get_emission_ring_radius() const {
+ return emission_ring_radius;
+}
+
+float CPUParticles3D::get_emission_ring_inner_radius() const {
+ return emission_ring_inner_radius;
+}
+
CPUParticles3D::EmissionShape CPUParticles3D::get_emission_shape() const {
return emission_shape;
}
@@ -442,7 +474,7 @@ void CPUParticles3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NONE;
}
- if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) {
+ if ((property.name == "emission_point_texture" || property.name == "emission_color_texture" || property.name == "emission_points") && (emission_shape != EMISSION_SHAPE_POINTS && (emission_shape != EMISSION_SHAPE_DIRECTED_POINTS))) {
property.usage = PROPERTY_USAGE_NONE;
}
@@ -450,6 +482,10 @@ void CPUParticles3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NONE;
}
+ if (property.name.begins_with("emission_ring_") && emission_shape != EMISSION_SHAPE_RING) {
+ property.usage = PROPERTY_USAGE_NONE;
+ }
+
if (property.name.begins_with("orbit_") && !particle_flags[PARTICLE_FLAG_DISABLE_Z]) {
property.usage = PROPERTY_USAGE_NONE;
}
@@ -746,6 +782,21 @@ void CPUParticles3D::_particles_process(float p_delta) {
p.base_color = emission_colors.get(random_idx);
}
} break;
+ case EMISSION_SHAPE_RING: {
+ float ring_random_angle = Math::randf() * 2.0 * Math_PI;
+ float ring_random_radius = Math::randf() * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;
+ Vector3 axis = emission_ring_axis.normalized();
+ Vector3 ortho_axis = Vector3();
+ if (axis == Vector3(1.0, 0.0, 0.0)) {
+ ortho_axis = Vector3(0.0, 1.0, 0.0).cross(axis);
+ } else {
+ ortho_axis = Vector3(1.0, 0.0, 0.0).cross(axis);
+ }
+ ortho_axis = ortho_axis.normalized();
+ ortho_axis.rotate(axis, ring_random_angle);
+ ortho_axis = ortho_axis.normalized();
+ p.transform.origin = ortho_axis * ring_random_radius + (Math::randf() * emission_ring_height - emission_ring_height / 2.0) * axis;
+ } break;
case EMISSION_SHAPE_MAX: { // Max value for validity check.
break;
}
@@ -1336,18 +1387,34 @@ void CPUParticles3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emission_colors", "array"), &CPUParticles3D::set_emission_colors);
ClassDB::bind_method(D_METHOD("get_emission_colors"), &CPUParticles3D::get_emission_colors);
+ ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &CPUParticles3D::set_emission_ring_axis);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &CPUParticles3D::get_emission_ring_axis);
+
+ ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &CPUParticles3D::set_emission_ring_height);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &CPUParticles3D::get_emission_ring_height);
+
+ ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &CPUParticles3D::set_emission_ring_radius);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &CPUParticles3D::get_emission_ring_radius);
+
+ ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &CPUParticles3D::set_emission_ring_inner_radius);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &CPUParticles3D::get_emission_ring_inner_radius);
+
ClassDB::bind_method(D_METHOD("get_gravity"), &CPUParticles3D::get_gravity);
ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &CPUParticles3D::set_gravity);
ClassDB::bind_method(D_METHOD("convert_from_particles", "particles"), &CPUParticles3D::convert_from_particles);
ADD_GROUP("Emission Shape", "emission_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points,Ring", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_emission_shape", "get_emission_shape");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01"), "set_emission_sphere_radius", "get_emission_sphere_radius");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_points"), "set_emission_points", "get_emission_points");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "emission_normals"), "set_emission_normals", "get_emission_normals");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_COLOR_ARRAY, "emission_colors"), "set_emission_colors", "get_emission_colors");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_ring_axis"), "set_emission_ring_axis", "get_emission_ring_axis");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_height"), "set_emission_ring_height", "get_emission_ring_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_radius"), "set_emission_ring_radius", "get_emission_ring_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_inner_radius"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius");
ADD_GROUP("Particle Flags", "particle_flag_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_rotate_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ROTATE_Y);
@@ -1433,6 +1500,7 @@ void CPUParticles3D::_bind_methods() {
BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
+ BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
}
@@ -1461,6 +1529,10 @@ CPUParticles3D::CPUParticles3D() {
set_emission_shape(EMISSION_SHAPE_POINT);
set_emission_sphere_radius(1);
set_emission_box_extents(Vector3(1, 1, 1));
+ set_emission_ring_axis(Vector3(0, 0, 1.0));
+ set_emission_ring_height(1);
+ set_emission_ring_radius(1);
+ set_emission_ring_inner_radius(0);
set_gravity(Vector3(0, -9.8, 0));
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index b35e659757..07d345ba2c 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -76,6 +76,7 @@ public:
EMISSION_SHAPE_BOX,
EMISSION_SHAPE_POINTS,
EMISSION_SHAPE_DIRECTED_POINTS,
+ EMISSION_SHAPE_RING,
EMISSION_SHAPE_MAX
};
@@ -171,6 +172,10 @@ private:
Vector<Vector3> emission_normals;
Vector<Color> emission_colors;
int emission_point_count = 0;
+ Vector3 emission_ring_axis;
+ float emission_ring_height;
+ float emission_ring_radius;
+ float emission_ring_inner_radius;
Vector3 gravity = Vector3(0, -9.8, 0);
@@ -268,6 +273,10 @@ public:
void set_emission_normals(const Vector<Vector3> &p_normals);
void set_emission_colors(const Vector<Color> &p_colors);
void set_emission_point_count(int p_count);
+ void set_emission_ring_axis(Vector3 p_axis);
+ void set_emission_ring_height(float p_height);
+ void set_emission_ring_radius(float p_radius);
+ void set_emission_ring_inner_radius(float p_radius);
EmissionShape get_emission_shape() const;
float get_emission_sphere_radius() const;
@@ -276,6 +285,10 @@ public:
Vector<Vector3> get_emission_normals() const;
Vector<Color> get_emission_colors() const;
int get_emission_point_count() const;
+ Vector3 get_emission_ring_axis() const;
+ float get_emission_ring_height() const;
+ float get_emission_ring_radius() const;
+ float get_emission_ring_inner_radius() const;
void set_gravity(const Vector3 &p_gravity);
Vector3 get_gravity() const;
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index 5af7b8ca07..05f023721b 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -33,7 +33,7 @@
void Decal::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->decal_set_extents(decal, p_extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 Decal::get_extents() const {
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index f78027e6c7..44cd7c10d8 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -99,7 +99,7 @@ void GPUParticles3D::set_randomness_ratio(float p_ratio) {
void GPUParticles3D::set_visibility_aabb(const AABB &p_aabb) {
visibility_aabb = p_aabb;
RS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb);
- update_gizmo();
+ update_gizmos();
}
void GPUParticles3D::set_use_local_coordinates(bool p_enable) {
diff --git a/scene/3d/gpu_particles_collision_3d.cpp b/scene/3d/gpu_particles_collision_3d.cpp
index 5b88a6ec9f..cc1b620025 100644
--- a/scene/3d/gpu_particles_collision_3d.cpp
+++ b/scene/3d/gpu_particles_collision_3d.cpp
@@ -73,7 +73,7 @@ void GPUParticlesCollisionSphere::_bind_methods() {
void GPUParticlesCollisionSphere::set_radius(float p_radius) {
radius = p_radius;
RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius);
- update_gizmo();
+ update_gizmos();
}
float GPUParticlesCollisionSphere::get_radius() const {
@@ -103,7 +103,7 @@ void GPUParticlesCollisionBox::_bind_methods() {
void GPUParticlesCollisionBox::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesCollisionBox::get_extents() const {
@@ -397,9 +397,7 @@ Ref<Image> GPUParticlesCollisionSDF::bake() {
bake_step_function(0, "Finding Meshes");
}
- for (List<PlotMesh>::Element *E = plot_meshes.front(); E; E = E->next()) {
- const PlotMesh &pm = E->get();
-
+ for (const PlotMesh &pm : plot_meshes) {
for (int i = 0; i < pm.mesh->get_surface_count(); i++) {
if (pm.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
continue; //only triangles
@@ -545,7 +543,7 @@ float GPUParticlesCollisionSDF::get_thickness() const {
void GPUParticlesCollisionSDF::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesCollisionSDF::get_extents() const {
@@ -554,7 +552,7 @@ Vector3 GPUParticlesCollisionSDF::get_extents() const {
void GPUParticlesCollisionSDF::set_resolution(Resolution p_resolution) {
resolution = p_resolution;
- update_gizmo();
+ update_gizmos();
}
GPUParticlesCollisionSDF::Resolution GPUParticlesCollisionSDF::get_resolution() const {
@@ -680,7 +678,7 @@ float GPUParticlesCollisionHeightField::get_follow_camera_push_ratio() const {
void GPUParticlesCollisionHeightField::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
RS::get_singleton()->particles_collision_height_field_update(_get_collision());
}
@@ -691,7 +689,7 @@ Vector3 GPUParticlesCollisionHeightField::get_extents() const {
void GPUParticlesCollisionHeightField::set_resolution(Resolution p_resolution) {
resolution = p_resolution;
RS::get_singleton()->particles_collision_set_height_field_resolution(_get_collision(), RS::ParticlesCollisionHeightfieldResolution(resolution));
- update_gizmo();
+ update_gizmos();
RS::get_singleton()->particles_collision_height_field_update(_get_collision());
}
@@ -761,7 +759,7 @@ float GPUParticlesAttractor3D::get_attenuation() const {
void GPUParticlesAttractor3D::set_directionality(float p_directionality) {
directionality = p_directionality;
RS::get_singleton()->particles_collision_set_attractor_directionality(collision, p_directionality);
- update_gizmo();
+ update_gizmos();
}
float GPUParticlesAttractor3D::get_directionality() const {
@@ -808,7 +806,7 @@ void GPUParticlesAttractorSphere::_bind_methods() {
void GPUParticlesAttractorSphere::set_radius(float p_radius) {
radius = p_radius;
RS::get_singleton()->particles_collision_set_sphere_radius(_get_collision(), radius);
- update_gizmo();
+ update_gizmos();
}
float GPUParticlesAttractorSphere::get_radius() const {
@@ -838,7 +836,7 @@ void GPUParticlesAttractorBox::_bind_methods() {
void GPUParticlesAttractorBox::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesAttractorBox::get_extents() const {
@@ -872,7 +870,7 @@ void GPUParticlesAttractorVectorField::_bind_methods() {
void GPUParticlesAttractorVectorField::set_extents(const Vector3 &p_extents) {
extents = p_extents;
RS::get_singleton()->particles_collision_set_box_extents(_get_collision(), extents);
- update_gizmo();
+ update_gizmos();
}
Vector3 GPUParticlesAttractorVectorField::get_extents() const {
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 8478821ba1..c2943a9606 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -45,7 +45,7 @@ void Light3D::set_param(Param p_param, float p_value) {
RS::get_singleton()->light_set_param(light, RS::LightParam(p_param), p_value);
if (p_param == PARAM_SPOT_ANGLE || p_param == PARAM_RANGE) {
- update_gizmo();
+ update_gizmos();
if (p_param == PARAM_SPOT_ANGLE) {
update_configuration_warnings();
@@ -95,7 +95,7 @@ void Light3D::set_color(const Color &p_color) {
color = p_color;
RS::get_singleton()->light_set_color(light, p_color);
// The gizmo color depends on the light color, so update it.
- update_gizmo();
+ update_gizmos();
}
Color Light3D::get_color() const {
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 66e3535fc4..0085c8933d 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -599,7 +599,7 @@ void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, f
const Vector3 *pp = probe_positions.ptr();
bool exists = false;
for (int j = 0; j < ppcount; j++) {
- if (pp[j].distance_to(real_pos) < CMP_EPSILON) {
+ if (pp[j].is_equal_approx(real_pos)) {
exists = true;
break;
}
@@ -1250,7 +1250,7 @@ void LightmapGI::set_light_data(const Ref<LightmapGIData> &p_data) {
}
}
- update_gizmo();
+ update_gizmos();
}
Ref<LightmapGIData> LightmapGI::get_light_data() const {
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index 28ccbd3e68..9ca1d55d0b 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -94,8 +94,8 @@ void MeshInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
ls.sort();
- for (List<String>::Element *E = ls.front(); E; E = E->next()) {
- p_list->push_back(PropertyInfo(Variant::FLOAT, E->get(), PROPERTY_HINT_RANGE, "-1,1,0.00001"));
+ for (const String &E : ls) {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, E, PROPERTY_HINT_RANGE, "-1,1,0.00001"));
}
if (mesh.is_valid()) {
@@ -133,7 +133,7 @@ void MeshInstance3D::set_mesh(const Ref<Mesh> &p_mesh) {
set_base(RID());
}
- update_gizmo();
+ update_gizmos();
notify_property_list_changed();
}
@@ -356,7 +356,7 @@ Ref<Material> MeshInstance3D::get_active_material(int p_surface) const {
void MeshInstance3D::_mesh_changed() {
ERR_FAIL_COND(mesh.is_null());
surface_override_materials.resize(mesh->get_surface_count());
- update_gizmo();
+ update_gizmos();
}
void MeshInstance3D::create_debug_tangents() {
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 19abb3f33a..2976dad39d 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -59,7 +59,7 @@ void NavigationRegion3D::set_enabled(bool p_enabled) {
}
}
- update_gizmo();
+ update_gizmos();
}
bool NavigationRegion3D::is_enabled() const {
@@ -134,7 +134,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref<NavigationMesh> &p_navmes
emit_signal(SNAME("navigation_mesh_changed"));
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
@@ -211,7 +211,7 @@ void NavigationRegion3D::_bind_methods() {
}
void NavigationRegion3D::_navigation_changed() {
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index d6c6ec75b4..0daee69ee5 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -76,7 +76,7 @@ Node3DGizmo::Node3DGizmo() {
void Node3D::_notify_dirty() {
#ifdef TOOLS_ENABLED
- if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
+ if ((!data.gizmos.is_empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
#else
if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) {
@@ -103,14 +103,14 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) {
data.children_lock++;
- for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) {
- if (E->get()->data.top_level_active) {
+ for (Node3D *&E : data.children) {
+ if (E->data.top_level_active) {
continue; //don't propagate to a top_level
}
- E->get()->_propagate_transform_changed(p_origin);
+ E->_propagate_transform_changed(p_origin);
}
#ifdef TOOLS_ENABLED
- if ((data.gizmo.is_valid() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
+ if ((!data.gizmos.is_empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
#else
if (data.notify_transform && !data.ignore_notification && !xform_change.in_list()) {
#endif
@@ -181,15 +181,14 @@ void Node3D::_notification(int p_what) {
}
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
- //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,SceneStringNames::get_singleton()->_spatial_editor_group,SceneStringNames::get_singleton()->_request_gizmo,this);
get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
- if (!data.gizmo_disabled) {
- if (data.gizmo.is_valid()) {
- data.gizmo->create();
+ if (!data.gizmos_disabled) {
+ for (int i = 0; i < data.gizmos.size(); i++) {
+ data.gizmos.write[i]->create();
if (is_visible_in_tree()) {
- data.gizmo->redraw();
+ data.gizmos.write[i]->redraw();
}
- data.gizmo->transform();
+ data.gizmos.write[i]->transform();
}
}
}
@@ -198,10 +197,7 @@ void Node3D::_notification(int p_what) {
} break;
case NOTIFICATION_EXIT_WORLD: {
#ifdef TOOLS_ENABLED
- if (data.gizmo.is_valid()) {
- data.gizmo->free();
- data.gizmo.unref();
- }
+ clear_gizmos();
#endif
if (get_script_instance()) {
@@ -215,8 +211,8 @@ void Node3D::_notification(int p_what) {
case NOTIFICATION_TRANSFORM_CHANGED: {
#ifdef TOOLS_ENABLED
- if (data.gizmo.is_valid()) {
- data.gizmo->transform();
+ for (int i = 0; i < data.gizmos.size(); i++) {
+ data.gizmos.write[i]->transform();
}
#endif
} break;
@@ -368,80 +364,119 @@ Vector3 Node3D::get_scale() const {
return data.scale;
}
-void Node3D::update_gizmo() {
+void Node3D::update_gizmos() {
#ifdef TOOLS_ENABLED
if (!is_inside_world()) {
return;
}
- if (!data.gizmo.is_valid()) {
- get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
+
+ if (data.gizmos.is_empty()) {
+ return;
}
- if (!data.gizmo.is_valid()) {
+ data.gizmos_dirty = true;
+ MessageQueue::get_singleton()->push_callable(callable_mp(this, &Node3D::_update_gizmos));
+#endif
+}
+
+void Node3D::clear_subgizmo_selection() {
+#ifdef TOOLS_ENABLED
+ if (!is_inside_world()) {
return;
}
- if (data.gizmo_dirty) {
+
+ if (data.gizmos.is_empty()) {
return;
}
- data.gizmo_dirty = true;
- MessageQueue::get_singleton()->push_call(this, "_update_gizmo");
+
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
+ get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_clear_subgizmo_selection, this);
+ }
#endif
}
-void Node3D::set_gizmo(const Ref<Node3DGizmo> &p_gizmo) {
+void Node3D::add_gizmo(Ref<Node3DGizmo> p_gizmo) {
#ifdef TOOLS_ENABLED
- if (data.gizmo_disabled) {
+ if (data.gizmos_disabled || p_gizmo.is_null()) {
return;
}
- if (data.gizmo.is_valid() && is_inside_world()) {
- data.gizmo->free();
- }
- data.gizmo = p_gizmo;
- if (data.gizmo.is_valid() && is_inside_world()) {
- data.gizmo->create();
+ data.gizmos.push_back(p_gizmo);
+
+ if (p_gizmo.is_valid() && is_inside_world()) {
+ p_gizmo->create();
if (is_visible_in_tree()) {
- data.gizmo->redraw();
+ p_gizmo->redraw();
}
- data.gizmo->transform();
+ p_gizmo->transform();
}
+#endif
+}
+
+void Node3D::remove_gizmo(Ref<Node3DGizmo> p_gizmo) {
+#ifdef TOOLS_ENABLED
+ int idx = data.gizmos.find(p_gizmo);
+ if (idx != -1) {
+ p_gizmo->free();
+ data.gizmos.remove(idx);
+ }
+#endif
+}
+
+void Node3D::clear_gizmos() {
+#ifdef TOOLS_ENABLED
+ for (int i = 0; i < data.gizmos.size(); i++) {
+ data.gizmos.write[i]->free();
+ }
+ data.gizmos.clear();
+#endif
+}
+
+Array Node3D::get_gizmos_bind() const {
+ Array ret;
+
+#ifdef TOOLS_ENABLED
+ for (int i = 0; i < data.gizmos.size(); i++) {
+ ret.push_back(Variant(data.gizmos[i].ptr()));
+ }
#endif
+
+ return ret;
}
-Ref<Node3DGizmo> Node3D::get_gizmo() const {
+Vector<Ref<Node3DGizmo>> Node3D::get_gizmos() const {
#ifdef TOOLS_ENABLED
- return data.gizmo;
+ return data.gizmos;
#else
- return Ref<Node3DGizmo>();
+ return Vector<Ref<Node3DGizmo>>();
#endif
}
-void Node3D::_update_gizmo() {
+void Node3D::_update_gizmos() {
#ifdef TOOLS_ENABLED
- if (!is_inside_world()) {
+ if (data.gizmos_disabled || !is_inside_world() || !data.gizmos_dirty) {
return;
}
- data.gizmo_dirty = false;
- if (data.gizmo.is_valid()) {
+ data.gizmos_dirty = false;
+ for (int i = 0; i < data.gizmos.size(); i++) {
if (is_visible_in_tree()) {
- data.gizmo->redraw();
+ data.gizmos.write[i]->redraw();
} else {
- data.gizmo->clear();
+ data.gizmos.write[i]->clear();
}
}
#endif
}
#ifdef TOOLS_ENABLED
-void Node3D::set_disable_gizmo(bool p_enabled) {
- data.gizmo_disabled = p_enabled;
- if (!p_enabled && data.gizmo.is_valid()) {
- data.gizmo = Ref<Node3DGizmo>();
+void Node3D::set_disable_gizmos(bool p_enabled) {
+ data.gizmos_disabled = p_enabled;
+ if (!p_enabled) {
+ clear_gizmos();
}
}
-
#endif
void Node3D::set_disable_scale(bool p_enabled) {
@@ -486,13 +521,13 @@ void Node3D::_propagate_visibility_changed() {
notification(NOTIFICATION_VISIBILITY_CHANGED);
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
#ifdef TOOLS_ENABLED
- if (data.gizmo.is_valid()) {
- _update_gizmo();
+ if (!data.gizmos.is_empty()) {
+ data.gizmos_dirty = true;
+ _update_gizmos();
}
#endif
- for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) {
- Node3D *c = E->get();
+ for (Node3D *c : data.children) {
if (!c || !c->data.visible) {
continue;
}
@@ -717,8 +752,7 @@ void Node3D::_update_visibility_parent(bool p_update_root) {
RS::get_singleton()->instance_set_visibility_parent(vi->get_instance(), data.visibility_parent);
}
- for (List<Node3D *>::Element *E = data.children.front(); E; E = E->next()) {
- Node3D *c = E->get();
+ for (Node3D *c : data.children) {
c->_update_visibility_parent(false);
}
}
@@ -758,11 +792,11 @@ void Node3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_visibility_parent", "path"), &Node3D::set_visibility_parent);
ClassDB::bind_method(D_METHOD("get_visibility_parent"), &Node3D::get_visibility_parent);
- ClassDB::bind_method(D_METHOD("_update_gizmo"), &Node3D::_update_gizmo);
-
- ClassDB::bind_method(D_METHOD("update_gizmo"), &Node3D::update_gizmo);
- ClassDB::bind_method(D_METHOD("set_gizmo", "gizmo"), &Node3D::set_gizmo);
- ClassDB::bind_method(D_METHOD("get_gizmo"), &Node3D::get_gizmo);
+ ClassDB::bind_method(D_METHOD("update_gizmos"), &Node3D::update_gizmos);
+ ClassDB::bind_method(D_METHOD("add_gizmo", "gizmo"), &Node3D::add_gizmo);
+ ClassDB::bind_method(D_METHOD("get_gizmos"), &Node3D::get_gizmos_bind);
+ ClassDB::bind_method(D_METHOD("clear_gizmos"), &Node3D::clear_gizmos);
+ ClassDB::bind_method(D_METHOD("clear_subgizmo_selection"), &Node3D::clear_subgizmo_selection);
ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Node3D::set_visible);
ClassDB::bind_method(D_METHOD("is_visible"), &Node3D::is_visible);
@@ -813,7 +847,6 @@ void Node3D::_bind_methods() {
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "visibility_parent", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GeometryInstance3D"), "set_visibility_parent", "get_visibility_parent");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "Node3DGizmo", PROPERTY_USAGE_NONE), "set_gizmo", "get_gizmo");
ADD_SIGNAL(MethodInfo("visibility_changed"));
}
diff --git a/scene/3d/node_3d.h b/scene/3d/node_3d.h
index fe6324c796..282f4805cc 100644
--- a/scene/3d/node_3d.h
+++ b/scene/3d/node_3d.h
@@ -90,16 +90,16 @@ class Node3D : public Node {
bool disable_scale = false;
#ifdef TOOLS_ENABLED
- Ref<Node3DGizmo> gizmo;
- bool gizmo_disabled = false;
- bool gizmo_dirty = false;
+ Vector<Ref<Node3DGizmo>> gizmos;
+ bool gizmos_disabled = false;
+ bool gizmos_dirty = false;
#endif
} data;
NodePath visibility_parent_path;
- void _update_gizmo();
+ void _update_gizmos();
void _notify_dirty();
void _propagate_transform_changed(Node3D *p_origin);
@@ -154,10 +154,14 @@ public:
void set_disable_scale(bool p_enabled);
bool is_scale_disabled() const;
- void set_disable_gizmo(bool p_enabled);
- void update_gizmo();
- void set_gizmo(const Ref<Node3DGizmo> &p_gizmo);
- Ref<Node3DGizmo> get_gizmo() const;
+ void set_disable_gizmos(bool p_enabled);
+ void update_gizmos();
+ void clear_subgizmo_selection();
+ Vector<Ref<Node3DGizmo>> get_gizmos() const;
+ Array get_gizmos_bind() const;
+ void add_gizmo(Ref<Node3DGizmo> p_gizmo);
+ void remove_gizmo(Ref<Node3DGizmo> p_gizmo);
+ void clear_gizmos();
_FORCE_INLINE_ bool is_inside_world() const { return data.inside_world; }
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index 7b736e689c..3d1a27911b 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -173,12 +173,12 @@ void OccluderInstance3D::set_occluder(const Ref<Occluder3D> &p_occluder) {
set_base(RID());
}
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
void OccluderInstance3D::_occluder_changed() {
- update_gizmo();
+ update_gizmos();
update_configuration_warnings();
}
diff --git a/scene/3d/path_3d.cpp b/scene/3d/path_3d.cpp
index 54ae2cef75..6af2e7f879 100644
--- a/scene/3d/path_3d.cpp
+++ b/scene/3d/path_3d.cpp
@@ -38,7 +38,7 @@ void Path3D::_notification(int p_what) {
void Path3D::_curve_changed() {
if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
- update_gizmo();
+ update_gizmos();
}
if (is_inside_tree()) {
emit_signal(SNAME("curve_changed"));
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index 760dbdadca..93ecb2cd3a 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -78,8 +78,7 @@ TypedArray<PhysicsBody3D> PhysicsBody3D::get_collision_exceptions() {
List<RID> exceptions;
PhysicsServer3D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
Array ret;
- for (List<RID>::Element *E = exceptions.front(); E; E = E->next()) {
- RID body = E->get();
+ for (const RID &body : exceptions) {
ObjectID instance_id = PhysicsServer3D::get_singleton()->body_get_object_instance_id(body);
Object *obj = ObjectDB::get_instance(instance_id);
PhysicsBody3D *physics_body = Object::cast_to<PhysicsBody3D>(obj);
@@ -2181,9 +2180,7 @@ bool PhysicalBone3D::_set(const StringName &p_name, const Variant &p_value) {
if (joint_data) {
if (joint_data->_set(p_name, p_value, joint)) {
#ifdef TOOLS_ENABLED
- if (get_gizmo().is_valid()) {
- get_gizmo()->redraw();
- }
+ update_gizmos();
#endif
return true;
}
@@ -2371,9 +2368,7 @@ void PhysicalBone3D::_update_joint_offset() {
set_ignore_transform_notification(false);
#ifdef TOOLS_ENABLED
- if (get_gizmo().is_valid()) {
- get_gizmo()->redraw();
- }
+ update_gizmos();
#endif
}
@@ -2540,9 +2535,7 @@ void PhysicalBone3D::set_joint_type(JointType p_joint_type) {
#ifdef TOOLS_ENABLED
notify_property_list_changed();
- if (get_gizmo().is_valid()) {
- get_gizmo()->redraw();
- }
+ update_gizmos();
#endif
}
diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp
index 01f10c171f..59440bd1a8 100644
--- a/scene/3d/physics_joint_3d.cpp
+++ b/scene/3d/physics_joint_3d.cpp
@@ -348,7 +348,7 @@ void HingeJoint3D::set_param(Param p_param, real_t p_value) {
PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer3D::HingeJointParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t HingeJoint3D::get_param(Param p_param) const {
@@ -363,7 +363,7 @@ void HingeJoint3D::set_flag(Flag p_flag, bool p_value) {
PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer3D::HingeJointFlag(p_flag), p_value);
}
- update_gizmo();
+ update_gizmos();
}
bool HingeJoint3D::get_flag(Flag p_flag) const {
@@ -497,7 +497,7 @@ void SliderJoint3D::set_param(Param p_param, real_t p_value) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer3D::SliderJointParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t SliderJoint3D::get_param(Param p_param) const {
@@ -602,7 +602,7 @@ void ConeTwistJoint3D::set_param(Param p_param, real_t p_value) {
PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t ConeTwistJoint3D::get_param(Param p_param) const {
@@ -857,7 +857,7 @@ void Generic6DOFJoint3D::set_param_x(Param p_param, real_t p_value) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t Generic6DOFJoint3D::get_param_x(Param p_param) const {
@@ -871,7 +871,7 @@ void Generic6DOFJoint3D::set_param_y(Param p_param, real_t p_value) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t Generic6DOFJoint3D::get_param_y(Param p_param) const {
@@ -885,7 +885,7 @@ void Generic6DOFJoint3D::set_param_z(Param p_param, real_t p_value) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value);
}
- update_gizmo();
+ update_gizmos();
}
real_t Generic6DOFJoint3D::get_param_z(Param p_param) const {
@@ -899,7 +899,7 @@ void Generic6DOFJoint3D::set_flag_x(Flag p_flag, bool p_enabled) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
- update_gizmo();
+ update_gizmos();
}
bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const {
@@ -913,7 +913,7 @@ void Generic6DOFJoint3D::set_flag_y(Flag p_flag, bool p_enabled) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
- update_gizmo();
+ update_gizmos();
}
bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const {
@@ -927,7 +927,7 @@ void Generic6DOFJoint3D::set_flag_z(Flag p_flag, bool p_enabled) {
if (is_configured()) {
PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled);
}
- update_gizmo();
+ update_gizmos();
}
bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const {
diff --git a/scene/3d/proximity_group_3d.cpp b/scene/3d/proximity_group_3d.cpp
index 037110eaa1..c8c61a9f00 100644
--- a/scene/3d/proximity_group_3d.cpp
+++ b/scene/3d/proximity_group_3d.cpp
@@ -128,6 +128,7 @@ void ProximityGroup3D::broadcast(String p_method, Variant p_parameters) {
void ProximityGroup3D::_proximity_group_broadcast(String p_method, Variant p_parameters) {
if (dispatch_mode == MODE_PROXY) {
+ ERR_FAIL_COND(!is_inside_tree());
get_parent()->call(p_method, p_parameters);
} else {
emit_signal(SNAME("broadcast"), p_method, p_parameters);
diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp
index dfab3d4a17..7356ce478b 100644
--- a/scene/3d/ray_cast_3d.cpp
+++ b/scene/3d/ray_cast_3d.cpp
@@ -37,7 +37,7 @@
void RayCast3D::set_target_position(const Vector3 &p_point) {
target_position = p_point;
- update_gizmo();
+ update_gizmos();
if (Engine::get_singleton()->is_editor_hint()) {
if (is_inside_tree()) {
@@ -102,7 +102,7 @@ Vector3 RayCast3D::get_collision_normal() const {
void RayCast3D::set_enabled(bool p_enabled) {
enabled = p_enabled;
- update_gizmo();
+ update_gizmos();
if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint()) {
set_physics_process_internal(p_enabled);
@@ -366,7 +366,7 @@ void RayCast3D::_update_debug_shape_vertices() {
void RayCast3D::set_debug_shape_thickness(const float p_debug_shape_thickness) {
debug_shape_thickness = p_debug_shape_thickness;
- update_gizmo();
+ update_gizmos();
if (Engine::get_singleton()->is_editor_hint()) {
if (is_inside_tree()) {
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index c289fc4fd7..719dbedd94 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -101,7 +101,7 @@ void ReflectionProbe::set_extents(const Vector3 &p_extents) {
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
- update_gizmo();
+ update_gizmos();
}
Vector3 ReflectionProbe::get_extents() const {
@@ -119,7 +119,7 @@ void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) {
RS::get_singleton()->reflection_probe_set_extents(probe, extents);
RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset);
- update_gizmo();
+ update_gizmos();
}
Vector3 ReflectionProbe::get_origin_offset() const {
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index fa3b16935c..9ce4c37457 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -264,8 +264,8 @@ void Skeleton3D::_notification(int p_what) {
b.global_pose_override_amount = 0.0;
}
- for (List<ObjectID>::Element *E = b.nodes_bound.front(); E; E = E->next()) {
- Object *obj = ObjectDB::get_instance(E->get());
+ for (const ObjectID &E : b.nodes_bound) {
+ Object *obj = ObjectDB::get_instance(E);
ERR_CONTINUE(!obj);
Node3D *node_3d = Object::cast_to<Node3D>(obj);
ERR_CONTINUE(!node_3d);
@@ -404,7 +404,7 @@ void Skeleton3D::add_bone(const String &p_name) {
process_order_dirty = true;
version++;
_make_dirty();
- update_gizmo();
+ update_gizmos();
}
int Skeleton3D::find_bone(const String &p_name) const {
@@ -524,8 +524,8 @@ void Skeleton3D::bind_child_node_to_bone(int p_bone, Node *p_node) {
ObjectID id = p_node->get_instance_id();
- for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
- if (E->get() == id) {
+ for (const ObjectID &E : bones[p_bone].nodes_bound) {
+ if (E == id) {
return; // already here
}
}
@@ -544,8 +544,8 @@ void Skeleton3D::unbind_child_node_from_bone(int p_bone, Node *p_node) {
void Skeleton3D::get_bound_child_nodes_to_bone(int p_bone, List<Node *> *p_bound) const {
ERR_FAIL_INDEX(p_bone, bones.size());
- for (const List<ObjectID>::Element *E = bones[p_bone].nodes_bound.front(); E; E = E->next()) {
- Object *obj = ObjectDB::get_instance(E->get());
+ for (const ObjectID &E : bones[p_bone].nodes_bound) {
+ Object *obj = ObjectDB::get_instance(E);
ERR_CONTINUE(!obj);
p_bound->push_back(Object::cast_to<Node>(obj));
}
diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp
index 05530c39a1..a7ff0842d2 100644
--- a/scene/3d/soft_body_3d.cpp
+++ b/scene/3d/soft_body_3d.cpp
@@ -592,8 +592,7 @@ Array SoftBody3D::get_collision_exceptions() {
List<RID> exceptions;
PhysicsServer3D::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions);
Array ret;
- for (List<RID>::Element *E = exceptions.front(); E; E = E->next()) {
- RID body = E->get();
+ for (const RID &body : exceptions) {
ObjectID instance_id = PhysicsServer3D::get_singleton()->body_get_object_instance_id(body);
Object *obj = ObjectDB::get_instance(instance_id);
PhysicsBody3D *physics_body = Object::cast_to<PhysicsBody3D>(obj);
diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp
index 1911e14d54..5e9265b4c3 100644
--- a/scene/3d/spring_arm_3d.cpp
+++ b/scene/3d/spring_arm_3d.cpp
@@ -84,7 +84,7 @@ real_t SpringArm3D::get_length() const {
void SpringArm3D::set_length(real_t p_length) {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_collisions_hint())) {
- update_gizmo();
+ update_gizmos();
}
spring_length = p_length;
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 2a53dd6aca..a901920dbe 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -60,8 +60,8 @@ void SpriteBase3D::_propagate_color_changed() {
color_dirty = true;
_queue_update();
- for (List<SpriteBase3D *>::Element *E = children.front(); E; E = E->next()) {
- E->get()->_propagate_color_changed();
+ for (SpriteBase3D *&E : children) {
+ E->_propagate_color_changed();
}
}
@@ -174,7 +174,7 @@ void SpriteBase3D::_queue_update() {
}
triangle_mesh.unref();
- update_gizmo();
+ update_gizmos();
pending_update = true;
call_deferred(SceneStringNames::get_singleton()->_im_update);
@@ -996,7 +996,7 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
}
property.hint_string += String(E->get());
- if (animation == E->get()) {
+ if (animation == E) {
current_found = true;
}
}
diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp
index b0e37b81a5..92c0e09947 100644
--- a/scene/3d/vehicle_body_3d.cpp
+++ b/scene/3d/vehicle_body_3d.cpp
@@ -149,7 +149,7 @@ void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) {
void VehicleWheel3D::set_radius(real_t p_radius) {
m_wheelRadius = p_radius;
- update_gizmo();
+ update_gizmos();
}
real_t VehicleWheel3D::get_radius() const {
@@ -158,7 +158,7 @@ real_t VehicleWheel3D::get_radius() const {
void VehicleWheel3D::set_suspension_rest_length(real_t p_length) {
m_suspensionRestLength = p_length;
- update_gizmo();
+ update_gizmos();
}
real_t VehicleWheel3D::get_suspension_rest_length() const {
diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp
index 682bcec449..6a80aa3f45 100644
--- a/scene/3d/visible_on_screen_notifier_3d.cpp
+++ b/scene/3d/visible_on_screen_notifier_3d.cpp
@@ -63,7 +63,7 @@ void VisibleOnScreenNotifier3D::set_aabb(const AABB &p_aabb) {
RS::get_singleton()->visibility_notifier_set_aabb(get_base(), aabb);
- update_gizmo();
+ update_gizmos();
}
AABB VisibleOnScreenNotifier3D::get_aabb() const {
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index bd47af8100..70a7021f22 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -238,8 +238,7 @@ bool GeometryInstance3D::_get(const StringName &p_name, Variant &r_ret) const {
void GeometryInstance3D::_get_property_list(List<PropertyInfo> *p_list) const {
List<PropertyInfo> pinfo;
RS::get_singleton()->instance_geometry_get_shader_parameter_list(get_instance(), &pinfo);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- PropertyInfo pi = E->get();
+ for (PropertyInfo &pi : pinfo) {
bool has_def_value = false;
Variant def_value = RS::get_singleton()->instance_geometry_get_shader_parameter_default_value(get_instance(), pi.name);
if (def_value.get_type() != Variant::NIL) {
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index 3da59ac4c0..5cf7522667 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -265,7 +265,7 @@ Ref<VoxelGIData> VoxelGI::get_probe_data() const {
void VoxelGI::set_subdiv(Subdiv p_subdiv) {
ERR_FAIL_INDEX(p_subdiv, SUBDIV_MAX);
subdiv = p_subdiv;
- update_gizmo();
+ update_gizmos();
}
VoxelGI::Subdiv VoxelGI::get_subdiv() const {
@@ -274,7 +274,7 @@ VoxelGI::Subdiv VoxelGI::get_subdiv() const {
void VoxelGI::set_extents(const Vector3 &p_extents) {
extents = p_extents;
- update_gizmo();
+ update_gizmos();
}
Vector3 VoxelGI::get_extents() const {
@@ -384,14 +384,14 @@ void VoxelGI::bake(Node *p_from_node, bool p_create_visual_debug) {
int pmc = 0;
- for (List<PlotMesh>::Element *E = mesh_list.front(); E; E = E->next()) {
+ for (PlotMesh &E : mesh_list) {
if (bake_step_function) {
bake_step_function(pmc, RTR("Plotting Meshes") + " " + itos(pmc) + "/" + itos(mesh_list.size()));
}
pmc++;
- baker.plot_mesh(E->get().local_xform, E->get().mesh, E->get().instance_materials, E->get().override_material);
+ baker.plot_mesh(E.local_xform, E.mesh, E.instance_materials, E.override_material);
}
if (bake_step_function) {
bake_step_function(pmc++, RTR("Finishing Plot"));
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index 12f055c01d..f1b9708f91 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -36,17 +36,17 @@
#include <stdlib.h>
static _FORCE_INLINE_ void get_uv_and_normal(const Vector3 &p_pos, const Vector3 *p_vtx, const Vector2 *p_uv, const Vector3 *p_normal, Vector2 &r_uv, Vector3 &r_normal) {
- if (p_pos.distance_squared_to(p_vtx[0]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_vtx[0])) {
r_uv = p_uv[0];
r_normal = p_normal[0];
return;
}
- if (p_pos.distance_squared_to(p_vtx[1]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_vtx[1])) {
r_uv = p_uv[1];
r_normal = p_normal[1];
return;
}
- if (p_pos.distance_squared_to(p_vtx[2]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_vtx[2])) {
r_uv = p_uv[2];
r_normal = p_normal[2];
return;
diff --git a/scene/animation/animation_blend_space_2d.cpp b/scene/animation/animation_blend_space_2d.cpp
index 6878cbaa12..d88a9badf4 100644
--- a/scene/animation/animation_blend_space_2d.cpp
+++ b/scene/animation/animation_blend_space_2d.cpp
@@ -387,19 +387,19 @@ Vector2 AnimationNodeBlendSpace2D::get_closest_point(const Vector2 &p_point) {
}
void AnimationNodeBlendSpace2D::_blend_triangle(const Vector2 &p_pos, const Vector2 *p_points, float *r_weights) {
- if (p_pos.distance_squared_to(p_points[0]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_points[0])) {
r_weights[0] = 1;
r_weights[1] = 0;
r_weights[2] = 0;
return;
}
- if (p_pos.distance_squared_to(p_points[1]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_points[1])) {
r_weights[0] = 0;
r_weights[1] = 1;
r_weights[2] = 0;
return;
}
- if (p_pos.distance_squared_to(p_points[2]) < CMP_EPSILON2) {
+ if (p_pos.is_equal_approx(p_points[2])) {
r_weights[0] = 0;
r_weights[1] = 0;
r_weights[2] = 1;
diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index 200a688067..4bddae3b14 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -1089,10 +1089,10 @@ bool AnimationNodeBlendTree::_get(const StringName &p_name, Variant &r_ret) cons
conns.resize(nc.size() * 3);
int idx = 0;
- for (List<NodeConnection>::Element *E = nc.front(); E; E = E->next()) {
- conns[idx * 3 + 0] = E->get().input_node;
- conns[idx * 3 + 1] = E->get().input_index;
- conns[idx * 3 + 2] = E->get().output_node;
+ for (const NodeConnection &E : nc) {
+ conns[idx * 3 + 0] = E.input_node;
+ conns[idx * 3 + 1] = E.input_index;
+ conns[idx * 3 + 2] = E.output_node;
idx++;
}
@@ -1110,8 +1110,8 @@ void AnimationNodeBlendTree::_get_property_list(List<PropertyInfo> *p_list) cons
}
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- String name = E->get();
+ for (const StringName &E : names) {
+ String name = E;
if (name != "output") {
p_list->push_back(PropertyInfo(Variant::OBJECT, "nodes/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR));
}
diff --git a/scene/animation/animation_cache.cpp b/scene/animation/animation_cache.cpp
index b8980fd56b..56743007e4 100644
--- a/scene/animation/animation_cache.cpp
+++ b/scene/animation/animation_cache.cpp
@@ -252,8 +252,8 @@ void AnimationCache::set_all(float p_time, float p_delta) {
List<int> indices;
animation->value_track_get_key_indices(i, p_time, p_delta, &indices);
- for (List<int>::Element *E = indices.front(); E; E = E->next()) {
- Variant v = animation->track_get_key_value(i, E->get());
+ for (int &E : indices) {
+ Variant v = animation->track_get_key_value(i, E);
set_track_value(i, v);
}
}
@@ -263,9 +263,9 @@ void AnimationCache::set_all(float p_time, float p_delta) {
List<int> indices;
animation->method_track_get_key_indices(i, p_time, p_delta, &indices);
- for (List<int>::Element *E = indices.front(); E; E = E->next()) {
- Vector<Variant> args = animation->method_track_get_params(i, E->get());
- StringName name = animation->method_track_get_name(i, E->get());
+ for (int &E : indices) {
+ Vector<Variant> args = animation->method_track_get_params(i, E);
+ StringName name = animation->method_track_get_name(i, E);
Callable::CallError err;
if (!args.size()) {
diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp
index 6496331cb0..bf53b554bf 100644
--- a/scene/animation/animation_node_state_machine.cpp
+++ b/scene/animation/animation_node_state_machine.cpp
@@ -512,8 +512,8 @@ void AnimationNodeStateMachine::get_parameter_list(List<PropertyInfo> *r_list) c
}
advance_conditions.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = advance_conditions.front(); E; E = E->next()) {
- r_list->push_back(PropertyInfo(Variant::BOOL, E->get()));
+ for (const StringName &E : advance_conditions) {
+ r_list->push_back(PropertyInfo(Variant::BOOL, E));
}
}
@@ -679,8 +679,8 @@ void AnimationNodeStateMachine::get_node_list(List<StringName> *r_nodes) const {
}
nodes.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = nodes.front(); E; E = E->next()) {
- r_nodes->push_back(E->get());
+ for (const StringName &E : nodes) {
+ r_nodes->push_back(E);
}
}
@@ -902,8 +902,7 @@ void AnimationNodeStateMachine::_get_property_list(List<PropertyInfo> *p_list) c
}
names.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
- String name = E->get();
+ for (const StringName &name : names) {
p_list->push_back(PropertyInfo(Variant::OBJECT, "states/" + name + "/node", PROPERTY_HINT_RESOURCE_TYPE, "AnimationNode", PROPERTY_USAGE_NOEDITOR));
p_list->push_back(PropertyInfo(Variant::VECTOR2, "states/" + name + "/position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 14ca325c25..67b6205a65 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -176,8 +176,8 @@ void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const {
anim_names.sort();
- for (List<PropertyInfo>::Element *E = anim_names.front(); E; E = E->next()) {
- p_list->push_back(E->get());
+ for (const PropertyInfo &E : anim_names) {
+ p_list->push_back(E);
}
p_list->push_back(PropertyInfo(Variant::ARRAY, "blend_times", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL));
@@ -485,8 +485,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
List<int> indices;
a->value_track_get_key_indices(i, p_time, p_delta, &indices);
- for (List<int>::Element *F = indices.front(); F; F = F->next()) {
- Variant value = a->track_get_key_value(i, F->get());
+ for (int &F : indices) {
+ Variant value = a->track_get_key_value(i, F);
switch (pa->special) {
case SP_NONE: {
bool valid;
@@ -544,9 +544,9 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, float
a->method_track_get_key_indices(i, p_time, p_delta, &indices);
- for (List<int>::Element *E = indices.front(); E; E = E->next()) {
- StringName method = a->method_track_get_name(i, E->get());
- Vector<Variant> params = a->method_track_get_params(i, E->get());
+ for (int &E : indices) {
+ StringName method = a->method_track_get_name(i, E);
+ Vector<Variant> params = a->method_track_get_params(i, E);
int s = params.size();
@@ -1076,8 +1076,8 @@ void AnimationPlayer::get_animation_list(List<StringName> *p_animations) const {
anims.sort();
- for (List<String>::Element *E = anims.front(); E; E = E->next()) {
- p_animations->push_back(E->get());
+ for (const String &E : anims) {
+ p_animations->push_back(E);
}
}
@@ -1118,8 +1118,8 @@ void AnimationPlayer::queue(const StringName &p_name) {
Vector<String> AnimationPlayer::get_queue() {
Vector<String> ret;
- for (List<StringName>::Element *E = queued.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const StringName &E : queued) {
+ ret.push_back(E);
}
return ret;
@@ -1502,8 +1502,8 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i
if (p_idx == 0 && (p_function == "play" || p_function == "play_backwards" || p_function == "remove_animation" || p_function == "has_animation" || p_function == "queue")) {
List<StringName> al;
get_animation_list(&al);
- for (List<StringName>::Element *E = al.front(); E; E = E->next()) {
- r_options->push_back(quote_style + String(E->get()) + quote_style);
+ for (const StringName &E : al) {
+ r_options->push_back(quote_style + String(E) + quote_style);
}
}
Node::get_argument_options(p_function, p_idx, r_options);
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 72448fc4f7..00b847168d 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -76,10 +76,10 @@ void AnimationNode::get_child_nodes(List<ChildNode> *r_child_nodes) {
Dictionary cn = get_script_instance()->call("_get_child_nodes");
List<Variant> keys;
cn.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
+ for (const Variant &E : keys) {
ChildNode child;
- child.name = E->get();
- child.node = cn[E->get()];
+ child.name = E;
+ child.node = cn[E];
r_child_nodes->push_back(child);
}
}
@@ -536,8 +536,8 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
List<StringName> sname;
player->get_animation_list(&sname);
- for (List<StringName>::Element *E = sname.front(); E; E = E->next()) {
- Ref<Animation> anim = player->get_animation(E->get());
+ for (const StringName &E : sname) {
+ Ref<Animation> anim = player->get_animation(E);
for (int i = 0; i < anim->get_track_count(); i++) {
NodePath path = anim->track_get_path(i);
Animation::TrackType track_type = anim->track_get_type(i);
@@ -561,7 +561,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
Node *child = parent->get_node_and_resource(path, resource, leftover_path);
if (!child) {
- ERR_PRINT("AnimationTree: '" + String(E->get()) + "', couldn't resolve track: '" + String(path) + "'");
+ ERR_PRINT("AnimationTree: '" + String(E) + "', couldn't resolve track: '" + String(path) + "'");
continue;
}
@@ -590,7 +590,7 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
Node3D *node_3d = Object::cast_to<Node3D>(child);
if (!node_3d) {
- ERR_PRINT("AnimationTree: '" + String(E->get()) + "', transform track does not point to Node3D: '" + String(path) + "'");
+ ERR_PRINT("AnimationTree: '" + String(E) + "', transform track does not point to Node3D: '" + String(path) + "'");
continue;
}
@@ -816,9 +816,7 @@ void AnimationTree::_process_graph(float p_delta) {
{
bool can_call = is_inside_tree() && !Engine::get_singleton()->is_editor_hint();
- for (List<AnimationNode::AnimationState>::Element *E = state.animation_states.front(); E; E = E->next()) {
- const AnimationNode::AnimationState &as = E->get();
-
+ for (const AnimationNode::AnimationState &as : state.animation_states) {
Ref<Animation> a = as.animation;
float time = as.time;
float delta = as.delta;
@@ -962,8 +960,8 @@ void AnimationTree::_process_graph(float p_delta) {
List<int> indices;
a->value_track_get_key_indices(i, time, delta, &indices);
- for (List<int>::Element *F = indices.front(); F; F = F->next()) {
- Variant value = a->track_get_key_value(i, F->get());
+ for (int &F : indices) {
+ Variant value = a->track_get_key_value(i, F);
t->object->set_indexed(t->subpath, value);
}
}
@@ -979,9 +977,9 @@ void AnimationTree::_process_graph(float p_delta) {
a->method_track_get_key_indices(i, time, delta, &indices);
- for (List<int>::Element *F = indices.front(); F; F = F->next()) {
- StringName method = a->method_track_get_name(i, F->get());
- Vector<Variant> params = a->method_track_get_params(i, F->get());
+ for (int &F : indices) {
+ StringName method = a->method_track_get_name(i, F);
+ Vector<Variant> params = a->method_track_get_params(i, F);
int s = params.size();
@@ -1355,9 +1353,7 @@ void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<A
List<PropertyInfo> plist;
node->get_parameter_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- PropertyInfo pinfo = E->get();
-
+ for (PropertyInfo &pinfo : plist) {
StringName key = pinfo.name;
if (!property_map.has(p_base_path + key)) {
@@ -1373,8 +1369,8 @@ void AnimationTree::_update_properties_for_node(const String &p_base_path, Ref<A
List<AnimationNode::ChildNode> children;
node->get_child_nodes(&children);
- for (List<AnimationNode::ChildNode>::Element *E = children.front(); E; E = E->next()) {
- _update_properties_for_node(p_base_path + E->get().name + "/", E->get().node);
+ for (const AnimationNode::ChildNode &E : children) {
+ _update_properties_for_node(p_base_path + E.name + "/", E.node);
}
}
@@ -1428,17 +1424,17 @@ void AnimationTree::_get_property_list(List<PropertyInfo> *p_list) const {
const_cast<AnimationTree *>(this)->_update_properties();
}
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- p_list->push_back(E->get());
+ for (const PropertyInfo &E : properties) {
+ p_list->push_back(E);
}
}
void AnimationTree::rename_parameter(const String &p_base, const String &p_new_base) {
//rename values first
- for (const List<PropertyInfo>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().name.begins_with(p_base)) {
- String new_name = E->get().name.replace_first(p_base, p_new_base);
- property_map[new_name] = property_map[E->get().name];
+ for (const PropertyInfo &E : properties) {
+ if (E.name.begins_with(p_base)) {
+ String new_name = E.name.replace_first(p_base, p_new_base);
+ property_map[new_name] = property_map[E.name];
}
}
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 761046c14a..a57e986877 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -46,8 +46,8 @@ void Tween::start_tweeners() {
ERR_FAIL_MSG("Tween without commands, aborting.");
}
- for (List<Ref<Tweener>>::Element *E = tweeners.write[current_step].front(); E; E = E->next()) {
- E->get()->start();
+ for (Ref<Tweener> &tweener : tweeners.write[current_step]) {
+ tweener->start();
}
}
@@ -253,11 +253,11 @@ bool Tween::step(float p_delta) {
float step_delta = rem_delta;
step_active = false;
- for (List<Ref<Tweener>>::Element *E = tweeners.write[current_step].front(); E; E = E->next()) {
+ for (Ref<Tweener> &tweener : tweeners.write[current_step]) {
// Modified inside Tweener.step().
float temp_delta = rem_delta;
// Turns to true if any Tweener returns true (i.e. is still not finished).
- step_active = E->get()->step(temp_delta) || step_active;
+ step_active = tweener->step(temp_delta) || step_active;
step_delta = MIN(temp_delta, rem_delta);
}
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index fd5637be11..ce2b320c96 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -292,9 +292,9 @@ SceneDebuggerObject::SceneDebuggerObject(ObjectID p_id) {
// Add base object properties.
List<PropertyInfo> pinfo;
obj->get_property_list(&pinfo, true);
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
- properties.push_back(SceneDebuggerProperty(E->get(), obj->get(E->get().name)));
+ for (const PropertyInfo &E : pinfo) {
+ if (E.usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
+ properties.push_back(SceneDebuggerProperty(E, obj->get(E.name)));
}
}
}
@@ -452,8 +452,7 @@ SceneDebuggerTree::SceneDebuggerTree(Node *p_root) {
}
void SceneDebuggerTree::serialize(Array &p_arr) {
- for (List<RemoteNode>::Element *E = nodes.front(); E; E = E->next()) {
- RemoteNode &n = E->get();
+ for (const RemoteNode &n : nodes) {
p_arr.push_back(n.child_count);
p_arr.push_back(n.name);
p_arr.push_back(n.type_name);
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index f302f64224..be5e0bf4e5 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -2128,7 +2128,7 @@ int CodeEdit::_is_in_delimiter(int p_line, int p_column, DelimiterType p_type) c
int region = (p_line <= 0 || delimiter_cache[p_line - 1].size() < 1) ? -1 : delimiter_cache[p_line - 1].back()->value();
bool in_region = region != -1 && delimiters[region].type == p_type;
for (Map<int, int>::Element *E = delimiter_cache[p_line].front(); E; E = E->next()) {
- /* If column is specified, loop untill the key is larger then the column. */
+ /* If column is specified, loop until the key is larger then the column. */
if (p_column != -1) {
if (E->key() > p_column) {
break;
@@ -2138,7 +2138,7 @@ int CodeEdit::_is_in_delimiter(int p_line, int p_column, DelimiterType p_type) c
continue;
}
- /* If no column, calulate if the entire line is a region */
+ /* If no column, calculate if the entire line is a region */
/* excluding whitespace. */
const String line = get_line(p_line);
if (!in_region) {
@@ -2288,14 +2288,14 @@ void CodeEdit::_filter_code_completion_candidates() {
TypedArray<Dictionary> completion_options_sources;
completion_options_sources.resize(code_completion_option_sources.size());
int i = 0;
- for (List<ScriptCodeCompletionOption>::Element *E = code_completion_option_sources.front(); E; E = E->next()) {
+ for (const ScriptCodeCompletionOption &E : code_completion_option_sources) {
Dictionary option;
- option["kind"] = E->get().kind;
- option["display_text"] = E->get().display;
- option["insert_text"] = E->get().insert_text;
- option["font_color"] = E->get().font_color;
- option["icon"] = E->get().icon;
- option["default_value"] = E->get().default_value;
+ option["kind"] = E.kind;
+ option["display_text"] = E.display;
+ option["insert_text"] = E.insert_text;
+ option["font_color"] = E.font_color;
+ option["icon"] = E.icon;
+ option["default_value"] = E.default_value;
completion_options_sources[i] = option;
i++;
}
@@ -2406,9 +2406,7 @@ void CodeEdit::_filter_code_completion_candidates() {
int max_width = 0;
String string_to_complete_lower = string_to_complete.to_lower();
- for (List<ScriptCodeCompletionOption>::Element *E = code_completion_option_sources.front(); E; E = E->next()) {
- ScriptCodeCompletionOption &option = E->get();
-
+ for (ScriptCodeCompletionOption &option : code_completion_option_sources) {
if (single_quote && option.display.is_quoted()) {
option.display = option.display.unquote().quote("'");
}
@@ -2527,8 +2525,7 @@ void CodeEdit::_lines_edited_from(int p_from_line, int p_to_line) {
int line_count = (p_to_line - p_from_line);
List<int> breakpoints;
breakpointed_lines.get_key_list(&breakpoints);
- for (const List<int>::Element *E = breakpoints.front(); E; E = E->next()) {
- int line = E->get();
+ for (const int line : breakpoints) {
if (line <= from_line) {
continue;
}
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 032533d4a9..c19ee849d3 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -343,73 +343,73 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
{
List<StringName> names;
theme->get_icon_list(get_class_name(), &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.icon_override.has(E->get())) {
+ if (data.icon_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_icons/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", usage));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_icons/" + E, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", usage));
}
}
{
List<StringName> names;
theme->get_stylebox_list(get_class_name(), &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.style_override.has(E->get())) {
+ if (data.style_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_styles/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", usage));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_styles/" + E, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", usage));
}
}
{
List<StringName> names;
theme->get_font_list(get_class_name(), &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.font_override.has(E->get())) {
+ if (data.font_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_fonts/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "Font", usage));
+ p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_fonts/" + E, PROPERTY_HINT_RESOURCE_TYPE, "Font", usage));
}
}
{
List<StringName> names;
theme->get_font_size_list(get_class_name(), &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.font_size_override.has(E->get())) {
+ if (data.font_size_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::INT, "custom_font_sizes/" + E->get(), PROPERTY_HINT_NONE, "", usage));
+ p_list->push_back(PropertyInfo(Variant::INT, "custom_font_sizes/" + E, PROPERTY_HINT_NONE, "", usage));
}
}
{
List<StringName> names;
theme->get_color_list(get_class_name(), &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.color_override.has(E->get())) {
+ if (data.color_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::COLOR, "custom_colors/" + E->get(), PROPERTY_HINT_NONE, "", usage));
+ p_list->push_back(PropertyInfo(Variant::COLOR, "custom_colors/" + E, PROPERTY_HINT_NONE, "", usage));
}
}
{
List<StringName> names;
theme->get_constant_list(get_class_name(), &names);
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
- if (data.constant_override.has(E->get())) {
+ if (data.constant_override.has(E)) {
usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
- p_list->push_back(PropertyInfo(Variant::INT, "custom_constants/" + E->get(), PROPERTY_HINT_RANGE, "-16384,16384", usage));
+ p_list->push_back(PropertyInfo(Variant::INT, "custom_constants/" + E, PROPERTY_HINT_RANGE, "-16384,16384", usage));
}
}
}
@@ -428,14 +428,14 @@ void Control::_validate_property(PropertyInfo &property) const {
Vector<StringName> unique_names;
String hint_string;
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
// Skip duplicate values.
- if (unique_names.has(E->get())) {
+ if (unique_names.has(E)) {
continue;
}
- hint_string += String(E->get()) + ",";
- unique_names.append(E->get());
+ hint_string += String(E) + ",";
+ unique_names.append(E);
}
property.hint_string = hint_string;
@@ -454,6 +454,8 @@ void Control::set_layout_direction(Control::LayoutDirection p_direction) {
ERR_FAIL_INDEX((int)p_direction, 4);
data.layout_dir = p_direction;
+ data.is_rtl_dirty = true;
+
propagate_notification(NOTIFICATION_LAYOUT_DIRECTION_CHANGED);
}
@@ -462,29 +464,35 @@ Control::LayoutDirection Control::get_layout_direction() const {
}
bool Control::is_layout_rtl() const {
- if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) {
- Window *parent_window = get_parent_window();
- Control *parent_control = get_parent_control();
- if (parent_control) {
- return parent_control->is_layout_rtl();
- } else if (parent_window) {
- return parent_window->is_layout_rtl();
- } else {
+ if (data.is_rtl_dirty) {
+ const_cast<Control *>(this)->data.is_rtl_dirty = false;
+ if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) {
+ Window *parent_window = get_parent_window();
+ Control *parent_control = get_parent_control();
+ if (parent_control) {
+ const_cast<Control *>(this)->data.is_rtl = parent_control->is_layout_rtl();
+ } else if (parent_window) {
+ const_cast<Control *>(this)->data.is_rtl = parent_window->is_layout_rtl();
+ } else {
+ if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
+ const_cast<Control *>(this)->data.is_rtl = true;
+ } else {
+ String locale = TranslationServer::get_singleton()->get_tool_locale();
+ const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
+ }
+ }
+ } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
- return true;
+ const_cast<Control *>(this)->data.is_rtl = true;
+ } else {
+ String locale = TranslationServer::get_singleton()->get_tool_locale();
+ const_cast<Control *>(this)->data.is_rtl = TS->is_locale_right_to_left(locale);
}
- String locale = TranslationServer::get_singleton()->get_tool_locale();
- return TS->is_locale_right_to_left(locale);
- }
- } else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
- if (GLOBAL_GET(SNAME("internationalization/rendering/force_right_to_left_layout_direction"))) {
- return true;
+ } else {
+ const_cast<Control *>(this)->data.is_rtl = (data.layout_dir == LAYOUT_DIRECTION_RTL);
}
- String locale = TranslationServer::get_singleton()->get_tool_locale();
- return TS->is_locale_right_to_left(locale);
- } else {
- return (data.layout_dir == LAYOUT_DIRECTION_RTL);
}
+ return data.is_rtl;
}
void Control::_clear_size_warning() {
@@ -534,6 +542,7 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_POST_ENTER_TREE: {
data.minimum_size_valid = false;
+ data.is_rtl_dirty = true;
_size_changed();
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -548,6 +557,7 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_ENTER_CANVAS: {
data.parent = Object::cast_to<Control>(get_parent());
data.parent_window = Object::cast_to<Window>(get_parent());
+ data.is_rtl_dirty = true;
Node *parent = this; //meh
Control *parent_control = nullptr;
@@ -613,6 +623,7 @@ void Control::_notification(int p_notification) {
data.parent = nullptr;
data.parent_canvas_item = nullptr;
data.parent_window = nullptr;
+ data.is_rtl_dirty = true;
} break;
case NOTIFICATION_MOVED_IN_PARENT: {
@@ -672,6 +683,7 @@ void Control::_notification(int p_notification) {
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
+ data.is_rtl_dirty = true;
_size_changed();
} break;
}
@@ -793,13 +805,13 @@ T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner
Window *theme_owner_window = p_theme_owner_window;
while (theme_owner || theme_owner_window) {
- for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
- if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E->get())) {
- return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E->get());
+ for (const StringName &E : p_theme_types) {
+ if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {
+ return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E);
}
- if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E->get())) {
- return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E->get());
+ if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) {
+ return theme_owner_window->theme->get_theme_item(p_data_type, p_name, E);
}
}
@@ -822,17 +834,17 @@ T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner
// Secondly, check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) {
- for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
- if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E->get())) {
- return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E->get());
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
+ return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E);
}
}
}
// Lastly, fall back on the items defined in the default Theme, if they exist.
- for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
- if (Theme::get_default()->has_theme_item(p_data_type, p_name, E->get())) {
- return Theme::get_default()->get_theme_item(p_data_type, p_name, E->get());
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
+ return Theme::get_default()->get_theme_item(p_data_type, p_name, E);
}
}
// If they don't exist, use any type to return the default/empty value.
@@ -848,12 +860,12 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
Window *theme_owner_window = p_theme_owner_window;
while (theme_owner || theme_owner_window) {
- for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
- if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E->get())) {
+ for (const StringName &E : p_theme_types) {
+ if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {
return true;
}
- if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E->get())) {
+ if (theme_owner_window && theme_owner_window->theme->has_theme_item(p_data_type, p_name, E)) {
return true;
}
}
@@ -877,16 +889,16 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
// Secondly, check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) {
- for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
- if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E->get())) {
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
return true;
}
}
}
// Lastly, fall back on the items defined in the default Theme, if they exist.
- for (List<StringName>::Element *E = p_theme_types.front(); E; E = E->next()) {
- if (Theme::get_default()->has_theme_item(p_data_type, p_name, E->get())) {
+ for (const StringName &E : p_theme_types) {
+ if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
return true;
}
}
@@ -1594,7 +1606,7 @@ void Control::set_rect(const Rect2 &p_rect) {
void Control::_set_size(const Size2 &p_size) {
#ifdef DEBUG_ENABLED
if (data.size_warning && (data.anchor[SIDE_LEFT] != data.anchor[SIDE_RIGHT] || data.anchor[SIDE_TOP] != data.anchor[SIDE_BOTTOM])) {
- WARN_PRINT("Nodes with non-equal opposite anchors will have their size overriden after _ready(). \nIf you want to set size, change the anchors or consider using set_deferred().");
+ WARN_PRINT("Nodes with non-equal opposite anchors will have their size overridden after _ready(). \nIf you want to set size, change the anchors or consider using set_deferred().");
}
#endif
set_size(p_size);
@@ -2580,8 +2592,8 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List
}
sn.sort_custom<StringName::AlphCompare>();
- for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
- r_options->push_back(quote_style + E->get() + quote_style);
+ for (const StringName &E : sn) {
+ r_options->push_back(quote_style + E + quote_style);
}
}
}
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 51b454b334..3779f9b308 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -179,6 +179,8 @@ private:
GrowDirection v_grow = GROW_DIRECTION_END;
LayoutDirection layout_dir = LAYOUT_DIRECTION_INHERITED;
+ bool is_rtl_dirty = true;
+ bool is_rtl = false;
real_t rotation = 0.0;
Vector2 scale = Vector2(1, 1);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 9ed3a2244e..2e4204e171 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -552,9 +552,9 @@ void FileDialog::update_file_list() {
bool match = patterns.is_empty();
String match_str;
- for (List<String>::Element *E = patterns.front(); E; E = E->next()) {
- if (files.front()->get().matchn(E->get())) {
- match_str = E->get();
+ for (const String &E : patterns) {
+ if (files.front()->get().matchn(E)) {
+ match_str = E;
match = true;
break;
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 2281fb19c6..1fac2b9129 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -217,8 +217,8 @@ Error GraphEdit::connect_node(const StringName &p_from, int p_from_port, const S
}
bool GraphEdit::is_node_connected(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port) {
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- if (E->get().from == p_from && E->get().from_port == p_from_port && E->get().to == p_to && E->get().to_port == p_to_port) {
+ for (const Connection &E : connections) {
+ if (E.from == p_from && E.from_port == p_from_port && E.to == p_to && E.to_port == p_to_port) {
return true;
}
}
@@ -227,7 +227,7 @@ bool GraphEdit::is_node_connected(const StringName &p_from, int p_from_port, con
}
void GraphEdit::disconnect_node(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port) {
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
+ for (const List<Connection>::Element *E = connections.front(); E; E = E->next()) {
if (E->get().from == p_from && E->get().from_port == p_from_port && E->get().to == p_to && E->get().to_port == p_to_port) {
connections.erase(E);
top_layer->update();
@@ -561,20 +561,20 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (is_in_hot_zone(pos / zoom, click_pos)) {
if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) {
//check disconnect
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- if (E->get().from == gn->get_name() && E->get().from_port == j) {
- Node *to = get_node(String(E->get().to));
+ for (const Connection &E : connections) {
+ if (E.from == gn->get_name() && E.from_port == j) {
+ Node *to = get_node(String(E.to));
if (Object::cast_to<GraphNode>(to)) {
- connecting_from = E->get().to;
- connecting_index = E->get().to_port;
+ connecting_from = E.to;
+ connecting_index = E.to_port;
connecting_out = false;
- connecting_type = Object::cast_to<GraphNode>(to)->get_connection_input_type(E->get().to_port);
- connecting_color = Object::cast_to<GraphNode>(to)->get_connection_input_color(E->get().to_port);
+ connecting_type = Object::cast_to<GraphNode>(to)->get_connection_input_type(E.to_port);
+ connecting_color = Object::cast_to<GraphNode>(to)->get_connection_input_color(E.to_port);
connecting_target = false;
connecting_to = pos;
just_disconnected = true;
- emit_signal(SNAME("disconnection_request"), E->get().from, E->get().from_port, E->get().to, E->get().to_port);
+ emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
to = get_node(String(connecting_from)); //maybe it was erased
if (Object::cast_to<GraphNode>(to)) {
connecting = true;
@@ -603,20 +603,20 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (is_in_hot_zone(pos / zoom, click_pos)) {
if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) {
//check disconnect
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- if (E->get().to == gn->get_name() && E->get().to_port == j) {
- Node *fr = get_node(String(E->get().from));
+ for (const Connection &E : connections) {
+ if (E.to == gn->get_name() && E.to_port == j) {
+ Node *fr = get_node(String(E.from));
if (Object::cast_to<GraphNode>(fr)) {
- connecting_from = E->get().from;
- connecting_index = E->get().from_port;
+ connecting_from = E.from;
+ connecting_index = E.from_port;
connecting_out = true;
- connecting_type = Object::cast_to<GraphNode>(fr)->get_connection_output_type(E->get().from_port);
- connecting_color = Object::cast_to<GraphNode>(fr)->get_connection_output_color(E->get().from_port);
+ connecting_type = Object::cast_to<GraphNode>(fr)->get_connection_output_type(E.from_port);
+ connecting_color = Object::cast_to<GraphNode>(fr)->get_connection_output_color(E.from_port);
connecting_target = false;
connecting_to = pos;
just_disconnected = true;
- emit_signal(SNAME("disconnection_request"), E->get().from, E->get().from_port, E->get().to, E->get().to_port);
+ emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port);
fr = get_node(String(connecting_from)); //maybe it was erased
if (Object::cast_to<GraphNode>(fr)) {
connecting = true;
@@ -1001,8 +1001,8 @@ void GraphEdit::_minimap_draw() {
// Draw node connections.
Color activity_color = get_theme_color(SNAME("activity"));
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- NodePath fromnp(E->get().from);
+ for (const Connection &E : connections) {
+ NodePath fromnp(E.from);
Node *from = get_node(fromnp);
if (!from) {
@@ -1013,7 +1013,7 @@ void GraphEdit::_minimap_draw() {
continue;
}
- NodePath tonp(E->get().to);
+ NodePath tonp(E.to);
Node *to = get_node(tonp);
if (!to) {
continue;
@@ -1023,16 +1023,16 @@ void GraphEdit::_minimap_draw() {
continue;
}
- Vector2 from_slot_position = gfrom->get_position_offset() * zoom + gfrom->get_connection_output_position(E->get().from_port);
+ Vector2 from_slot_position = gfrom->get_position_offset() * zoom + gfrom->get_connection_output_position(E.from_port);
Vector2 from_position = minimap->_convert_from_graph_position(from_slot_position - graph_offset) + minimap_offset;
- Color from_color = gfrom->get_connection_output_color(E->get().from_port);
- Vector2 to_slot_position = gto->get_position_offset() * zoom + gto->get_connection_input_position(E->get().to_port);
+ Color from_color = gfrom->get_connection_output_color(E.from_port);
+ Vector2 to_slot_position = gto->get_position_offset() * zoom + gto->get_connection_input_position(E.to_port);
Vector2 to_position = minimap->_convert_from_graph_position(to_slot_position - graph_offset) + minimap_offset;
- Color to_color = gto->get_connection_input_color(E->get().to_port);
+ Color to_color = gto->get_connection_input_color(E.to_port);
- if (E->get().activity > 0) {
- from_color = from_color.lerp(activity_color, E->get().activity);
- to_color = to_color.lerp(activity_color, E->get().activity);
+ if (E.activity > 0) {
+ from_color = from_color.lerp(activity_color, E.activity);
+ to_color = to_color.lerp(activity_color, E.activity);
}
_draw_cos_line(minimap, from_position, to_position, from_color, to_color, 1.0, 0.5);
}
@@ -1360,15 +1360,15 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
void GraphEdit::set_connection_activity(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port, float p_activity) {
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- if (E->get().from == p_from && E->get().from_port == p_from_port && E->get().to == p_to && E->get().to_port == p_to_port) {
- if (Math::is_equal_approx(E->get().activity, p_activity)) {
+ for (Connection &E : connections) {
+ if (E.from == p_from && E.from_port == p_from_port && E.to == p_to && E.to_port == p_to_port) {
+ if (Math::is_equal_approx(E.activity, p_activity)) {
//update only if changed
top_layer->update();
minimap->update();
connections_layer->update();
}
- E->get().activity = p_activity;
+ E.activity = p_activity;
return;
}
}
@@ -1500,12 +1500,12 @@ Array GraphEdit::_get_connection_list() const {
List<Connection> conns;
get_connection_list(&conns);
Array arr;
- for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
+ for (const Connection &E : conns) {
Dictionary d;
- d["from"] = E->get().from;
- d["from_port"] = E->get().from_port;
- d["to"] = E->get().to;
- d["to_port"] = E->get().to_port;
+ d["from"] = E.from;
+ d["from_port"] = E.from_port;
+ d["to"] = E.to;
+ d["to_port"] = E.to_port;
arr.push_back(d);
}
return arr;
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 1e9baa77fc..cf1f41d0fc 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -55,6 +55,36 @@ void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
}
}
+void MenuButton::_popup_visibility_changed(bool p_visible) {
+ set_pressed(p_visible);
+
+ if (!p_visible) {
+ set_process_internal(false);
+ return;
+ }
+
+ if (switch_on_hover) {
+ Window *window = Object::cast_to<Window>(get_viewport());
+ if (window) {
+ mouse_pos_adjusted = window->get_position();
+
+ if (window->is_embedded()) {
+ Window *window_parent = Object::cast_to<Window>(window->get_parent()->get_viewport());
+ while (window_parent) {
+ if (!window_parent->is_embedded()) {
+ mouse_pos_adjusted += window_parent->get_position();
+ break;
+ }
+
+ window_parent = Object::cast_to<Window>(window_parent->get_parent()->get_viewport());
+ }
+ }
+
+ set_process_internal(true);
+ }
+ }
+}
+
void MenuButton::pressed() {
Size2 size = get_size();
@@ -94,10 +124,22 @@ bool MenuButton::is_switch_on_hover() {
}
void MenuButton::_notification(int p_what) {
- if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- if (!is_visible_in_tree()) {
- popup->hide();
- }
+ switch (p_what) {
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (!is_visible_in_tree()) {
+ popup->hide();
+ }
+ } break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ Vector2i mouse_pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted;
+ MenuButton *menu_btn_other = Object::cast_to<MenuButton>(get_viewport()->gui_find_control(mouse_pos));
+
+ if (menu_btn_other && menu_btn_other != this && menu_btn_other->is_switch_on_hover() && !menu_btn_other->is_disabled() &&
+ (get_parent()->is_ancestor_of(menu_btn_other) || menu_btn_other->get_parent()->is_ancestor_of(popup))) {
+ popup->hide();
+ menu_btn_other->pressed();
+ }
+ } break;
}
}
@@ -130,8 +172,8 @@ MenuButton::MenuButton() {
popup = memnew(PopupMenu);
popup->hide();
add_child(popup);
- popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); // For when switching from another MenuButton.
- popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false));
+ popup->connect("about_to_popup", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(true));
+ popup->connect("popup_hide", callable_mp(this, &MenuButton::_popup_visibility_changed), varray(false));
}
MenuButton::~MenuButton() {
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index fd9ae6021e..cc2ca117c4 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -42,11 +42,15 @@ class MenuButton : public Button {
bool disable_shortcuts = false;
PopupMenu *popup;
+ Vector2i mouse_pos_adjusted;
+
Array _get_items() const;
void _set_items(const Array &p_items);
void _gui_input(Ref<InputEvent> p_event) override;
+ void _popup_visibility_changed(bool p_visible);
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 5e1c8cec37..f7e7e1cd60 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -72,6 +72,7 @@ void Popup::_notification(int p_what) {
} else {
_deinitialize_visible_parents();
emit_signal(SNAME("popup_hide"));
+ popped_up = false;
}
} break;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index ee9e0e8ab8..7790a0970c 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -397,17 +397,17 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) {
- if (!item_clickable_area.has_point(m->get_position())) {
- return;
- }
-
- for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
- if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) {
+ for (const Rect2 &E : autohide_areas) {
+ if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E.has_point(m->get_position())) {
_close_pressed();
return;
}
}
+ if (!item_clickable_area.has_point(m->get_position())) {
+ return;
+ }
+
int over = _get_mouse_over(m->get_position());
int id = (over < 0 || items[over].separator || items[over].disabled) ? -1 : (items[over].id >= 0 ? items[over].id : over);
@@ -747,12 +747,12 @@ void PopupMenu::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
//only used when using operating system windows
- if (get_window_id() != DisplayServer::INVALID_WINDOW_ID && autohide_areas.size()) {
+ if (!is_embedded() && autohide_areas.size()) {
Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
mouse_pos -= get_position();
- for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
- if (!Rect2(Point2(), get_size()).has_point(mouse_pos) && E->get().has_point(mouse_pos)) {
+ for (const Rect2 &E : autohide_areas) {
+ if (!Rect2(Point2(), get_size()).has_point(mouse_pos) && E.has_point(mouse_pos)) {
_close_pressed();
return;
}
@@ -786,7 +786,7 @@ void PopupMenu::_notification(int p_what) {
set_process_internal(false);
} else {
- if (get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ if (!is_embedded()) {
set_process_internal(true);
}
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 74718395d3..aedc5d0155 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -140,7 +140,6 @@ class PopupMenu : public Popup {
void _close_pressed();
protected:
- friend class MenuButton;
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 99395aae30..3925e0c38e 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -238,9 +238,9 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font>
}
int idx = 0;
- for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
- ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
- ItemFrame *frame = static_cast<ItemFrame *>(E->get());
+ for (Item *E : table->subitems) {
+ ERR_CONTINUE(E->type != ITEM_FRAME); // Children should all be frames.
+ ItemFrame *frame = static_cast<ItemFrame *>(E);
for (int i = 0; i < frame->lines.size(); i++) {
_resize_line(frame, i, p_base_font, p_base_font_size, 1);
}
@@ -316,9 +316,9 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font>
Vector2 offset;
float row_height = 0.0;
- for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
- ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
- ItemFrame *frame = static_cast<ItemFrame *>(E->get());
+ for (Item *E : table->subitems) {
+ ERR_CONTINUE(E->type != ITEM_FRAME); // Children should all be frames.
+ ItemFrame *frame = static_cast<ItemFrame *>(E);
int column = idx % col_count;
@@ -472,9 +472,9 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
const int available_width = p_width - hseparation * (col_count - 1);
int idx = 0;
- for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
- ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
- ItemFrame *frame = static_cast<ItemFrame *>(E->get());
+ for (Item *E : table->subitems) {
+ ERR_CONTINUE(E->type != ITEM_FRAME); // Children should all be frames.
+ ItemFrame *frame = static_cast<ItemFrame *>(E);
int column = idx % col_count;
for (int i = 0; i < frame->lines.size(); i++) {
@@ -556,7 +556,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
Vector2 offset;
float row_height = 0.0;
- for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
+ for (const List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
ItemFrame *frame = static_cast<ItemFrame *>(E->get());
@@ -783,8 +783,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
int row_count = table->rows.size();
int idx = 0;
- for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
- ItemFrame *frame = static_cast<ItemFrame *>(E->get());
+ for (Item *E : table->subitems) {
+ ItemFrame *frame = static_cast<ItemFrame *>(E);
int col = idx % col_count;
int row = idx / col_count;
@@ -1203,8 +1203,8 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
int col_count = table->columns.size();
int row_count = table->rows.size();
- for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
- ItemFrame *frame = static_cast<ItemFrame *>(E->get());
+ for (Item *E : table->subitems) {
+ ItemFrame *frame = static_cast<ItemFrame *>(E);
int col = idx % col_count;
int row = idx / col_count;
@@ -2080,8 +2080,8 @@ bool RichTextLabel::_find_layout_subitem(Item *from, Item *to) {
return true;
}
- for (List<Item *>::Element *E = from->subitems.front(); E; E = E->next()) {
- bool layout = _find_layout_subitem(E->get(), to);
+ for (Item *E : from->subitems) {
+ bool layout = _find_layout_subitem(E, to);
if (layout) {
return true;
@@ -3448,8 +3448,8 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
}
Vector<ItemFX *> fx_items;
- for (List<Item *>::Element *E = main->subitems.front(); E; E = E->next()) {
- Item *subitem = static_cast<Item *>(E->get());
+ for (Item *E : main->subitems) {
+ Item *subitem = static_cast<Item *>(E);
_fetch_item_fx_stack(subitem, fx_items);
if (fx_items.size()) {
@@ -3719,9 +3719,9 @@ String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p
ItemTable *table = static_cast<ItemTable *>(it);
int idx = 0;
int col_count = table->columns.size();
- for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) {
- ERR_CONTINUE(E->get()->type != ITEM_FRAME); // Children should all be frames.
- ItemFrame *frame = static_cast<ItemFrame *>(E->get());
+ for (Item *E : table->subitems) {
+ ERR_CONTINUE(E->type != ITEM_FRAME); // Children should all be frames.
+ ItemFrame *frame = static_cast<ItemFrame *>(E);
int column = idx % col_count;
for (int i = 0; i < frame->lines.size(); i++) {
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 5a12480577..0a76351885 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -956,8 +956,7 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) {
}
}
- for (List<CanvasItem *>::Element *E = p_node->children_items.front(); E; E = E->next()) {
- CanvasItem *ci = E->get();
+ for (CanvasItem *ci : p_node->children_items) {
if (ci->top_level) {
continue;
}
@@ -1334,9 +1333,9 @@ void CanvasItem::_update_texture_filter_changed(bool p_propagate) {
update();
if (p_propagate) {
- for (List<CanvasItem *>::Element *E = children_items.front(); E; E = E->next()) {
- if (!E->get()->top_level && E->get()->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
- E->get()->_update_texture_filter_changed(true);
+ for (CanvasItem *E : children_items) {
+ if (!E->top_level && E->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
+ E->_update_texture_filter_changed(true);
}
}
}
@@ -1374,9 +1373,9 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) {
RS::get_singleton()->canvas_item_set_default_texture_repeat(get_canvas_item(), texture_repeat_cache);
update();
if (p_propagate) {
- for (List<CanvasItem *>::Element *E = children_items.front(); E; E = E->next()) {
- if (!E->get()->top_level && E->get()->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
- E->get()->_update_texture_repeat_changed(true);
+ for (CanvasItem *E : children_items) {
+ if (!E->top_level && E->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
+ E->_update_texture_repeat_changed(true);
}
}
}
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index f649380afa..2c6cefa771 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -220,8 +220,8 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
client->get_response_headers(&rheaders);
response_headers.resize(0);
downloaded.set(0);
- for (List<String>::Element *E = rheaders.front(); E; E = E->next()) {
- response_headers.push_back(E->get());
+ for (const String &E : rheaders) {
+ response_headers.push_back(E);
}
if (response_code == 301 || response_code == 302) {
@@ -235,9 +235,9 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
String new_request;
- for (List<String>::Element *E = rheaders.front(); E; E = E->next()) {
- if (E->get().findn("Location: ") != -1) {
- new_request = E->get().substr(9, E->get().length()).strip_edges();
+ for (const String &E : rheaders) {
+ if (E.findn("Location: ") != -1) {
+ new_request = E.substr(9, E.length()).strip_edges();
}
}
diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp
index 89dac5f5a8..b5ba1899ec 100644
--- a/scene/main/instance_placeholder.cpp
+++ b/scene/main/instance_placeholder.cpp
@@ -42,9 +42,9 @@ bool InstancePlaceholder::_set(const StringName &p_name, const Variant &p_value)
}
bool InstancePlaceholder::_get(const StringName &p_name, Variant &r_ret) const {
- for (const List<PropSet>::Element *E = stored_values.front(); E; E = E->next()) {
- if (E->get().name == p_name) {
- r_ret = E->get().value;
+ for (const PropSet &E : stored_values) {
+ if (E.name == p_name) {
+ r_ret = E.value;
return true;
}
}
@@ -52,10 +52,10 @@ bool InstancePlaceholder::_get(const StringName &p_name, Variant &r_ret) const {
}
void InstancePlaceholder::_get_property_list(List<PropertyInfo> *p_list) const {
- for (const List<PropSet>::Element *E = stored_values.front(); E; E = E->next()) {
+ for (const PropSet &E : stored_values) {
PropertyInfo pi;
- pi.name = E->get().name;
- pi.type = E->get().value.get_type();
+ pi.name = E.name;
+ pi.type = E.value.get_type();
pi.usage = PROPERTY_USAGE_STORAGE;
p_list->push_back(pi);
@@ -95,8 +95,8 @@ Node *InstancePlaceholder::create_instance(bool p_replace, const Ref<PackedScene
scene->set_name(get_name());
int pos = get_index();
- for (List<PropSet>::Element *E = stored_values.front(); E; E = E->next()) {
- scene->set(E->get().name, E->get().value);
+ for (const PropSet &E : stored_values) {
+ scene->set(E.name, E.value);
}
if (p_replace) {
@@ -114,10 +114,10 @@ Dictionary InstancePlaceholder::get_stored_values(bool p_with_order) {
Dictionary ret;
PackedStringArray order;
- for (List<PropSet>::Element *E = stored_values.front(); E; E = E->next()) {
- ret[E->get().name] = E->get().value;
+ for (const PropSet &E : stored_values) {
+ ret[E.name] = E.value;
if (p_with_order) {
- order.push_back(E->get().name);
+ order.push_back(E.name);
}
};
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 0d060240de..f1e5574351 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1597,8 +1597,8 @@ Array Node::_get_groups() const {
Array groups;
List<GroupInfo> gi;
get_groups(&gi);
- for (List<GroupInfo>::Element *E = gi.front(); E; E = E->next()) {
- groups.push_back(E->get().name);
+ for (const GroupInfo &E : gi) {
+ groups.push_back(E.name);
}
return groups;
@@ -1947,18 +1947,18 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
List<PropertyInfo> plist;
N->get()->get_property_list(&plist);
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : plist) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- String name = E->get().name;
+ String name = E.name;
if (name == script_property_name) {
continue;
}
Variant value = N->get()->get(name).duplicate(true);
- if (E->get().usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) {
+ if (E.usage & PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE) {
Resource *res = Object::cast_to<Resource>(value);
if (res) { // Duplicate only if it's a resource
current_node->set(name, res->duplicate());
@@ -1983,14 +1983,14 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
if (p_flags & DUPLICATE_GROUPS) {
List<GroupInfo> gi;
get_groups(&gi);
- for (List<GroupInfo>::Element *E = gi.front(); E; E = E->next()) {
+ for (const GroupInfo &E : gi) {
#ifdef TOOLS_ENABLED
- if ((p_flags & DUPLICATE_FROM_EDITOR) && !E->get().persistent) {
+ if ((p_flags & DUPLICATE_FROM_EDITOR) && !E.persistent) {
continue;
}
#endif
- node->add_to_group(E->get().name, E->get().persistent);
+ node->add_to_group(E.name, E.persistent);
}
}
@@ -2014,21 +2014,21 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
}
}
- for (List<const Node *>::Element *E = hidden_roots.front(); E; E = E->next()) {
- Node *parent = node->get_node(get_path_to(E->get()->data.parent));
+ for (const Node *&E : hidden_roots) {
+ Node *parent = node->get_node(get_path_to(E->data.parent));
if (!parent) {
memdelete(node);
return nullptr;
}
- Node *dup = E->get()->_duplicate(p_flags, r_duplimap);
+ Node *dup = E->_duplicate(p_flags, r_duplimap);
if (!dup) {
memdelete(node);
return nullptr;
}
parent->add_child(dup);
- int pos = E->get()->get_index();
+ int pos = E->get_index();
if (pos < parent->get_child_count() - 1) {
parent->move_child(dup, pos);
@@ -2073,17 +2073,17 @@ void Node::remap_node_resources(Node *p_node, const Map<RES, RES> &p_resource_re
List<PropertyInfo> props;
p_node->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant v = p_node->get(E->get().name);
+ Variant v = p_node->get(E.name);
if (v.is_ref()) {
RES res = v;
if (res.is_valid()) {
if (p_resource_remap.has(res)) {
- p_node->set(E->get().name, p_resource_remap[res]);
+ p_node->set(E.name, p_resource_remap[res]);
remap_nested_resources(res, p_resource_remap);
}
}
@@ -2099,17 +2099,17 @@ void Node::remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resourc
List<PropertyInfo> props;
p_resource->get_property_list(&props);
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- Variant v = p_resource->get(E->get().name);
+ Variant v = p_resource->get(E.name);
if (v.is_ref()) {
RES res = v;
if (res.is_valid()) {
if (p_resource_remap.has(res)) {
- p_resource->set(E->get().name, p_resource_remap[res]);
+ p_resource->set(E.name, p_resource_remap[res]);
remap_nested_resources(res, p_resource_remap);
}
}
@@ -2135,13 +2135,13 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
List<Connection> conns;
n->get_all_signal_connections(&conns);
- for (List<Connection>::Element *E = conns.front(); E; E = E->next()) {
- if (E->get().flags & CONNECT_PERSIST) {
+ for (const Connection &E : conns) {
+ if (E.flags & CONNECT_PERSIST) {
//user connected
NodePath p = p_original->get_path_to(n);
Node *copy = p_copy->get_node(p);
- Node *target = Object::cast_to<Node>(E->get().callable.get_object());
+ Node *target = Object::cast_to<Node>(E.callable.get_object());
if (!target) {
continue;
}
@@ -2158,9 +2158,9 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const {
}
if (copy && copytarget) {
- const Callable copy_callable = Callable(copytarget, E->get().callable.get_method());
- if (!copy->is_connected(E->get().signal.get_name(), copy_callable)) {
- copy->connect(E->get().signal.get_name(), copy_callable, E->get().binds, E->get().flags);
+ const Callable copy_callable = Callable(copytarget, E.callable.get_method());
+ if (!copy->is_connected(E.signal.get_name(), copy_callable)) {
+ copy->connect(E.signal.get_name(), copy_callable, E.binds, E.flags);
}
}
}
@@ -2194,8 +2194,8 @@ void Node::replace_by(Node *p_node, bool p_keep_groups) {
List<GroupInfo> groups;
get_groups(&groups);
- for (List<GroupInfo>::Element *E = groups.front(); E; E = E->next()) {
- p_node->add_to_group(E->get().name, E->get().persistent);
+ for (const GroupInfo &E : groups) {
+ p_node->add_to_group(E.name, E.persistent);
}
}
@@ -2241,9 +2241,7 @@ void Node::_replace_connections_target(Node *p_new_target) {
List<Connection> cl;
get_signals_connected_to_this(&cl);
- for (List<Connection>::Element *E = cl.front(); E; E = E->next()) {
- Connection &c = E->get();
-
+ for (const Connection &c : cl) {
if (c.flags & CONNECT_PERSIST) {
c.signal.get_object()->disconnect(c.signal.get_name(), Callable(this, c.callable.get_method()));
bool valid = p_new_target->has_method(c.callable.get_method()) || Ref<Script>(p_new_target->get_script()).is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.callable.get_method());
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 2fe5d7aa78..dcbbebbc55 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -66,11 +66,11 @@ void SceneTreeTimer::_bind_methods() {
ADD_SIGNAL(MethodInfo("timeout"));
}
-void SceneTreeTimer::set_time_left(float p_time) {
+void SceneTreeTimer::set_time_left(double p_time) {
time_left = p_time;
}
-float SceneTreeTimer::get_time_left() const {
+double SceneTreeTimer::get_time_left() const {
return time_left;
}
@@ -82,12 +82,19 @@ bool SceneTreeTimer::is_process_always() {
return process_always;
}
+void SceneTreeTimer::set_ignore_time_scale(bool p_ignore) {
+ ignore_time_scale = p_ignore;
+}
+
+bool SceneTreeTimer::is_ignore_time_scale() {
+ return ignore_time_scale;
+}
+
void SceneTreeTimer::release_connections() {
List<Connection> connections;
get_all_signal_connections(&connections);
- for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
- Connection const &connection = E->get();
+ for (const Connection &connection : connections) {
disconnect(connection.signal.get_name(), connection.callable);
}
}
@@ -396,7 +403,7 @@ void SceneTree::initialize() {
MainLoop::initialize();
}
-bool SceneTree::physics_process(float p_time) {
+bool SceneTree::physics_process(double p_time) {
root_lock++;
current_frame++;
@@ -425,7 +432,7 @@ bool SceneTree::physics_process(float p_time) {
return _quit;
}
-bool SceneTree::process(float p_time) {
+bool SceneTree::process(double p_time) {
root_lock++;
MainLoop::process(p_time);
@@ -466,8 +473,13 @@ bool SceneTree::process(float p_time) {
E = N;
continue;
}
- float time_left = E->get()->get_time_left();
- time_left -= p_time;
+
+ double time_left = E->get()->get_time_left();
+ if (E->get()->is_ignore_time_scale()) {
+ time_left -= Engine::get_singleton()->get_process_step();
+ } else {
+ time_left -= p_time;
+ }
E->get()->set_time_left(time_left);
if (time_left < 0) {
@@ -559,8 +571,8 @@ void SceneTree::finalize() {
}
// cleanup timers
- for (List<Ref<SceneTreeTimer>>::Element *E = timers.front(); E; E = E->next()) {
- E->get()->release_connections();
+ for (Ref<SceneTreeTimer> &timer : timers) {
+ timer->release_connections();
}
timers.clear();
}
@@ -1112,7 +1124,7 @@ void SceneTree::add_current_scene(Node *p_current) {
root->add_child(p_current);
}
-Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_always) {
+Ref<SceneTreeTimer> SceneTree::create_timer(double p_delay_sec, bool p_process_always) {
Ref<SceneTreeTimer> stt;
stt.instantiate();
stt->set_process_always(p_process_always);
@@ -1134,8 +1146,8 @@ Array SceneTree::get_processed_tweens() {
ret.resize(tweens.size());
int i = 0;
- for (List<Ref<Tween>>::Element *E = tweens.front(); E; E = E->next()) {
- ret[i] = E->get();
+ for (const Ref<Tween> &tween : tweens) {
+ ret[i] = tween;
i++;
}
@@ -1390,11 +1402,11 @@ SceneTree::SceneTree() {
List<String> exts;
ResourceLoader::get_recognized_extensions_for_type("Environment", &exts);
String ext_hint;
- for (List<String>::Element *E = exts.front(); E; E = E->next()) {
+ for (const String &E : exts) {
if (ext_hint != String()) {
ext_hint += ",";
}
- ext_hint += "*." + E->get();
+ ext_hint += "*." + E;
}
// Get path.
String env_path = GLOBAL_DEF("rendering/environment/defaults/default_environment", "");
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 0be0e185a5..cfb95bd6b5 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -52,19 +52,23 @@ class Tween;
class SceneTreeTimer : public RefCounted {
GDCLASS(SceneTreeTimer, RefCounted);
- float time_left = 0.0;
+ double time_left = 0.0;
bool process_always = true;
+ bool ignore_time_scale = false;
protected:
static void _bind_methods();
public:
- void set_time_left(float p_time);
- float get_time_left() const;
+ void set_time_left(double p_time);
+ double get_time_left() const;
void set_process_always(bool p_process_always);
bool is_process_always();
+ void set_ignore_time_scale(bool p_ignore);
+ bool is_ignore_time_scale();
+
void release_connections();
SceneTreeTimer();
@@ -87,8 +91,8 @@ private:
Window *root = nullptr;
uint64_t tree_version = 1;
- float physics_process_time = 1.0;
- float process_time = 1.0;
+ double physics_process_time = 1.0;
+ double process_time = 1.0;
bool accept_quit = true;
bool quit_on_go_back = true;
@@ -233,8 +237,8 @@ public:
virtual void initialize() override;
- virtual bool physics_process(float p_time) override;
- virtual bool process(float p_time) override;
+ virtual bool physics_process(double p_time) override;
+ virtual bool process(double p_time) override;
virtual void finalize() override;
@@ -243,8 +247,8 @@ public:
void quit(int p_exit_code = EXIT_SUCCESS);
- _FORCE_INLINE_ float get_physics_process_time() const { return physics_process_time; }
- _FORCE_INLINE_ float get_process_time() const { return process_time; }
+ _FORCE_INLINE_ double get_physics_process_time() const { return physics_process_time; }
+ _FORCE_INLINE_ double get_process_time() const { return process_time; }
#ifdef TOOLS_ENABLED
bool is_node_being_edited(const Node *p_node) const;
@@ -313,7 +317,7 @@ public:
Error change_scene_to(const Ref<PackedScene> &p_scene);
Error reload_current_scene();
- Ref<SceneTreeTimer> create_timer(float p_delay_sec, bool p_process_always = true);
+ Ref<SceneTreeTimer> create_timer(double p_delay_sec, bool p_process_always = true);
Ref<Tween> create_tween();
Array get_processed_tweens();
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index ef8245076f..b5a2a30b3b 100644
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -81,12 +81,12 @@ void Timer::_notification(int p_what) {
}
}
-void Timer::set_wait_time(float p_time) {
+void Timer::set_wait_time(double p_time) {
ERR_FAIL_COND_MSG(p_time <= 0, "Time should be greater than zero.");
wait_time = p_time;
}
-float Timer::get_wait_time() const {
+double Timer::get_wait_time() const {
return wait_time;
}
@@ -106,7 +106,7 @@ bool Timer::has_autostart() const {
return autostart;
}
-void Timer::start(float p_time) {
+void Timer::start(double p_time) {
ERR_FAIL_COND_MSG(!is_inside_tree(), "Timer was not added to the SceneTree. Either add it or set autostart to true.");
if (p_time > 0) {
@@ -139,7 +139,7 @@ bool Timer::is_stopped() const {
return get_time_left() <= 0;
}
-float Timer::get_time_left() const {
+double Timer::get_time_left() const {
return time_left > 0 ? time_left : 0;
}
diff --git a/scene/main/timer.h b/scene/main/timer.h
index 3d9e21d7fc..2b9faddcb9 100644
--- a/scene/main/timer.h
+++ b/scene/main/timer.h
@@ -36,7 +36,7 @@
class Timer : public Node {
GDCLASS(Timer, Node);
- float wait_time = 1.0;
+ double wait_time = 1.0;
bool one_shot = false;
bool autostart = false;
bool processing = false;
@@ -54,8 +54,8 @@ public:
TIMER_PROCESS_IDLE,
};
- void set_wait_time(float p_time);
- float get_wait_time() const;
+ void set_wait_time(double p_time);
+ double get_wait_time() const;
void set_one_shot(bool p_one_shot);
bool is_one_shot() const;
@@ -63,7 +63,7 @@ public:
void set_autostart(bool p_start);
bool has_autostart() const;
- void start(float p_time = -1);
+ void start(double p_time = -1);
void stop();
void set_paused(bool p_paused);
@@ -71,7 +71,7 @@ public:
bool is_stopped() const;
- float get_time_left() const;
+ double get_time_left() const;
void set_timer_process_callback(TimerProcessCallback p_callback);
TimerProcessCallback get_timer_process_callback() const;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 5a0a27520b..27e42db1bd 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -502,17 +502,6 @@ void Viewport::_notification(int p_what) {
RS::get_singleton()->viewport_set_active(viewport, false);
RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, RID());
-
- } break;
- case NOTIFICATION_INTERNAL_PROCESS: {
- if (gui.tooltip_timer >= 0) {
- gui.tooltip_timer -= get_process_delta_time();
- if (gui.tooltip_timer < 0) {
- _gui_show_tooltip();
- set_process_internal(false);
- }
- }
-
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) {
@@ -584,8 +573,7 @@ void Viewport::_process_picking() {
// if no mouse event exists, create a motion one. This is necessary because objects or camera may have moved.
// while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame
bool has_mouse_event = false;
- for (List<Ref<InputEvent>>::Element *E = physics_picking_events.front(); E; E = E->next()) {
- Ref<InputEventMouse> m = E->get();
+ for (const Ref<InputEvent> &m : physics_picking_events) {
if (m.is_valid()) {
has_mouse_event = true;
break;
@@ -1489,8 +1477,10 @@ void Viewport::_gui_sort_roots() {
void Viewport::_gui_cancel_tooltip() {
gui.tooltip_control = nullptr;
- gui.tooltip_timer = -1;
- set_process_internal(false);
+ if (gui.tooltip_timer.is_valid()) {
+ gui.tooltip_timer->release_connections();
+ gui.tooltip_timer = Ref<SceneTreeTimer>();
+ }
if (gui.tooltip_popup) {
gui.tooltip_popup->queue_delete();
gui.tooltip_popup = nullptr;
@@ -1710,7 +1700,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) {
//_unblock();
}
-Control *Viewport::_gui_find_control(const Point2 &p_global) {
+Control *Viewport::gui_find_control(const Point2 &p_global) {
//aca va subwindows
_gui_sort_roots();
@@ -1850,7 +1840,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
parent_xform=data.parent_canvas_item->get_global_transform();
*/
- gui.mouse_focus = _gui_find_control(pos);
+ gui.mouse_focus = gui_find_control(pos);
gui.last_mouse_focus = gui.mouse_focus;
if (!gui.mouse_focus) {
@@ -1991,7 +1981,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
- over = _gui_find_control(mpos);
+ over = gui_find_control(mpos);
}
if (gui.mouse_focus_mask == 0 && over != gui.mouse_over) {
@@ -2074,7 +2064,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.mouse_focus) {
over = gui.mouse_focus;
} else {
- over = _gui_find_control(mpos);
+ over = gui_find_control(mpos);
}
if (over != gui.mouse_over) {
@@ -2139,10 +2129,15 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
if (can_tooltip && !is_tooltip_shown) {
+ if (gui.tooltip_timer.is_valid()) {
+ gui.tooltip_timer->release_connections();
+ gui.tooltip_timer = Ref<SceneTreeTimer>();
+ }
gui.tooltip_control = over;
gui.tooltip_pos = over->get_screen_transform().xform(pos);
- gui.tooltip_timer = gui.tooltip_delay;
- set_process_internal(true);
+ gui.tooltip_timer = get_tree()->create_timer(gui.tooltip_delay);
+ gui.tooltip_timer->set_ignore_time_scale(true);
+ gui.tooltip_timer->connect("timeout", callable_mp(this, &Viewport::_gui_show_tooltip));
}
}
@@ -2262,7 +2257,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Transform2D ai = (viewport_under->get_final_transform().affine_inverse() * viewport_under->_get_input_pre_xform());
viewport_pos = ai.xform(viewport_pos);
//find control under at pos
- gui.drag_mouse_over = viewport_under->_gui_find_control(viewport_pos);
+ gui.drag_mouse_over = viewport_under->gui_find_control(viewport_pos);
if (gui.drag_mouse_over) {
Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse();
gui.drag_mouse_over_pos = localizer.xform(viewport_pos);
@@ -2290,7 +2285,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (touch_event.is_valid()) {
Size2 pos = touch_event->get_position();
if (touch_event->is_pressed()) {
- Control *over = _gui_find_control(pos);
+ Control *over = gui_find_control(pos);
if (over) {
if (over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); //make a copy
@@ -2325,7 +2320,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Size2 pos = gesture_event->get_position();
- Control *over = _gui_find_control(pos);
+ Control *over = gui_find_control(pos);
if (over) {
if (over->can_process()) {
gesture_event = gesture_event->xformed_by(Transform2D()); //make a copy
@@ -2346,7 +2341,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (drag_event.is_valid()) {
Control *over = gui.mouse_focus;
if (!over) {
- over = _gui_find_control(drag_event->get_position());
+ over = gui_find_control(drag_event->get_position());
}
if (over) {
if (over->can_process()) {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 7b7f1c3818..b5c49a8a97 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -50,6 +50,7 @@ class Label;
class Timer;
class Viewport;
class CollisionObject3D;
+class SceneTreeTimer;
class ViewportTexture : public Texture2D {
GDCLASS(ViewportTexture, Texture2D);
@@ -263,7 +264,7 @@ private:
Transform3D physics_last_camera_transform;
ObjectID physics_last_id;
bool physics_has_last_mousepos = false;
- Vector2 physics_last_mousepos = Vector2(Math_INF, Math_INF);
+ Vector2 physics_last_mousepos = Vector2(INFINITY, INFINITY);
struct {
bool alt = false;
bool control = false;
@@ -373,7 +374,7 @@ private:
bool drag_attempted = false;
Variant drag_data;
ObjectID drag_preview_id;
- float tooltip_timer = -1.0;
+ Ref<SceneTreeTimer> tooltip_timer;
float tooltip_delay = 0.0;
Transform2D focus_inv_xform;
bool roots_order_dirty = false;
@@ -404,7 +405,6 @@ private:
void _gui_call_notification(Control *p_control, int p_what);
void _gui_sort_roots();
- Control *_gui_find_control(const Point2 &p_global);
Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform);
void _gui_input_event(Ref<InputEvent> p_event);
@@ -629,6 +629,8 @@ public:
bool gui_is_dragging() const;
+ Control *gui_find_control(const Point2 &p_global);
+
void set_sdf_oversize(SDFOversize p_sdf_oversize);
SDFOversize get_sdf_oversize() const;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index bf7512e8eb..ab1846660b 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -1356,14 +1356,14 @@ void Window::_validate_property(PropertyInfo &property) const {
Vector<StringName> unique_names;
String hint_string;
- for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
+ for (const StringName &E : names) {
// Skip duplicate values.
- if (unique_names.has(E->get())) {
+ if (unique_names.has(E)) {
continue;
}
- hint_string += String(E->get()) + ",";
- unique_names.append(E->get());
+ hint_string += String(E) + ",";
+ unique_names.append(E);
}
property.hint_string = hint_string;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 2d83f59bb5..8ede8e9a0b 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -909,7 +909,6 @@ void register_scene_types() {
ClassDB::add_compatibility_class("Generic6DOFJoint", "Generic6DOFJoint3D");
ClassDB::add_compatibility_class("HeightMapShape", "HeightMapShape3D");
ClassDB::add_compatibility_class("HingeJoint", "HingeJoint3D");
- ClassDB::add_compatibility_class("ImmediateGeometry", "ImmediateGeometry3D");
ClassDB::add_compatibility_class("Joint", "Joint3D");
ClassDB::add_compatibility_class("KinematicBody", "CharacterBody3D");
ClassDB::add_compatibility_class("KinematicBody2D", "CharacterBody2D");
@@ -1085,6 +1084,10 @@ void unregister_scene_types() {
BaseMaterial3D::finish_shaders();
#endif // _3D_DISABLED
+ PhysicalSkyMaterial::cleanup_shader();
+ PanoramaSkyMaterial::cleanup_shader();
+ ProceduralSkyMaterial::cleanup_shader();
+
ParticlesMaterial::finish_shaders();
CanvasItemMaterial::finish_shaders();
ColorPicker::finish_shaders();
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index 1484007333..920ee2e5ab 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -228,8 +228,8 @@ private:
value_track_get_key_indices(p_track, p_time, p_delta, &idxs);
Vector<int> idxr;
- for (List<int>::Element *E = idxs.front(); E; E = E->next()) {
- idxr.push_back(E->get());
+ for (int &E : idxs) {
+ idxr.push_back(E);
}
return idxr;
}
@@ -238,8 +238,8 @@ private:
method_track_get_key_indices(p_track, p_time, p_delta, &idxs);
Vector<int> idxr;
- for (List<int>::Element *E = idxs.front(); E; E = E->next()) {
- idxr.push_back(E->get());
+ for (int &E : idxs) {
+ idxr.push_back(E);
}
return idxr;
}
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 53979e16df..c13db83d6d 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -729,8 +729,8 @@ void Curve2D::_bake() const {
Vector2 *w = baked_point_cache.ptrw();
int idx = 0;
- for (List<Vector2>::Element *E = pointlist.front(); E; E = E->next()) {
- w[idx] = E->get();
+ for (const Vector2 &E : pointlist) {
+ w[idx] = E;
idx++;
}
}
@@ -1239,9 +1239,9 @@ void Curve3D::_bake() const {
Vector3 prev_up = Vector3(0, 1, 0);
Vector3 prev_forward = Vector3(0, 0, 1);
- for (List<Plane>::Element *E = pointlist.front(); E; E = E->next()) {
- w[idx] = E->get().normal;
- wt[idx] = E->get().d;
+ for (const Plane &E : pointlist) {
+ w[idx] = E.normal;
+ wt[idx] = E.d;
if (!up_vector_enabled) {
idx++;
diff --git a/scene/resources/immediate_mesh.cpp b/scene/resources/immediate_mesh.cpp
index ebe65605f8..05d1a7bf94 100644
--- a/scene/resources/immediate_mesh.cpp
+++ b/scene/resources/immediate_mesh.cpp
@@ -146,7 +146,7 @@ void ImmediateMesh::surface_add_vertex_2d(const Vector2 &p_vertex) {
}
void ImmediateMesh::surface_end() {
ERR_FAIL_COND_MSG(!surface_active, "Not creating any surface. Use surface_begin() to do it.");
- ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface cant be created.");
+ ERR_FAIL_COND_MSG(!vertices.size(), "No vertices were added, surface can't be created.");
uint32_t format = ARRAY_FORMAT_VERTEX;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 7d49533afd..08f7274ff6 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -278,8 +278,8 @@ void ShaderMaterial::get_argument_options(const StringName &p_function, int p_id
if (shader.is_valid()) {
List<PropertyInfo> pl;
shader->get_param_list(&pl);
- for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) {
- r_options->push_back(quote_style + E->get().name.replace_first("shader_param/", "") + quote_style);
+ for (const PropertyInfo &E : pl) {
+ r_options->push_back(quote_style + E.name.replace_first("shader_param/", "") + quote_style);
}
}
}
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index d2be2bdba1..ddc50c0490 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -329,9 +329,7 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() {
Vector3 *tw = tmeshfaces.ptrw();
int tidx = 0;
- for (List<Face3>::Element *E = faces.front(); E; E = E->next()) {
- const Face3 &f = E->get();
-
+ for (const Face3 &f : faces) {
for (int j = 0; j < 3; j++) {
tw[tidx++] = f.vertex[j];
_EdgeKey ek;
@@ -366,8 +364,8 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() {
{
Vector3 *w = varr.ptrw();
int idx = 0;
- for (List<Vector3>::Element *E = lines.front(); E; E = E->next()) {
- w[idx++] = E->get();
+ for (const Vector3 &E : lines) {
+ w[idx++] = E;
}
}
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 9bb2a4ddb8..eddbb9a842 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -206,8 +206,8 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
node->set(snames[nprops[j].name], props[nprops[j].value], &valid);
//restore old state for new script, if exists
- for (List<Pair<StringName, Variant>>::Element *E = old_state.front(); E; E = E->next()) {
- node->set(E->get().first, E->get().second);
+ for (const Pair<StringName, Variant> &E : old_state) {
+ node->set(E.first, E.second);
}
} else {
Variant value = props[nprops[j].value];
@@ -477,13 +477,13 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
script->update_exports();
}
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : plist) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- String name = E->get().name;
- Variant value = p_node->get(E->get().name);
+ String name = E.name;
+ Variant value = p_node->get(E.name);
bool isdefault = false;
Variant default_value = ClassDB::class_get_default_property_value(type, name);
@@ -497,7 +497,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
}
// the version above makes more sense, because it does not rely on placeholder or usage flag
// in the script, just the default value function.
- // if (E->get().usage & PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE) {
+ // if (E.usage & PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE) {
// isdefault = true; //is script default value
// }
@@ -507,7 +507,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
// only save what has been changed
// only save changed properties in instance
- if ((E->get().usage & PROPERTY_USAGE_NO_INSTANCE_STATE) || E->get().name == "__meta__") {
+ if ((E.usage & PROPERTY_USAGE_NO_INSTANCE_STATE) || E.name == "__meta__") {
//property has requested that no instance state is saved, sorry
//also, meta won't be overridden or saved
continue;
@@ -520,7 +520,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
//check all levels of pack to see if the property exists somewhere
const PackState &ps = F->get();
- original = ps.state->get_property_value(ps.node, E->get().name, exists);
+ original = ps.state->get_property_value(ps.node, E.name, exists);
if (exists) {
break;
}
@@ -565,9 +565,7 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
List<Node::GroupInfo> groups;
p_node->get_groups(&groups);
- for (List<Node::GroupInfo>::Element *E = groups.front(); E; E = E->next()) {
- Node::GroupInfo &gi = E->get();
-
+ for (const Node::GroupInfo &gi : groups) {
if (!gi.persistent) {
continue;
}
@@ -577,9 +575,9 @@ Error SceneState::_parse_node(Node *p_owner, Node *p_node, int p_parent_idx, Map
*/
bool skip = false;
- for (List<PackState>::Element *F = pack_state_stack.front(); F; F = F->next()) {
+ for (const PackState &F : pack_state_stack) {
//check all levels of pack to see if the group was added somewhere
- const PackState &ps = F->get();
+ const PackState &ps = F;
if (ps.state->is_node_in_group(ps.node, gi.name)) {
skip = true;
break;
@@ -679,14 +677,14 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName
//ERR_FAIL_COND_V( !node_map.has(p_node), ERR_BUG);
//NodeData &nd = nodes[node_map[p_node]];
- for (List<MethodInfo>::Element *E = _signals.front(); E; E = E->next()) {
+ for (const MethodInfo &E : _signals) {
List<Node::Connection> conns;
- p_node->get_signal_connection_list(E->get().name, &conns);
+ p_node->get_signal_connection_list(E.name, &conns);
conns.sort();
- for (List<Node::Connection>::Element *F = conns.front(); F; F = F->next()) {
- const Node::Connection &c = F->get();
+ for (const Node::Connection &F : conns) {
+ const Node::Connection &c = F;
if (!(c.flags & CONNECT_PERSIST)) { //only persistent connections get saved
continue;
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index 00bea312b3..7da9cb96ee 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -90,6 +90,10 @@ void ParticlesMaterial::init_shaders() {
shader_names->emission_texture_points = "emission_texture_points";
shader_names->emission_texture_normal = "emission_texture_normal";
shader_names->emission_texture_color = "emission_texture_color";
+ shader_names->emission_ring_axis = "emission_ring_axis";
+ shader_names->emission_ring_height = "emission_ring_height";
+ shader_names->emission_ring_radius = "emission_ring_radius";
+ shader_names->emission_ring_inner_radius = "emission_ring_inner_radius";
shader_names->gravity = "gravity";
@@ -194,6 +198,12 @@ void ParticlesMaterial::_update_shader() {
code += "uniform sampler2D emission_texture_color : hint_white;\n";
}
} break;
+ case EMISSION_SHAPE_RING: {
+ code += "uniform vec3 " + shader_names->emission_ring_axis + ";\n";
+ code += "uniform float " + shader_names->emission_ring_height + ";\n";
+ code += "uniform float " + shader_names->emission_ring_radius + ";\n";
+ code += "uniform float " + shader_names->emission_ring_inner_radius + ";\n";
+ } break;
case EMISSION_SHAPE_MAX: { // Max value for validity check.
break;
}
@@ -396,6 +406,28 @@ void ParticlesMaterial::_update_shader() {
}
}
} break;
+ case EMISSION_SHAPE_RING: {
+ code += " float ring_spawn_angle = rand_from_seed(alt_seed) * 2.0 * pi;\n";
+ code += " float ring_random_radius = rand_from_seed(alt_seed) * (emission_ring_radius - emission_ring_inner_radius) + emission_ring_inner_radius;\n";
+ code += " vec3 axis = normalize(emission_ring_axis);\n";
+ code += " vec3 ortho_axis = vec3(0.0);\n";
+ code += " if (axis == vec3(1.0, 0.0, 0.0)) {\n";
+ code += " ortho_axis = cross(axis, vec3(0.0, 1.0, 0.0));\n";
+ code += " } else {\n";
+ code += " ortho_axis = cross(axis, vec3(1.0, 0.0, 0.0));\n";
+ code += " }\n";
+ code += " ortho_axis = normalize(ortho_axis);\n";
+ code += " float s = sin(ring_spawn_angle);\n";
+ code += " float c = cos(ring_spawn_angle);\n";
+ code += " float oc = 1.0 - c;\n";
+ code += " ortho_axis = mat3(\n";
+ code += " vec3(c + axis.x * axis.x * oc, axis.x * axis.y * oc - axis.z * s, axis.x * axis.z *oc + axis.y * s),\n";
+ code += " vec3(axis.x * axis.y * oc + s * axis.z, c + axis.y * axis.y * oc, axis.y * axis.z * oc - axis.x * s),\n";
+ code += " vec3(axis.z * axis.x * oc - axis.y * s, axis.z * axis.y * oc + axis.x * s, c + axis.z * axis.z * oc)\n";
+ code += " ) * ortho_axis;\n";
+ code += " ortho_axis = normalize(ortho_axis);\n";
+ code += " TRANSFORM[3].xyz = ortho_axis * ring_random_radius + (rand_from_seed(alt_seed) * emission_ring_height - emission_ring_height / 2.0) * axis;\n";
+ } break;
case EMISSION_SHAPE_MAX: { // Max value for validity check.
break;
}
@@ -990,6 +1022,26 @@ void ParticlesMaterial::set_emission_point_count(int p_count) {
RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count);
}
+void ParticlesMaterial::set_emission_ring_axis(Vector3 p_axis) {
+ emission_ring_axis = p_axis;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_axis, p_axis);
+}
+
+void ParticlesMaterial::set_emission_ring_height(float p_height) {
+ emission_ring_height = p_height;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_height, p_height);
+}
+
+void ParticlesMaterial::set_emission_ring_radius(float p_radius) {
+ emission_ring_radius = p_radius;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_radius, p_radius);
+}
+
+void ParticlesMaterial::set_emission_ring_inner_radius(float p_radius) {
+ emission_ring_inner_radius = p_radius;
+ RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_inner_radius, p_radius);
+}
+
ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const {
return emission_shape;
}
@@ -1018,6 +1070,22 @@ int ParticlesMaterial::get_emission_point_count() const {
return emission_point_count;
}
+Vector3 ParticlesMaterial::get_emission_ring_axis() const {
+ return emission_ring_axis;
+}
+
+float ParticlesMaterial::get_emission_ring_height() const {
+ return emission_ring_height;
+}
+
+float ParticlesMaterial::get_emission_ring_radius() const {
+ return emission_ring_radius;
+}
+
+float ParticlesMaterial::get_emission_ring_inner_radius() const {
+ return emission_ring_inner_radius;
+}
+
void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) {
gravity = p_gravity;
Vector3 gset = gravity;
@@ -1054,7 +1122,7 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NONE;
}
- if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape < EMISSION_SHAPE_POINTS)) {
+ if ((property.name == "emission_point_texture" || property.name == "emission_color_texture") && (emission_shape != EMISSION_SHAPE_POINTS && emission_shape != EMISSION_SHAPE_DIRECTED_POINTS)) {
property.usage = PROPERTY_USAGE_NONE;
}
@@ -1066,6 +1134,10 @@ void ParticlesMaterial::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NONE;
}
+ if (property.name.begins_with("emission_ring_") && emission_shape != EMISSION_SHAPE_RING) {
+ property.usage = PROPERTY_USAGE_NONE;
+ }
+
if (property.name == "sub_emitter_frequency" && sub_emitter_mode != SUB_EMITTER_CONSTANT) {
property.usage = PROPERTY_USAGE_NONE;
}
@@ -1212,6 +1284,18 @@ void ParticlesMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count);
ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count);
+ ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &ParticlesMaterial::set_emission_ring_axis);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &ParticlesMaterial::get_emission_ring_axis);
+
+ ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &ParticlesMaterial::set_emission_ring_height);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &ParticlesMaterial::get_emission_ring_height);
+
+ ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &ParticlesMaterial::set_emission_ring_radius);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &ParticlesMaterial::get_emission_ring_radius);
+
+ ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticlesMaterial::set_emission_ring_inner_radius);
+ ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticlesMaterial::get_emission_ring_inner_radius);
+
ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity);
ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity);
@@ -1249,13 +1333,17 @@ void ParticlesMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness");
ADD_GROUP("Emission Shape", "emission_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points"), "set_emission_shape", "get_emission_shape");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_shape", PROPERTY_HINT_ENUM, "Point,Sphere,Box,Points,Directed Points,Ring"), "set_emission_shape", "get_emission_shape");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_sphere_radius", PROPERTY_HINT_RANGE, "0.01,128,0.01,or_greater"), "set_emission_sphere_radius", "get_emission_sphere_radius");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_box_extents"), "set_emission_box_extents", "get_emission_box_extents");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_point_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_emission_point_texture", "get_emission_point_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_normal_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_emission_normal_texture", "get_emission_normal_texture");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "emission_color_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_emission_color_texture", "get_emission_color_texture");
ADD_PROPERTY(PropertyInfo(Variant::INT, "emission_point_count", PROPERTY_HINT_RANGE, "0,1000000,1"), "set_emission_point_count", "get_emission_point_count");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "emission_ring_axis"), "set_emission_ring_axis", "get_emission_ring_axis");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_height"), "set_emission_ring_height", "get_emission_ring_height");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_radius"), "set_emission_ring_radius", "get_emission_ring_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "emission_ring_inner_radius"), "set_emission_ring_inner_radius", "get_emission_ring_inner_radius");
ADD_GROUP("ParticleFlags", "particle_flag_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_align_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "particle_flag_rotate_y"), "set_particle_flag", "get_particle_flag", PARTICLE_FLAG_ROTATE_Y);
@@ -1355,6 +1443,7 @@ void ParticlesMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(EMISSION_SHAPE_BOX);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_POINTS);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_DIRECTED_POINTS);
+ BIND_ENUM_CONSTANT(EMISSION_SHAPE_RING);
BIND_ENUM_CONSTANT(EMISSION_SHAPE_MAX);
BIND_ENUM_CONSTANT(SUB_EMITTER_DISABLED);
@@ -1384,6 +1473,10 @@ ParticlesMaterial::ParticlesMaterial() :
set_emission_shape(EMISSION_SHAPE_POINT);
set_emission_sphere_radius(1);
set_emission_box_extents(Vector3(1, 1, 1));
+ set_emission_ring_axis(Vector3(0, 0, 1.0));
+ set_emission_ring_height(1);
+ set_emission_ring_radius(1);
+ set_emission_ring_inner_radius(0);
set_gravity(Vector3(0, -9.8, 0));
set_lifetime_randomness(0);
diff --git a/scene/resources/particles_material.h b/scene/resources/particles_material.h
index 3f874bd68c..8b0b26a3d1 100644
--- a/scene/resources/particles_material.h
+++ b/scene/resources/particles_material.h
@@ -74,6 +74,7 @@ public:
EMISSION_SHAPE_BOX,
EMISSION_SHAPE_POINTS,
EMISSION_SHAPE_DIRECTED_POINTS,
+ EMISSION_SHAPE_RING,
EMISSION_SHAPE_MAX
};
@@ -195,6 +196,10 @@ private:
StringName emission_texture_points;
StringName emission_texture_normal;
StringName emission_texture_color;
+ StringName emission_ring_axis;
+ StringName emission_ring_height;
+ StringName emission_ring_radius;
+ StringName emission_ring_inner_radius;
StringName gravity;
@@ -235,6 +240,10 @@ private:
Ref<Texture2D> emission_point_texture;
Ref<Texture2D> emission_normal_texture;
Ref<Texture2D> emission_color_texture;
+ Vector3 emission_ring_axis;
+ float emission_ring_height;
+ float emission_ring_radius;
+ float emission_ring_inner_radius;
int emission_point_count = 1;
bool anim_loop;
@@ -293,6 +302,10 @@ public:
void set_emission_point_texture(const Ref<Texture2D> &p_points);
void set_emission_normal_texture(const Ref<Texture2D> &p_normals);
void set_emission_color_texture(const Ref<Texture2D> &p_colors);
+ void set_emission_ring_axis(Vector3 p_axis);
+ void set_emission_ring_height(float p_height);
+ void set_emission_ring_radius(float p_radius);
+ void set_emission_ring_inner_radius(float p_radius);
void set_emission_point_count(int p_count);
EmissionShape get_emission_shape() const;
@@ -301,6 +314,10 @@ public:
Ref<Texture2D> get_emission_point_texture() const;
Ref<Texture2D> get_emission_normal_texture() const;
Ref<Texture2D> get_emission_color_texture() const;
+ Vector3 get_emission_ring_axis() const;
+ float get_emission_ring_height() const;
+ float get_emission_ring_radius() const;
+ float get_emission_ring_inner_radius() const;
int get_emission_point_count() const;
void set_gravity(const Vector3 &p_gravity);
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index ee61e64ed3..3f6e926aa7 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -35,8 +35,9 @@
#include "core/io/resource_format_binary.h"
#include "core/version.h"
-//version 2: changed names for basis, aabb, Vectors, etc.
-#define FORMAT_VERSION 2
+// Version 2: changed names for Basis, AABB, Vectors, etc.
+// Version 3: new string ID for ext/subresources, breaks forward compat.
+#define FORMAT_VERSION 3
#include "core/io/dir_access.h"
#include "core/version.h"
@@ -56,22 +57,23 @@ Ref<Resource> ResourceLoaderText::get_resource() {
Error ResourceLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
VariantParser::Token token;
VariantParser::get_token(p_stream, token, line, r_err_str);
- if (token.type != VariantParser::TK_NUMBER) {
- r_err_str = "Expected number (sub-resource index)";
+ if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
+ r_err_str = "Expected number (old style) or string (sub-resource index)";
return ERR_PARSE_ERROR;
}
- int index = token.value;
+ String unique_id = token.value;
- if (!p_data->resource_map.has(index)) {
+ if (!p_data->resource_map.has(unique_id)) {
Ref<DummyResource> dr;
dr.instantiate();
- dr->set_subindex(index);
- p_data->resource_map[index] = dr;
- p_data->resource_set.insert(dr);
+ dr->set_scene_unique_id(unique_id);
+ p_data->resource_map[unique_id] = dr;
+ uint32_t im_size = p_data->resource_index_map.size();
+ p_data->resource_index_map.insert(dr, im_size);
}
- r_res = p_data->resource_map[index];
+ r_res = p_data->resource_map[unique_id];
VariantParser::get_token(p_stream, token, line, r_err_str);
if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
@@ -85,12 +87,12 @@ Error ResourceLoaderText::_parse_sub_resource_dummy(DummyReadData *p_data, Varia
Error ResourceLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
VariantParser::Token token;
VariantParser::get_token(p_stream, token, line, r_err_str);
- if (token.type != VariantParser::TK_NUMBER) {
- r_err_str = "Expected number (sub-resource index)";
+ if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
+ r_err_str = "Expected number (old style sub-resource index) or String (ext-resource ID)";
return ERR_PARSE_ERROR;
}
- int id = token.value;
+ String id = token.value;
ERR_FAIL_COND_V(!p_data->rev_external_resources.has(id), ERR_PARSE_ERROR);
@@ -108,14 +110,14 @@ Error ResourceLoaderText::_parse_ext_resource_dummy(DummyReadData *p_data, Varia
Error ResourceLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
VariantParser::Token token;
VariantParser::get_token(p_stream, token, line, r_err_str);
- if (token.type != VariantParser::TK_NUMBER) {
- r_err_str = "Expected number (sub-resource index)";
+ if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
+ r_err_str = "Expected number (old style sub-resource index) or string";
return ERR_PARSE_ERROR;
}
- int index = token.value;
- ERR_FAIL_COND_V(!int_resources.has(index), ERR_INVALID_PARAMETER);
- r_res = int_resources[index];
+ String id = token.value;
+ ERR_FAIL_COND_V(!int_resources.has(id), ERR_INVALID_PARAMETER);
+ r_res = int_resources[id];
VariantParser::get_token(p_stream, token, line, r_err_str);
if (token.type != VariantParser::TK_PARENTHESIS_CLOSE) {
@@ -129,16 +131,16 @@ Error ResourceLoaderText::_parse_sub_resource(VariantParser::Stream *p_stream, R
Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) {
VariantParser::Token token;
VariantParser::get_token(p_stream, token, line, r_err_str);
- if (token.type != VariantParser::TK_NUMBER) {
- r_err_str = "Expected number (sub-resource index)";
+ if (token.type != VariantParser::TK_NUMBER && token.type != VariantParser::TK_STRING) {
+ r_err_str = "Expected number (old style sub-resource index) or String (ext-resource ID)";
return ERR_PARSE_ERROR;
}
- int id = token.value;
+ String id = token.value;
if (!ignore_resource_parsing) {
if (!ext_resources.has(id)) {
- r_err_str = "Can't load cached ext-resource #" + itos(id);
+ r_err_str = "Can't load cached ext-resource id: " + id;
return ERR_PARSE_ERROR;
}
@@ -409,7 +411,18 @@ Error ResourceLoaderText::load() {
String path = next_tag.fields["path"];
String type = next_tag.fields["type"];
- int index = next_tag.fields["id"];
+ String id = next_tag.fields["id"];
+
+ if (next_tag.fields.has("uid")) {
+ String uidt = next_tag.fields["uid"];
+ ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(uidt);
+ if (uid != ResourceUID::INVALID_ID && ResourceUID::get_singleton()->has_id(uid)) {
+ // If a UID is found and the path is valid, it will be used, otherwise, it falls back to the path.
+ path = ResourceUID::get_singleton()->get_id_path(uid);
+ } else {
+ WARN_PRINT(String(res_path + ":" + itos(lines) + " - ext_resource, invalid UUID: " + uidt + " - using text path instead: " + path).utf8().get_data());
+ }
+ }
if (path.find("://") == -1 && path.is_rel_path()) {
// path is relative to file being loaded, so convert to a resource path
@@ -453,14 +466,14 @@ Error ResourceLoaderText::load() {
} else {
#ifdef TOOLS_ENABLED
//remember ID for saving
- res->set_id_for_path(local_path, index);
+ res->set_id_for_path(local_path, id);
#endif
}
er.cache = res;
}
- ext_resources[index] = er;
+ ext_resources[id] = er;
error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
@@ -489,15 +502,15 @@ Error ResourceLoaderText::load() {
if (!next_tag.fields.has("id")) {
error = ERR_FILE_CORRUPT;
- error_text = "Missing 'index' in external resource tag";
+ error_text = "Missing 'id' in external resource tag";
_printerr();
return error;
}
String type = next_tag.fields["type"];
- int id = next_tag.fields["id"];
+ String id = next_tag.fields["id"];
- String path = local_path + "::" + itos(id);
+ String path = local_path + "::" + id;
//bool exists=ResourceCache::has(path);
@@ -575,7 +588,7 @@ Error ResourceLoaderText::load() {
int_resources[id] = res; //always assign int resources
if (do_assign && cache_mode != ResourceFormatLoader::CACHE_MODE_IGNORE) {
res->set_path(path, cache_mode == ResourceFormatLoader::CACHE_MODE_REPLACE);
- res->set_subindex(id);
+ res->set_scene_unique_id(id);
}
if (progress && resources_total > 0) {
@@ -736,7 +749,7 @@ void ResourceLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_depen
if (!next_tag.fields.has("id")) {
error = ERR_FILE_CORRUPT;
- error_text = "Missing 'index' in external resource tag";
+ error_text = "Missing 'id' in external resource tag";
_printerr();
return;
}
@@ -744,7 +757,18 @@ void ResourceLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_depen
String path = next_tag.fields["path"];
String type = next_tag.fields["type"];
- if (path.find("://") == -1 && path.is_rel_path()) {
+ bool using_uid = false;
+ if (next_tag.fields.has("uid")) {
+ //if uid exists, return uid in text format, not the path
+ String uidt = next_tag.fields["uid"];
+ ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(uidt);
+ if (uid != ResourceUID::INVALID_ID) {
+ path = ResourceUID::get_singleton()->id_to_text(uid);
+ using_uid = true;
+ }
+ }
+
+ if (!using_uid && path.find("://") == -1 && path.is_rel_path()) {
// path is relative to file being loaded, so convert to a resource path
path = ProjectSettings::get_singleton()->localize_path(local_path.get_base_dir().plus_file(path));
}
@@ -814,9 +838,17 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
}
String path = next_tag.fields["path"];
- int index = next_tag.fields["id"];
+ String id = next_tag.fields["id"];
String type = next_tag.fields["type"];
+ if (next_tag.fields.has("uid")) {
+ String uidt = next_tag.fields["uid"];
+ ResourceUID::ID uid = ResourceUID::get_singleton()->text_to_id(uidt);
+ if (uid != ResourceUID::INVALID_ID && ResourceUID::get_singleton()->has_id(uid)) {
+ // If a UID is found and the path is valid, it will be used, otherwise, it falls back to the path.
+ path = ResourceUID::get_singleton()->get_id_path(uid);
+ }
+ }
bool relative = false;
if (!path.begins_with("res://")) {
path = base_path.plus_file(path).simplify_path();
@@ -833,7 +865,14 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
path = base_path.path_to_file(path);
}
- fw->store_line("[ext_resource path=\"" + path + "\" type=\"" + type + "\" id=" + itos(index) + "]");
+ String s = "[ext_resource type=\"" + type + "\"";
+
+ ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(path);
+ if (uid != ResourceUID::INVALID_ID) {
+ s += " uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\"";
+ }
+ s += " path=\"" + path + "\" id=\"" + id + "\"]";
+ fw->store_line(s); // Bundled.
tag_end = f->get_position();
}
@@ -919,6 +958,12 @@ void ResourceLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) {
return;
}
+ if (tag.fields.has("uid")) {
+ res_uid = ResourceUID::get_singleton()->text_to_id(tag.fields["uid"]);
+ } else {
+ res_uid = ResourceUID::INVALID_ID;
+ }
+
if (tag.fields.has("load_steps")) {
resources_total = tag.fields["load_steps"];
} else {
@@ -974,7 +1019,12 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
bs_save_unicode_string(wf.f, is_scene ? "PackedScene" : resource_type);
wf->store_64(0); //offset to import metadata, this is no longer used
- for (int i = 0; i < 14; i++) {
+
+ f->store_32(ResourceFormatSaverBinaryInstance::FORMAT_FLAG_NAMED_SCENE_IDS | ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS);
+
+ f->store_64(res_uid);
+
+ for (int i = 0; i < 5; i++) {
wf->store_32(0); // reserved
}
@@ -1015,17 +1065,23 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
String path = next_tag.fields["path"];
String type = next_tag.fields["type"];
- int index = next_tag.fields["id"];
+ String id = next_tag.fields["id"];
+ ResourceUID::ID uid = ResourceUID::INVALID_ID;
+ if (next_tag.fields.has("uid")) {
+ String uidt = next_tag.fields["uid"];
+ uid = ResourceUID::get_singleton()->text_to_id(uidt);
+ }
bs_save_unicode_string(wf.f, type);
bs_save_unicode_string(wf.f, path);
+ wf.f->store_64(uid);
int lindex = dummy_read.external_resources.size();
Ref<DummyResource> dr;
dr.instantiate();
dr->set_path("res://dummy" + itos(lindex)); //anything is good to detect it for saving as external
dummy_read.external_resources[dr] = lindex;
- dummy_read.rev_external_resources[index] = dr;
+ dummy_read.rev_external_resources[id] = dr;
error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
@@ -1069,7 +1125,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
if (!next_tag.fields.has("id")) {
error = ERR_FILE_CORRUPT;
- error_text = "Missing 'index' in external resource tag";
+ error_text = "Missing 'id' in external resource tag";
_printerr();
return error;
}
@@ -1114,7 +1170,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
if (assign != String()) {
Map<StringName, int> empty_string_map; //unused
bs_save_unicode_string(wf2, assign, true);
- ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
+ ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
prop_count++;
} else if (next_tag.name != String()) {
@@ -1165,17 +1221,17 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
int prop_count = 0;
- for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
- String name = E->get().name;
+ String name = E.name;
Variant value = packed_scene->get(name);
Map<StringName, int> empty_string_map; //unused
bs_save_unicode_string(wf2, name, true);
- ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_set, dummy_read.external_resources, empty_string_map);
+ ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
prop_count++;
}
@@ -1255,6 +1311,32 @@ String ResourceLoaderText::recognize(FileAccess *p_f) {
return tag.fields["type"];
}
+ResourceUID::ID ResourceLoaderText::get_uid(FileAccess *p_f) {
+ error = OK;
+
+ lines = 1;
+ f = p_f;
+
+ stream.f = f;
+
+ ignore_resource_parsing = true;
+
+ VariantParser::Tag tag;
+ Error err = VariantParser::parse_tag(&stream, lines, error_text, tag);
+
+ if (err) {
+ _printerr();
+ return ResourceUID::INVALID_ID;
+ }
+
+ if (tag.fields.has("uid")) { //field is optional
+ String uidt = tag.fields["uid"];
+ return ResourceUID::get_singleton()->text_to_id(uidt);
+ }
+
+ return ResourceUID::INVALID_ID;
+}
+
/////////////////////
RES ResourceFormatLoaderText::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) {
@@ -1275,7 +1357,6 @@ RES ResourceFormatLoaderText::load(const String &p_path, const String &p_origina
loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
loader.progress = r_progress;
loader.res_path = loader.local_path;
- //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
loader.open(f);
err = loader.load();
if (r_error) {
@@ -1318,7 +1399,7 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
return String();
}
- //for anyhting else must test..
+ // ...for anything else must test...
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
@@ -1328,11 +1409,28 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
ResourceLoaderText loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
String r = loader.recognize(f);
return ClassDB::get_compatibility_remapped_class(r);
}
+ResourceUID::ID ResourceFormatLoaderText::get_resource_uid(const String &p_path) const {
+ String ext = p_path.get_extension().to_lower();
+
+ if (ext != "tscn" && ext != "tres") {
+ return ResourceUID::INVALID_ID;
+ }
+
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
+ if (!f) {
+ return ResourceUID::INVALID_ID; //could not read
+ }
+
+ ResourceLoaderText loader;
+ loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
+ loader.res_path = loader.local_path;
+ return loader.get_uid(f);
+}
+
void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
if (!f) {
@@ -1342,7 +1440,6 @@ void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<Strin
ResourceLoaderText loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
loader.get_dependencies(f, p_dependencies, p_add_types);
}
@@ -1355,7 +1452,6 @@ Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const
ResourceLoaderText loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
loader.res_path = loader.local_path;
- //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
return loader.rename_dependencies(f, p_path, p_map);
}
@@ -1371,7 +1467,6 @@ Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path,
const String &path = p_src_path;
loader.local_path = ProjectSettings::get_singleton()->localize_path(path);
loader.res_path = loader.local_path;
- //loader.set_local_path( ProjectSettings::get_singleton()->localize_path(p_path) );
loader.open(f);
return loader.save_as_binary(f, p_dst_path);
}
@@ -1394,10 +1489,10 @@ String ResourceFormatSaverTextInstance::_write_resources(void *ud, const RES &p_
String ResourceFormatSaverTextInstance::_write_resource(const RES &res) {
if (external_resources.has(res)) {
- return "ExtResource( " + itos(external_resources[res]) + " )";
+ return "ExtResource( \"" + external_resources[res] + "\" )";
} else {
if (internal_resources.has(res)) {
- return "SubResource( " + itos(internal_resources[res]) + " )";
+ return "SubResource( \"" + internal_resources[res] + "\" )";
} else if (res->get_path().length() && res->get_path().find("::") == -1) {
if (res->get_path() == local_path) { //circular reference attempt
return "null";
@@ -1426,8 +1521,11 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
ERR_PRINT("Circular reference to resource being saved found: '" + local_path + "' will be null next time it's loaded.");
return;
}
- int index = external_resources.size();
- external_resources[res] = index;
+
+ // Use a numeric ID as a base, because they are sorted in natural order before saving.
+ // This increases the chances of thread loading to fetch them first.
+ String id = itos(external_resources.size() + 1) + "_" + Resource::generate_scene_unique_id();
+ external_resources[res] = id;
return;
}
@@ -1483,8 +1581,8 @@ void ResourceFormatSaverTextInstance::_find_resources(const Variant &p_variant,
Dictionary d = p_variant;
List<Variant> keys;
d.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- Variant v = d[E->get()];
+ for (const Variant &E : keys) {
+ Variant v = d[E];
_find_resources(v);
}
} break;
@@ -1513,11 +1611,11 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
takeover_paths = false;
}
- // save resources
+ // Save resources.
_find_resources(p_resource, true);
if (packed_scene.is_valid()) {
- //add instances to external resources if saving a packed scene
+ // Add instances to external resources if saving a packed scene.
for (int i = 0; i < packed_scene->get_state()->get_node_count(); i++) {
if (packed_scene->get_state()->is_node_instance_placeholder(i)) {
continue;
@@ -1525,8 +1623,8 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
Ref<PackedScene> instance = packed_scene->get_state()->get_node_instance(i);
if (instance.is_valid() && !external_resources.has(instance)) {
- int index = external_resources.size();
- external_resources[instance] = index;
+ int index = external_resources.size() + 1;
+ external_resources[instance] = itos(index) + "_" + Resource::generate_scene_unique_id(); // Keep the order for improved thread loading performance.
}
}
}
@@ -1537,64 +1635,74 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
title += "type=\"" + p_resource->get_class() + "\" ";
}
int load_steps = saved_resources.size() + external_resources.size();
- /*
- if (packed_scene.is_valid()) {
- load_steps+=packed_scene->get_node_count();
- }
- //no, better to not use load steps from nodes, no point to that
- */
if (load_steps > 1) {
title += "load_steps=" + itos(load_steps) + " ";
}
title += "format=" + itos(FORMAT_VERSION) + "";
+ ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(local_path, true);
+
+ if (uid != ResourceUID::INVALID_ID) {
+ title += " uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\"";
+ }
+
f->store_string(title);
- f->store_line("]\n"); //one empty line
+ f->store_line("]\n"); // One empty line.
}
#ifdef TOOLS_ENABLED
- //keep order from cached ids
- Set<int> cached_ids_found;
- for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
- int cached_id = E->key()->get_id_for_path(local_path);
- if (cached_id < 0 || cached_ids_found.has(cached_id)) {
- E->get() = -1; //reset
+ // Keep order from cached ids.
+ Set<String> cached_ids_found;
+ for (Map<RES, String>::Element *E = external_resources.front(); E; E = E->next()) {
+ String cached_id = E->key()->get_id_for_path(local_path);
+ if (cached_id == "" || cached_ids_found.has(cached_id)) {
+ int sep_pos = E->get().find("_");
+ if (sep_pos != -1) {
+ E->get() = E->get().substr(0, sep_pos + 1); // Keep the order found, for improved thread loading performance.
+ } else {
+ E->get() = "";
+ }
+
} else {
E->get() = cached_id;
cached_ids_found.insert(cached_id);
}
}
- //create IDs for non cached resources
- for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
- if (cached_ids_found.has(E->get())) { //already cached, go on
+ // Create IDs for non cached resources.
+ for (Map<RES, String>::Element *E = external_resources.front(); E; E = E->next()) {
+ if (cached_ids_found.has(E->get())) { // Already cached, go on.
continue;
}
- int attempt = 1; //start from one, more readable format
- while (cached_ids_found.has(attempt)) {
- attempt++;
+ String attempt;
+ while (true) {
+ attempt = E->get() + Resource::generate_scene_unique_id();
+ if (!cached_ids_found.has(attempt)) {
+ break;
+ }
}
cached_ids_found.insert(attempt);
E->get() = attempt;
- //update also in resource
+ // Update also in resource.
Ref<Resource> res = E->key();
res->set_id_for_path(local_path, attempt);
}
#else
- //make sure to start from one, as it makes format more readable
- for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
- E->get() = E->get() + 1;
+ // Make sure to start from one, as it makes format more readable.
+ int counter = 1;
+ for (Map<RES, String>::Element *E = external_resources.front(); E; E = E->next()) {
+ E->get() = itos(counter++);
}
#endif
Vector<ResourceSort> sorted_er;
- for (Map<RES, int>::Element *E = external_resources.front(); E; E = E->next()) {
+ for (Map<RES, String>::Element *E = external_resources.front(); E; E = E->next()) {
ResourceSort rs;
rs.resource = E->key();
- rs.index = E->get();
+ rs.id = E->get();
sorted_er.push_back(rs);
}
@@ -1603,23 +1711,30 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
for (int i = 0; i < sorted_er.size(); i++) {
String p = sorted_er[i].resource->get_path();
- f->store_string("[ext_resource path=\"" + p + "\" type=\"" + sorted_er[i].resource->get_save_class() + "\" id=" + itos(sorted_er[i].index) + "]\n"); //bundled
+ String s = "[ext_resource type=\"" + sorted_er[i].resource->get_save_class() + "\"";
+
+ ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(p, false);
+ if (uid != ResourceUID::INVALID_ID) {
+ s += " uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\"";
+ }
+ s += " path=\"" + p + "\" id=\"" + sorted_er[i].id + "\"]\n";
+ f->store_string(s); // Bundled.
}
if (external_resources.size()) {
- f->store_line(String()); //separate
+ f->store_line(String()); // Separate.
}
- Set<int> used_indices;
+ Set<String> used_unique_ids;
for (List<RES>::Element *E = saved_resources.front(); E; E = E->next()) {
RES res = E->get();
if (E->next() && (res->get_path() == "" || res->get_path().find("::") != -1)) {
- if (res->get_subindex() != 0) {
- if (used_indices.has(res->get_subindex())) {
- res->set_subindex(0); //repeated
+ if (res->get_scene_unique_id() != "") {
+ if (used_unique_ids.has(res->get_scene_unique_id())) {
+ res->set_scene_unique_id(""); // Repeated.
} else {
- used_indices.insert(res->get_subindex());
+ used_unique_ids.insert(res->get_scene_unique_id());
}
}
}
@@ -1631,31 +1746,35 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
bool main = (E->next() == nullptr);
if (main && packed_scene.is_valid()) {
- break; //save as a scene
+ break; // Save as a scene.
}
if (main) {
f->store_line("[resource]");
} else {
String line = "[sub_resource ";
- if (res->get_subindex() == 0) {
- int new_subindex = 1;
- if (used_indices.size()) {
- new_subindex = used_indices.back()->get() + 1;
+ if (res->get_scene_unique_id() == "") {
+ String new_id;
+ while (true) {
+ new_id = res->get_class() + "_" + Resource::generate_scene_unique_id();
+
+ if (!used_unique_ids.has(new_id)) {
+ break;
+ }
}
- res->set_subindex(new_subindex);
- used_indices.insert(new_subindex);
+ res->set_scene_unique_id(new_id);
+ used_unique_ids.insert(new_id);
}
- int idx = res->get_subindex();
- line += "type=\"" + res->get_class() + "\" id=" + itos(idx);
- f->store_line(line + "]");
+ String id = res->get_scene_unique_id();
+ line += "type=\"" + res->get_class() + "\" id=\"" + id;
+ f->store_line(line + "\"]");
if (takeover_paths) {
- res->set_path(p_path + "::" + itos(idx), true);
+ res->set_path(p_path + "::" + id, true);
}
- internal_resources[res] = idx;
+ internal_resources[res] = id;
#ifdef TOOLS_ENABLED
res->set_edited(false);
#endif
@@ -1663,7 +1782,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
List<PropertyInfo> property_list;
res->get_property_list(&property_list);
- //property_list.sort();
for (List<PropertyInfo>::Element *PE = property_list.front(); PE; PE = PE->next()) {
if (skip_editor && PE->get().name.begins_with("__editor")) {
continue;
@@ -1704,7 +1822,7 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
}
if (packed_scene.is_valid()) {
- //if this is a scene, save nodes and connections!
+ // If this is a scene, save nodes and connections!
Ref<SceneState> state = packed_scene->get_state();
for (int i = 0; i < state->get_node_count(); i++) {
StringName type = state->get_node_type(i);
@@ -1812,7 +1930,6 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
}
f->close();
- //memdelete(f);
return OK;
}
diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h
index f5d9cca859..373e71b2c4 100644
--- a/scene/resources/resource_format_text.h
+++ b/scene/resources/resource_format_text.h
@@ -58,10 +58,8 @@ class ResourceLoaderText {
bool ignore_resource_parsing = false;
- //Map<String,String> remaps;
-
- Map<int, ExtResource> ext_resources;
- Map<int, RES> int_resources;
+ Map<String, ExtResource> ext_resources;
+ Map<String, RES> int_resources;
int resources_total = 0;
int resource_current = 0;
@@ -76,8 +74,9 @@ class ResourceLoaderText {
mutable int lines = 0;
+ ResourceUID::ID res_uid = ResourceUID::INVALID_ID;
+
Map<String, String> remaps;
- //void _printerr();
static Error _parse_sub_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceLoaderText *>(p_self)->_parse_sub_resource(p_stream, r_res, line, r_err_str); }
static Error _parse_ext_resources(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return reinterpret_cast<ResourceLoaderText *>(p_self)->_parse_ext_resource(p_stream, r_res, line, r_err_str); }
@@ -92,9 +91,9 @@ class ResourceLoaderText {
struct DummyReadData {
Map<RES, int> external_resources;
- Map<int, RES> rev_external_resources;
- Set<RES> resource_set;
- Map<int, RES> resource_map;
+ Map<String, RES> rev_external_resources;
+ Map<RES, int> resource_index_map;
+ Map<String, RES> resource_map;
};
static Error _parse_sub_resource_dummys(void *p_self, VariantParser::Stream *p_stream, Ref<Resource> &r_res, int &line, String &r_err_str) { return _parse_sub_resource_dummy((DummyReadData *)(p_self), p_stream, r_res, line, r_err_str); }
@@ -123,6 +122,7 @@ public:
void open(FileAccess *p_f, bool p_skip_first_tag = false);
String recognize(FileAccess *p_f);
+ ResourceUID::ID get_uid(FileAccess *p_f);
void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
Error rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map);
@@ -139,6 +139,7 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
+ virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
@@ -168,14 +169,14 @@ class ResourceFormatSaverTextInstance {
Set<RES> resource_set;
List<RES> saved_resources;
- Map<RES, int> external_resources;
- Map<RES, int> internal_resources;
+ Map<RES, String> external_resources;
+ Map<RES, String> internal_resources;
struct ResourceSort {
RES resource;
- int index = 0;
+ String id;
bool operator<(const ResourceSort &p_right) const {
- return index < p_right.index;
+ return id.naturalnocasecmp_to(p_right.id) < 0;
}
};
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index f19d08dbb1..424a54f344 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -72,13 +72,12 @@ void Shader::get_param_list(List<PropertyInfo> *p_params) const {
params_cache.clear();
params_cache_dirty = false;
- for (List<PropertyInfo>::Element *E = local.front(); E; E = E->next()) {
- PropertyInfo pi = E->get();
+ for (PropertyInfo &pi : local) {
if (default_textures.has(pi.name)) { //do not show default textures
continue;
}
pi.name = "shader_param/" + pi.name;
- params_cache[pi.name] = E->get().name;
+ params_cache[pi.name] = pi.name;
if (p_params) {
//small little hack
if (pi.type == Variant::RID) {
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index b34d3feb47..ec00f9d7b7 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -30,6 +30,9 @@
#include "sky_material.h"
+Mutex ProceduralSkyMaterial::shader_mutex;
+RID ProceduralSkyMaterial::shader;
+
void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) {
sky_top_color = p_sky_top;
RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear());
@@ -128,7 +131,17 @@ Shader::Mode ProceduralSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY;
}
+RID ProceduralSkyMaterial::get_rid() const {
+ _update_shader();
+ if (!shader_set) {
+ RS::get_singleton()->material_set_shader(_get_material(), shader);
+ shader_set = true;
+ }
+ return _get_material();
+}
+
RID ProceduralSkyMaterial::get_shader_rid() const {
+ _update_shader();
return shader;
}
@@ -180,10 +193,18 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sun_curve", PROPERTY_HINT_EXP_EASING), "set_sun_curve", "get_sun_curve");
}
-ProceduralSkyMaterial::ProceduralSkyMaterial() {
- shader = RS::get_singleton()->shader_create();
+void ProceduralSkyMaterial::cleanup_shader() {
+ if (shader.is_valid()) {
+ RS::get_singleton()->free(shader);
+ }
+}
- RS::get_singleton()->shader_set_code(shader, R"(
+void ProceduralSkyMaterial::_update_shader() {
+ shader_mutex.lock();
+ if (shader.is_null()) {
+ shader = RS::get_singleton()->shader_create();
+
+ RS::get_singleton()->shader_set_code(shader, R"(
shader_type sky;
uniform vec4 sky_top_color : hint_color = vec4(0.35, 0.46, 0.71, 1.0);
@@ -250,9 +271,11 @@ void sky() {
COLOR = mix(ground, sky, step(0.0, EYEDIR.y));
}
)");
+ }
+ shader_mutex.unlock();
+}
- RS::get_singleton()->material_set_shader(_get_material(), shader);
-
+ProceduralSkyMaterial::ProceduralSkyMaterial() {
set_sky_top_color(Color(0.35, 0.46, 0.71));
set_sky_horizon_color(Color(0.55, 0.69, 0.81));
set_sky_curve(0.09);
@@ -268,7 +291,6 @@ void sky() {
}
ProceduralSkyMaterial::~ProceduralSkyMaterial() {
- RS::get_singleton()->free(shader);
RS::get_singleton()->material_set_shader(_get_material(), RID());
}
@@ -293,7 +315,17 @@ Shader::Mode PanoramaSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY;
}
+RID PanoramaSkyMaterial::get_rid() const {
+ _update_shader();
+ if (!shader_set) {
+ RS::get_singleton()->material_set_shader(_get_material(), shader);
+ shader_set = true;
+ }
+ return _get_material();
+}
+
RID PanoramaSkyMaterial::get_shader_rid() const {
+ _update_shader();
return shader;
}
@@ -304,10 +336,21 @@ void PanoramaSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "panorama", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_panorama", "get_panorama");
}
-PanoramaSkyMaterial::PanoramaSkyMaterial() {
- shader = RS::get_singleton()->shader_create();
+Mutex PanoramaSkyMaterial::shader_mutex;
+RID PanoramaSkyMaterial::shader;
- RS::get_singleton()->shader_set_code(shader, R"(
+void PanoramaSkyMaterial::cleanup_shader() {
+ if (shader.is_valid()) {
+ RS::get_singleton()->free(shader);
+ }
+}
+
+void PanoramaSkyMaterial::_update_shader() {
+ shader_mutex.lock();
+ if (shader.is_null()) {
+ shader = RS::get_singleton()->shader_create();
+
+ RS::get_singleton()->shader_set_code(shader, R"(
shader_type sky;
uniform sampler2D source_panorama : filter_linear;
@@ -316,12 +359,15 @@ void sky() {
COLOR = texture(source_panorama, SKY_COORDS).rgb;
}
)");
+ }
- RS::get_singleton()->material_set_shader(_get_material(), shader);
+ shader_mutex.unlock();
+}
+
+PanoramaSkyMaterial::PanoramaSkyMaterial() {
}
PanoramaSkyMaterial::~PanoramaSkyMaterial() {
- RS::get_singleton()->free(shader);
RS::get_singleton()->material_set_shader(_get_material(), RID());
}
@@ -436,10 +482,23 @@ Shader::Mode PhysicalSkyMaterial::get_shader_mode() const {
return Shader::MODE_SKY;
}
+RID PhysicalSkyMaterial::get_rid() const {
+ _update_shader();
+ if (!shader_set) {
+ RS::get_singleton()->material_set_shader(_get_material(), shader);
+ shader_set = true;
+ }
+ return _get_material();
+}
+
RID PhysicalSkyMaterial::get_shader_rid() const {
+ _update_shader();
return shader;
}
+Mutex PhysicalSkyMaterial::shader_mutex;
+RID PhysicalSkyMaterial::shader;
+
void PhysicalSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_rayleigh_coefficient", "rayleigh"), &PhysicalSkyMaterial::set_rayleigh_coefficient);
ClassDB::bind_method(D_METHOD("get_rayleigh_coefficient"), &PhysicalSkyMaterial::get_rayleigh_coefficient);
@@ -491,10 +550,18 @@ void PhysicalSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "night_sky", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_night_sky", "get_night_sky");
}
-PhysicalSkyMaterial::PhysicalSkyMaterial() {
- shader = RS::get_singleton()->shader_create();
+void PhysicalSkyMaterial::cleanup_shader() {
+ if (shader.is_valid()) {
+ RS::get_singleton()->free(shader);
+ }
+}
- RS::get_singleton()->shader_set_code(shader, R"(
+void PhysicalSkyMaterial::_update_shader() {
+ shader_mutex.lock();
+ if (shader.is_null()) {
+ shader = RS::get_singleton()->shader_create();
+
+ RS::get_singleton()->shader_set_code(shader, R"(
shader_type sky;
uniform float rayleigh : hint_range(0, 64) = 2.0;
@@ -588,9 +655,12 @@ void sky() {
}
}
)");
+ }
- RS::get_singleton()->material_set_shader(_get_material(), shader);
+ shader_mutex.unlock();
+}
+PhysicalSkyMaterial::PhysicalSkyMaterial() {
set_rayleigh_coefficient(2.0);
set_rayleigh_color(Color(0.056, 0.14, 0.3));
set_mie_coefficient(0.005);
@@ -604,5 +674,4 @@ void sky() {
}
PhysicalSkyMaterial::~PhysicalSkyMaterial() {
- RS::get_singleton()->free(shader);
}
diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h
index 8fe015519d..63e730617b 100644
--- a/scene/resources/sky_material.h
+++ b/scene/resources/sky_material.h
@@ -51,7 +51,10 @@ private:
float sun_angle_max;
float sun_curve;
- RID shader;
+ static Mutex shader_mutex;
+ static RID shader;
+ static void _update_shader();
+ mutable bool shader_set = false;
protected:
static void _bind_methods();
@@ -90,6 +93,9 @@ public:
virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override;
+ virtual RID get_rid() const override;
+
+ static void cleanup_shader();
ProceduralSkyMaterial();
~ProceduralSkyMaterial();
@@ -103,7 +109,11 @@ class PanoramaSkyMaterial : public Material {
private:
Ref<Texture2D> panorama;
- RID shader;
+
+ static Mutex shader_mutex;
+ static RID shader;
+ static void _update_shader();
+ mutable bool shader_set = false;
protected:
static void _bind_methods();
@@ -115,6 +125,9 @@ public:
virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override;
+ virtual RID get_rid() const override;
+
+ static void cleanup_shader();
PanoramaSkyMaterial();
~PanoramaSkyMaterial();
@@ -127,7 +140,8 @@ class PhysicalSkyMaterial : public Material {
GDCLASS(PhysicalSkyMaterial, Material);
private:
- RID shader;
+ static Mutex shader_mutex;
+ static RID shader;
float rayleigh;
Color rayleigh_color;
@@ -140,6 +154,8 @@ private:
float exposure;
float dither_strength;
Ref<Texture2D> night_sky;
+ static void _update_shader();
+ mutable bool shader_set = false;
protected:
static void _bind_methods();
@@ -182,6 +198,9 @@ public:
virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override;
+ static void cleanup_shader();
+ virtual RID get_rid() const override;
+
PhysicalSkyMaterial();
~PhysicalSkyMaterial();
};
diff --git a/scene/resources/sprite_frames.cpp b/scene/resources/sprite_frames.cpp
index df80084c5c..e9adf67559 100644
--- a/scene/resources/sprite_frames.cpp
+++ b/scene/resources/sprite_frames.cpp
@@ -100,8 +100,8 @@ Vector<String> SpriteFrames::_get_animation_list() const {
Vector<String> ret;
List<StringName> al;
get_animation_list(&al);
- for (List<StringName>::Element *E = al.front(); E; E = E->next()) {
- ret.push_back(E->get());
+ for (const StringName &E : al) {
+ ret.push_back(E);
}
return ret;
diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp
index bf889d7a1c..173ce2adce 100644
--- a/scene/resources/syntax_highlighter.cpp
+++ b/scene/resources/syntax_highlighter.cpp
@@ -529,8 +529,8 @@ void CodeHighlighter::set_color_regions(const Dictionary &p_color_regions) {
List<Variant> keys;
p_color_regions.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- String key = E->get();
+ for (const Variant &E : keys) {
+ String key = E;
String start_key = key.get_slice(" ", 0);
String end_key = key.get_slice_count(" ") > 1 ? key.get_slice(" ", 1) : String();
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index 303bbf38f4..e4a731c7f7 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -447,8 +447,8 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
// Sort and store properties.
list.sort();
- for (List<PropertyInfo>::Element *E = list.front(); E; E = E->next()) {
- p_list->push_back(E->get());
+ for (const PropertyInfo &E : list) {
+ p_list->push_back(E);
}
}
@@ -1275,15 +1275,15 @@ void Theme::get_type_variation_list(const StringName &p_base_type, List<StringNa
return;
}
- for (const List<StringName>::Element *E = variation_base_map[p_base_type].front(); E; E = E->next()) {
+ for (const StringName &E : variation_base_map[p_base_type]) {
// Prevent infinite loops if variants were set to be cross-dependent (that's still invalid usage, but handling for stability sake).
- if (p_list->find(E->get())) {
+ if (p_list->find(E)) {
continue;
}
- p_list->push_back(E->get());
+ p_list->push_back(E);
// Continue looking for sub-variations.
- get_type_variation_list(E->get(), p_list);
+ get_type_variation_list(E, p_list);
}
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index deb5a50eb2..737b47ed95 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -41,6 +41,8 @@
/////////////////////////////// TileSet //////////////////////////////////////
+const int TileSet::INVALID_SOURCE = -1;
+
const char *TileSet::CELL_NEIGHBOR_ENUM_TO_TEXT[] = {
"right_side",
"right_corner",
@@ -127,8 +129,8 @@ void TileSet::_compute_next_source_id() {
// Sources management
int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source_id_override) {
- ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), -1);
- ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), -1, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
+ ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), TileSet::INVALID_SOURCE);
+ ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), TileSet::INVALID_SOURCE, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
sources[new_source_id] = p_tile_set_source;
@@ -191,7 +193,7 @@ int TileSet::get_source_count() const {
}
int TileSet::get_source_id(int p_index) const {
- ERR_FAIL_INDEX_V(p_index, source_ids.size(), -1);
+ ERR_FAIL_INDEX_V(p_index, source_ids.size(), TileSet::INVALID_SOURCE);
return source_ids[p_index];
}
@@ -607,6 +609,254 @@ Variant::Type TileSet::get_custom_data_type(int p_layer_id) const {
return custom_data_layers[p_layer_id].type;
}
+void TileSet::set_source_level_tile_proxy(int p_source_from, int p_source_to) {
+ ERR_FAIL_COND(p_source_from == TileSet::INVALID_SOURCE || p_source_to == TileSet::INVALID_SOURCE);
+
+ source_level_proxies[p_source_from] = p_source_to;
+
+ emit_changed();
+}
+
+int TileSet::get_source_level_tile_proxy(int p_source_from) {
+ ERR_FAIL_COND_V(!source_level_proxies.has(p_source_from), TileSet::INVALID_SOURCE);
+
+ return source_level_proxies[p_source_from];
+}
+
+bool TileSet::has_source_level_tile_proxy(int p_source_from) {
+ return source_level_proxies.has(p_source_from);
+}
+
+void TileSet::remove_source_level_tile_proxy(int p_source_from) {
+ ERR_FAIL_COND(!source_level_proxies.has(p_source_from));
+
+ source_level_proxies.erase(p_source_from);
+
+ emit_changed();
+}
+
+void TileSet::set_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_source_to, Vector2i p_coords_to) {
+ ERR_FAIL_COND(p_source_from == TileSet::INVALID_SOURCE || p_source_to == TileSet::INVALID_SOURCE);
+ ERR_FAIL_COND(p_coords_from == TileSetSource::INVALID_ATLAS_COORDS || p_coords_to == TileSetSource::INVALID_ATLAS_COORDS);
+
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+
+ Array to;
+ to.push_back(p_source_to);
+ to.push_back(p_coords_to);
+
+ coords_level_proxies[from] = to;
+
+ emit_changed();
+}
+
+Array TileSet::get_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from) {
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+
+ ERR_FAIL_COND_V(!coords_level_proxies.has(from), Array());
+
+ return coords_level_proxies[from];
+}
+
+bool TileSet::has_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from) {
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+
+ return coords_level_proxies.has(from);
+}
+
+void TileSet::remove_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from) {
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+
+ ERR_FAIL_COND(!coords_level_proxies.has(from));
+
+ coords_level_proxies.erase(from);
+
+ emit_changed();
+}
+
+void TileSet::set_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from, int p_source_to, Vector2i p_coords_to, int p_alternative_to) {
+ ERR_FAIL_COND(p_source_from == TileSet::INVALID_SOURCE || p_source_to == TileSet::INVALID_SOURCE);
+ ERR_FAIL_COND(p_coords_from == TileSetSource::INVALID_ATLAS_COORDS || p_coords_to == TileSetSource::INVALID_ATLAS_COORDS);
+
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+ from.push_back(p_alternative_from);
+
+ Array to;
+ to.push_back(p_source_to);
+ to.push_back(p_coords_to);
+ to.push_back(p_alternative_to);
+
+ alternative_level_proxies[from] = to;
+
+ emit_changed();
+}
+
+Array TileSet::get_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) {
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+ from.push_back(p_alternative_from);
+
+ ERR_FAIL_COND_V(!alternative_level_proxies.has(from), Array());
+
+ return alternative_level_proxies[from];
+}
+
+bool TileSet::has_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) {
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+ from.push_back(p_alternative_from);
+
+ return alternative_level_proxies.has(from);
+}
+
+void TileSet::remove_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) {
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+ from.push_back(p_alternative_from);
+
+ ERR_FAIL_COND(!alternative_level_proxies.has(from));
+
+ alternative_level_proxies.erase(from);
+
+ emit_changed();
+}
+
+Array TileSet::get_source_level_tile_proxies() const {
+ Array output;
+ for (Map<int, int>::Element *E = source_level_proxies.front(); E; E = E->next()) {
+ Array proxy;
+ proxy.push_back(E->key());
+ proxy.push_back(E->get());
+ output.push_back(proxy);
+ }
+ return output;
+}
+
+Array TileSet::get_coords_level_tile_proxies() const {
+ Array output;
+ for (Map<Array, Array>::Element *E = coords_level_proxies.front(); E; E = E->next()) {
+ Array proxy;
+ proxy.append_array(E->key());
+ proxy.append_array(E->get());
+ output.push_back(proxy);
+ }
+ return output;
+}
+
+Array TileSet::get_alternative_level_tile_proxies() const {
+ Array output;
+ for (Map<Array, Array>::Element *E = alternative_level_proxies.front(); E; E = E->next()) {
+ Array proxy;
+ proxy.append_array(E->key());
+ proxy.append_array(E->get());
+ output.push_back(proxy);
+ }
+ return output;
+}
+
+Array TileSet::map_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) const {
+ Array from;
+ from.push_back(p_source_from);
+ from.push_back(p_coords_from);
+ from.push_back(p_alternative_from);
+
+ // Check if the tile is valid, and if so, don't map the tile and return the input.
+ if (has_source(p_source_from)) {
+ Ref<TileSetSource> source = get_source(p_source_from);
+ if (source->has_tile(p_coords_from) && source->has_alternative_tile(p_coords_from, p_alternative_from)) {
+ return from;
+ }
+ }
+
+ // Source, coords and alternative match.
+ if (alternative_level_proxies.has(from)) {
+ return alternative_level_proxies[from].duplicate();
+ }
+
+ // Source and coords match.
+ from.pop_back();
+ if (coords_level_proxies.has(from)) {
+ Array output = coords_level_proxies[from].duplicate();
+ output.push_back(p_alternative_from);
+ return output;
+ }
+
+ // Source matches.
+ if (source_level_proxies.has(p_source_from)) {
+ Array output;
+ output.push_back(source_level_proxies[p_source_from]);
+ output.push_back(p_coords_from);
+ output.push_back(p_alternative_from);
+ return output;
+ }
+
+ Array output;
+ output.push_back(p_source_from);
+ output.push_back(p_coords_from);
+ output.push_back(p_alternative_from);
+ return output;
+}
+
+void TileSet::cleanup_invalid_tile_proxies() {
+ // Source level.
+ Vector<int> source_to_remove;
+ for (Map<int, int>::Element *E = source_level_proxies.front(); E; E = E->next()) {
+ if (has_source(E->key())) {
+ source_to_remove.append(E->key());
+ }
+ }
+ for (int i = 0; i < source_to_remove.size(); i++) {
+ remove_source_level_tile_proxy(source_to_remove[i]);
+ }
+
+ // Coords level.
+ Vector<Array> coords_to_remove;
+ for (Map<Array, Array>::Element *E = coords_level_proxies.front(); E; E = E->next()) {
+ Array a = E->key();
+ if (has_source(a[0]) && get_source(a[0])->has_tile(a[1])) {
+ coords_to_remove.append(a);
+ }
+ }
+ for (int i = 0; i < coords_to_remove.size(); i++) {
+ Array a = coords_to_remove[i];
+ remove_coords_level_tile_proxy(a[0], a[1]);
+ }
+
+ // Alternative level.
+ Vector<Array> alternative_to_remove;
+ for (Map<Array, Array>::Element *E = alternative_level_proxies.front(); E; E = E->next()) {
+ Array a = E->key();
+ if (has_source(a[0]) && get_source(a[0])->has_tile(a[1]) && get_source(a[0])->has_alternative_tile(a[1], a[2])) {
+ alternative_to_remove.append(a);
+ }
+ }
+ for (int i = 0; i < alternative_to_remove.size(); i++) {
+ Array a = alternative_to_remove[i];
+ remove_alternative_level_tile_proxy(a[0], a[1], a[2]);
+ }
+}
+
+void TileSet::clear_tile_proxies() {
+ source_level_proxies.clear();
+ coords_level_proxies.clear();
+ alternative_level_proxies.clear();
+
+ emit_changed();
+}
+
Vector<Vector2> TileSet::get_tile_shape_polygon() {
Vector<Vector2> points;
if (tile_shape == TileSet::TILE_SHAPE_SQUARE) {
@@ -1539,7 +1789,7 @@ const Vector2i TileSetSource::INVALID_ATLAS_COORDS = Vector2i(-1, -1);
const int TileSetSource::INVALID_TILE_ALTERNATIVE = -1;
#ifndef DISABLE_DEPRECATED
-void TileSet::compatibility_conversion() {
+void TileSet::_compatibility_conversion() {
for (Map<int, CompatibilityTileData *>::Element *E = compatibility_data.front(); E; E = E->next()) {
CompatibilityTileData *ctd = E->value();
@@ -1551,13 +1801,93 @@ void TileSet::compatibility_conversion() {
// Handle each tile as a new source. Not optimal but at least it should stay compatible.
switch (ctd->tile_mode) {
- case 0: // SINGLE_TILE
- // TODO
- break;
- case 1: // AUTO_TILE
- // TODO
- break;
- case 2: // ATLAS_TILE
+ case COMPATIBILITY_TILE_MODE_SINGLE_TILE: {
+ atlas_source->set_margins(ctd->region.get_position());
+ atlas_source->set_texture_region_size(ctd->region.get_size());
+
+ Vector2i coords;
+ for (int flags = 0; flags < 8; flags++) {
+ bool flip_h = flags & 1;
+ bool flip_v = flags & 2;
+ bool transpose = flags & 4;
+
+ int alternative_tile = 0;
+ if (!atlas_source->has_tile(coords)) {
+ atlas_source->create_tile(coords);
+ } else {
+ alternative_tile = atlas_source->create_alternative_tile(coords);
+ }
+
+ // Add to the mapping.
+ Array key_array;
+ key_array.push_back(flip_h);
+ key_array.push_back(flip_v);
+ key_array.push_back(transpose);
+
+ Array value_array;
+ value_array.push_back(source_id);
+ value_array.push_back(coords);
+ value_array.push_back(alternative_tile);
+
+ if (!compatibility_tilemap_mapping.has(E->key())) {
+ compatibility_tilemap_mapping[E->key()] = Map<Array, Array>();
+ }
+ compatibility_tilemap_mapping[E->key()][key_array] = value_array;
+ compatibility_tilemap_mapping_tile_modes[E->key()] = COMPATIBILITY_TILE_MODE_SINGLE_TILE;
+
+ TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(coords, alternative_tile));
+
+ tile_data->set_flip_h(flip_h);
+ tile_data->set_flip_v(flip_v);
+ tile_data->set_transpose(transpose);
+ tile_data->tile_set_material(ctd->material);
+ tile_data->set_modulate(ctd->modulate);
+ tile_data->set_z_index(ctd->z_index);
+
+ if (ctd->occluder.is_valid()) {
+ if (get_occlusion_layers_count() < 1) {
+ set_occlusion_layers_count(1);
+ }
+ tile_data->set_occluder(0, ctd->occluder);
+ }
+ if (ctd->navigation.is_valid()) {
+ if (get_navigation_layers_count() < 1) {
+ set_navigation_layers_count(1);
+ }
+ tile_data->set_navigation_polygon(0, ctd->autotile_navpoly_map[coords]);
+ }
+
+ tile_data->set_z_index(ctd->z_index);
+
+ // Add the shapes.
+ if (ctd->shapes.size() > 0) {
+ if (get_physics_layers_count() < 1) {
+ set_physics_layers_count(1);
+ }
+ }
+ for (int k = 0; k < ctd->shapes.size(); k++) {
+ CompatibilityShapeData csd = ctd->shapes[k];
+ if (csd.autotile_coords == coords) {
+ Ref<ConvexPolygonShape2D> convex_shape = csd.shape; // Only ConvexPolygonShape2D are supported, which is the default type used by the 3.x editor
+ if (convex_shape.is_valid()) {
+ Vector<Vector2> polygon = convex_shape->get_points();
+ for (int point_index = 0; point_index < polygon.size(); point_index++) {
+ polygon.write[point_index] = csd.transform.xform(polygon[point_index]);
+ }
+ tile_data->set_collision_polygons_count(0, tile_data->get_collision_polygons_count(0) + 1);
+ int index = tile_data->get_collision_polygons_count(0) - 1;
+ tile_data->set_collision_polygon_one_way(0, index, csd.one_way);
+ tile_data->set_collision_polygon_one_way_margin(0, index, csd.one_way_margin);
+ tile_data->set_collision_polygon_points(0, index, polygon);
+ }
+ }
+ }
+ }
+ } break;
+ case COMPATIBILITY_TILE_MODE_AUTO_TILE: {
+ // Not supported. It would need manual conversion.
+ } break;
+ case COMPATIBILITY_TILE_MODE_ATLAS_TILE: {
atlas_source->set_margins(ctd->region.get_position());
atlas_source->set_separation(Vector2i(ctd->autotile_spacing, ctd->autotile_spacing));
atlas_source->set_texture_region_size(ctd->autotile_tile_size);
@@ -1578,6 +1908,25 @@ void TileSet::compatibility_conversion() {
} else {
alternative_tile = atlas_source->create_alternative_tile(coords);
}
+
+ // Add to the mapping.
+ Array key_array;
+ key_array.push_back(coords);
+ key_array.push_back(flip_h);
+ key_array.push_back(flip_v);
+ key_array.push_back(transpose);
+
+ Array value_array;
+ value_array.push_back(source_id);
+ value_array.push_back(coords);
+ value_array.push_back(alternative_tile);
+
+ if (!compatibility_tilemap_mapping.has(E->key())) {
+ compatibility_tilemap_mapping[E->key()] = Map<Array, Array>();
+ }
+ compatibility_tilemap_mapping[E->key()][key_array] = value_array;
+ compatibility_tilemap_mapping_tile_modes[E->key()] = COMPATIBILITY_TILE_MODE_ATLAS_TILE;
+
TileData *tile_data = Object::cast_to<TileData>(atlas_source->get_tile_data(coords, alternative_tile));
tile_data->set_flip_h(flip_h);
@@ -1641,7 +1990,7 @@ void TileSet::compatibility_conversion() {
}
}
}
- break;
+ } break;
}
// Offset all shapes
@@ -1655,9 +2004,6 @@ void TileSet::compatibility_conversion() {
convex->set_points(points);
}
}
-
- // Add the mapping to the map
- compatibility_source_mapping.insert(E->key(), source_id);
}
// Reset compatibility data
@@ -1666,14 +2012,50 @@ void TileSet::compatibility_conversion() {
}
compatibility_data = Map<int, CompatibilityTileData *>();
}
+
+Array TileSet::compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool p_flip_h, bool p_flip_v, bool p_transpose) {
+ Array cannot_convert_array;
+ cannot_convert_array.push_back(TileSet::INVALID_SOURCE);
+ cannot_convert_array.push_back(TileSetAtlasSource::INVALID_ATLAS_COORDS);
+ cannot_convert_array.push_back(TileSetAtlasSource::INVALID_TILE_ALTERNATIVE);
+
+ if (!compatibility_tilemap_mapping.has(p_tile_id)) {
+ return cannot_convert_array;
+ }
+
+ int tile_mode = compatibility_tilemap_mapping_tile_modes[p_tile_id];
+ switch (tile_mode) {
+ case COMPATIBILITY_TILE_MODE_SINGLE_TILE: {
+ Array a;
+ a.push_back(p_flip_h);
+ a.push_back(p_flip_v);
+ a.push_back(p_transpose);
+ return compatibility_tilemap_mapping[p_tile_id][a];
+ }
+ case COMPATIBILITY_TILE_MODE_AUTO_TILE:
+ return cannot_convert_array;
+ break;
+ case COMPATIBILITY_TILE_MODE_ATLAS_TILE: {
+ Array a;
+ a.push_back(p_coords);
+ a.push_back(p_flip_h);
+ a.push_back(p_flip_v);
+ a.push_back(p_transpose);
+ return compatibility_tilemap_mapping[p_tile_id][a];
+ }
+ default:
+ return cannot_convert_array;
+ break;
+ }
+};
+
#endif // DISABLE_DEPRECATED
bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
Vector<String> components = String(p_name).split("/", true, 2);
#ifndef DISABLE_DEPRECATED
- // TODO: THIS IS HOW WE CHECK IF WE HAVE A DEPRECATED RESOURCE
- // This should be moved to a dedicated conversion system
+ // TODO: This should be moved to a dedicated conversion system (see #50691)
if (components.size() >= 1 && components[0].is_valid_int()) {
int id = components[0].to_int();
@@ -1809,29 +2191,23 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
/*
// IGNORED FOR NOW, they seem duplicated data compared to the shapes array
} else if (what == "shape") {
- // TODO
} else if (what == "shape_offset") {
- // TODO
} else if (what == "shape_transform") {
- // TODO
} else if (what == "shape_one_way") {
- // TODO
} else if (what == "shape_one_way_margin") {
- // TODO
}
// IGNORED FOR NOW, maybe useless ?
else if (what == "occluder_offset") {
// Not
} else if (what == "navigation_offset") {
- // TODO
}
*/
} else if (what == "z_index") {
ctd->z_index = p_value;
- // TODO: remove the conversion from here, it's not where it should be done
- compatibility_conversion();
+ // TODO: remove the conversion from here, it's not where it should be done (see #50691)
+ _compatibility_conversion();
} else {
return false;
}
@@ -1966,6 +2342,31 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
add_source(p_value, source_id);
}
return true;
+ } else if (components.size() == 2 && components[0] == "tile_proxies") {
+ ERR_FAIL_COND_V(p_value.get_type() != Variant::ARRAY, false);
+ Array a = p_value;
+ ERR_FAIL_COND_V(a.size() % 2 != 0, false);
+ if (components[1] == "source_level") {
+ for (int i = 0; i < a.size(); i += 2) {
+ set_source_level_tile_proxy(a[i], a[i + 1]);
+ }
+ return true;
+ } else if (components[1] == "coords_level") {
+ for (int i = 0; i < a.size(); i += 2) {
+ Array key = a[i];
+ Array value = a[i + 1];
+ set_coords_level_tile_proxy(key[0], key[1], value[0], value[1]);
+ }
+ return true;
+ } else if (components[1] == "alternative_level") {
+ for (int i = 0; i < a.size(); i += 2) {
+ Array key = a[i];
+ Array value = a[i + 1];
+ set_alternative_level_tile_proxy(key[0], key[1], key[2], value[0], value[1], value[2]);
+ }
+ return true;
+ }
+ return false;
}
#ifndef DISABLE_DEPRECATED
@@ -2065,6 +2466,33 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const {
} else {
return false;
}
+ } else if (components.size() == 2 && components[0] == "tile_proxies") {
+ if (components[1] == "source_level") {
+ Array a;
+ for (Map<int, int>::Element *E = source_level_proxies.front(); E; E = E->next()) {
+ a.push_back(E->key());
+ a.push_back(E->get());
+ }
+ r_ret = a;
+ return true;
+ } else if (components[1] == "coords_level") {
+ Array a;
+ for (Map<Array, Array>::Element *E = coords_level_proxies.front(); E; E = E->next()) {
+ a.push_back(E->key());
+ a.push_back(E->get());
+ }
+ r_ret = a;
+ return true;
+ } else if (components[1] == "alternative_level") {
+ Array a;
+ for (Map<Array, Array>::Element *E = alternative_level_proxies.front(); E; E = E->next()) {
+ a.push_back(E->key());
+ a.push_back(E->get());
+ }
+ r_ret = a;
+ return true;
+ }
+ return false;
}
return false;
@@ -2138,12 +2566,19 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const {
for (Map<int, Ref<TileSetSource>>::Element *E_source = sources.front(); E_source; E_source = E_source->next()) {
p_list->push_back(PropertyInfo(Variant::INT, vformat("sources/%d", E_source->key()), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
+
+ // Tile Proxies.
+ // Note: proxies need to be set after sources are set.
+ p_list->push_back(PropertyInfo(Variant::NIL, "Tile Proxies", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR));
}
void TileSet::_bind_methods() {
// Sources management.
ClassDB::bind_method(D_METHOD("get_next_source_id"), &TileSet::get_next_source_id);
- ClassDB::bind_method(D_METHOD("add_source", "atlas_source_id_override"), &TileSet::add_source, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_source", "atlas_source_id_override"), &TileSet::add_source, DEFVAL(TileSet::INVALID_SOURCE));
ClassDB::bind_method(D_METHOD("remove_source", "source_id"), &TileSet::remove_source);
ClassDB::bind_method(D_METHOD("set_source_id", "source_id"), &TileSet::set_source_id);
ClassDB::bind_method(D_METHOD("get_source_count"), &TileSet::get_source_count);
@@ -2212,6 +2647,27 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_custom_data_layers_count", "custom_data_layers_count"), &TileSet::set_custom_data_layers_count);
ClassDB::bind_method(D_METHOD("get_custom_data_layers_count"), &TileSet::get_custom_data_layers_count);
+ // Tile proxies
+ ClassDB::bind_method(D_METHOD("set_source_level_tile_proxy", "source_from", "source_to"), &TileSet::set_source_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("get_source_level_tile_proxy", "source_from"), &TileSet::get_source_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("has_source_level_tile_proxy", "source_from"), &TileSet::has_source_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("remove_source_level_tile_proxy", "source_from"), &TileSet::remove_source_level_tile_proxy);
+
+ ClassDB::bind_method(D_METHOD("set_coords_level_tile_proxy", "p_source_from", "coords_from", "source_to", "coords_to"), &TileSet::set_coords_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("get_coords_level_tile_proxy", "source_from", "coords_from"), &TileSet::get_coords_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("has_coords_level_tile_proxy", "source_from", "coords_from"), &TileSet::has_coords_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("remove_coords_level_tile_proxy", "source_from", "coords_from"), &TileSet::remove_coords_level_tile_proxy);
+
+ ClassDB::bind_method(D_METHOD("set_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from", "source_to", "coords_to", "alternative_to"), &TileSet::set_alternative_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("get_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::get_alternative_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("has_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::has_alternative_level_tile_proxy);
+ ClassDB::bind_method(D_METHOD("remove_alternative_level_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::remove_alternative_level_tile_proxy);
+
+ ClassDB::bind_method(D_METHOD("map_tile_proxy", "source_from", "coords_from", "alternative_from"), &TileSet::map_tile_proxy);
+
+ ClassDB::bind_method(D_METHOD("cleanup_invalid_tile_proxies"), &TileSet::cleanup_invalid_tile_proxies);
+ ClassDB::bind_method(D_METHOD("clear_tile_proxies"), &TileSet::clear_tile_proxies);
+
ADD_GROUP("Rendering", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uv_clipping"), "set_uv_clipping", "is_uv_clipping");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "y_sorting"), "set_y_sorting", "is_y_sorting");
@@ -2272,7 +2728,7 @@ TileSet::TileSet() {
tile_lines_mesh.instantiate();
tile_filled_mesh.instantiate();
- // Instanciate and list all plugins.
+ // Instantiate and list all plugins.
tile_set_plugins_vector.append(memnew(TileSetPluginAtlasRendering));
tile_set_plugins_vector.append(memnew(TileSetPluginAtlasPhysics));
tile_set_plugins_vector.append(memnew(TileSetPluginAtlasNavigation));
@@ -2755,8 +3211,8 @@ void TileSetAtlasSource::clear_tiles_outside_texture() {
}
int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, int p_alternative_id_override) {
- ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
- ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && tiles[p_atlas_coords].alternatives.has(p_alternative_id_override), -1, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override));
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("TileSetAtlasSource has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_V_MSG(p_alternative_id_override >= 0 && tiles[p_atlas_coords].alternatives.has(p_alternative_id_override), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("Cannot create alternative tile. Another alternative exists with id %d.", p_alternative_id_override));
int new_alternative_id = p_alternative_id_override >= 0 ? p_alternative_id_override : tiles[p_atlas_coords].next_alternative_id;
@@ -2809,7 +3265,7 @@ bool TileSetAtlasSource::has_alternative_tile(const Vector2i p_atlas_coords, int
}
int TileSetAtlasSource::get_next_alternative_tile_id(const Vector2i p_atlas_coords) const {
- ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
return tiles[p_atlas_coords].next_alternative_id;
}
@@ -2819,8 +3275,8 @@ int TileSetAtlasSource::get_alternative_tiles_count(const Vector2i p_atlas_coord
}
int TileSetAtlasSource::get_alternative_tile_id(const Vector2i p_atlas_coords, int p_index) const {
- ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), -1, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
- ERR_FAIL_INDEX_V(p_index, tiles[p_atlas_coords].alternatives_ids.size(), -1);
+ ERR_FAIL_COND_V_MSG(!tiles.has(p_atlas_coords), TileSetSource::INVALID_TILE_ALTERNATIVE, vformat("The TileSetAtlasSource atlas has no tile at %s.", String(p_atlas_coords)));
+ ERR_FAIL_INDEX_V(p_index, tiles[p_atlas_coords].alternatives_ids.size(), TileSetSource::INVALID_TILE_ALTERNATIVE);
return tiles[p_atlas_coords].alternatives_ids[p_index];
}
@@ -2861,7 +3317,7 @@ void TileSetAtlasSource::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_tile_at_coords", "atlas_coords"), &TileSetAtlasSource::get_tile_at_coords);
// Alternative tiles
- ClassDB::bind_method(D_METHOD("create_alternative_tile", "atlas_coords", "alternative_id_override"), &TileSetAtlasSource::create_alternative_tile, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("create_alternative_tile", "atlas_coords", "alternative_id_override"), &TileSetAtlasSource::create_alternative_tile, DEFVAL(INVALID_TILE_ALTERNATIVE));
ClassDB::bind_method(D_METHOD("remove_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetAtlasSource::remove_alternative_tile);
ClassDB::bind_method(D_METHOD("set_alternative_tile_id", "atlas_coords", "alternative_tile", "new_id"), &TileSetAtlasSource::set_alternative_tile_id);
ClassDB::bind_method(D_METHOD("has_alternative_tile", "atlas_coords", "alternative_tile"), &TileSetAtlasSource::has_alternative_tile);
@@ -2948,7 +3404,7 @@ bool TileSetScenesCollectionSource::has_alternative_tile(const Vector2i p_atlas_
}
int TileSetScenesCollectionSource::create_scene_tile(Ref<PackedScene> p_packed_scene, int p_id_override) {
- ERR_FAIL_COND_V_MSG(p_id_override >= 0 && scenes.has(p_id_override), -1, vformat("Cannot create scene tile. Another scene tile exists with id %d.", p_id_override));
+ ERR_FAIL_COND_V_MSG(p_id_override >= 0 && scenes.has(p_id_override), INVALID_TILE_ALTERNATIVE, vformat("Cannot create scene tile. Another scene tile exists with id %d.", p_id_override));
int new_scene_id = p_id_override >= 0 ? p_id_override : next_scene_id;
@@ -3096,7 +3552,7 @@ void TileSetScenesCollectionSource::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scene_tiles_count"), &TileSetScenesCollectionSource::get_scene_tiles_count);
ClassDB::bind_method(D_METHOD("get_scene_tile_id", "index"), &TileSetScenesCollectionSource::get_scene_tile_id);
ClassDB::bind_method(D_METHOD("has_scene_tile_id", "id"), &TileSetScenesCollectionSource::has_scene_tile_id);
- ClassDB::bind_method(D_METHOD("create_scene_tile", "packed_scene", "id_override"), &TileSetScenesCollectionSource::create_scene_tile, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("create_scene_tile", "packed_scene", "id_override"), &TileSetScenesCollectionSource::create_scene_tile, DEFVAL(INVALID_TILE_ALTERNATIVE));
ClassDB::bind_method(D_METHOD("set_scene_tile_id", "id", "new_id"), &TileSetScenesCollectionSource::set_scene_tile_id);
ClassDB::bind_method(D_METHOD("set_scene_tile_scene", "id", "packed_scene"), &TileSetScenesCollectionSource::set_scene_tile_scene);
ClassDB::bind_method(D_METHOD("get_scene_tile_scene", "id"), &TileSetScenesCollectionSource::get_scene_tile_scene);
@@ -3901,14 +4357,14 @@ void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
RenderingServer *rs = RenderingServer::get_singleton();
// Free the canvas items.
- for (List<RID>::Element *E = q.canvas_items.front(); E; E = E->next()) {
- rs->free(E->get());
+ for (const RID &E : q.canvas_items) {
+ rs->free(E);
}
q.canvas_items.clear();
// Free the occluders.
- for (List<RID>::Element *E = q.occluders.front(); E; E = E->next()) {
- rs->free(E->get());
+ for (const RID &E : q.occluders) {
+ rs->free(E);
}
q.occluders.clear();
@@ -3919,7 +4375,7 @@ void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
// Iterate over the cells of the quadrant.
for (Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator>::Element *E_cell = q.world_to_map.front(); E_cell; E_cell = E_cell->next()) {
- TileMapCell c = p_tile_map->get_cell(E_cell->value());
+ TileMapCell c = p_tile_map->get_cell(E_cell->value(), true);
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
@@ -4017,8 +4473,8 @@ void TileSetPluginAtlasRendering::update_dirty_quadrants(TileMap *p_tile_map, Se
// Sort the quadrants
for (Map<Vector2i, Vector2i, TileMapQuadrant::CoordsWorldComparator>::Element *E = world_to_map.front(); E; E = E->next()) {
TileMapQuadrant &q = quadrant_map[E->value()];
- for (List<RID>::Element *F = q.canvas_items.front(); F; F = F->next()) {
- RS::get_singleton()->canvas_item_set_draw_index(F->get(), index++);
+ for (const RID &F : q.canvas_items) {
+ RS::get_singleton()->canvas_item_set_draw_index(F, index++);
}
}
@@ -4035,14 +4491,14 @@ void TileSetPluginAtlasRendering::create_quadrant(TileMap *p_tile_map, TileMapQu
void TileSetPluginAtlasRendering::cleanup_quadrant(TileMap *p_tile_map, TileMapQuadrant *p_quadrant) {
// Free the canvas items.
- for (List<RID>::Element *E = p_quadrant->canvas_items.front(); E; E = E->next()) {
- RenderingServer::get_singleton()->free(E->get());
+ for (const RID &E : p_quadrant->canvas_items) {
+ RenderingServer::get_singleton()->free(E);
}
p_quadrant->canvas_items.clear();
// Free the occluders.
- for (List<RID>::Element *E = p_quadrant->occluders.front(); E; E = E->next()) {
- RenderingServer::get_singleton()->free(E->get());
+ for (const RID &E : p_quadrant->occluders) {
+ RenderingServer::get_singleton()->free(E);
}
p_quadrant->occluders.clear();
}
@@ -4059,7 +4515,7 @@ void TileSetPluginAtlasRendering::draw_quadrant_debug(TileMap *p_tile_map, TileM
RenderingServer *rs = RenderingServer::get_singleton();
Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
- const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
+ const TileMapCell &c = p_tile_map->get_cell(E_cell->get(), true);
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
@@ -4151,7 +4607,7 @@ void TileSetPluginAtlasPhysics::update_dirty_quadrants(TileMap *p_tile_map, Self
}
for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
- TileMapCell c = p_tile_map->get_cell(E_cell->get());
+ TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
@@ -4276,7 +4732,7 @@ void TileSetPluginAtlasPhysics::draw_quadrant_debug(TileMap *p_tile_map, TileMap
Color debug_collision_color = p_tile_map->get_tree()->get_debug_collisions_color();
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
- TileMapCell c = p_tile_map->get_cell(E_cell->get());
+ TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
Transform2D xform;
xform.set_origin(p_tile_map->map_to_world(E_cell->get()) - quadrant_pos);
@@ -4370,7 +4826,7 @@ void TileSetPluginAtlasNavigation::update_dirty_quadrants(TileMap *p_tile_map, S
// Get the navigation polygons and create regions.
for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
- TileMapCell c = p_tile_map->get_cell(E_cell->get());
+ TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
@@ -4455,7 +4911,7 @@ void TileSetPluginAtlasNavigation::draw_quadrant_debug(TileMap *p_tile_map, Tile
Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
- TileMapCell c = p_tile_map->get_cell(E_cell->get());
+ TileMapCell c = p_tile_map->get_cell(E_cell->get(), true);
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
@@ -4526,7 +4982,7 @@ void TileSetPluginScenesCollections::update_dirty_quadrants(TileMap *p_tile_map,
// Recreate the scenes.
for (Set<Vector2i>::Element *E_cell = q.cells.front(); E_cell; E_cell = E_cell->next()) {
- const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
+ const TileMapCell &c = p_tile_map->get_cell(E_cell->get(), true);
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
@@ -4585,7 +5041,7 @@ void TileSetPluginScenesCollections::draw_quadrant_debug(TileMap *p_tile_map, Ti
RenderingServer *rs = RenderingServer::get_singleton();
Vector2 quadrant_pos = p_tile_map->map_to_world(p_quadrant->coords * p_tile_map->get_effective_quadrant_size());
for (Set<Vector2i>::Element *E_cell = p_quadrant->cells.front(); E_cell; E_cell = E_cell->next()) {
- const TileMapCell &c = p_tile_map->get_cell(E_cell->get());
+ const TileMapCell &c = p_tile_map->get_cell(E_cell->get(), true);
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h
index dbf6dbabe6..0a07981171 100644
--- a/scene/resources/tile_set.h
+++ b/scene/resources/tile_set.h
@@ -79,15 +79,15 @@ private:
Vector2 tex_offset;
Ref<ShaderMaterial> material;
Rect2 region;
- int tile_mode;
- Color modulate;
+ int tile_mode = 0;
+ Color modulate = Color(1, 1, 1);
// Atlas or autotiles data
- int autotile_bitmask_mode;
+ int autotile_bitmask_mode = 0;
Vector2 autotile_icon_coordinate;
Size2i autotile_tile_size = Size2i(16, 16);
- int autotile_spacing;
+ int autotile_spacing = 0;
Map<Vector2i, int> autotile_bitmask_flags;
Map<Vector2i, Ref<OccluderPolygon2D>> autotile_occluder_map;
Map<Vector2i, Ref<NavigationPolygon>> autotile_navpoly_map;
@@ -99,23 +99,29 @@ private:
Vector2 occluder_offset;
Ref<NavigationPolygon> navigation;
Vector2 navigation_offset;
- int z_index;
+ int z_index = 0;
};
- Map<int, CompatibilityTileData *> compatibility_data = Map<int, CompatibilityTileData *>();
- Map<int, int> compatibility_source_mapping = Map<int, int>();
+ enum CompatibilityTileMode {
+ COMPATIBILITY_TILE_MODE_SINGLE_TILE = 0,
+ COMPATIBILITY_TILE_MODE_AUTO_TILE,
+ COMPATIBILITY_TILE_MODE_ATLAS_TILE,
+ };
-private:
- void compatibility_conversion();
+ Map<int, CompatibilityTileData *> compatibility_data;
+ Map<int, int> compatibility_tilemap_mapping_tile_modes;
+ Map<int, Map<Array, Array>> compatibility_tilemap_mapping;
-public:
- int compatibility_get_source_for_tile_id(int p_old_source) {
- return compatibility_source_mapping[p_old_source];
- };
+ void _compatibility_conversion();
+public:
+ // Format of output array [source_id, atlas_coords, alternative]
+ Array compatibility_tilemap_map(int p_tile_id, Vector2i p_coords, bool p_flip_h, bool p_flip_v, bool p_transpose);
#endif // DISABLE_DEPRECATED
public:
+ static const int INVALID_SOURCE; // -1;
+
enum CellNeighbor {
CELL_NEIGHBOR_RIGHT_SIDE = 0,
CELL_NEIGHBOR_RIGHT_CORNER,
@@ -165,7 +171,6 @@ public:
TILE_OFFSET_AXIS_VERTICAL,
};
-public:
struct PackedSceneSource {
Ref<PackedScene> scene;
Vector2 offset;
@@ -246,6 +251,11 @@ private:
void _compute_next_source_id();
void _source_changed();
+ // Tile proxies
+ Map<int, int> source_level_proxies;
+ Map<Array, Array> coords_level_proxies;
+ Map<Array, Array> alternative_level_proxies;
+
// Helpers
Vector<Point2> _get_square_corner_or_side_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
Vector<Point2> _get_square_corner_terrain_bit_polygon(Vector2i p_size, TileSet::CellNeighbor p_bit);
@@ -341,6 +351,31 @@ public:
void set_custom_data_type(int p_layer_id, Variant::Type p_value);
Variant::Type get_custom_data_type(int p_layer_id) const;
+ // Tiles proxies.
+ void set_source_level_tile_proxy(int p_source_from, int p_source_to);
+ int get_source_level_tile_proxy(int p_source_from);
+ bool has_source_level_tile_proxy(int p_source_from);
+ void remove_source_level_tile_proxy(int p_source_from);
+
+ void set_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_source_to, Vector2i p_coords_to);
+ Array get_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from);
+ bool has_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from);
+ void remove_coords_level_tile_proxy(int p_source_from, Vector2i p_coords_from);
+
+ void set_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from, int p_source_to, Vector2i p_coords_to, int p_alternative_to);
+ Array get_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from);
+ bool has_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from);
+ void remove_alternative_level_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from);
+
+ Array get_source_level_tile_proxies() const;
+ Array get_coords_level_tile_proxies() const;
+ Array get_alternative_level_tile_proxies() const;
+
+ Array map_tile_proxy(int p_source_from, Vector2i p_coords_from, int p_alternative_from) const;
+
+ void cleanup_invalid_tile_proxies();
+ void clear_tile_proxies();
+
// Helpers
Vector<Vector2> get_tile_shape_polygon();
void draw_tile_shape(CanvasItem *p_canvas_item, Rect2 p_region, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>());
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 0f6412e6e9..7292728251 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -628,8 +628,8 @@ bool VisualShader::is_node_connection(Type p_type, int p_from_node, int p_from_p
ERR_FAIL_INDEX_V(p_type, TYPE_MAX, false);
const Graph *g = &graph[p_type];
- for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
+ for (const Connection &E : g->connections) {
+ if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
return true;
}
}
@@ -642,12 +642,12 @@ bool VisualShader::is_nodes_connected_relatively(const Graph *p_graph, int p_nod
const VisualShader::Node &node = p_graph->nodes[p_node];
- for (const List<int>::Element *E = node.prev_connected_nodes.front(); E; E = E->next()) {
- if (E->get() == p_target) {
+ for (const int &E : node.prev_connected_nodes) {
+ if (E == p_target) {
return true;
}
- result = is_nodes_connected_relatively(p_graph, E->get(), p_target);
+ result = is_nodes_connected_relatively(p_graph, E, p_target);
if (result) {
break;
}
@@ -686,8 +686,8 @@ bool VisualShader::can_connect_nodes(Type p_type, int p_from_node, int p_from_po
return false;
}
- for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
+ for (const Connection &E : g->connections) {
+ if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
return false;
}
}
@@ -739,8 +739,8 @@ Error VisualShader::connect_nodes(Type p_type, int p_from_node, int p_from_port,
ERR_FAIL_COND_V_MSG(!is_port_types_compatible(from_port_type, to_port_type), ERR_INVALID_PARAMETER, "Incompatible port types (scalar/vec/bool) with transform.");
- for (List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
- if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
+ for (const Connection &E : g->connections) {
+ if (E.from_node == p_from_node && E.from_port == p_from_port && E.to_node == p_to_node && E.to_port == p_to_port) {
ERR_FAIL_V(ERR_ALREADY_EXISTS);
}
}
@@ -763,7 +763,7 @@ void VisualShader::disconnect_nodes(Type p_type, int p_from_node, int p_from_por
ERR_FAIL_INDEX(p_type, TYPE_MAX);
Graph *g = &graph[p_type];
- for (List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
+ for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
if (E->get().from_node == p_from_node && E->get().from_port == p_from_port && E->get().to_node == p_to_node && E->get().to_port == p_to_port) {
g->connections.erase(E);
g->nodes[p_to_node].prev_connected_nodes.erase(p_from_node);
@@ -780,12 +780,12 @@ Array VisualShader::_get_node_connections(Type p_type) const {
const Graph *g = &graph[p_type];
Array ret;
- for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
+ for (const Connection &E : g->connections) {
Dictionary d;
- d["from_node"] = E->get().from_node;
- d["from_port"] = E->get().from_port;
- d["to_node"] = E->get().to_node;
- d["to_port"] = E->get().to_port;
+ d["from_node"] = E.from_node;
+ d["from_port"] = E.from_port;
+ d["to_node"] = E.to_node;
+ d["to_port"] = E.to_port;
ret.push_back(d);
}
@@ -796,8 +796,8 @@ void VisualShader::get_node_connections(Type p_type, List<Connection> *r_connect
ERR_FAIL_INDEX(p_type, TYPE_MAX);
const Graph *g = &graph[p_type];
- for (const List<Connection>::Element *E = g->connections.front(); E; E = E->next()) {
- r_connections->push_back(E->get());
+ for (const Connection &E : g->connections) {
+ r_connections->push_back(E);
}
}
@@ -1190,11 +1190,11 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
String index = name.get_slicec('/', 2);
if (index == "connections") {
Vector<int> conns;
- for (const List<Connection>::Element *E = graph[type].connections.front(); E; E = E->next()) {
- conns.push_back(E->get().from_node);
- conns.push_back(E->get().from_port);
- conns.push_back(E->get().to_node);
- conns.push_back(E->get().to_port);
+ for (const Connection &E : graph[type].connections) {
+ conns.push_back(E.from_node);
+ conns.push_back(E.from_port);
+ conns.push_back(E.to_node);
+ conns.push_back(E.to_port);
}
r_ret = conns;
@@ -1740,6 +1740,7 @@ void VisualShader::_update_shader() const {
}
Map<int, String> code_map;
+ Set<int> empty_funcs;
for (int i = 0; i < TYPE_MAX; i++) {
if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
@@ -1776,6 +1777,7 @@ void VisualShader::_update_shader() const {
}
if (is_empty_func) {
+ empty_funcs.insert(i);
continue;
}
@@ -1789,8 +1791,8 @@ void VisualShader::_update_shader() const {
ERR_FAIL_COND(err != OK);
if (emitters.has(i)) {
- for (List<int>::Element *E = emitters[i].front(); E; E = E->next()) {
- err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E->get(), processed, false, classes);
+ for (int &E : emitters[i]) {
+ err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
ERR_FAIL_COND(err != OK);
}
}
@@ -1934,7 +1936,11 @@ void VisualShader::_update_shader() const {
if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
continue;
}
- tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]);
+ String func_code = global_code_per_func[Type(i)].as_string();
+ if (empty_funcs.has(Type(i)) && !func_code.is_empty()) {
+ func_code = vformat("%s%s%s", String("\nvoid " + String(func_name[i]) + "() {\n"), func_code, "}\n");
+ }
+ tcode = tcode.insert(insertion_pos[i], func_code);
}
final_code += tcode;
@@ -2580,8 +2586,8 @@ void VisualShaderNodeUniformRef::clear_uniforms() {
}
bool VisualShaderNodeUniformRef::has_uniform(const String &p_name) {
- for (List<VisualShaderNodeUniformRef::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
- if (E->get().name == p_name) {
+ for (const VisualShaderNodeUniformRef::Uniform &E : uniforms) {
+ if (E.name == p_name) {
return true;
}
}
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index d53d155cce..b8173c9623 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -136,6 +136,7 @@ SceneStringNames::SceneStringNames() {
_spatial_editor_group = StaticCString::create("_spatial_editor_group");
_request_gizmo = StaticCString::create("_request_gizmo");
+ _clear_subgizmo_selection = StaticCString::create("_clear_subgizmo_selection");
offset = StaticCString::create("offset");
unit_offset = StaticCString::create("unit_offset");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index a141c2b3aa..eddb0c33eb 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -156,6 +156,7 @@ public:
StringName _spatial_editor_group;
StringName _request_gizmo;
+ StringName _clear_subgizmo_selection;
StringName offset;
StringName unit_offset;
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index be2a813fd1..3d44484033 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -346,8 +346,6 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item);
ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear);
- ClassDB::bind_method(D_METHOD("alert", "text", "title"), &DisplayServer::alert, DEFVAL("Alert!"));
-
ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode);
ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode);
diff --git a/servers/display_server.h b/servers/display_server.h
index 8d289b10fd..788206768c 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -143,8 +143,6 @@ public:
virtual void global_menu_remove_item(const String &p_menu_root, int p_idx);
virtual void global_menu_clear(const String &p_menu_root);
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0;
-
enum MouseMode {
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index 870401b180..d9ee91084f 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -55,8 +55,6 @@ public:
bool has_feature(Feature p_feature) const override { return false; }
String get_name() const override { return "headless"; }
- void alert(const String &p_alert, const String &p_title = "ALERT!") override {}
-
int get_screen_count() const override { return 0; }
Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Point2i(); }
Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override { return Size2i(); }
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 6f244deb1e..7aa2f9b7de 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -532,13 +532,13 @@ void Body2DSW::integrate_velocities(real_t p_step) {
}
void Body2DSW::wakeup_neighbours() {
- for (List<Pair<Constraint2DSW *, int>>::Element *E = constraint_list.front(); E; E = E->next()) {
- const Constraint2DSW *c = E->get().first;
+ for (const Pair<Constraint2DSW *, int> &E : constraint_list) {
+ const Constraint2DSW *c = E.first;
Body2DSW **n = c->get_body_ptr();
int bc = c->get_body_count();
for (int i = 0; i < bc; i++) {
- if (i == E->get().second) {
+ if (i == E.second) {
continue;
}
Body2DSW *b = n[i];
diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp
index b8cb4cddc5..8b30160cc1 100644
--- a/servers/physics_2d/step_2d_sw.cpp
+++ b/servers/physics_2d/step_2d_sw.cpp
@@ -46,8 +46,8 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod
p_body_island.push_back(p_body);
}
- for (const List<Pair<Constraint2DSW *, int>>::Element *E = p_body->get_constraint_list().front(); E; E = E->next()) {
- Constraint2DSW *constraint = (Constraint2DSW *)E->get().first;
+ for (const Pair<Constraint2DSW *, int> &E : p_body->get_constraint_list()) {
+ Constraint2DSW *constraint = (Constraint2DSW *)E.first;
if (constraint->get_island_step() == _step) {
continue; // Already processed.
}
@@ -56,7 +56,7 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod
all_constraints.push_back(constraint);
for (int i = 0; i < constraint->get_body_count(); i++) {
- if (i == E->get().second) {
+ if (i == E.second) {
continue;
}
Body2DSW *other_body = constraint->get_body_ptr()[i];
diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp
index 1cfb9ba3ad..6a7f2b73c5 100644
--- a/servers/physics_3d/collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/collision_solver_3d_sat.cpp
@@ -629,9 +629,7 @@ public:
_FORCE_INLINE_ bool test_axis(const Vector3 &p_axis, bool p_directional = false) {
Vector3 axis = p_axis;
- if (Math::abs(axis.x) < CMP_EPSILON &&
- Math::abs(axis.y) < CMP_EPSILON &&
- Math::abs(axis.z) < CMP_EPSILON) {
+ if (axis.is_equal_approx(Vector3())) {
// strange case, try an upwards separator
axis = Vector3(0.0, 1.0, 0.0);
}
diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
index d46437e782..d0f3dbbd35 100644
--- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
+++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
@@ -322,12 +322,12 @@ public:
m_angularLimits[2].m_hiLimit = angularUpper.z;
}
- //! Retrieves the angular limit informacion
+ //! Retrieves the angular limit information.
G6DOFRotationalLimitMotor3DSW *getRotationalLimitMotor(int index) {
return &m_angularLimits[index];
}
- //! Retrieves the limit informacion
+ //! Retrieves the limit information.
G6DOFTranslationalLimitMotor3DSW *getTranslationalLimitMotor() {
return &m_linearLimits;
}
diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/slider_joint_3d_sw.cpp
index db9bdb2986..1895fe1e2e 100644
--- a/servers/physics_3d/joints/slider_joint_3d_sw.cpp
+++ b/servers/physics_3d/joints/slider_joint_3d_sw.cpp
@@ -200,7 +200,7 @@ void SliderJoint3DSW::solve(real_t p_step) {
real_t softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin);
real_t restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin);
real_t damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin);
- // calcutate and apply impulse
+ // Calculate and apply impulse.
real_t normalImpulse = softness * (restitution * depth / p_step - damping * rel_vel) * m_jacLinDiagABInv[i];
Vector3 impulse_vector = normal * normalImpulse;
if (dynamic_A) {
diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp
index 2ffab0c923..04a174f9c8 100644
--- a/servers/physics_3d/shape_3d_sw.cpp
+++ b/servers/physics_3d/shape_3d_sw.cpp
@@ -1783,7 +1783,7 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
int z = floor(local_begin.z);
// Workaround cases where the ray starts at an integer position.
- if (Math::abs(cross_x) < CMP_EPSILON) {
+ if (Math::is_zero_approx(cross_x)) {
cross_x += delta_x;
// If going backwards, we should ignore the position we would get by the above flooring,
// because the ray is not heading in that direction.
@@ -1792,7 +1792,7 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
}
}
- if (Math::abs(cross_z) < CMP_EPSILON) {
+ if (Math::is_zero_approx(cross_z)) {
cross_z += delta_z;
if (z_step == -1) {
z -= 1;
diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h
index bc8bd3e695..0d1b7cc3d7 100644
--- a/servers/physics_3d/shape_3d_sw.h
+++ b/servers/physics_3d/shape_3d_sw.h
@@ -128,7 +128,7 @@ class PlaneShape3DSW : public Shape3DSW {
public:
Plane get_plane() const;
- virtual real_t get_area() const { return Math_INF; }
+ virtual real_t get_area() const { return INFINITY; }
virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_PLANE; }
virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3 &p_normal) const;
diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/soft_body_3d_sw.cpp
index 63a0fe11ba..724125bea8 100644
--- a/servers/physics_3d/soft_body_3d_sw.cpp
+++ b/servers/physics_3d/soft_body_3d_sw.cpp
@@ -1172,7 +1172,7 @@ struct _SoftBodyIntersectSegmentInfo {
Vector3 dir;
Vector3 hit_position;
uint32_t hit_face_index = -1;
- real_t hit_dist_sq = Math_INF;
+ real_t hit_dist_sq = INFINITY;
static bool process_hit(uint32_t p_face_index, void *p_userdata) {
_SoftBodyIntersectSegmentInfo &query_info = *(_SoftBodyIntersectSegmentInfo *)(p_userdata);
@@ -1203,7 +1203,7 @@ bool SoftBodyShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3
soft_body->query_ray(p_begin, p_end, _SoftBodyIntersectSegmentInfo::process_hit, &query_info);
- if (query_info.hit_dist_sq != Math_INF) {
+ if (query_info.hit_dist_sq != INFINITY) {
r_result = query_info.hit_position;
r_normal = soft_body->get_face_normal(query_info.hit_face_index);
return true;
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 717b4e8d14..857f112102 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -205,7 +205,7 @@ void register_server_types() {
GDREGISTER_CLASS(RDPipelineColorBlendStateAttachment);
GDREGISTER_CLASS(RDPipelineColorBlendState);
GDREGISTER_CLASS(RDShaderSource);
- GDREGISTER_CLASS(RDShaderBytecode);
+ GDREGISTER_CLASS(RDShaderSPIRV);
GDREGISTER_CLASS(RDShaderFile);
GDREGISTER_CLASS(RDPipelineSpecializationConstant);
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index ebb81abdad..c0c03eb26a 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -235,7 +235,7 @@ public:
Transform3D xform = view_xform * p_transform;
float radius = xform.basis.get_uniform_scale();
- if (radius > 0.98 || radius < 1.02) {
+ if (radius < 0.98 || radius > 1.02) {
xform.basis.orthonormalize();
}
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index 5cf8895c8e..47bb756d55 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -383,6 +383,8 @@ void EffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i
}
void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the compute version of the gaussian blur with the mobile renderer.");
+
memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
uint32_t base_flags = 0;
@@ -416,6 +418,8 @@ void EffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back
}
void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
+
memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW;
@@ -449,6 +453,57 @@ void EffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const
RD::get_singleton()->compute_list_end();
}
+void EffectsRD::gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the fragment version of the gaussian glow with the clustered renderer.");
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
+ uint32_t base_flags = 0;
+
+ blur_raster.push_constant.pixel_size[0] = p_pixel_size.x;
+ blur_raster.push_constant.pixel_size[1] = p_pixel_size.y;
+
+ blur_raster.push_constant.glow_strength = p_strength;
+ blur_raster.push_constant.glow_bloom = p_bloom;
+ blur_raster.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold;
+ blur_raster.push_constant.glow_hdr_scale = p_hdr_bleed_scale;
+ blur_raster.push_constant.glow_exposure = p_exposure;
+ blur_raster.push_constant.glow_white = 0; //actually unused
+ blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
+
+ blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+
+ //HORIZONTAL
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
+ if (p_auto_exposure.is_valid() && p_first_pass) {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1);
+ }
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ blur_mode = BLUR_MODE_GAUSSIAN_GLOW;
+
+ //VERTICAL
+ draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ blur_raster.push_constant.flags = base_flags;
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
@@ -736,6 +791,8 @@ void EffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Tone
}
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
+
luminance_reduce.push_constant.source_size[0] = p_source_size.x;
luminance_reduce.push_constant.source_size[1] = p_source_size.y;
luminance_reduce.push_constant.max_luminance = p_max_luminance;
@@ -774,7 +831,41 @@ void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_
RD::get_singleton()->compute_list_end();
}
+void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use fragment version of luminance reduction with the clustered renderer.");
+ ERR_FAIL_COND_MSG(p_reduce.size() != p_fb.size(), "Incorrect frame buffer account for luminance reduction.");
+
+ luminance_reduce_raster.push_constant.max_luminance = p_max_luminance;
+ luminance_reduce_raster.push_constant.min_luminance = p_min_luminance;
+ luminance_reduce_raster.push_constant.exposure_adjust = p_adjust;
+
+ for (int i = 0; i < p_reduce.size(); i++) {
+ luminance_reduce_raster.push_constant.source_size[0] = i == 0 ? p_source_size.x : luminance_reduce_raster.push_constant.dest_size[0];
+ luminance_reduce_raster.push_constant.source_size[1] = i == 0 ? p_source_size.y : luminance_reduce_raster.push_constant.dest_size[1];
+ luminance_reduce_raster.push_constant.dest_size[0] = MAX(luminance_reduce_raster.push_constant.source_size[0] / 8, 1);
+ luminance_reduce_raster.push_constant.dest_size[1] = MAX(luminance_reduce_raster.push_constant.source_size[1] / 8, 1);
+
+ bool final = !p_set && (luminance_reduce_raster.push_constant.dest_size[0] == 1) && (luminance_reduce_raster.push_constant.dest_size[1] == 1);
+ LuminanceReduceRasterMode mode = final ? LUMINANCE_REDUCE_FRAGMENT_FINAL : (i == 0 ? LUMINANCE_REDUCE_FRAGMENT_FIRST : LUMINANCE_REDUCE_FRAGMENT);
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_fb[i])));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(i == 0 ? p_source_texture : p_reduce[i - 1]), 0);
+ if (final) {
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_prev_luminance), 1);
+ }
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &luminance_reduce_raster.push_constant, sizeof(LuminanceReduceRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+}
+
void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of BOKEH DOF with the mobile renderer.");
+
bokeh.push_constant.blur_far_active = p_dof_far;
bokeh.push_constant.blur_far_begin = p_dof_far_begin;
bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
@@ -924,6 +1015,78 @@ void EffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i
RD::get_singleton()->compute_list_end();
}
+void EffectsRD::blur_dof_raster(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_base_fb, RID p_secondary_texture, RID p_secondary_fb, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use blur DOF with the clustered renderer.");
+
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+
+ BlurRasterMode blur_mode;
+ int qsteps[4] = { 4, 4, 10, 20 };
+ uint32_t base_flags = p_cam_orthogonal ? BLUR_FLAG_USE_ORTHOGONAL_PROJECTION : 0;
+
+ Vector2 pixel_size = Vector2(1.0 / p_base_texture_size.width, 1.0 / p_base_texture_size.height);
+
+ blur_raster.push_constant.dof_radius = (p_dof_blur_amount * p_dof_blur_amount) / qsteps[p_quality];
+ blur_raster.push_constant.pixel_size[0] = pixel_size.x;
+ blur_raster.push_constant.pixel_size[1] = pixel_size.y;
+ blur_raster.push_constant.camera_z_far = p_cam_zfar;
+ blur_raster.push_constant.camera_z_near = p_cam_znear;
+
+ if (p_dof_far || p_dof_near) {
+ if (p_quality == RS::DOF_BLUR_QUALITY_HIGH) {
+ blur_mode = BLUR_MODE_DOF_HIGH;
+ } else if (p_quality == RS::DOF_BLUR_QUALITY_MEDIUM) {
+ blur_mode = BLUR_MODE_DOF_MEDIUM;
+ } else { // for LOW or VERYLOW we use LOW
+ blur_mode = BLUR_MODE_DOF_LOW;
+ }
+
+ if (p_dof_far) {
+ base_flags |= BLUR_FLAG_DOF_FAR;
+ blur_raster.push_constant.dof_far_begin = p_dof_far_begin;
+ blur_raster.push_constant.dof_far_end = p_dof_far_begin + p_dof_far_size;
+ }
+
+ if (p_dof_near) {
+ base_flags |= BLUR_FLAG_DOF_NEAR;
+ blur_raster.push_constant.dof_near_begin = p_dof_near_begin;
+ blur_raster.push_constant.dof_near_end = p_dof_near_begin - p_dof_near_size;
+ }
+
+ //HORIZONTAL
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_secondary_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_secondary_fb)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_depth_texture), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ blur_raster.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL;
+ blur_raster.push_constant.dof_dir[0] = 1.0;
+ blur_raster.push_constant.dof_dir[1] = 0.0;
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ //VERTICAL
+ draw_list = RD::get_singleton()->draw_list_begin(p_base_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_base_fb)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary_texture), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_depth_texture), 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
+
+ blur_raster.push_constant.flags = base_flags;
+ blur_raster.push_constant.dof_dir[0] = 0.0;
+ blur_raster.push_constant.dof_dir[1] = 1.0;
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+ }
+}
+
void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
@@ -1188,8 +1351,9 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep
if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
if (pass < blur_passes - 2) {
blur_pipeline = SSAO_BLUR_PASS_WIDE;
+ } else {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
}
- blur_pipeline = SSAO_BLUR_PASS_SMART;
}
for (int i = 0; i < 4; i++) {
@@ -1464,7 +1628,35 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
RD::get_singleton()->compute_list_end();
}
-EffectsRD::EffectsRD() {
+EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
+ prefer_raster_effects = p_prefer_raster_effects;
+
+ if (prefer_raster_effects) {
+ // init blur shader (on compute use copy shader)
+
+ Vector<String> blur_modes;
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); // BLUR_MODE_GAUSSIAN_BLUR
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); // BLUR_MODE_GAUSSIAN_GLOW
+ blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); // BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE
+ blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_LOW\n"); // BLUR_MODE_DOF_LOW
+ blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_MEDIUM\n"); // BLUR_MODE_DOF_MEDIUM
+ blur_modes.push_back("\n#define MODE_DOF_BLUR\n#define DOF_QUALITY_HIGH\n"); // BLUR_MODE_DOF_HIGH
+
+ blur_raster.shader.initialize(blur_modes);
+ memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
+ blur_raster.shader_version = blur_raster.shader.version_create();
+
+ for (int i = 0; i < BLUR_MODE_MAX; i++) {
+ blur_raster.pipelines[i].setup(blur_raster.shader.version_get_shader(blur_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+
+ } else {
+ // not used in clustered
+ for (int i = 0; i < BLUR_MODE_MAX; i++) {
+ blur_raster.pipelines[i].clear();
+ }
+ }
+
{ // Initialize copy
Vector<String> copy_modes;
copy_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n");
@@ -1483,10 +1675,21 @@ EffectsRD::EffectsRD() {
copy.shader.initialize(copy_modes);
memset(&copy.push_constant, 0, sizeof(CopyPushConstant));
+
+ if (prefer_raster_effects) {
+ // disable shaders we can't use
+ copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY, false);
+ copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_COPY_8BIT, false);
+ copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW, false);
+ copy.shader.set_variant_enabled(COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, false);
+ }
+
copy.shader_version = copy.shader.version_create();
for (int i = 0; i < COPY_MODE_MAX; i++) {
- copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
+ if (copy.shader.is_variant_enabled(i)) {
+ copy.pipelines[i] = RD::get_singleton()->compute_pipeline_create(copy.shader.version_get_shader(copy.shader_version, i));
+ }
}
}
{
@@ -1551,7 +1754,20 @@ EffectsRD::EffectsRD() {
}
}
- {
+ if (prefer_raster_effects) {
+ Vector<String> luminance_reduce_modes;
+ luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
+ luminance_reduce_modes.push_back("\n"); // LUMINANCE_REDUCE_FRAGMENT
+ luminance_reduce_modes.push_back("\n#define FINAL_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FINAL
+
+ luminance_reduce_raster.shader.initialize(luminance_reduce_modes);
+ memset(&luminance_reduce_raster.push_constant, 0, sizeof(LuminanceReduceRasterPushConstant));
+ luminance_reduce_raster.shader_version = luminance_reduce_raster.shader.version_create();
+
+ for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
+ luminance_reduce_raster.pipelines[i].setup(luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ }
+ } else {
// Initialize luminance_reduce
Vector<String> luminance_reduce_modes;
luminance_reduce_modes.push_back("\n#define READ_TEXTURE\n");
@@ -1565,6 +1781,10 @@ EffectsRD::EffectsRD() {
for (int i = 0; i < LUMINANCE_REDUCE_MAX; i++) {
luminance_reduce.pipelines[i] = RD::get_singleton()->compute_pipeline_create(luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, i));
}
+
+ for (int i = 0; i < LUMINANCE_REDUCE_FRAGMENT_MAX; i++) {
+ luminance_reduce_raster.pipelines[i].clear();
+ }
}
{
@@ -1583,7 +1803,9 @@ EffectsRD::EffectsRD() {
cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
}
- {
+ if (prefer_raster_effects) {
+ // not supported
+ } else {
// Initialize bokeh
Vector<String> bokeh_modes;
bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n");
@@ -1974,13 +2196,18 @@ EffectsRD::~EffectsRD() {
RD::get_singleton()->free(ssao.gather_constants_buffer);
RD::get_singleton()->free(ssao.importance_map_load_counter);
- bokeh.shader.version_free(bokeh.shader_version);
+ if (prefer_raster_effects) {
+ blur_raster.shader.version_free(blur_raster.shader_version);
+ luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
+ } else {
+ bokeh.shader.version_free(bokeh.shader_version);
+ luminance_reduce.shader.version_free(luminance_reduce.shader_version);
+ }
copy.shader.version_free(copy.shader_version);
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
cube_to_dp.shader.version_free(cube_to_dp.shader_version);
cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version);
filter.shader.version_free(filter.shader_version);
- luminance_reduce.shader.version_free(luminance_reduce.shader_version);
resolve.shader.version_free(resolve.shader_version);
roughness.shader.version_free(roughness.shader_version);
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 33d32f0c57..d072564c23 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -33,6 +33,7 @@
#include "core/math/camera_matrix.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/blur_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/bokeh_dof.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/copy.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/copy_to_fb.glsl.gen.h"
@@ -41,6 +42,7 @@
#include "servers/rendering/renderer_rd/shaders/cubemap_filter.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h"
@@ -60,6 +62,63 @@
#include "servers/rendering_server.h"
class EffectsRD {
+ enum BlurRasterMode {
+ BLUR_MODE_GAUSSIAN_BLUR,
+ BLUR_MODE_GAUSSIAN_GLOW,
+ BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
+
+ BLUR_MODE_DOF_LOW,
+ BLUR_MODE_DOF_MEDIUM,
+ BLUR_MODE_DOF_HIGH,
+
+ BLUR_MODE_MAX
+ };
+
+ enum {
+ BLUR_FLAG_HORIZONTAL = (1 << 0),
+ BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 1),
+ BLUR_FLAG_GLOW_FIRST_PASS = (1 << 2),
+ BLUR_FLAG_DOF_FAR = (1 << 3),
+ BLUR_FLAG_DOF_NEAR = (1 << 4),
+ };
+
+ struct BlurRasterPushConstant {
+ float pixel_size[2];
+ uint32_t flags;
+ uint32_t pad;
+
+ //glow
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+
+ //dof
+ float dof_far_begin;
+ float dof_far_end;
+ float dof_near_begin;
+ float dof_near_end;
+
+ float dof_radius;
+ float dof_pad[3];
+
+ float dof_dir[2];
+ float camera_z_far;
+ float camera_z_near;
+ };
+
+ struct BlurRaster {
+ BlurRasterPushConstant push_constant;
+ BlurRasterShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[BLUR_MODE_MAX];
+ } blur_raster;
+
enum CopyMode {
COPY_MODE_GAUSSIAN_COPY,
COPY_MODE_GAUSSIAN_COPY_8BIT,
@@ -239,6 +298,29 @@ class EffectsRD {
RID pipelines[LUMINANCE_REDUCE_MAX];
} luminance_reduce;
+ enum LuminanceReduceRasterMode {
+ LUMINANCE_REDUCE_FRAGMENT_FIRST,
+ LUMINANCE_REDUCE_FRAGMENT,
+ LUMINANCE_REDUCE_FRAGMENT_FINAL,
+ LUMINANCE_REDUCE_FRAGMENT_MAX
+ };
+
+ struct LuminanceReduceRasterPushConstant {
+ int32_t source_size[2];
+ int32_t dest_size[2];
+ float exposure_adjust;
+ float min_luminance;
+ float max_luminance;
+ float pad[1];
+ };
+
+ struct LuminanceReduceFragment {
+ LuminanceReduceRasterPushConstant push_constant;
+ LuminanceReduceRasterShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX];
+ } luminance_reduce_raster;
+
struct CopyToDPPushConstant {
float z_far;
float z_near;
@@ -656,6 +738,8 @@ class EffectsRD {
RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
+ bool prefer_raster_effects;
+
public:
void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID());
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
@@ -666,12 +750,16 @@ public:
void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_texture, const Rect2 &p_rect, float p_z_near, float p_z_far, bool p_dp_flip);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
+ void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
+
void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void blur_dof_raster(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_base_fb, RID p_secondary_texture, RID p_secondary_fb, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
struct TonemapSettings {
bool use_glow = false;
@@ -751,7 +839,7 @@ public:
void sort_buffer(RID p_uniform_set, int p_size);
- EffectsRD();
+ EffectsRD(bool p_prefer_raster_effects);
~EffectsRD();
};
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index 438bbff53c..5f6d9465c7 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -96,10 +96,6 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
- if (color_format == RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32) {
- // @TODO add a second color buffer for alpha as this format is RGB only
- }
-
Vector<RID> fb;
fb.push_back(p_color_buffer);
fb.push_back(depth);
@@ -164,16 +160,13 @@ bool RenderForwardMobile::free(RID p_rid) {
/* Render functions */
RD::DataFormat RenderForwardMobile::_render_buffers_get_color_format() {
- // Using 32bit buffers enables AFBC on mobile devices which should have a definate performance improvement (MALI G710 and newer support this on 64bit RTs)
- // NO ALPHA and unsigned float.
- // @TODO No alpha is an issue, recommendation here is to add a second RT for alpha
+ // Using 32bit buffers enables AFBC on mobile devices which should have a definite performance improvement (MALI G710 and newer support this on 64bit RTs)
return RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
}
bool RenderForwardMobile::_render_buffers_can_be_storage() {
- // Using 32bit buffers enables AFBC on mobile devices which should have a definate performance improvement (MALI G710 and newer support this on 64bit RTs)
- // NO ALPHA and unsigned float.
- // @TODO No alpha is an issue, recommendation here is to add a second RT for alpha
+ // Using 32bit buffers enables AFBC on mobile devices which should have a definite performance improvement (MALI G710 and newer support this on 64bit RTs)
+ // Doesn't support storage
return false;
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 6a66e9fa01..18c1fe02a0 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -620,7 +620,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
RD::get_singleton()->draw_list_draw(p_draw_list, true);
- //restore if overrided
+ // Restore if overridden.
push_constant.color_texture_pixel_size[0] = texpixel_size.x;
push_constant.color_texture_pixel_size[1] = texpixel_size.y;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index e6ae66d56f..a7ee0dd141 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -280,6 +280,9 @@ RendererCompositorRD::RendererCompositorRD() {
// default to our high end renderer
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
}
+
+ // now we're ready to create our effects,
+ storage->init_effects(!scene->_render_buffers_can_be_storage());
}
RendererCompositorRD::~RendererCompositorRD() {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 4870f5f397..2e0e7c3c43 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -1383,12 +1383,20 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH);
+ // TODO make sure texture_create_shared_from_slice works for multiview
+
RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
tf.width = rb->width;
tf.height = rb->height;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
+ tf.array_layers = rb->view_count;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ if (_render_buffers_can_be_storage()) {
+ tf.usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
+ } else {
+ tf.usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
tf.mipmaps = mipmaps_required;
rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -1408,11 +1416,40 @@ void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
mm.width = base_width;
mm.height = base_height;
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
+
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+
+ if (!_render_buffers_can_be_storage()) {
+ // and half texture, this is an intermediate result so just allocate a texture, is this good enough?
+ tf.width = MAX(1, base_width >> 1);
+ tf.height = base_height;
+ tf.mipmaps = 1; // 1 or 0?
+
+ mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> half_fb;
+ half_fb.push_back(mm.half_texture);
+ mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb);
+ }
+
rb->blur[0].mipmaps.push_back(mm);
if (i > 0) {
mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1);
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
+
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
+
+ // We can re-use the half texture here as it is an intermediate result
+ }
+
rb->blur[1].mipmaps.push_back(mm);
}
@@ -1435,26 +1472,48 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
tf.format = RD::DATA_FORMAT_R32_SFLOAT;
tf.width = w;
tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
bool final = w == 1 && h == 1;
- if (final) {
- tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
+ if (_render_buffers_can_be_storage()) {
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+ if (final) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
+ }
+ } else {
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
}
RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
rb->luminance.reduce.push_back(texture);
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(texture);
+
+ rb->luminance.fb.push_back(RD::get_singleton()->framebuffer_create(fb));
+ }
if (final) {
rb->luminance.current = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ if (!_render_buffers_can_be_storage()) {
+ Vector<RID> fb;
+ fb.push_back(rb->luminance.current);
+
+ rb->luminance.current_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
break;
}
}
}
void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
+ if (rb->texture_fb.is_valid()) {
+ RD::get_singleton()->free(rb->texture_fb);
+ rb->texture_fb = RID();
+ }
+
if (rb->texture.is_valid()) {
RD::get_singleton()->free(rb->texture);
rb->texture = RID();
@@ -1466,19 +1525,43 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
}
for (int i = 0; i < 2; i++) {
+ for (int m = 0; m < rb->blur[i].mipmaps.size(); m++) {
+ // do we free the texture slice here? or is it enough to free the main texture?
+
+ // do free the mobile extra stuff
+ if (rb->blur[i].mipmaps[m].fb.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].mipmaps[m].fb);
+ }
+ if (rb->blur[i].mipmaps[m].half_fb.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_fb);
+ }
+ if (rb->blur[i].mipmaps[m].half_texture.is_valid()) {
+ RD::get_singleton()->free(rb->blur[i].mipmaps[m].half_texture);
+ }
+ }
+ rb->blur[i].mipmaps.clear();
+
if (rb->blur[i].texture.is_valid()) {
RD::get_singleton()->free(rb->blur[i].texture);
rb->blur[i].texture = RID();
- rb->blur[i].mipmaps.clear();
}
}
+ for (int i = 0; i < rb->luminance.fb.size(); i++) {
+ RD::get_singleton()->free(rb->luminance.fb[i]);
+ }
+ rb->luminance.fb.clear();
+
for (int i = 0; i < rb->luminance.reduce.size(); i++) {
RD::get_singleton()->free(rb->luminance.reduce[i]);
}
-
rb->luminance.reduce.clear();
+ if (rb->luminance.current_fb.is_valid()) {
+ RD::get_singleton()->free(rb->luminance.current_fb);
+ rb->luminance.current_fb = RID();
+ }
+
if (rb->luminance.current.is_valid()) {
RD::get_singleton()->free(rb->luminance.current);
rb->luminance.current = RID();
@@ -1750,17 +1833,27 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
CameraEffects *camfx = camera_effects_owner.getornull(p_render_data->camera_effects);
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ bool can_use_storage = _render_buffers_can_be_storage();
+
+ // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
+ RD::get_singleton()->draw_command_begin_label("DOF");
if (rb->blur[0].texture.is_null()) {
_allocate_blur_textures(rb);
}
- float bokeh_size = camfx->dof_blur_amount * 64.0;
- storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
+ if (can_use_storage) {
+ float bokeh_size = camfx->dof_blur_amount * 64.0;
+ storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
+ } else {
+ storage->get_effects()->blur_dof_raster(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->texture_fb, rb->blur[0].mipmaps[0].texture, rb->blur[0].mipmaps[0].fb, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, camfx->dof_blur_amount, dof_blur_quality, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal);
+ }
+ RD::get_singleton()->draw_command_end_label();
}
if (can_use_effects && env && env->auto_exposure) {
+ RD::get_singleton()->draw_command_begin_label("Auto exposure");
if (rb->luminance.current.is_null()) {
_allocate_luminance_textures(rb);
}
@@ -1769,16 +1862,26 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
rb->auto_exposure_version = env->auto_exposure_version;
double step = env->auto_exp_speed * time_step;
- storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
-
+ if (can_use_storage) {
+ storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ } else {
+ storage->get_effects()->luminance_reduction_raster(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ }
//swap final reduce with prev luminance
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
+ if (!can_use_storage) {
+ SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
+ }
+
RenderingServerDefault::redraw_request(); //redraw all the time if auto exposure rendering is on
+ RD::get_singleton()->draw_command_end_label();
}
int max_glow_level = -1;
if (can_use_effects && env && env->glow_enabled) {
+ RD::get_singleton()->draw_command_begin_label("Gaussian Glow");
+
/* see that blur textures are allocated */
if (rb->blur[1].texture.is_null()) {
@@ -1804,14 +1907,26 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (env->auto_exposure && rb->luminance.current.is_valid()) {
luminance_texture = rb->luminance.current;
}
- storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ if (can_use_storage) {
+ storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ } else {
+ storage->get_effects()->gaussian_glow_raster(rb->texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ }
} else {
- storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ if (can_use_storage) {
+ storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ } else {
+ storage->get_effects()->gaussian_glow_raster(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].half_fb, rb->blur[1].mipmaps[i].half_texture, rb->blur[1].mipmaps[i].fb, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, glow_high_quality);
+ }
}
}
+
+ RD::get_singleton()->draw_command_end_label();
}
{
+ RD::get_singleton()->draw_command_begin_label("Tonemap");
+
//tonemap
EffectsRD::TonemapSettings tonemap;
@@ -1870,6 +1985,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.view_count = p_render_data->view_count;
storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+
+ RD::get_singleton()->draw_command_end_label();
}
storage->render_target_disable_clear_request(rb->render_target);
@@ -2133,7 +2250,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
}
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
- ERR_FAIL_COND_MSG(p_view_count == 0, "Must have atleast 1 view");
+ ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);
rb->width = p_width;
@@ -2197,6 +2314,14 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
}
+ if (!_render_buffers_can_be_storage()) {
+ // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
+ Vector<RID> fb;
+ fb.push_back(rb->texture);
+
+ rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
+ }
+
rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 5e0281002d..bb06eb608f 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -450,6 +450,7 @@ private:
RID texture; //main texture for rendering to, must be filled after done rendering
RID depth_texture; //main depth texture
+ RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
RendererSceneGIRD::SDFGI *sdfgi = nullptr;
VolumetricFog *volumetric_fog = nullptr;
@@ -465,6 +466,11 @@ private:
RID texture;
int width;
int height;
+
+ // only used on mobile renderer
+ RID fb;
+ RID half_texture;
+ RID half_fb;
};
Vector<Mipmap> mipmaps;
@@ -475,6 +481,10 @@ private:
struct Luminance {
Vector<RID> reduce;
RID current;
+
+ // used only on mobile renderer
+ Vector<RID> fb;
+ RID current_fb;
} luminance;
struct SSAO {
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 2657fa3ae8..d5c7db6fd2 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -2716,9 +2716,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
mesh->surfaces[mesh->surface_count] = s;
mesh->surface_count++;
- for (List<MeshInstance *>::Element *E = mesh->instances.front(); E; E = E->next()) {
- //update instances
- MeshInstance *mi = E->get();
+ for (MeshInstance *mi : mesh->instances) {
_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
}
@@ -3029,8 +3027,7 @@ void RendererStorageRD::mesh_clear(RID p_mesh) {
mesh->surface_count = 0;
mesh->material_cache.clear();
//clear instance data
- for (List<MeshInstance *>::Element *E = mesh->instances.front(); E; E = E->next()) {
- MeshInstance *mi = E->get();
+ for (MeshInstance *mi : mesh->instances) {
_mesh_instance_clear(mi);
}
mesh->has_bone_weights = false;
@@ -4962,7 +4959,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &
RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
RD::get_singleton()->compute_list_end();
- effects.sort_buffer(particles->particles_sort_uniform_set, particles->amount);
+ effects->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
}
copy_push_constant.total_particles *= copy_push_constant.total_particles;
@@ -7538,7 +7535,7 @@ void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, c
//single texture copy for backbuffer
//RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
- effects.copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+ effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
if (!p_gen_mipmaps) {
return;
@@ -7554,7 +7551,7 @@ void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, c
region.size.y = MAX(1, region.size.y >> 1);
const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
- effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
+ effects->gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
prev_texture = mm.mipmap;
}
}
@@ -7577,7 +7574,7 @@ void RendererStorageRD::render_target_clear_back_buffer(RID p_render_target, con
}
//single texture copy for backbuffer
- effects.set_color(rt->backbuffer_mipmap0, p_color, region, true);
+ effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
}
void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
@@ -7607,7 +7604,7 @@ void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_targe
region.size.y = MAX(1, region.size.y >> 1);
const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i];
- effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
+ effects->gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true);
prev_texture = mm.mipmap;
}
}
@@ -7928,14 +7925,14 @@ void RendererStorageRD::_update_decal_atlas() {
while ((K = decal_atlas.textures.next(K))) {
DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
Texture *src_tex = texture_owner.getornull(*K);
- effects.copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
+ effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
}
RD::get_singleton()->draw_list_end();
prev_texture = mm.texture;
} else {
- effects.copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
+ effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
prev_texture = mm.texture;
}
} else {
@@ -8413,10 +8410,10 @@ void RendererStorageRD::global_variables_load_settings(bool p_load_textures) {
List<PropertyInfo> settings;
ProjectSettings::get_singleton()->get_property_list(&settings);
- for (List<PropertyInfo>::Element *E = settings.front(); E; E = E->next()) {
- if (E->get().name.begins_with("shader_globals/")) {
- StringName name = E->get().name.get_slice("/", 1);
- Dictionary d = ProjectSettings::get_singleton()->get(E->get().name);
+ for (const PropertyInfo &E : settings) {
+ if (E.name.begins_with("shader_globals/")) {
+ StringName name = E.name.get_slice("/", 1);
+ Dictionary d = ProjectSettings::get_singleton()->get(E.name);
ERR_CONTINUE(!d.has("type"));
ERR_CONTINUE(!d.has("value"));
@@ -8584,8 +8581,8 @@ void RendererStorageRD::_update_global_variables() {
if (global_variables.must_update_buffer_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (List<RID>::Element *E = global_variables.materials_using_buffer.front(); E; E = E->next()) {
- Material *material = material_owner.getornull(E->get());
+ for (const RID &E : global_variables.materials_using_buffer) {
+ Material *material = material_owner.getornull(E);
ERR_CONTINUE(!material); //wtf
_material_queue_update(material, true, false);
@@ -8597,8 +8594,8 @@ void RendererStorageRD::_update_global_variables() {
if (global_variables.must_update_texture_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (List<RID>::Element *E = global_variables.materials_using_texture.front(); E; E = E->next()) {
- Material *material = material_owner.getornull(E->get());
+ for (const RID &E : global_variables.materials_using_texture) {
+ Material *material = material_owner.getornull(E);
ERR_CONTINUE(!material); //wtf
_material_queue_update(material, false, true);
@@ -8807,8 +8804,13 @@ bool RendererStorageRD::free(RID p_rid) {
return true;
}
+void RendererStorageRD::init_effects(bool p_prefer_raster_effects) {
+ effects = memnew(EffectsRD(p_prefer_raster_effects));
+}
+
EffectsRD *RendererStorageRD::get_effects() {
- return &effects;
+ ERR_FAIL_NULL_V_MSG(effects, nullptr, "Effects haven't been initialised yet.");
+ return effects;
}
void RendererStorageRD::capture_timestamps_begin() {
@@ -9538,4 +9540,9 @@ RendererStorageRD::~RendererStorageRD() {
if (decal_atlas.texture.is_valid()) {
RD::get_singleton()->free(decal_atlas.texture);
}
+
+ if (effects) {
+ memdelete(effects);
+ effects = NULL;
+ }
}
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index f471874c8e..b290c07705 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -1290,7 +1290,7 @@ private:
void _update_global_variables();
/* EFFECTS */
- EffectsRD effects;
+ EffectsRD *effects = NULL;
public:
virtual bool can_create_resources_async() const;
@@ -2374,6 +2374,7 @@ public:
static RendererStorageRD *base_singleton;
+ void init_effects(bool p_prefer_raster_effects);
EffectsRD *get_effects();
RendererStorageRD();
diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
index 1dde92d8ff..9c1068ea2e 100644
--- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp
@@ -571,7 +571,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
max_texture_uniforms++;
} else {
if (E->get().scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue; //instances are indexed directly, dont need index uniforms
+ continue; // Instances are indexed directly, don't need index uniforms.
}
max_uniforms++;
@@ -605,7 +605,7 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
if (uniform.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
//insert, but don't generate any code.
p_actions.uniforms->insert(uniform_name, uniform);
- continue; //instances are indexed directly, dont need index uniforms
+ continue; // Instances are indexed directly, don't need index uniforms.
}
if (SL::is_sampler_type(uniform.type)) {
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_order) + ") uniform ";
@@ -760,11 +760,11 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge
if (var_frag_to_light.size() > 0) {
String gcode = "\n\nstruct {\n";
- for (List<Pair<StringName, SL::ShaderNode::Varying>>::Element *E = var_frag_to_light.front(); E; E = E->next()) {
- gcode += "\t" + _prestr(E->get().second.precision) + _typestr(E->get().second.type) + " " + _mkid(E->get().first);
- if (E->get().second.array_size > 0) {
+ for (const Pair<StringName, SL::ShaderNode::Varying> &E : var_frag_to_light) {
+ gcode += "\t" + _prestr(E.second.precision) + _typestr(E.second.type) + " " + _mkid(E.first);
+ if (E.second.array_size > 0) {
gcode += "[";
- gcode += itos(E->get().second.array_size);
+ gcode += itos(E.second.array_size);
gcode += "]";
}
gcode += ";\n";
@@ -1394,8 +1394,8 @@ void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) {
ShaderLanguage::get_builtin_funcs(&func_list);
- for (List<String>::Element *E = func_list.front(); E; E = E->next()) {
- internal_functions.insert(E->get());
+ for (const String &E : func_list) {
+ internal_functions.insert(E);
}
texture_functions.insert("texture");
texture_functions.insert("textureProj");
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 27305cc938..1b9f54d1c8 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -116,8 +116,10 @@ void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, con
}
StringBuilder tohash;
- tohash.append("[VersionKey]");
- tohash.append(RenderingDevice::get_singleton()->shader_get_cache_key());
+ tohash.append("[SpirvCacheKey]");
+ tohash.append(RenderingDevice::get_singleton()->shader_get_spirv_cache_key());
+ tohash.append("[BinaryCacheKey]");
+ tohash.append(RenderingDevice::get_singleton()->shader_get_binary_cache_key());
tohash.append("[Vertex]");
tohash.append(p_vertex_code ? p_vertex_code : "");
tohash.append("[Fragment]");
@@ -148,8 +150,8 @@ void ShaderRD::_clear_version(Version *p_version) {
}
memdelete_arr(p_version->variants);
- if (p_version->variant_stages) {
- memdelete_arr(p_version->variant_stages);
+ if (p_version->variant_data) {
+ memdelete_arr(p_version->variant_data);
}
p_version->variants = nullptr;
}
@@ -203,7 +205,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
return; //variant is disabled, return
}
- Vector<RD::ShaderStageData> &stages = p_version->variant_stages[p_variant];
+ Vector<RD::ShaderStageSPIRVData> stages;
String error;
String current_source;
@@ -217,8 +219,8 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
_build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_VERTEX]);
current_source = builder.as_string();
- RD::ShaderStageData stage;
- stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_VERTEX, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
+ RD::ShaderStageSPIRVData stage;
+ stage.spir_v = RD::get_singleton()->shader_compile_spirv_from_source(RD::SHADER_STAGE_VERTEX, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
if (stage.spir_v.size() == 0) {
build_ok = false;
} else {
@@ -235,8 +237,8 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
_build_variant_code(builder, p_variant, p_version, stage_templates[STAGE_TYPE_FRAGMENT]);
current_source = builder.as_string();
- RD::ShaderStageData stage;
- stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_FRAGMENT, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
+ RD::ShaderStageSPIRVData stage;
+ stage.spir_v = RD::get_singleton()->shader_compile_spirv_from_source(RD::SHADER_STAGE_FRAGMENT, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
if (stage.spir_v.size() == 0) {
build_ok = false;
} else {
@@ -254,8 +256,8 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
current_source = builder.as_string();
- RD::ShaderStageData stage;
- stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_COMPUTE, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
+ RD::ShaderStageSPIRVData stage;
+ stage.spir_v = RD::get_singleton()->shader_compile_spirv_from_source(RD::SHADER_STAGE_COMPUTE, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
if (stage.spir_v.size() == 0) {
build_ok = false;
} else {
@@ -275,10 +277,15 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
return;
}
- RID shader = RD::get_singleton()->shader_create(stages);
+ Vector<uint8_t> shader_data = RD::get_singleton()->shader_compile_binary_from_spirv(stages);
+
+ ERR_FAIL_COND(shader_data.size() == 0);
+
+ RID shader = RD::get_singleton()->shader_create_from_bytecode(shader_data);
{
MutexLock lock(variant_set_mutex);
p_version->variants[p_variant] = shader;
+ p_version->variant_data[p_variant] = shader_data;
}
}
@@ -364,14 +371,12 @@ String ShaderRD::_version_get_sha1(Version *p_version) const {
}
static const char *shader_file_header = "GDSC";
-static const uint32_t cache_file_version = 1;
+static const uint32_t cache_file_version = 2;
bool ShaderRD::_load_from_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
- uint64_t time_from = OS::get_singleton()->get_ticks_usec();
-
FileAccessRef f = FileAccess::open(path, FileAccess::READ);
if (!f) {
return false;
@@ -390,76 +395,43 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
ERR_FAIL_COND_V(variant_count != (uint32_t)variant_defines.size(), false); //should not happen but check
- bool success = true;
for (uint32_t i = 0; i < variant_count; i++) {
- uint32_t stage_count = f->get_32();
- p_version->variant_stages[i].resize(stage_count);
- for (uint32_t j = 0; j < stage_count; j++) {
- p_version->variant_stages[i].write[j].shader_stage = RD::ShaderStage(f->get_32());
-
- int compression = f->get_32();
- uint32_t length = f->get_32();
-
- if (compression == 0) {
- Vector<uint8_t> data;
- data.resize(length);
-
- f->get_buffer(data.ptrw(), length);
-
- p_version->variant_stages[i].write[j].spir_v = data;
- } else {
- Vector<uint8_t> data;
-
- if (compression == 2) {
- //zstd
- int smol_length = f->get_32();
- Vector<uint8_t> zstd_data;
-
- zstd_data.resize(smol_length);
- f->get_buffer(zstd_data.ptrw(), smol_length);
-
- data.resize(length);
- Compression::decompress(data.ptrw(), data.size(), zstd_data.ptr(), zstd_data.size(), Compression::MODE_ZSTD);
-
- } else {
- data.resize(length);
- f->get_buffer(data.ptrw(), length);
- }
-
- Vector<uint8_t> spirv;
- uint32_t spirv_size = smolv::GetDecodedBufferSize(data.ptr(), data.size());
- spirv.resize(spirv_size);
- if (!smolv::Decode(data.ptr(), data.size(), spirv.ptrw(), spirv_size)) {
- ERR_PRINT("Malformed smolv input uncompressing shader " + name + ", variant #" + itos(i) + " stage :" + itos(j));
- success = false;
- break;
- }
- p_version->variant_stages[i].write[j].spir_v = spirv;
- }
+ uint32_t variant_size = f->get_32();
+ ERR_FAIL_COND_V(variant_size == 0 && variants_enabled[i], false);
+ if (!variants_enabled[i]) {
+ continue;
}
- }
+ Vector<uint8_t> variant_bytes;
+ variant_bytes.resize(variant_size);
- if (!success) {
- for (uint32_t i = 0; i < variant_count; i++) {
- p_version->variant_stages[i].resize(0);
- }
- return false;
- }
+ uint32_t br = f->get_buffer(variant_bytes.ptrw(), variant_size);
- float time_ms = double(OS::get_singleton()->get_ticks_usec() - time_from) / 1000.0;
+ ERR_FAIL_COND_V(br != variant_size, false);
- print_verbose("Shader cache load success '" + path + "' " + rtos(time_ms) + "ms.");
+ p_version->variant_data[i] = variant_bytes;
+ }
for (uint32_t i = 0; i < variant_count; i++) {
- RID shader = RD::get_singleton()->shader_create(p_version->variant_stages[i]);
+ if (!variants_enabled[i]) {
+ MutexLock lock(variant_set_mutex);
+ p_version->variants[i] = RID();
+ continue;
+ }
+ RID shader = RD::get_singleton()->shader_create_from_bytecode(p_version->variant_data[i]);
+ if (shader.is_null()) {
+ for (uint32_t j = 0; j < i; j++) {
+ RD::get_singleton()->free(p_version->variants[i]);
+ }
+ ERR_FAIL_COND_V(shader.is_null(), false);
+ }
{
MutexLock lock(variant_set_mutex);
p_version->variants[i] = shader;
}
}
- memdelete_arr(p_version->variant_stages); //clear stages
- p_version->variant_stages = nullptr;
+ memdelete_arr(p_version->variant_data); //clear stages
+ p_version->variant_data = nullptr;
p_version->valid = true;
return true;
}
@@ -476,49 +448,8 @@ void ShaderRD::_save_to_cache(Version *p_version) {
f->store_32(variant_count); //variant count
for (uint32_t i = 0; i < variant_count; i++) {
- f->store_32(p_version->variant_stages[i].size()); //stage count
- for (int j = 0; j < p_version->variant_stages[i].size(); j++) {
- f->store_32(p_version->variant_stages[i][j].shader_stage); //stage count
- Vector<uint8_t> spirv = p_version->variant_stages[i][j].spir_v;
-
- bool save_uncompressed = true;
- if (shader_cache_save_compressed) {
- smolv::ByteArray smolv;
- bool strip_debug = !shader_cache_save_debug;
- if (!smolv::Encode(spirv.ptr(), spirv.size(), smolv, strip_debug ? smolv::kEncodeFlagStripDebugInfo : 0)) {
- ERR_PRINT("Error compressing shader " + name + ", variant #" + itos(i) + " stage :" + itos(i));
- } else {
- bool compress_zstd = shader_cache_save_compressed_zstd;
-
- if (compress_zstd) {
- Vector<uint8_t> zstd;
- zstd.resize(Compression::get_max_compressed_buffer_size(smolv.size(), Compression::MODE_ZSTD));
- int dst_size = Compression::compress(zstd.ptrw(), &smolv[0], smolv.size(), Compression::MODE_ZSTD);
- if (dst_size >= 0 && (uint32_t)dst_size < smolv.size()) {
- f->store_32(2); //compressed zstd
- f->store_32(smolv.size()); //size of smolv buffer
- f->store_32(dst_size); //size of smolv buffer
- f->store_buffer(zstd.ptr(), dst_size); //smolv buffer
- } else {
- compress_zstd = false;
- }
- }
-
- if (!compress_zstd) {
- f->store_32(1); //compressed
- f->store_32(smolv.size()); //size of smolv buffer
- f->store_buffer(&smolv[0], smolv.size()); //smolv buffer
- }
- save_uncompressed = false;
- }
- }
-
- if (save_uncompressed) {
- f->store_32(0); //uncompressed
- f->store_32(spirv.size()); //stage count
- f->store_buffer(spirv.ptr(), spirv.size()); //stage count
- }
- }
+ f->store_32(p_version->variant_data[i].size()); //stage count
+ f->store_buffer(p_version->variant_data[i].ptr(), p_version->variant_data[i].size());
}
f->close();
@@ -531,8 +462,8 @@ void ShaderRD::_compile_version(Version *p_version) {
p_version->dirty = false;
p_version->variants = memnew_arr(RID, variant_defines.size());
- typedef Vector<RD::ShaderStageData> ShaderStageArray;
- p_version->variant_stages = memnew_arr(ShaderStageArray, variant_defines.size());
+ typedef Vector<uint8_t> ShaderStageData;
+ p_version->variant_data = memnew_arr(ShaderStageData, variant_defines.size());
if (shader_cache_dir_valid) {
if (_load_from_cache(p_version)) {
@@ -571,19 +502,19 @@ void ShaderRD::_compile_version(Version *p_version) {
}
}
memdelete_arr(p_version->variants);
- if (p_version->variant_stages) {
- memdelete_arr(p_version->variant_stages);
+ if (p_version->variant_data) {
+ memdelete_arr(p_version->variant_data);
}
p_version->variants = nullptr;
- p_version->variant_stages = nullptr;
+ p_version->variant_data = nullptr;
return;
} else if (shader_cache_dir_valid) {
//save shader cache
_save_to_cache(p_version);
}
- memdelete_arr(p_version->variant_stages); //clear stages
- p_version->variant_stages = nullptr;
+ memdelete_arr(p_version->variant_data); //clear stages
+ p_version->variant_data = nullptr;
p_version->valid = true;
}
diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h
index 9a68e02007..529328f0ed 100644
--- a/servers/rendering/renderer_rd/shader_rd.h
+++ b/servers/rendering/renderer_rd/shader_rd.h
@@ -59,7 +59,7 @@ class ShaderRD {
Map<StringName, CharString> code_sections;
Vector<CharString> custom_defines;
- Vector<RD::ShaderStageData> *variant_stages = nullptr;
+ Vector<uint8_t> *variant_data = nullptr;
RID *variants = nullptr; //same size as version defines
bool valid;
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
new file mode 100644
index 0000000000..b1d1c2365e
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/blur_raster.glsl
@@ -0,0 +1,228 @@
+/* clang-format off */
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "blur_raster_inc.glsl"
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+}
+
+/* clang-format off */
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "blur_raster_inc.glsl"
+
+layout(location = 0) in vec2 uv_interp;
+/* clang-format on */
+
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+
+#ifdef GLOW_USE_AUTO_EXPOSURE
+layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
+#endif
+
+layout(location = 0) out vec4 frag_color;
+
+//DOF
+#ifdef MODE_DOF_BLUR
+
+layout(set = 1, binding = 0) uniform sampler2D dof_source_depth;
+
+#ifdef DOF_QUALITY_LOW
+const int dof_kernel_size = 5;
+const int dof_kernel_from = 2;
+const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
+#endif
+
+#ifdef DOF_QUALITY_MEDIUM
+const int dof_kernel_size = 11;
+const int dof_kernel_from = 5;
+const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
+
+#endif
+
+#ifdef DOF_QUALITY_HIGH
+const int dof_kernel_size = 21;
+const int dof_kernel_from = 10;
+const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
+#endif
+
+#endif
+
+void main() {
+#ifdef MODE_MIPMAP
+
+ vec2 pix_size = blur.pixel_size;
+ vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size);
+ color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size);
+ color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size);
+ color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size);
+ frag_color = color / 4.0;
+
+#endif
+
+#ifdef MODE_GAUSSIAN_BLUR
+
+ //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
+
+ if (bool(blur.flags & FLAG_HORIZONTAL)) {
+ vec2 pix_size = blur.pixel_size;
+ pix_size *= 0.5; //reading from larger buffer, so use more samples
+ vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
+ color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
+ color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
+ color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
+ color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
+ color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
+ color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
+ frag_color = color;
+ } else {
+ vec2 pix_size = blur.pixel_size;
+ vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
+ color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
+ color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
+ color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
+ color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
+ frag_color = color;
+ }
+#endif
+
+#ifdef MODE_GAUSSIAN_GLOW
+
+ //Glow uses larger sigma 1 for a more rounded blur effect
+
+#define GLOW_ADD(m_ofs, m_mult) \
+ { \
+ vec2 ofs = uv_interp + m_ofs * pix_size; \
+ vec4 c = texture(source_color, ofs) * m_mult; \
+ if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \
+ c *= 0.0; \
+ } \
+ color += c; \
+ }
+
+ if (bool(blur.flags & FLAG_HORIZONTAL)) {
+ vec2 pix_size = blur.pixel_size;
+ pix_size *= 0.5; //reading from larger buffer, so use more samples
+ vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
+ GLOW_ADD(vec2(1.0, 0.0), 0.165569);
+ GLOW_ADD(vec2(2.0, 0.0), 0.140367);
+ GLOW_ADD(vec2(3.0, 0.0), 0.106595);
+ GLOW_ADD(vec2(-1.0, 0.0), 0.165569);
+ GLOW_ADD(vec2(-2.0, 0.0), 0.140367);
+ GLOW_ADD(vec2(-3.0, 0.0), 0.106595);
+ color *= blur.glow_strength;
+ frag_color = color;
+ } else {
+ vec2 pix_size = blur.pixel_size;
+ vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
+ GLOW_ADD(vec2(0.0, 1.0), 0.233062);
+ GLOW_ADD(vec2(0.0, 2.0), 0.122581);
+ GLOW_ADD(vec2(0.0, -1.0), 0.233062);
+ GLOW_ADD(vec2(0.0, -2.0), 0.122581);
+ color *= blur.glow_strength;
+ frag_color = color;
+ }
+
+#undef GLOW_ADD
+
+ if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
+#ifdef GLOW_USE_AUTO_EXPOSURE
+
+ frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
+#endif
+ frag_color *= blur.glow_exposure;
+
+ float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
+ float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
+
+ frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
+ }
+
+#endif
+
+#ifdef MODE_DOF_BLUR
+
+ vec4 color_accum = vec4(0.0);
+
+ float depth = texture(dof_source_depth, uv_interp, 0.0).r;
+ depth = depth * 2.0 - 1.0;
+
+ if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
+ depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
+ } else {
+ depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
+ }
+
+ // mix near and far blur amount
+ float amount = 1.0;
+ if (bool(blur.flags & FLAG_DOF_FAR)) {
+ amount *= 1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, depth);
+ }
+ if (bool(blur.flags & FLAG_DOF_NEAR)) {
+ amount *= smoothstep(blur.dof_near_end, blur.dof_near_begin, depth);
+ }
+ amount = 1.0 - amount;
+
+ if (amount > 0.0) {
+ float k_accum = 0.0;
+
+ for (int i = 0; i < dof_kernel_size; i++) {
+ int int_ofs = i - dof_kernel_from;
+ vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius;
+
+ float tap_k = dof_kernel[i];
+
+ float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
+ tap_depth = tap_depth * 2.0 - 1.0;
+
+ if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
+ tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
+ } else {
+ tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
+ }
+
+ // mix near and far blur amount
+ float tap_amount = 1.0;
+ if (bool(blur.flags & FLAG_DOF_FAR)) {
+ tap_amount *= mix(1.0 - smoothstep(blur.dof_far_begin, blur.dof_far_end, tap_depth), 0.0, int_ofs == 0);
+ }
+ if (bool(blur.flags & FLAG_DOF_NEAR)) {
+ tap_amount *= mix(smoothstep(blur.dof_near_end, blur.dof_near_begin, tap_depth), 0.0, int_ofs == 0);
+ }
+ tap_amount = 1.0 - tap_amount;
+
+ tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
+
+ vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k;
+
+ k_accum += tap_k * tap_amount;
+ color_accum += tap_color * tap_amount;
+ }
+
+ if (k_accum > 0.0) {
+ color_accum /= k_accum;
+ }
+
+ frag_color = color_accum; ///k_accum;
+ } else {
+ // we are in focus, don't waste time
+ frag_color = texture(source_color, uv_interp, 0.0);
+ }
+
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
new file mode 100644
index 0000000000..6ea968e595
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/blur_raster_inc.glsl
@@ -0,0 +1,36 @@
+#define FLAG_HORIZONTAL (1 << 0)
+#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 1)
+#define FLAG_GLOW_FIRST_PASS (1 << 2)
+#define FLAG_DOF_FAR (1 << 3)
+#define FLAG_DOF_NEAR (1 << 4)
+
+layout(push_constant, binding = 1, std430) uniform Blur {
+ vec2 pixel_size;
+ uint flags;
+ uint pad;
+
+ // Glow.
+ float glow_strength;
+ float glow_bloom;
+ float glow_hdr_threshold;
+ float glow_hdr_scale;
+
+ float glow_exposure;
+ float glow_white;
+ float glow_luminance_cap;
+ float glow_auto_exposure_grey;
+
+ // DOF.
+ float dof_far_begin;
+ float dof_far_end;
+ float dof_near_begin;
+ float dof_near_end;
+
+ float dof_radius;
+ float dof_pad[3];
+
+ vec2 dof_dir;
+ float camera_z_far;
+ float camera_z_near;
+}
+blur;
diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl
new file mode 100644
index 0000000000..29ebd74a90
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl
@@ -0,0 +1,74 @@
+/* clang-format off */
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "luminance_reduce_raster_inc.glsl"
+
+layout(location = 0) out vec2 uv_interp;
+/* clang-format on */
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+}
+
+/* clang-format off */
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#include "luminance_reduce_raster_inc.glsl"
+
+layout(location = 0) in vec2 uv_interp;
+/* clang-format on */
+
+layout(set = 0, binding = 0) uniform sampler2D source_exposure;
+
+#ifdef FINAL_PASS
+layout(set = 1, binding = 0) uniform sampler2D prev_luminance;
+#endif
+
+layout(location = 0) out highp float luminance;
+
+void main() {
+ ivec2 dest_pos = ivec2(uv_interp * settings.dest_size);
+ ivec2 src_pos = ivec2(uv_interp * settings.source_size);
+
+ ivec2 next_pos = (dest_pos + ivec2(1)) * settings.source_size / settings.dest_size;
+ next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel
+
+ highp vec3 source_color = vec3(0.0);
+ for (int i = src_pos.x; i < next_pos.x; i++) {
+ for (int j = src_pos.y; j < next_pos.y; j++) {
+ source_color += texelFetch(source_exposure, ivec2(i, j), 0).rgb;
+ }
+ }
+
+ source_color /= float((next_pos.x - src_pos.x) * (next_pos.y - src_pos.y));
+
+#ifdef FIRST_PASS
+ luminance = max(source_color.r, max(source_color.g, source_color.b));
+
+ // This formula should be more "accurate" but gave an overexposed result when testing.
+ // Leaving it here so we can revisit it if we want.
+ // luminance = source_color.r * 0.21 + source_color.g * 0.71 + source_color.b * 0.07;
+#else
+ luminance = source_color.r;
+#endif
+
+#ifdef FINAL_PASS
+ // Obtain our target luminance
+ luminance = clamp(luminance, settings.min_luminance, settings.max_luminance);
+
+ // Now smooth to our transition
+ highp float prev_lum = texelFetch(prev_luminance, ivec2(0, 0), 0).r; //1 pixel previous luminance
+ luminance = prev_lum + (luminance - prev_lum) * clamp(settings.exposure_adjust, 0.0, 1.0);
+#endif
+}
diff --git a/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
new file mode 100644
index 0000000000..ed389ffe56
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/luminance_reduce_raster_inc.glsl
@@ -0,0 +1,11 @@
+
+layout(push_constant, binding = 1, std430) uniform PushConstant {
+ ivec2 source_size;
+ ivec2 dest_size;
+
+ float exposure_adjust;
+ float min_luminance;
+ float max_luminance;
+ float pad;
+}
+settings;
diff --git a/servers/rendering/renderer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl
index 4dceeea995..e88e68b511 100644
--- a/servers/rendering/renderer_rd/shaders/particles_copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl
@@ -138,7 +138,7 @@ void main() {
if (bool(particles.data[particle].flags & PARTICLE_FLAG_ACTIVE) || bool(particles.data[particle].flags & PARTICLE_FLAG_TRAILED)) {
txform = particles.data[particle].xform;
if (params.trail_size > 1) {
- // since the steps dont fit precisely in the history frames, must do a tiny bit of
+ // Since the steps don't fit precisely in the history frames, must do a tiny bit of
// interpolation to get them close to their intended location.
uint part_ofs = particle % params.trail_size;
float natural_ofs = fract((float(part_ofs) / float(params.trail_size)) * float(params.trail_total)) * params.frame_delta;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index ef1c9bacfb..b3a349c948 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -1214,7 +1214,7 @@ void main() {
specular_light *= specular * metallic * albedo * 2.0;
#else
- // scales the specular reflections, needs to be be computed before lighting happens,
+ // scales the specular reflections, needs to be computed before lighting happens,
// but after environment, GI, and reflection probes are added
// Environment brdf approximation (Lazarov 2013)
// see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index 3a05275652..b53bf6a6d4 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -177,7 +177,7 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
uint cluster_type_size;
uint max_cluster_element_count_div_32;
- //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
+ // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted.
vec4 directional_penumbra_shadow_kernel[32];
vec4 directional_soft_shadow_kernel[32];
vec4 penumbra_shadow_kernel[32];
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 7e72ece5dc..70900a847c 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -981,7 +981,7 @@ void main() {
specular_light *= specular * metallic * albedo * 2.0;
#else
- // scales the specular reflections, needs to be be computed before lighting happens,
+ // scales the specular reflections, needs to be computed before lighting happens,
// but after environment, GI, and reflection probes are added
// Environment brdf approximation (Lazarov 2013)
// see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 1b8e21551c..d9682d7b23 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -138,7 +138,7 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
vec2 viewport_size;
vec2 screen_pixel_size;
- //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
+ // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted.
vec4 directional_penumbra_shadow_kernel[32];
vec4 directional_soft_shadow_kernel[32];
vec4 penumbra_shadow_kernel[32];
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
index 99db35bb34..d6e5c6a92e 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
@@ -20,10 +20,10 @@ layout(set = 0, binding = 3, std430) restrict readonly buffer DispatchData {
dispatch_data;
struct ProcessVoxel {
- uint position; //xyz 7 bit packed, extra 11 bits for neigbours
- uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours
- uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
- uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
+ uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
+ uint albedo; // rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors.
+ uint light; // rgbe8985 encoded total saved light, extra 2 bits for neighbors.
+ uint light_aniso; // 55555 light anisotropy, extra 2 bits for neighbors.
//total neighbours: 26
};
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
index bc376e9522..eedd28959c 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
@@ -266,9 +266,9 @@ void main() {
} else if (params.sky_mode == SKY_MODE_SKY) {
#ifdef USE_CUBEMAP_ARRAY
- light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates
+ light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates.
#else
- light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates
+ light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates.
#endif
light.rgb *= params.sky_energy;
light.a = 0.0;
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl
index aa4ded146f..4d9fa85a74 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl
+++ b/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl
@@ -101,7 +101,7 @@ layout(set = 0, binding = 10, std430) restrict buffer DispatchData {
dispatch_data;
struct ProcessVoxel {
- uint position; //xyz 7 bit packed, extra 11 bits for neigbours
+ uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours
uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
@@ -134,7 +134,7 @@ layout(set = 0, binding = 5, std430) restrict buffer readonly DispatchData {
dispatch_data;
struct ProcessVoxel {
- uint position; //xyz 7 bit packed, extra 11 bits for neigbours
+ uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours
uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
@@ -183,7 +183,7 @@ void main() {
ivec3 write_pos = read_pos + params.scroll;
if (any(lessThan(write_pos, ivec3(0))) || any(greaterThanEqual(write_pos, ivec3(params.grid_size)))) {
- return; //fits outside the 3D texture, dont do anything
+ return; // Fits outside the 3D texture, don't do anything.
}
uint albedo = ((src_process_voxels.data[index].albedo & 0x7FFF) << 1) | 1; //add solid bit
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 3336623f21..83d1b33bf2 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -1259,7 +1259,7 @@ void RendererSceneCull::_update_instance_visibility_depth(Instance *p_instance)
}
if (cycle_detected) {
- ERR_PRINT("Cycle detected in the visibility dependecies tree.");
+ ERR_PRINT("Cycle detected in the visibility dependencies tree.");
for (Set<Instance *>::Element *E = traversed_nodes.front(); E; E = E->next()) {
Instance *instance = E->get();
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
@@ -2876,8 +2876,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
Vector<Instance *> lights_with_shadow;
- for (List<Instance *>::Element *E = scenario->directional_lights.front(); E; E = E->next()) {
- if (!E->get()->visible) {
+ for (Instance *E : scenario->directional_lights) {
+ if (!E->visible) {
continue;
}
@@ -2885,13 +2885,13 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
break;
}
- InstanceLightData *light = static_cast<InstanceLightData *>(E->get()->base_data);
+ InstanceLightData *light = static_cast<InstanceLightData *>(E->base_data);
//check shadow..
if (light) {
- if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base) && !(RSG::storage->light_get_type(E->get()->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->get()->base))) {
- lights_with_shadow.push_back(E->get());
+ if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->base) && !(RSG::storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_is_sky_only(E->base))) {
+ lights_with_shadow.push_back(E);
}
//add to list
directional_lights.push_back(light->instance);
@@ -3391,8 +3391,7 @@ void RendererSceneCull::render_probes() {
idx++;
}
- for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) {
- Instance *instance = E->get();
+ for (const Instance *instance : probe->owner->scenario->directional_lights) {
InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
if (!instance->visible) {
continue;
@@ -3465,8 +3464,7 @@ void RendererSceneCull::render_probes() {
idx++;
}
- for (List<Instance *>::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) {
- Instance *instance = E->get();
+ for (const Instance *instance : probe->owner->scenario->directional_lights) {
InstanceLightData *instance_light = (InstanceLightData *)instance->base_data;
if (!instance->visible) {
continue;
@@ -3573,26 +3571,26 @@ void RendererSceneCull::render_particle_colliders() {
void RendererSceneCull::_update_instance_shader_parameters_from_material(Map<StringName, Instance::InstanceShaderParameter> &isparams, const Map<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
List<RendererStorage::InstanceShaderParam> plist;
RSG::storage->material_get_instance_shader_parameters(p_material, &plist);
- for (List<RendererStorage::InstanceShaderParam>::Element *E = plist.front(); E; E = E->next()) {
- StringName name = E->get().info.name;
+ for (const RendererStorage::InstanceShaderParam &E : plist) {
+ StringName name = E.info.name;
if (isparams.has(name)) {
- if (isparams[name].info.type != E->get().info.type) {
- WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different data types. Only the first one (in order) will display correctly.");
+ if (isparams[name].info.type != E.info.type) {
+ WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E.info.name + "', but they do it with different data types. Only the first one (in order) will display correctly.");
}
- if (isparams[name].index != E->get().index) {
- WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E->get().info.name + "', but they do it with different indices. Only the first one (in order) will display correctly.");
+ if (isparams[name].index != E.index) {
+ WARN_PRINT("More than one material in instance export the same instance shader uniform '" + E.info.name + "', but they do it with different indices. Only the first one (in order) will display correctly.");
}
continue; //first one found always has priority
}
Instance::InstanceShaderParameter isp;
- isp.index = E->get().index;
- isp.info = E->get().info;
- isp.default_value = E->get().default_value;
+ isp.index = E.index;
+ isp.info = E.info;
+ isp.default_value = E.default_value;
if (existing_isparams.has(name)) {
isp.value = existing_isparams[name].value;
} else {
- isp.value = E->get().default_value;
+ isp.value = E.default_value;
}
isparams[name] = isp;
}
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 3594939362..b298ad193b 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -38,23 +38,23 @@ RenderingDevice *RenderingDevice::get_singleton() {
return singleton;
}
-RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = nullptr;
+RenderingDevice::ShaderCompileToSPIRVFunction RenderingDevice::compile_to_spirv_function = nullptr;
RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = nullptr;
-RenderingDevice::ShaderGetCacheKeyFunction RenderingDevice::get_cache_key_function = nullptr;
+RenderingDevice::ShaderSPIRVGetCacheKeyFunction RenderingDevice::get_spirv_cache_key_function = nullptr;
-void RenderingDevice::shader_set_compile_function(ShaderCompileFunction p_function) {
- compile_function = p_function;
+void RenderingDevice::shader_set_compile_to_spirv_function(ShaderCompileToSPIRVFunction p_function) {
+ compile_to_spirv_function = p_function;
}
-void RenderingDevice::shader_set_cache_function(ShaderCacheFunction p_function) {
+void RenderingDevice::shader_set_spirv_cache_function(ShaderCacheFunction p_function) {
cache_function = p_function;
}
-void RenderingDevice::shader_set_get_cache_key_function(ShaderGetCacheKeyFunction p_function) {
- get_cache_key_function = p_function;
+void RenderingDevice::shader_set_get_cache_key_function(ShaderSPIRVGetCacheKeyFunction p_function) {
+ get_spirv_cache_key_function = p_function;
}
-Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) {
+Vector<uint8_t> RenderingDevice::shader_compile_spirv_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) {
if (p_allow_cache && cache_function) {
Vector<uint8_t> cache = cache_function(p_stage, p_source_code, p_language);
if (cache.size()) {
@@ -62,18 +62,24 @@ Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage,
}
}
- ERR_FAIL_COND_V(!compile_function, Vector<uint8_t>());
+ ERR_FAIL_COND_V(!compile_to_spirv_function, Vector<uint8_t>());
- return compile_function(p_stage, p_source_code, p_language, r_error, &device_capabilities);
+ return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, &device_capabilities);
}
-String RenderingDevice::shader_get_cache_key() const {
- if (get_cache_key_function) {
- return get_cache_key_function(&device_capabilities);
+String RenderingDevice::shader_get_spirv_cache_key() const {
+ if (get_spirv_cache_key_function) {
+ return get_spirv_cache_key_function(&device_capabilities);
}
return String();
}
+RID RenderingDevice::shader_create_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv) {
+ Vector<uint8_t> bytecode = shader_compile_binary_from_spirv(p_spirv);
+ ERR_FAIL_COND_V(bytecode.size() == 0, RID());
+ return shader_create_from_bytecode(bytecode);
+}
+
RID RenderingDevice::_texture_create(const Ref<RDTextureFormat> &p_format, const Ref<RDTextureView> &p_view, const TypedArray<PackedByteArray> &p_data) {
ERR_FAIL_COND_V(p_format.is_null(), RID());
ERR_FAIL_COND_V(p_view.is_null(), RID());
@@ -170,40 +176,59 @@ RID RenderingDevice::_vertex_array_create(uint32_t p_vertex_count, VertexFormatI
return vertex_array_create(p_vertex_count, p_vertex_format, buffers);
}
-Ref<RDShaderBytecode> RenderingDevice::_shader_compile_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache) {
- ERR_FAIL_COND_V(p_source.is_null(), Ref<RDShaderBytecode>());
+Ref<RDShaderSPIRV> RenderingDevice::_shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache) {
+ ERR_FAIL_COND_V(p_source.is_null(), Ref<RDShaderSPIRV>());
- Ref<RDShaderBytecode> bytecode;
+ Ref<RDShaderSPIRV> bytecode;
bytecode.instantiate();
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String error;
ShaderStage stage = ShaderStage(i);
- Vector<uint8_t> spirv = shader_compile_from_source(stage, p_source->get_stage_source(stage), p_source->get_language(), &error, p_allow_cache);
+ Vector<uint8_t> spirv = shader_compile_spirv_from_source(stage, p_source->get_stage_source(stage), p_source->get_language(), &error, p_allow_cache);
bytecode->set_stage_bytecode(stage, spirv);
bytecode->set_stage_compile_error(stage, error);
}
return bytecode;
}
-RID RenderingDevice::shader_create_from_bytecode(const Ref<RDShaderBytecode> &p_bytecode) {
- ERR_FAIL_COND_V(p_bytecode.is_null(), RID());
+Vector<uint8_t> RenderingDevice::_shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_spirv) {
+ ERR_FAIL_COND_V(p_spirv.is_null(), Vector<uint8_t>());
- Vector<ShaderStageData> stage_data;
+ Vector<ShaderStageSPIRVData> stage_data;
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
ShaderStage stage = ShaderStage(i);
- ShaderStageData sd;
+ ShaderStageSPIRVData sd;
sd.shader_stage = stage;
- String error = p_bytecode->get_stage_compile_error(stage);
- ERR_FAIL_COND_V_MSG(error != String(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
- sd.spir_v = p_bytecode->get_stage_bytecode(stage);
+ String error = p_spirv->get_stage_compile_error(stage);
+ ERR_FAIL_COND_V_MSG(error != String(), Vector<uint8_t>(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
+ sd.spir_v = p_spirv->get_stage_bytecode(stage);
if (sd.spir_v.is_empty()) {
continue;
}
stage_data.push_back(sd);
}
- return shader_create(stage_data);
+ return shader_compile_binary_from_spirv(stage_data);
+}
+
+RID RenderingDevice::_shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv) {
+ ERR_FAIL_COND_V(p_spirv.is_null(), RID());
+
+ Vector<ShaderStageSPIRVData> stage_data;
+ for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
+ ShaderStage stage = ShaderStage(i);
+ ShaderStageSPIRVData sd;
+ sd.shader_stage = stage;
+ String error = p_spirv->get_stage_compile_error(stage);
+ ERR_FAIL_COND_V_MSG(error != String(), RID(), "Can't create a shader from an errored bytecode. Check errors in source bytecode.");
+ sd.spir_v = p_spirv->get_stage_bytecode(stage);
+ if (sd.spir_v.is_empty()) {
+ continue;
+ }
+ stage_data.push_back(sd);
+ }
+ return shader_create_from_spirv(stage_data);
}
RID RenderingDevice::_uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set) {
@@ -366,8 +391,10 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create);
- ClassDB::bind_method(D_METHOD("shader_compile_from_source", "shader_source", "allow_cache"), &RenderingDevice::_shader_compile_from_source, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("shader_create", "shader_data"), &RenderingDevice::shader_create_from_bytecode);
+ ClassDB::bind_method(D_METHOD("shader_compile_spirv_from_source", "shader_source", "allow_cache"), &RenderingDevice::_shader_compile_spirv_from_source, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("shader_compile_binary_from_spirv", "spirv_data"), &RenderingDevice::_shader_compile_binary_from_spirv);
+ ClassDB::bind_method(D_METHOD("shader_create_from_spirv", "spirv_data"), &RenderingDevice::_shader_compile_binary_from_spirv);
+ ClassDB::bind_method(D_METHOD("shader_create_from_bytecode", "binary_data"), &RenderingDevice::shader_create_from_bytecode);
ClassDB::bind_method(D_METHOD("shader_get_vertex_input_attribute_mask", "shader"), &RenderingDevice::shader_get_vertex_input_attribute_mask);
ClassDB::bind_method(D_METHOD("uniform_buffer_create", "size_bytes", "data"), &RenderingDevice::uniform_buffer_create, DEFVAL(Vector<uint8_t>()));
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 9a154ef7e9..eaf1ace798 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -41,7 +41,7 @@ class RDAttachmentFormat;
class RDSamplerState;
class RDVertexAttribute;
class RDShaderSource;
-class RDShaderBytecode;
+class RDShaderSPIRV;
class RDUniforms;
class RDPipelineRasterizationState;
class RDPipelineMultisampleState;
@@ -105,14 +105,14 @@ public:
bool supports_multiview = false; // If true this device supports multiview options
};
- typedef String (*ShaderGetCacheKeyFunction)(const Capabilities *p_capabilities);
- typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);
+ typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities);
+ typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
private:
- static ShaderCompileFunction compile_function;
+ static ShaderCompileToSPIRVFunction compile_to_spirv_function;
static ShaderCacheFunction cache_function;
- static ShaderGetCacheKeyFunction get_cache_key_function;
+ static ShaderSPIRVGetCacheKeyFunction get_spirv_cache_key_function;
static RenderingDevice *singleton;
@@ -651,24 +651,28 @@ public:
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
- virtual Vector<uint8_t> shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);
- virtual String shader_get_cache_key() const;
+ virtual Vector<uint8_t> shader_compile_spirv_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);
+ virtual String shader_get_spirv_cache_key() const;
- static void shader_set_compile_function(ShaderCompileFunction p_function);
- static void shader_set_cache_function(ShaderCacheFunction p_function);
- static void shader_set_get_cache_key_function(ShaderGetCacheKeyFunction p_function);
+ static void shader_set_compile_to_spirv_function(ShaderCompileToSPIRVFunction p_function);
+ static void shader_set_spirv_cache_function(ShaderCacheFunction p_function);
+ static void shader_set_get_cache_key_function(ShaderSPIRVGetCacheKeyFunction p_function);
- struct ShaderStageData {
+ struct ShaderStageSPIRVData {
ShaderStage shader_stage;
Vector<uint8_t> spir_v;
- ShaderStageData() {
+ ShaderStageSPIRVData() {
shader_stage = SHADER_STAGE_VERTEX;
}
};
- RID shader_create_from_bytecode(const Ref<RDShaderBytecode> &p_bytecode);
- virtual RID shader_create(const Vector<ShaderStageData> &p_stages) = 0;
+ virtual String shader_get_binary_cache_key() const = 0;
+ virtual Vector<uint8_t> shader_compile_binary_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv) = 0;
+
+ virtual RID shader_create_from_spirv(const Vector<ShaderStageSPIRVData> &p_spirv);
+ virtual RID shader_create_from_bytecode(const Vector<uint8_t> &p_shader_binary) = 0;
+
virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader) = 0;
/******************/
@@ -1194,7 +1198,9 @@ protected:
VertexFormatID _vertex_format_create(const TypedArray<RDVertexAttribute> &p_vertex_formats);
RID _vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const TypedArray<RID> &p_src_buffers);
- Ref<RDShaderBytecode> _shader_compile_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache = true);
+ Ref<RDShaderSPIRV> _shader_compile_spirv_from_source(const Ref<RDShaderSource> &p_source, bool p_allow_cache = true);
+ Vector<uint8_t> _shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_bytecode);
+ RID _shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv);
RID _uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set);
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index 2652edb1bc..fa3f2f3895 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -172,7 +172,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
/* STEP 2, Compile the versions, add to shader file */
for (Map<StringName, String>::Element *E = version_texts.front(); E; E = E->next()) {
- Ref<RDShaderBytecode> bytecode;
+ Ref<RDShaderSPIRV> bytecode;
bytecode.instantiate();
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
@@ -182,7 +182,7 @@ Error RDShaderFile::parse_versions_from_text(const String &p_text, const String
}
code = code.replace("VERSION_DEFINES", E->get());
String error;
- Vector<uint8_t> spirv = RenderingDevice::get_singleton()->shader_compile_from_source(RD::ShaderStage(i), code, RD::SHADER_LANGUAGE_GLSL, &error, false);
+ Vector<uint8_t> spirv = RenderingDevice::get_singleton()->shader_compile_spirv_from_source(RD::ShaderStage(i), code, RD::SHADER_LANGUAGE_GLSL, &error, false);
bytecode->set_stage_bytecode(RD::ShaderStage(i), spirv);
if (error != "") {
error += String() + "\n\nStage '" + stage_str[i] + "' source code: \n\n";
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index 4c31880faf..ccc3e2fb39 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -263,8 +263,8 @@ protected:
}
};
-class RDShaderBytecode : public Resource {
- GDCLASS(RDShaderBytecode, Resource)
+class RDShaderSPIRV : public Resource {
+ GDCLASS(RDShaderSPIRV, Resource)
Vector<uint8_t> bytecode[RD::SHADER_STAGE_MAX];
String compile_error[RD::SHADER_STAGE_MAX];
@@ -280,6 +280,19 @@ public:
return bytecode[p_stage];
}
+ Vector<RD::ShaderStageSPIRVData> get_stages() const {
+ Vector<RD::ShaderStageSPIRVData> stages;
+ for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
+ if (bytecode[i].size()) {
+ RD::ShaderStageSPIRVData stage;
+ stage.shader_stage = RD::ShaderStage(i);
+ stage.spir_v = bytecode[i];
+ stages.push_back(stage);
+ }
+ }
+ return stages;
+ }
+
void set_stage_compile_error(RD::ShaderStage p_stage, const String &p_compile_error) {
ERR_FAIL_INDEX(p_stage, RD::SHADER_STAGE_MAX);
compile_error[p_stage] = p_compile_error;
@@ -292,11 +305,11 @@ public:
protected:
static void _bind_methods() {
- ClassDB::bind_method(D_METHOD("set_stage_bytecode", "stage", "bytecode"), &RDShaderBytecode::set_stage_bytecode);
- ClassDB::bind_method(D_METHOD("get_stage_bytecode", "stage"), &RDShaderBytecode::get_stage_bytecode);
+ ClassDB::bind_method(D_METHOD("set_stage_bytecode", "stage", "bytecode"), &RDShaderSPIRV::set_stage_bytecode);
+ ClassDB::bind_method(D_METHOD("get_stage_bytecode", "stage"), &RDShaderSPIRV::get_stage_bytecode);
- ClassDB::bind_method(D_METHOD("set_stage_compile_error", "stage", "compile_error"), &RDShaderBytecode::set_stage_compile_error);
- ClassDB::bind_method(D_METHOD("get_stage_compile_error", "stage"), &RDShaderBytecode::get_stage_compile_error);
+ ClassDB::bind_method(D_METHOD("set_stage_compile_error", "stage", "compile_error"), &RDShaderSPIRV::set_stage_compile_error);
+ ClassDB::bind_method(D_METHOD("get_stage_compile_error", "stage"), &RDShaderSPIRV::get_stage_compile_error);
ADD_GROUP("Bytecode", "bytecode_");
ADD_PROPERTYI(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "bytecode_vertex"), "set_stage_bytecode", "get_stage_bytecode", RD::SHADER_STAGE_VERTEX);
@@ -316,24 +329,29 @@ protected:
class RDShaderFile : public Resource {
GDCLASS(RDShaderFile, Resource)
- Map<StringName, Ref<RDShaderBytecode>> versions;
+ Map<StringName, Ref<RDShaderSPIRV>> versions;
String base_error;
public:
- void set_bytecode(const Ref<RDShaderBytecode> &p_bytecode, const StringName &p_version = StringName()) {
+ void set_bytecode(const Ref<RDShaderSPIRV> &p_bytecode, const StringName &p_version = StringName()) {
ERR_FAIL_COND(p_bytecode.is_null());
versions[p_version] = p_bytecode;
emit_changed();
}
- Ref<RDShaderBytecode> get_bytecode(const StringName &p_version = StringName()) const {
- ERR_FAIL_COND_V(!versions.has(p_version), Ref<RDShaderBytecode>());
+ Ref<RDShaderSPIRV> get_spirv(const StringName &p_version = StringName()) const {
+ ERR_FAIL_COND_V(!versions.has(p_version), Ref<RDShaderSPIRV>());
return versions[p_version];
}
+ Vector<RD::ShaderStageSPIRVData> get_spirv_stages(const StringName &p_version = StringName()) const {
+ ERR_FAIL_COND_V(!versions.has(p_version), Vector<RD::ShaderStageSPIRVData>());
+ return versions[p_version]->get_stages();
+ }
+
Vector<StringName> get_version_list() const {
Vector<StringName> vnames;
- for (Map<StringName, Ref<RDShaderBytecode>>::Element *E = versions.front(); E; E = E->next()) {
+ for (Map<StringName, Ref<RDShaderSPIRV>>::Element *E = versions.front(); E; E = E->next()) {
vnames.push_back(E->key());
}
vnames.sort_custom<StringName::AlphCompare>();
@@ -353,7 +371,7 @@ public:
if (base_error != "") {
ERR_PRINT("Error parsing shader '" + p_file + "':\n\n" + base_error);
} else {
- for (Map<StringName, Ref<RDShaderBytecode>>::Element *E = versions.front(); E; E = E->next()) {
+ for (Map<StringName, Ref<RDShaderSPIRV>>::Element *E = versions.front(); E; E = E->next()) {
for (int i = 0; i < RD::SHADER_STAGE_MAX; i++) {
String error = E->get()->get_stage_compile_error(RD::ShaderStage(i));
if (error != String()) {
@@ -388,9 +406,9 @@ protected:
versions.clear();
List<Variant> keys;
p_versions.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- StringName name = E->get();
- Ref<RDShaderBytecode> bc = p_versions[E->get()];
+ for (const Variant &E : keys) {
+ StringName name = E;
+ Ref<RDShaderSPIRV> bc = p_versions[E];
ERR_CONTINUE(bc.is_null());
versions[name] = bc;
}
@@ -400,7 +418,7 @@ protected:
static void _bind_methods() {
ClassDB::bind_method(D_METHOD("set_bytecode", "bytecode", "version"), &RDShaderFile::set_bytecode, DEFVAL(StringName()));
- ClassDB::bind_method(D_METHOD("get_bytecode", "version"), &RDShaderFile::get_bytecode, DEFVAL(StringName()));
+ ClassDB::bind_method(D_METHOD("get_spirv", "version"), &RDShaderFile::get_spirv, DEFVAL(StringName()));
ClassDB::bind_method(D_METHOD("get_version_list"), &RDShaderFile::get_version_list);
ClassDB::bind_method(D_METHOD("set_base_error", "error"), &RDShaderFile::set_base_error);
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index f771d6d0ef..baa5381554 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -912,6 +912,8 @@ void ShaderLanguage::clear() {
completion_class = SubClassTag::TAG_GLOBAL;
completion_struct = StringName();
+ unknown_varying_usages.clear();
+
#ifdef DEBUG_ENABLED
used_constants.clear();
used_varyings.clear();
@@ -946,7 +948,9 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden
break;
case IdentifierType::IDENTIFIER_VARYING:
if (HAS_WARNING(ShaderWarning::UNUSED_VARYING_FLAG) && used_varyings.has(p_identifier)) {
- used_varyings[p_identifier].used = true;
+ if (shader->varyings[p_identifier].stage != ShaderNode::Varying::STAGE_VERTEX && shader->varyings[p_identifier].stage != ShaderNode::Varying::STAGE_FRAGMENT) {
+ used_varyings[p_identifier].used = true;
+ }
}
break;
case IdentifierType::IDENTIFIER_UNIFORM:
@@ -2434,6 +2438,10 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI
if (shader->uniforms.has(varname)) {
fail = true;
} else {
+ if (shader->varyings.has(varname)) {
+ _set_error(vformat("Varyings cannot be passed for '%s' parameter!", "out"));
+ return false;
+ }
if (p_function_info.built_ins.has(varname)) {
BuiltInInfo info = p_function_info.built_ins[varname];
if (info.constant) {
@@ -2812,6 +2820,20 @@ bool ShaderLanguage::is_token_operator(TokenType p_type) {
p_type == TK_COLON);
}
+bool ShaderLanguage::is_token_operator_assign(TokenType p_type) {
+ return (p_type == TK_OP_ASSIGN ||
+ p_type == TK_OP_ASSIGN_ADD ||
+ p_type == TK_OP_ASSIGN_SUB ||
+ p_type == TK_OP_ASSIGN_MUL ||
+ p_type == TK_OP_ASSIGN_DIV ||
+ p_type == TK_OP_ASSIGN_MOD ||
+ p_type == TK_OP_ASSIGN_SHIFT_LEFT ||
+ p_type == TK_OP_ASSIGN_SHIFT_RIGHT ||
+ p_type == TK_OP_ASSIGN_BIT_AND ||
+ p_type == TK_OP_ASSIGN_BIT_OR ||
+ p_type == TK_OP_ASSIGN_BIT_XOR);
+}
+
bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) {
if (p_constant->datatype == p_to_type) {
if (p_value) {
@@ -3306,8 +3328,8 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
}
bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
- if (current_function == String("light")) {
- *r_message = RTR("Varying may not be assigned in the 'light' function.");
+ if (current_function != String("vertex") && current_function != String("fragment")) {
+ *r_message = vformat(RTR("Varying may not be assigned in the '%s' function."), current_function);
return false;
}
switch (p_varying.stage) {
@@ -3318,12 +3340,14 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT;
}
break;
+ case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT:
case ShaderNode::Varying::STAGE_VERTEX:
if (current_function == varying_function_names.fragment) {
*r_message = RTR("Varyings which assigned in 'vertex' function may not be reassigned in 'fragment' or 'light'.");
return false;
}
break;
+ case ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT:
case ShaderNode::Varying::STAGE_FRAGMENT:
if (current_function == varying_function_names.vertex) {
*r_message = RTR("Varyings which assigned in 'fragment' function may not be reassigned in 'vertex' or 'light'.");
@@ -3339,13 +3363,14 @@ bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, St
bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, String *r_message) {
switch (p_varying.stage) {
case ShaderNode::Varying::STAGE_UNKNOWN:
- *r_message = RTR("Varying must be assigned before using!");
- return false;
+ VaryingUsage usage;
+ usage.var = &p_varying;
+ usage.line = tk_line;
+ unknown_varying_usages.push_back(usage);
+ break;
case ShaderNode::Varying::STAGE_VERTEX:
- if (current_function == varying_function_names.fragment) {
- p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT;
- } else if (current_function == varying_function_names.light) {
- p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT;
+ if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
+ p_varying.stage = ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT;
}
break;
case ShaderNode::Varying::STAGE_FRAGMENT:
@@ -3353,24 +3378,25 @@ bool ShaderLanguage::_validate_varying_using(ShaderNode::Varying &p_varying, Str
p_varying.stage = ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT;
}
break;
- case ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT:
- if (current_function == varying_function_names.light) {
- *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
- return false;
- }
- break;
- case ShaderNode::Varying::STAGE_VERTEX_TO_LIGHT:
- if (current_function == varying_function_names.fragment) {
- *r_message = RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'");
- return false;
- }
- break;
default:
break;
}
return true;
}
+bool ShaderLanguage::_check_varying_usages(int *r_error_line, String *r_error_message) const {
+ for (const List<ShaderLanguage::VaryingUsage>::Element *E = unknown_varying_usages.front(); E; E = E->next()) {
+ ShaderNode::Varying::Stage stage = E->get().var->stage;
+ if (stage != ShaderNode::Varying::STAGE_UNKNOWN && stage != ShaderNode::Varying::STAGE_VERTEX && stage != ShaderNode::Varying::STAGE_VERTEX_TO_FRAGMENT_LIGHT) {
+ *r_error_line = E->get().line;
+ *r_error_message = RTR("Fragment-stage varying could not been accessed in custom function!");
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool ShaderLanguage::_check_node_constness(const Node *p_node) const {
switch (p_node->type) {
case Node::TYPE_OPERATOR: {
@@ -4114,6 +4140,10 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
} else if (shader->uniforms.has(varname)) {
error = true;
} else {
+ if (shader->varyings.has(varname)) {
+ _set_error(vformat("Varyings cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier)));
+ return nullptr;
+ }
if (p_function_info.built_ins.has(varname)) {
BuiltInInfo info = p_function_info.built_ins[varname];
if (info.constant) {
@@ -4224,7 +4254,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
Token next_token = _get_token();
_set_tkpos(prev_pos);
String error;
- if (next_token.type == TK_OP_ASSIGN) {
+
+ if (is_token_operator_assign(next_token.type)) {
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
_set_error(error);
return nullptr;
@@ -4435,12 +4466,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
String member_name = String(ident.ptr());
if (shader->structs.has(st)) {
StructNode *n = shader->structs[st].shader_struct;
- for (List<MemberNode *>::Element *E = n->members.front(); E; E = E->next()) {
- if (String(E->get()->name) == member_name) {
- member_type = E->get()->datatype;
- array_size = E->get()->array_size;
+ for (const MemberNode *E : n->members) {
+ if (String(E->name) == member_name) {
+ member_type = E->datatype;
+ array_size = E->array_size;
if (member_type == TYPE_STRUCT) {
- member_struct_name = E->get()->struct_name;
+ member_struct_name = E->struct_name;
}
ok = true;
break;
@@ -4765,10 +4796,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
String member_struct_name;
if (expr->get_array_size() > 0) {
- uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
- if (index_constant >= (uint32_t)expr->get_array_size()) {
- _set_error(vformat("Index [%s] out of range [%s..%s]", index_constant, 0, expr->get_array_size() - 1));
- return nullptr;
+ if (index->type == Node::TYPE_CONSTANT) {
+ uint32_t index_constant = static_cast<ConstantNode *>(index)->values[0].uint;
+ if (index_constant >= (uint32_t)expr->get_array_size()) {
+ _set_error(vformat("Index [%s] out of range [%s..%s]", index_constant, 0, expr->get_array_size() - 1));
+ return nullptr;
+ }
}
member_type = expr->get_datatype();
if (member_type == TYPE_STRUCT) {
@@ -7863,12 +7896,12 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
tk = _get_token();
}
- for (Map<StringName, ShaderNode::Varying>::Element *E = shader->varyings.front(); E; E = E->next()) {
- if (E->get().stage == ShaderNode::Varying::STAGE_VERTEX || E->get().stage == ShaderNode::Varying::STAGE_FRAGMENT) {
- _set_tkpos(E->get().tkpos);
- _set_error(RTR("Varying must only be used in two different stages, which can be 'vertex' 'fragment' and 'light'"));
- return ERR_PARSE_ERROR;
- }
+ int error_line;
+ String error_message;
+ if (!_check_varying_usages(&error_line, &error_message)) {
+ _set_tkpos({ 0, error_line });
+ _set_error(error_message);
+ return ERR_PARSE_ERROR;
}
return OK;
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index a91fa57a8e..c02d6c47ec 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -646,10 +646,9 @@ public:
struct Varying {
enum Stage {
STAGE_UNKNOWN,
- STAGE_VERTEX, // transition stage to STAGE_VERTEX_TO_FRAGMENT or STAGE_VERTEX_TO_LIGHT, emits error if they are not used
- STAGE_FRAGMENT, // transition stage to STAGE_FRAGMENT_TO_LIGHT, emits error if it's not used
- STAGE_VERTEX_TO_FRAGMENT,
- STAGE_VERTEX_TO_LIGHT,
+ STAGE_VERTEX, // transition stage to STAGE_VERTEX_TO_FRAGMENT_LIGHT, emits warning if it's not used
+ STAGE_FRAGMENT, // transition stage to STAGE_FRAGMENT_TO_LIGHT, emits warning if it's not used
+ STAGE_VERTEX_TO_FRAGMENT_LIGHT,
STAGE_FRAGMENT_TO_LIGHT,
};
@@ -767,6 +766,7 @@ public:
static String get_datatype_name(DataType p_type);
static bool is_token_nonvoid_datatype(TokenType p_type);
static bool is_token_operator(TokenType p_type);
+ static bool is_token_operator_assign(TokenType p_type);
static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = nullptr);
static DataType get_scalar_type(DataType p_type);
@@ -876,6 +876,14 @@ private:
VaryingFunctionNames varying_function_names;
+ struct VaryingUsage {
+ ShaderNode::Varying *var;
+ int line;
+ };
+ List<VaryingUsage> unknown_varying_usages;
+
+ bool _check_varying_usages(int *r_error_line, String *r_error_message) const;
+
TkPos _get_tkpos() {
TkPos tkp;
tkp.char_idx = char_idx;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index a39d0e89ee..1f01f47fff 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -53,15 +53,15 @@ Array RenderingServer::_texture_debug_usage_bind() {
List<TextureInfo> list;
texture_debug_usage(&list);
Array arr;
- for (const List<TextureInfo>::Element *E = list.front(); E; E = E->next()) {
+ for (const TextureInfo &E : list) {
Dictionary dict;
- dict["texture"] = E->get().texture;
- dict["width"] = E->get().width;
- dict["height"] = E->get().height;
- dict["depth"] = E->get().depth;
- dict["format"] = E->get().format;
- dict["bytes"] = E->get().bytes;
- dict["path"] = E->get().path;
+ dict["texture"] = E.texture;
+ dict["width"] = E.width;
+ dict["height"] = E.height;
+ dict["depth"] = E.depth;
+ dict["format"] = E.format;
+ dict["bytes"] = E.bytes;
+ dict["path"] = E.path;
arr.push_back(dict);
}
return arr;
@@ -972,10 +972,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
if (index_array_len) {
List<Variant> keys;
p_lods.get_key_list(&keys);
- for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
- float distance = E->get();
+ for (const Variant &E : keys) {
+ float distance = E;
ERR_CONTINUE(distance <= 0.0);
- Vector<int> indices = p_lods[E->get()];
+ Vector<int> indices = p_lods[E];
ERR_CONTINUE(indices.size() == 0);
uint32_t index_count = indices.size();
ERR_CONTINUE(index_count >= (uint32_t)index_array_len); //should be smaller..
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 6031bd7003..6b248c9554 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -41,7 +41,7 @@ struct BlitToScreen;
/**
@author Bastiaan Olij <mux213@gmail.com>
- The XR interface is a template class ontop of which we build interface to different AR, VR and tracking SDKs.
+ The XR interface is a template class on top of which we build interface to different AR, VR and tracking SDKs.
The idea is that we subclass this class, implement the logic, and then instantiate a singleton of each interface
when Godot starts. These instances do not initialize themselves but register themselves with the AR/VR server.
diff --git a/tests/test_class_db.h b/tests/test_class_db.h
index 29edf5a4a0..ea680da5d6 100644
--- a/tests/test_class_db.h
+++ b/tests/test_class_db.h
@@ -108,9 +108,9 @@ struct ExposedClass {
List<SignalData> signals_;
const PropertyData *find_property_by_name(const StringName &p_name) const {
- for (const List<PropertyData>::Element *E = properties.front(); E; E = E->next()) {
- if (E->get().name == p_name) {
- return &E->get();
+ for (const PropertyData &E : properties) {
+ if (E.name == p_name) {
+ return &E;
}
}
@@ -118,9 +118,9 @@ struct ExposedClass {
}
const MethodData *find_method_by_name(const StringName &p_name) const {
- for (const List<MethodData>::Element *E = methods.front(); E; E = E->next()) {
- if (E->get().name == p_name) {
- return &E->get();
+ for (const MethodData &E : methods) {
+ if (E.name == p_name) {
+ return &E;
}
}
@@ -395,8 +395,8 @@ void validate_method(const Context &p_context, const ExposedClass &p_class, cons
}
}
- for (const List<ArgumentData>::Element *F = p_method.arguments.front(); F; F = F->next()) {
- const ArgumentData &arg = F->get();
+ for (const ArgumentData &F : p_method.arguments) {
+ const ArgumentData &arg = F;
const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
if (arg_class) {
@@ -427,8 +427,8 @@ void validate_method(const Context &p_context, const ExposedClass &p_class, cons
}
void validate_signal(const Context &p_context, const ExposedClass &p_class, const SignalData &p_signal) {
- for (const List<ArgumentData>::Element *F = p_signal.arguments.front(); F; F = F->next()) {
- const ArgumentData &arg = F->get();
+ for (const ArgumentData &F : p_signal.arguments) {
+ const ArgumentData &arg = F;
const ExposedClass *arg_class = p_context.find_exposed_class(arg.type);
if (arg_class) {
@@ -469,16 +469,16 @@ void validate_class(const Context &p_context, const ExposedClass &p_exposed_clas
TEST_FAIL_COND((is_derived_type && !p_context.exposed_classes.has(p_exposed_class.base)),
"Base type '", p_exposed_class.base.operator String(), "' does not exist, for class '", p_exposed_class.name, "'.");
- for (const List<PropertyData>::Element *F = p_exposed_class.properties.front(); F; F = F->next()) {
- validate_property(p_context, p_exposed_class, F->get());
+ for (const PropertyData &F : p_exposed_class.properties) {
+ validate_property(p_context, p_exposed_class, F);
}
- for (const List<MethodData>::Element *F = p_exposed_class.methods.front(); F; F = F->next()) {
- validate_method(p_context, p_exposed_class, F->get());
+ for (const MethodData &F : p_exposed_class.methods) {
+ validate_method(p_context, p_exposed_class, F);
}
- for (const List<SignalData>::Element *F = p_exposed_class.signals_.front(); F; F = F->next()) {
- validate_signal(p_context, p_exposed_class, F->get());
+ for (const SignalData &F : p_exposed_class.signals_) {
+ validate_signal(p_context, p_exposed_class, F);
}
}
@@ -526,9 +526,7 @@ void add_exposed_classes(Context &r_context) {
Map<StringName, StringName> accessor_methods;
- for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
- const PropertyInfo &property = E->get();
-
+ for (const PropertyInfo &property : property_list) {
if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY) {
continue;
}
@@ -561,8 +559,8 @@ void add_exposed_classes(Context &r_context) {
ClassDB::get_method_list(class_name, &method_list, true);
method_list.sort();
- for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
- const MethodInfo &method_info = E->get();
+ for (const MethodInfo &E : method_list) {
+ const MethodInfo &method_info = E;
int argc = method_info.arguments.size();
@@ -667,8 +665,8 @@ void add_exposed_classes(Context &r_context) {
// Methods starting with an underscore are ignored unless they're virtual or used as a property setter or getter.
if (!method.is_virtual && String(method.name)[0] == '_') {
- for (const List<PropertyData>::Element *F = exposed_class.properties.front(); F; F = F->next()) {
- const PropertyData &prop = F->get();
+ for (const PropertyData &F : exposed_class.properties) {
+ const PropertyData &prop = F;
if (prop.setter == method.name || prop.getter == method.name) {
exposed_class.methods.push_back(method);
@@ -752,8 +750,8 @@ void add_exposed_classes(Context &r_context) {
enum_.name = *k;
const List<StringName> &enum_constants = enum_map.get(*k);
- for (const List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
- const StringName &constant_name = E->get();
+ for (const StringName &E : enum_constants) {
+ const StringName &constant_name = E;
TEST_FAIL_COND(String(constant_name).find("::") != -1,
"Enum constant contains '::', check bindings to remove the scope: '",
String(class_name), ".", String(enum_.name), ".", String(constant_name), "'.");
@@ -774,12 +772,12 @@ void add_exposed_classes(Context &r_context) {
r_context.enum_types.push_back(String(class_name) + "." + String(*k));
}
- for (const List<String>::Element *E = constants.front(); E; E = E->next()) {
- const String &constant_name = E->get();
+ for (const String &E : constants) {
+ const String &constant_name = E;
TEST_FAIL_COND(constant_name.find("::") != -1,
"Constant contains '::', check bindings to remove the scope: '",
String(class_name), ".", constant_name, "'.");
- int *value = class_info->constant_map.getptr(StringName(E->get()));
+ int *value = class_info->constant_map.getptr(StringName(E));
TEST_FAIL_COND(!value, "Missing constant value: '", String(class_name), ".", String(constant_name), "'.");
ConstantData constant;
@@ -829,8 +827,8 @@ void add_global_enums(Context &r_context) {
}
}
- for (List<EnumData>::Element *E = r_context.global_enums.front(); E; E = E->next()) {
- r_context.enum_types.push_back(E->get().name);
+ for (const EnumData &E : r_context.global_enums) {
+ r_context.enum_types.push_back(E.name);
}
}
@@ -840,10 +838,10 @@ void add_global_enums(Context &r_context) {
hardcoded_enums.push_back("Vector2i.Axis");
hardcoded_enums.push_back("Vector3.Axis");
hardcoded_enums.push_back("Vector3i.Axis");
- for (List<StringName>::Element *E = hardcoded_enums.front(); E; E = E->next()) {
+ for (const StringName &E : hardcoded_enums) {
// These enums are not generated and must be written manually (e.g.: Vector3.Axis)
// Here, we assume core types do not begin with underscore
- r_context.enum_types.push_back(E->get());
+ r_context.enum_types.push_back(E);
}
}
diff --git a/tests/test_math.cpp b/tests/test_math.cpp
index 67d9a52539..d0b9fdef4b 100644
--- a/tests/test_math.cpp
+++ b/tests/test_math.cpp
@@ -549,8 +549,8 @@ MainLoop *test() {
List<StringName> tl;
ClassDB::get_class_list(&tl);
- for (List<StringName>::Element *E = tl.front(); E; E = E->next()) {
- Vector<uint8_t> m5b = E->get().operator String().md5_buffer();
+ for (const StringName &E : tl) {
+ Vector<uint8_t> m5b = E.operator String().md5_buffer();
hashes.push_back(hashes.size());
}
diff --git a/tests/test_object.h b/tests/test_object.h
index 36f9ef2a51..a18adf31b6 100644
--- a/tests/test_object.h
+++ b/tests/test_object.h
@@ -139,7 +139,7 @@ TEST_CASE("[Object] Metadata") {
Color(object.get_meta(meta_path)).is_equal_approx(Color(0, 1, 0)),
"The returned object metadata after setting should match the expected value.");
- List<String> meta_list;
+ List<StringName> meta_list;
object.get_meta_list(&meta_list);
CHECK_MESSAGE(
meta_list.size() == 1,
@@ -154,7 +154,7 @@ TEST_CASE("[Object] Metadata") {
"The returned object metadata after removing should match the expected value.");
ERR_PRINT_ON;
- List<String> meta_list2;
+ List<StringName> meta_list2;
object.get_meta_list(&meta_list2);
CHECK_MESSAGE(
meta_list2.size() == 0,
diff --git a/tests/test_physics_2d.cpp b/tests/test_physics_2d.cpp
index a9e2e92b34..40dc74e89c 100644
--- a/tests/test_physics_2d.cpp
+++ b/tests/test_physics_2d.cpp
@@ -386,7 +386,7 @@ public:
//_add_plane(Vector2(-1,0).normalized(),-600);
}
- virtual bool process(float p_time) override {
+ virtual bool process(double p_time) override {
return false;
}
virtual void finalize() override {
diff --git a/tests/test_physics_3d.cpp b/tests/test_physics_3d.cpp
index 4488e4bf64..ed49b60c71 100644
--- a/tests/test_physics_3d.cpp
+++ b/tests/test_physics_3d.cpp
@@ -313,7 +313,7 @@ public:
test_fall();
quit = false;
}
- virtual bool physics_process(float p_time) override {
+ virtual bool physics_process(double p_time) override {
if (mover.is_valid()) {
static real_t joy_speed = 10;
PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
@@ -399,7 +399,7 @@ public:
create_static_plane(Plane(Vector3(0, 1, 0), -1));
}
- virtual bool process(float p_time) override {
+ virtual bool process(double p_time) override {
return false;
}
diff --git a/tests/test_render.cpp b/tests/test_render.cpp
index fe223ca258..beff86dd83 100644
--- a/tests/test_render.cpp
+++ b/tests/test_render.cpp
@@ -199,7 +199,7 @@ public:
ofs = 0;
quit = false;
}
- virtual bool iteration(float p_time) {
+ virtual bool iteration(double p_time) {
RenderingServer *vs = RenderingServer::get_singleton();
//Transform3D t;
//t.rotate(Vector3(0, 1, 0), ofs);
@@ -210,12 +210,12 @@ public:
//return quit;
- for (List<InstanceInfo>::Element *E = instances.front(); E; E = E->next()) {
- Transform3D pre(Basis(E->get().rot_axis, ofs), Vector3());
- vs->instance_set_transform(E->get().instance, pre * E->get().base);
+ for (const InstanceInfo &E : instances) {
+ Transform3D pre(Basis(E.rot_axis, ofs), Vector3());
+ vs->instance_set_transform(E.instance, pre * E.base);
/*
if( !E->next() ) {
- vs->free( E->get().instance );
+ vs->free( E.instance );
instances.erase(E );
}*/
}
@@ -223,7 +223,7 @@ public:
return quit;
}
- virtual bool idle(float p_time) {
+ virtual bool idle(double p_time) {
return quit;
}
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index f6a56f1f5d..3e353d7eec 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -353,8 +353,8 @@ public:
}
// Remove disconnected peers from map.
- for (List<String>::Element *E = remove.front(); E; E = E->next()) {
- peers.erase(E->get());
+ for (String &E : remove) {
+ peers.erase(E);
}
return err; // OK, ERR_BUSY, or possibly an error.