summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-tidy2
-rw-r--r--.github/workflows/linux_builds.yml16
-rw-r--r--core/config/engine.h2
-rw-r--r--core/core_bind.h2
-rw-r--r--core/io/file_access.h2
-rw-r--r--core/io/file_access_pack.h6
-rw-r--r--core/io/ip.h2
-rw-r--r--core/io/resource_format_binary.h2
-rw-r--r--core/io/resource_uid.h2
-rw-r--r--core/io/udp_server.h2
-rw-r--r--core/math/bvh.h27
-rw-r--r--core/math/dynamic_bvh.h7
-rw-r--r--core/math/expression.h2
-rw-r--r--core/math/octree.h37
-rw-r--r--core/object/callable_method_pointer.h2
-rw-r--r--core/object/class_db.h4
-rw-r--r--core/object/message_queue.h4
-rw-r--r--core/object/object.h6
-rw-r--r--core/object/script_language.h15
-rw-r--r--core/object/script_language_extension.cpp5
-rw-r--r--core/object/script_language_extension.h3
-rw-r--r--core/os/memory.h6
-rw-r--r--core/os/os.h2
-rw-r--r--core/os/pool_allocator.h8
-rw-r--r--core/string/string_name.h2
-rw-r--r--core/templates/command_queue_mt.h2
-rw-r--r--core/templates/map.h6
-rw-r--r--core/templates/oa_hash_map.h2
-rw-r--r--core/templates/safe_list.h8
-rw-r--r--core/templates/self_list.h2
-rw-r--r--core/templates/set.h4
-rw-r--r--core/templates/thread_work_pool.h2
-rw-r--r--doc/classes/AcceptDialog.xml2
-rw-r--r--doc/classes/EditorFileSystemImportFormatSupportQuery.xml31
-rw-r--r--doc/classes/NavigationAgent2D.xml3
-rw-r--r--doc/classes/NavigationAgent3D.xml3
-rw-r--r--doc/classes/ProjectSettings.xml8
-rw-r--r--doc/classes/RichTextLabel.xml6
-rw-r--r--doc/classes/ScriptLanguageExtension.xml12
-rw-r--r--doc/classes/SpinBox.xml1
-rw-r--r--doc/classes/String.xml3
-rw-r--r--doc/classes/TabContainer.xml21
-rw-r--r--doc/classes/Tween.xml7
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h8
-rw-r--r--drivers/gles3/rasterizer_gles3.h3
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp202
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h140
-rw-r--r--drivers/gles3/storage/material_storage.h4
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp257
-rw-r--r--drivers/gles3/storage/mesh_storage.h204
-rw-r--r--drivers/gles3/storage/texture_storage.h10
-rw-r--r--drivers/gles3/texture_loader_gles3.cpp2
-rw-r--r--drivers/unix/dir_access_unix.h2
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp179
-rw-r--r--editor/action_map_editor.h36
-rw-r--r--editor/animation_bezier_editor.h4
-rw-r--r--editor/animation_track_editor.h122
-rw-r--r--editor/code_editor.h60
-rw-r--r--editor/connections_dialog.h50
-rw-r--r--editor/create_dialog.h12
-rw-r--r--editor/debugger/debug_adapter/debug_adapter_protocol.h2
-rw-r--r--editor/debugger/editor_debugger_inspector.h2
-rw-r--r--editor/debugger/editor_network_profiler.h12
-rw-r--r--editor/debugger/editor_performance_profiler.h6
-rw-r--r--editor/debugger/editor_profiler.h20
-rw-r--r--editor/debugger/editor_visual_profiler.h22
-rw-r--r--editor/debugger/script_editor_debugger.h78
-rw-r--r--editor/dependency_editor.h26
-rw-r--r--editor/editor_about.h10
-rw-r--r--editor/editor_asset_installer.h6
-rw-r--r--editor/editor_audio_buses.h56
-rw-r--r--editor/editor_autoload_settings.cpp2
-rw-r--r--editor/editor_command_palette.h4
-rw-r--r--editor/editor_dir_dialog.h10
-rw-r--r--editor/editor_export.h2
-rw-r--r--editor/editor_feature_profile.h30
-rw-r--r--editor/editor_file_dialog.h78
-rw-r--r--editor/editor_file_system.cpp55
-rw-r--r--editor/editor_file_system.h42
-rw-r--r--editor/editor_help.h28
-rw-r--r--editor/editor_help_search.h14
-rw-r--r--editor/editor_inspector.h56
-rw-r--r--editor/editor_layouts_dialog.h6
-rw-r--r--editor/editor_log.h16
-rw-r--r--editor/editor_node.cpp1
-rw-r--r--editor/editor_node.h226
-rw-r--r--editor/editor_path.h10
-rw-r--r--editor/editor_plugin_settings.h8
-rw-r--r--editor/editor_properties.h84
-rw-r--r--editor/editor_properties_array_dict.h42
-rw-r--r--editor/editor_property_name_processor.cpp13
-rw-r--r--editor/editor_resource_picker.h6
-rw-r--r--editor/editor_run_script.h2
-rw-r--r--editor/editor_sectioned_inspector.h6
-rw-r--r--editor/editor_settings.cpp4
-rw-r--r--editor/editor_settings_dialog.h28
-rw-r--r--editor/editor_spin_slider.h2
-rw-r--r--editor/editor_toaster.h8
-rw-r--r--editor/editor_zoom_widget.h6
-rw-r--r--editor/export_template_manager.h40
-rw-r--r--editor/fileserver/editor_file_server.h2
-rw-r--r--editor/filesystem_dock.h78
-rw-r--r--editor/find_in_files.h44
-rw-r--r--editor/groups_editor.h44
-rw-r--r--editor/import/dynamic_font_import_settings.h2
-rw-r--r--editor/import/scene_import_settings.h54
-rw-r--r--editor/import_defaults_editor.h10
-rw-r--r--editor/import_dock.h24
-rw-r--r--editor/inspector_dock.h40
-rw-r--r--editor/localization_editor.h24
-rw-r--r--editor/node_dock.h12
-rw-r--r--editor/plugin_config_dialog.h22
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.h16
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.h52
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.h64
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.h18
-rw-r--r--editor/plugins/animation_player_editor_plugin.h50
-rw-r--r--editor/plugins/animation_state_machine_editor.h44
-rw-r--r--editor/plugins/animation_tree_editor_plugin.h12
-rw-r--r--editor/plugins/asset_library_editor_plugin.h100
-rw-r--r--editor/plugins/audio_stream_editor_plugin.h2
-rw-r--r--editor/plugins/camera_3d_editor_plugin.h6
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h116
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.h2
-rw-r--r--editor/plugins/collision_shape_2d_editor_plugin.h8
-rw-r--r--editor/plugins/control_editor_plugin.h24
-rw-r--r--editor/plugins/cpu_particles_2d_editor_plugin.h18
-rw-r--r--editor/plugins/cpu_particles_3d_editor_plugin.h4
-rw-r--r--editor/plugins/curve_editor_plugin.h4
-rw-r--r--editor/plugins/debugger_editor_plugin.h6
-rw-r--r--editor/plugins/gpu_particles_2d_editor_plugin.h22
-rw-r--r--editor/plugins/gpu_particles_3d_editor_plugin.h24
-rw-r--r--editor/plugins/gpu_particles_collision_sdf_editor_plugin.h8
-rw-r--r--editor/plugins/gradient_editor_plugin.h6
-rw-r--r--editor/plugins/input_event_editor_plugin.h6
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.h2
-rw-r--r--editor/plugins/lightmap_gi_editor_plugin.h6
-rw-r--r--editor/plugins/line_2d_editor_plugin.cpp5
-rw-r--r--editor/plugins/line_2d_editor_plugin.h2
-rw-r--r--editor/plugins/mesh_editor_plugin.h16
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.h16
-rw-r--r--editor/plugins/mesh_library_editor_plugin.h10
-rw-r--r--editor/plugins/multimesh_editor_plugin.h32
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.cpp5
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.h2
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h6
-rw-r--r--editor/plugins/node_3d_editor_plugin.h170
-rw-r--r--editor/plugins/occluder_instance_3d_editor_plugin.h6
-rw-r--r--editor/plugins/ot_features_plugin.h2
-rw-r--r--editor/plugins/path_2d_editor_plugin.h26
-rw-r--r--editor/plugins/path_3d_editor_plugin.h16
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.cpp3
-rw-r--r--editor/plugins/physical_bone_3d_editor_plugin.h4
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h42
-rw-r--r--editor/plugins/polygon_3d_editor_plugin.h18
-rw-r--r--editor/plugins/replication_editor_plugin.h4
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.h18
-rw-r--r--editor/plugins/root_motion_editor_plugin.h8
-rw-r--r--editor/plugins/script_editor_plugin.cpp7
-rw-r--r--editor/plugins/script_editor_plugin.h92
-rw-r--r--editor/plugins/script_text_editor.cpp3
-rw-r--r--editor/plugins/script_text_editor.h47
-rw-r--r--editor/plugins/shader_editor_plugin.h22
-rw-r--r--editor/plugins/shader_file_editor_plugin.h10
-rw-r--r--editor/plugins/skeleton_2d_editor_plugin.h8
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.h30
-rw-r--r--editor/plugins/skeleton_ik_3d_editor_plugin.h4
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.h22
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h70
-rw-r--r--editor/plugins/style_box_editor_plugin.h2
-rw-r--r--editor/plugins/text_control_editor_plugin.h2
-rw-r--r--editor/plugins/texture_3d_editor_plugin.h6
-rw-r--r--editor/plugins/texture_layered_editor_plugin.h6
-rw-r--r--editor/plugins/texture_region_editor_plugin.h44
-rw-r--r--editor/plugins/theme_editor_plugin.h212
-rw-r--r--editor/plugins/theme_editor_preview.h16
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.h16
-rw-r--r--editor/plugins/tiles/tile_atlas_view.h36
-rw-r--r--editor/plugins/tiles/tile_data_editors.h46
-rw-r--r--editor/plugins/tiles/tile_map_editor.h110
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.h22
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.h70
-rw-r--r--editor/plugins/tiles/tile_set_editor.h32
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.h22
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.h8
-rw-r--r--editor/plugins/version_control_editor_plugin.h76
-rw-r--r--editor/plugins/voxel_gi_editor_plugin.h8
-rw-r--r--editor/progress_dialog.h6
-rw-r--r--editor/project_export.h74
-rw-r--r--editor/project_settings_editor.h56
-rw-r--r--editor/property_editor.h38
-rw-r--r--editor/property_selector.h8
-rw-r--r--editor/quick_open.h4
-rw-r--r--editor/rename_dialog.h50
-rw-r--r--editor/reparent_dialog.h4
-rw-r--r--editor/scene_tree_dock.h72
-rw-r--r--editor/scene_tree_editor.h18
-rw-r--r--editor/script_create_dialog.h44
-rw-r--r--editor/shader_globals_editor.h10
-rwxr-xr-xeditor/translations/extract.py10
-rw-r--r--main/main.cpp6
-rw-r--r--modules/csg/csg_shape.h2
-rw-r--r--modules/gdscript/gdscript.h16
-rw-r--r--modules/gdscript/gdscript_editor.cpp139
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h2
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp2
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.h4
-rw-r--r--modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml4
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp309
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.h35
-rw-r--r--modules/gltf/register_types.cpp26
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.h36
-rw-r--r--modules/mono/glue/arguments_vector.h2
-rw-r--r--modules/mono/managed_callable.h2
-rw-r--r--modules/mono/mono_gd/gd_mono.h18
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h4
-rw-r--r--modules/mono/mono_gd/gd_mono_cache.h144
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_field.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h10
-rw-r--r--modules/mono/mono_gd/gd_mono_method.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_property.h6
-rw-r--r--modules/mono/mono_gd/gd_mono_wasm_m2n.h4
-rw-r--r--modules/mono/signal_awaiter_utils.h2
-rw-r--r--modules/navigation/editor/navigation_mesh_editor_plugin.h14
-rw-r--r--modules/navigation/godot_navigation_server.cpp4
-rw-r--r--modules/navigation/nav_utils.h2
-rw-r--r--modules/noise/noise.h2
-rw-r--r--modules/openxr/SCsub4
-rw-r--r--modules/openxr/action_map/openxr_action.cpp23
-rw-r--r--modules/openxr/action_map/openxr_action.h29
-rw-r--r--modules/openxr/action_map/openxr_action_map.cpp111
-rw-r--r--modules/openxr/action_map/openxr_action_map.h34
-rw-r--r--modules/openxr/action_map/openxr_action_set.cpp44
-rw-r--r--modules/openxr/action_map/openxr_action_set.h25
-rw-r--r--modules/openxr/action_map/openxr_defs.cpp325
-rw-r--r--modules/openxr/action_map/openxr_defs.h99
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.cpp61
-rw-r--r--modules/openxr/action_map/openxr_interaction_profile.h40
-rw-r--r--modules/openxr/doc_classes/OpenXRActionMap.xml42
-rw-r--r--modules/openxr/doc_classes/OpenXRActionSet.xml9
-rw-r--r--modules/openxr/doc_classes/OpenXRIPBinding.xml33
-rw-r--r--modules/openxr/doc_classes/OpenXRInteractionProfile.xml15
-rw-r--r--modules/openxr/editor/SCsub5
-rw-r--r--modules/openxr/editor/openxr_action_editor.cpp112
-rw-r--r--modules/openxr/editor/openxr_action_editor.h67
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp370
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.h100
-rw-r--r--modules/openxr/editor/openxr_action_set_editor.cpp218
-rw-r--r--modules/openxr/editor/openxr_action_set_editor.h88
-rw-r--r--modules/openxr/editor/openxr_editor_plugin.cpp58
-rw-r--r--modules/openxr/editor/openxr_editor_plugin.h53
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.cpp272
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.h83
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.cpp135
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.h67
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp125
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.h66
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper.h2
-rw-r--r--modules/openxr/extensions/openxr_vulkan_extension.cpp6
-rw-r--r--modules/openxr/openxr_api.cpp16
-rw-r--r--modules/openxr/openxr_api.h2
-rw-r--r--modules/openxr/register_types.cpp20
-rw-r--r--modules/raycast/raycast_occlusion_cull.h4
-rw-r--r--modules/regex/regex.h2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp8
-rw-r--r--modules/text_server_fb/text_server_fb.cpp8
-rw-r--r--modules/theora/video_stream_theora.h2
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.h38
-rw-r--r--modules/visual_script/visual_script.h2
-rw-r--r--platform/android/display_server_android.cpp7
-rw-r--r--platform/android/display_server_android.h1
-rw-r--r--platform/android/export/export_plugin.cpp5
-rw-r--r--platform/android/export/gradle_export_util.cpp8
-rw-r--r--platform/android/java/editor/src/main/AndroidManifest.xml9
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java14
-rw-r--r--platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.java3
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java6
-rw-r--r--platform/android/java_godot_io_wrapper.cpp11
-rw-r--r--platform/android/java_godot_io_wrapper.h2
-rw-r--r--platform/android/os_android.h8
-rw-r--r--platform/iphone/os_iphone.h6
-rw-r--r--platform/linuxbsd/detect.py1
-rw-r--r--platform/linuxbsd/display_server_x11.h6
-rw-r--r--platform/linuxbsd/gl_manager_x11.h4
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp10
-rw-r--r--platform/linuxbsd/os_linuxbsd.h2
-rw-r--r--platform/osx/detect.py1
-rw-r--r--platform/osx/godot_main_osx.mm10
-rw-r--r--platform/osx/joypad_osx.h2
-rw-r--r--platform/osx/os_osx.mm33
-rw-r--r--platform/uwp/joypad_uwp.h2
-rw-r--r--platform/uwp/os_uwp.h10
-rw-r--r--platform/windows/display_server_windows.h2
-rw-r--r--platform/windows/gl_manager_windows.h2
-rw-r--r--platform/windows/joypad_windows.h4
-rw-r--r--platform/windows/os_windows.h4
-rw-r--r--scene/2d/collision_object_2d.cpp2
-rw-r--r--scene/2d/navigation_agent_2d.cpp21
-rw-r--r--scene/2d/navigation_agent_2d.h1
-rw-r--r--scene/2d/physical_bone_2d.h2
-rw-r--r--scene/2d/touch_screen_button.cpp4
-rw-r--r--scene/3d/navigation_agent_3d.cpp30
-rw-r--r--scene/3d/navigation_agent_3d.h6
-rw-r--r--scene/3d/skeleton_3d.h4
-rw-r--r--scene/animation/tween.cpp8
-rw-r--r--scene/animation/tween.h2
-rw-r--r--scene/gui/control.cpp2
-rw-r--r--scene/gui/dialogs.cpp15
-rw-r--r--scene/gui/dialogs.h14
-rw-r--r--scene/gui/file_dialog.h50
-rw-r--r--scene/gui/gradient_edit.h4
-rw-r--r--scene/gui/graph_edit.h32
-rw-r--r--scene/gui/item_list.h2
-rw-r--r--scene/gui/menu_button.h2
-rw-r--r--scene/gui/option_button.h2
-rw-r--r--scene/gui/popup.h2
-rw-r--r--scene/gui/popup_menu.h8
-rw-r--r--scene/gui/range.h2
-rw-r--r--scene/gui/rich_text_label.cpp29
-rw-r--r--scene/gui/rich_text_label.h1
-rw-r--r--scene/gui/scroll_container.h4
-rw-r--r--scene/gui/spin_box.h4
-rw-r--r--scene/gui/tab_container.cpp19
-rw-r--r--scene/gui/tab_container.h6
-rw-r--r--scene/gui/text_edit.cpp69
-rw-r--r--scene/gui/text_edit.h10
-rw-r--r--scene/gui/tree.h14
-rw-r--r--scene/gui/view_panner.cpp2
-rw-r--r--scene/main/http_request.h2
-rw-r--r--scene/main/scene_tree.h4
-rw-r--r--scene/multiplayer/scene_cache_interface.h2
-rw-r--r--scene/multiplayer/scene_replication_interface.h2
-rw-r--r--scene/resources/navigation_mesh.cpp4
-rw-r--r--scene/resources/skeleton_modification_2d.h2
-rw-r--r--scene/resources/skeleton_modification_3d.h2
-rw-r--r--scene/resources/text_line.cpp32
-rw-r--r--scene/resources/text_paragraph.cpp32
-rw-r--r--scene/resources/texture.cpp2
-rw-r--r--servers/audio/audio_driver_dummy.h2
-rw-r--r--servers/audio/audio_filter_sw.h2
-rw-r--r--servers/audio/audio_rb_resampler.h4
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.h2
-rw-r--r--servers/audio/effects/audio_stream_generator.h2
-rw-r--r--servers/audio/effects/reverb.h2
-rw-r--r--servers/audio_server.cpp1
-rw-r--r--servers/audio_server.h2
-rw-r--r--servers/extensions/physics_server_3d_extension.h2
-rw-r--r--servers/physics_3d/godot_area_pair_3d.h12
-rw-r--r--servers/physics_3d/godot_physics_server_3d.h2
-rw-r--r--servers/physics_3d/godot_space_3d.h2
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h3
-rw-r--r--servers/rendering/dummy/rasterizer_storage_dummy.h79
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h129
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp10
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_canvas_render.h41
-rw-r--r--servers/rendering/renderer_compositor.h2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp261
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h21
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp135
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h43
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp58
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h2
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h4
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp48
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h11
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h10
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h24
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.h10
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp1900
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h610
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl10
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h8
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp1921
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h694
-rw-r--r--servers/rendering/renderer_scene_cull.cpp48
-rw-r--r--servers/rendering/renderer_scene_cull.h32
-rw-r--r--servers/rendering/renderer_scene_render.h2
-rw-r--r--servers/rendering/renderer_storage.h89
-rw-r--r--servers/rendering/renderer_viewport.h2
-rw-r--r--servers/rendering/rendering_device.h1
-rw-r--r--servers/rendering/rendering_server_default.cpp1
-rw-r--r--servers/rendering/rendering_server_default.h23
-rw-r--r--servers/rendering/rendering_server_globals.cpp1
-rw-r--r--servers/rendering/rendering_server_globals.h2
-rw-r--r--servers/rendering/shader_language.cpp24
-rw-r--r--servers/rendering/shader_language.h14
-rw-r--r--servers/rendering/storage/mesh_storage.h136
-rw-r--r--servers/text_server.cpp2
-rw-r--r--tests/core/math/test_geometry_3d.h4
-rw-r--r--thirdparty/README.md6
399 files changed, 10143 insertions, 6088 deletions
diff --git a/.clang-tidy b/.clang-tidy
index b623aef133..fa57c94a21 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,5 +1,5 @@
---
-Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-use-default-member-init,modernize-use-nullptr,readability-braces-around-statements'
+Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-use-default-member-init,modernize-use-nullptr,readability-braces-around-statements,readability-redundant-member-init'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index c9f1b2f41e..1594f5b2d9 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -30,7 +30,7 @@ jobs:
build-mono: true
artifact: true
- - name: Editor with doubles and sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes)
+ - name: Editor with doubles and GCC sanitizers (target=debug, tools=yes, float=64, tests=yes, use_asan=yes, use_ubsan=yes)
cache-name: linux-editor-double-sanitizers
target: debug
tools: true
@@ -45,6 +45,17 @@ jobs:
# Skip 2GiB artifact speeding up action.
artifact: false
+ - name: Editor with clang sanitizers (target=debug, tools=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes)
+ cache-name: linux-editor-llvm-sanitizers
+ target: debug
+ tools: true
+ tests: true
+ sconsflags: use_asan=yes use_ubsan=yes use_llvm=yes
+ bin: "./bin/godot.linuxbsd.tools.64.llvm.san"
+ build-mono: false
+ # Skip 2GiB artifact speeding up action.
+ artifact: false
+
- name: Template w/ Mono (target=release, tools=no)
cache-name: linux-template-mono
target: release
@@ -75,7 +86,8 @@ jobs:
# The actual dependencies
sudo apt-get install build-essential pkg-config libx11-dev libxcursor-dev \
libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev \
- libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm xvfb wget unzip
+ libdbus-1-dev libudev-dev libxi-dev libxrandr-dev yasm xvfb wget unzip \
+ llvm
- name: Setup Godot build cache
uses: ./.github/actions/godot-cache
diff --git a/core/config/engine.h b/core/config/engine.h
index 1adab9b96f..eac96852b3 100644
--- a/core/config/engine.h
+++ b/core/config/engine.h
@@ -40,7 +40,7 @@ class Engine {
public:
struct Singleton {
StringName name;
- Object *ptr;
+ Object *ptr = nullptr;
StringName class_name; //used for binding generation hinting
bool user_created = false;
Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr, const StringName &p_class_name = StringName());
diff --git a/core/core_bind.h b/core/core_bind.h
index 907f37c5fa..4d26698f99 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -447,7 +447,7 @@ public:
class Directory : public RefCounted {
GDCLASS(Directory, RefCounted);
- DirAccess *d;
+ DirAccess *d = nullptr;
bool dir_open = false;
bool include_navigational = false;
diff --git a/core/io/file_access.h b/core/io/file_access.h
index a6cb5d9fc6..a5150010da 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -183,7 +183,7 @@ struct FileAccessRef {
operator bool() const { return f != nullptr; }
- FileAccess *f;
+ FileAccess *f = nullptr;
operator FileAccess *() { return f; }
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 6eee2f593d..fe4b12aef6 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -64,7 +64,7 @@ public:
uint64_t offset; //if offset is ZERO, the file was ERASED
uint64_t size;
uint8_t md5[16];
- PackSource *src;
+ PackSource *src = nullptr;
bool encrypted;
};
@@ -103,7 +103,7 @@ private:
Vector<PackSource *> sources;
- PackedDir *root;
+ PackedDir *root = nullptr;
static PackedData *singleton;
bool disabled = false;
@@ -150,7 +150,7 @@ class FileAccessPack : public FileAccess {
mutable bool eof;
uint64_t off;
- FileAccess *f;
+ FileAccess *f = nullptr;
virtual Error _open(const String &p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
diff --git a/core/io/ip.h b/core/io/ip.h
index ebd944a949..06ff8a4d70 100644
--- a/core/io/ip.h
+++ b/core/io/ip.h
@@ -62,7 +62,7 @@ public:
typedef int ResolverID;
private:
- _IP_ResolverPrivate *resolver;
+ _IP_ResolverPrivate *resolver = nullptr;
protected:
static IP *singleton;
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index c80c9b0ac9..5403168a53 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -127,7 +127,7 @@ class ResourceFormatSaverBinaryInstance {
bool skip_editor;
bool big_endian;
bool takeover_paths;
- FileAccess *f;
+ FileAccess *f = nullptr;
String magic;
Set<RES> resource_set;
diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h
index 1ea44b9d06..0b7ffdf6d0 100644
--- a/core/io/resource_uid.h
+++ b/core/io/resource_uid.h
@@ -46,7 +46,7 @@ public:
static String get_cache_file();
private:
- void *crypto; // CryptoCore::RandomGenerator (avoid including crypto_core.h)
+ void *crypto = nullptr; // CryptoCore::RandomGenerator (avoid including crypto_core.h)
Mutex mutex;
struct Cache {
CharString cs;
diff --git a/core/io/udp_server.h b/core/io/udp_server.h
index 4a7546fddf..47f06b2490 100644
--- a/core/io/udp_server.h
+++ b/core/io/udp_server.h
@@ -43,7 +43,7 @@ protected:
};
struct Peer {
- PacketPeerUDP *peer;
+ PacketPeerUDP *peer = nullptr;
IPAddress ip;
uint16_t port = 0;
diff --git a/core/math/bvh.h b/core/math/bvh.h
index f429ce189b..9f6ab9f736 100644
--- a/core/math/bvh.h
+++ b/core/math/bvh.h
@@ -763,19 +763,19 @@ private:
tree._extra[p_handle.id()].last_updated_tick = 0;
}
- PairCallback pair_callback;
- UnpairCallback unpair_callback;
- CheckPairCallback check_pair_callback;
- void *pair_callback_userdata;
- void *unpair_callback_userdata;
- void *check_pair_callback_userdata;
+ PairCallback pair_callback = nullptr;
+ UnpairCallback unpair_callback = nullptr;
+ CheckPairCallback check_pair_callback = nullptr;
+ void *pair_callback_userdata = nullptr;
+ void *unpair_callback_userdata = nullptr;
+ void *check_pair_callback_userdata = nullptr;
BVHTREE_CLASS tree;
// for collision pairing,
// maintain a list of all items moved etc on each frame / tick
LocalVector<BVHHandle, uint32_t, true> changed_items;
- uint32_t _tick;
+ uint32_t _tick = 1; // Start from 1 so items with 0 indicate never updated.
class BVHLockedFunction {
public:
@@ -801,23 +801,16 @@ private:
}
private:
- Mutex *_mutex;
+ Mutex *_mutex = nullptr;
};
Mutex _mutex;
// local toggle for turning on and off thread safety in project settings
- bool _thread_safe;
+ bool _thread_safe = BVH_THREAD_SAFE;
public:
- BVH_Manager() {
- _tick = 1; // start from 1 so items with 0 indicate never updated
- pair_callback = nullptr;
- unpair_callback = nullptr;
- pair_callback_userdata = nullptr;
- unpair_callback_userdata = nullptr;
- _thread_safe = BVH_THREAD_SAFE;
- }
+ BVH_Manager() {}
};
#undef BVHTREE_CLASS
diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h
index 50ec2c2b30..74831089f3 100644
--- a/core/math/dynamic_bvh.h
+++ b/core/math/dynamic_bvh.h
@@ -183,7 +183,7 @@ private:
Node *parent = nullptr;
union {
Node *childs[2];
- void *data;
+ void *data = nullptr;
};
_FORCE_INLINE_ bool is_leaf() const { return childs[1] == nullptr; }
@@ -215,10 +215,7 @@ private:
return axis.dot(volume.get_center() - org) <= 0;
}
- Node() {
- childs[0] = nullptr;
- childs[1] = nullptr;
- }
+ Node() {}
};
PagedAllocator<Node> node_allocator;
diff --git a/core/math/expression.h b/core/math/expression.h
index 9b87bdd6ec..d43cc4091a 100644
--- a/core/math/expression.h
+++ b/core/math/expression.h
@@ -147,7 +147,7 @@ private:
bool is_op = false;
union {
Variant::Operator op;
- ENode *node;
+ ENode *node = nullptr;
};
};
diff --git a/core/math/octree.h b/core/math/octree.h
index e73f8213b3..65ab9e2292 100644
--- a/core/math/octree.h
+++ b/core/math/octree.h
@@ -134,7 +134,7 @@ private:
List<PairData *, AL> pair_list;
struct OctantOwner {
- Octant *octant;
+ Octant *octant = nullptr;
typename List<Element *, AL>::Element *E;
}; // an element can be in max 8 octants
@@ -147,7 +147,7 @@ private:
int refcount;
bool intersect;
Element *A, *B;
- void *ud;
+ void *ud = nullptr;
typename List<PairData *, AL>::Element *eA, *eB;
};
@@ -156,18 +156,18 @@ private:
ElementMap element_map;
PairMap pair_map;
- PairCallback pair_callback;
- UnpairCallback unpair_callback;
- void *pair_callback_userdata;
- void *unpair_callback_userdata;
+ PairCallback pair_callback = nullptr;
+ UnpairCallback unpair_callback = nullptr;
+ void *pair_callback_userdata = nullptr;
+ void *unpair_callback_userdata = nullptr;
- OctreeElementID last_element_id;
- uint64_t pass;
+ OctreeElementID last_element_id = 1;
+ uint64_t pass = 1;
- real_t unit_size;
- Octant *root;
- int octant_count;
- int pair_count;
+ real_t unit_size = 1.0;
+ Octant *root = nullptr;
+ int octant_count = 0;
+ int pair_count = 0;
_FORCE_INLINE_ void _pair_check(PairData *p_pair) {
bool intersect = p_pair->A->aabb.intersects_inclusive(p_pair->B->aabb);
@@ -294,7 +294,7 @@ private:
const Vector3 *points;
int point_count;
T **result_array;
- int *result_idx;
+ int *result_idx = nullptr;
int result_max;
uint32_t mask;
};
@@ -1265,18 +1265,7 @@ void Octree<T, use_pairs, AL>::set_unpair_callback(UnpairCallback p_callback, vo
template <class T, bool use_pairs, class AL>
Octree<T, use_pairs, AL>::Octree(real_t p_unit_size) {
- last_element_id = 1;
- pass = 1;
unit_size = p_unit_size;
- root = nullptr;
-
- octant_count = 0;
- pair_count = 0;
-
- pair_callback = nullptr;
- unpair_callback = nullptr;
- pair_callback_userdata = nullptr;
- unpair_callback_userdata = nullptr;
}
#endif // OCTREE_H
diff --git a/core/object/callable_method_pointer.h b/core/object/callable_method_pointer.h
index 3cd9ad3819..577d4b9fbd 100644
--- a/core/object/callable_method_pointer.h
+++ b/core/object/callable_method_pointer.h
@@ -38,7 +38,7 @@
#include "core/variant/callable.h"
class CallableCustomMethodPointerBase : public CallableCustom {
- uint32_t *comp_ptr;
+ uint32_t *comp_ptr = nullptr;
uint32_t comp_size;
uint32_t h;
#ifdef DEBUG_METHODS_ENABLED
diff --git a/core/object/class_db.h b/core/object/class_db.h
index b8a4b3ea2b..5da8523743 100644
--- a/core/object/class_db.h
+++ b/core/object/class_db.h
@@ -85,8 +85,8 @@ public:
int index;
StringName setter;
StringName getter;
- MethodBind *_setptr;
- MethodBind *_getptr;
+ MethodBind *_setptr = nullptr;
+ MethodBind *_getptr = nullptr;
Variant::Type type;
};
diff --git a/core/object/message_queue.h b/core/object/message_queue.h
index eaab01d0aa..2219cdb8f6 100644
--- a/core/object/message_queue.h
+++ b/core/object/message_queue.h
@@ -62,10 +62,10 @@ class MessageQueue {
};
};
- uint8_t *buffer;
+ uint8_t *buffer = nullptr;
uint32_t buffer_end = 0;
uint32_t buffer_max_used = 0;
- uint32_t buffer_size;
+ uint32_t buffer_size = 0;
void _call_function(const Callable &p_callable, const Variant *p_args, int p_argcount, bool p_show_error);
diff --git a/core/object/object.h b/core/object/object.h
index b640c4e78a..eeef03dcb9 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -538,8 +538,8 @@ private:
std::mutex _instance_binding_mutex;
struct InstanceBinding {
- void *binding;
- void *token;
+ void *binding = nullptr;
+ void *token = nullptr;
GDNativeInstanceBindingFreeCallback free_callback = nullptr;
GDNativeInstanceBindingReferenceCallback reference_callback = nullptr;
};
@@ -849,7 +849,7 @@ class ObjectDB {
uint64_t validator : OBJECTDB_VALIDATOR_BITS;
uint64_t next_free : OBJECTDB_SLOT_MAX_COUNT_BITS;
uint64_t is_ref_counted : 1;
- Object *object;
+ Object *object = nullptr;
};
static SpinLock spin_lock;
diff --git a/core/object/script_language.h b/core/object/script_language.h
index 6161a0fc0f..08b82d798e 100644
--- a/core/object/script_language.h
+++ b/core/object/script_language.h
@@ -311,6 +311,13 @@ public:
CODE_COMPLETION_KIND_MAX
};
+ enum CodeCompletionLocation {
+ LOCATION_LOCAL = 0,
+ LOCATION_PARENT_MASK = 1 << 8,
+ LOCATION_OTHER_USER_CODE = 1 << 9,
+ LOCATION_OTHER = 1 << 10,
+ };
+
struct CodeCompletionOption {
CodeCompletionKind kind = CODE_COMPLETION_KIND_PLAIN_TEXT;
String display;
@@ -319,13 +326,15 @@ public:
RES icon;
Variant default_value;
Vector<Pair<int, int>> matches;
+ int location = LOCATION_OTHER;
CodeCompletionOption() {}
- CodeCompletionOption(const String &p_text, CodeCompletionKind p_kind) {
+ CodeCompletionOption(const String &p_text, CodeCompletionKind p_kind, int p_location = LOCATION_OTHER) {
display = p_text;
insert_text = p_text;
kind = p_kind;
+ location = p_location;
}
};
@@ -421,11 +430,11 @@ public:
extern uint8_t script_encryption_key[32];
class PlaceHolderScriptInstance : public ScriptInstance {
- Object *owner;
+ Object *owner = nullptr;
List<PropertyInfo> properties;
Map<StringName, Variant> values;
Map<StringName, Variant> constants;
- ScriptLanguage *language;
+ ScriptLanguage *language = nullptr;
Ref<Script> script;
public:
diff --git a/core/object/script_language_extension.cpp b/core/object/script_language_extension.cpp
index bf0966c803..21d7685674 100644
--- a/core/object/script_language_extension.cpp
+++ b/core/object/script_language_extension.cpp
@@ -161,6 +161,11 @@ void ScriptLanguageExtension::_bind_methods() {
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE);
BIND_ENUM_CONSTANT(LOOKUP_RESULT_MAX);
+ BIND_ENUM_CONSTANT(LOCATION_LOCAL);
+ BIND_ENUM_CONSTANT(LOCATION_PARENT_MASK);
+ BIND_ENUM_CONSTANT(LOCATION_OTHER_USER_CODE);
+ BIND_ENUM_CONSTANT(LOCATION_OTHER);
+
BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_CLASS);
BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_FUNCTION);
BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_SIGNAL);
diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h
index b9ec79da26..40f18ab30d 100644
--- a/core/object/script_language_extension.h
+++ b/core/object/script_language_extension.h
@@ -387,6 +387,8 @@ public:
option.icon = op["icon"];
ERR_CONTINUE(!op.has("default_value"));
option.default_value = op["default_value"];
+ ERR_CONTINUE(!op.has("location"));
+ option.location = op["location"];
if (op.has("matches")) {
PackedInt32Array matches = op["matches"];
ERR_CONTINUE(matches.size() & 1);
@@ -639,6 +641,7 @@ public:
VARIANT_ENUM_CAST(ScriptLanguageExtension::LookupResultType)
VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionKind)
+VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation)
class ScriptInstanceExtension : public ScriptInstance {
public:
diff --git a/core/os/memory.h b/core/os/memory.h
index 27eaad5010..baa96ef3e9 100644
--- a/core/os/memory.h
+++ b/core/os/memory.h
@@ -186,9 +186,9 @@ void memdelete_arr(T *p_class) {
struct _GlobalNil {
int color = 1;
- _GlobalNil *right;
- _GlobalNil *left;
- _GlobalNil *parent;
+ _GlobalNil *right = nullptr;
+ _GlobalNil *left = nullptr;
+ _GlobalNil *parent = nullptr;
_GlobalNil();
};
diff --git a/core/os/os.h b/core/os/os.h
index 808d704b3d..b3c66ff18c 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -60,8 +60,6 @@ class OS {
bool _stdout_enabled = true;
bool _stderr_enabled = true;
- char *last_error;
-
CompositeLogger *_logger = nullptr;
bool restart_on_exit = false;
diff --git a/core/os/pool_allocator.h b/core/os/pool_allocator.h
index 11a252bc54..0919a024e2 100644
--- a/core/os/pool_allocator.h
+++ b/core/os/pool_allocator.h
@@ -75,13 +75,13 @@ private:
typedef int EntryArrayPos;
typedef int EntryIndicesPos;
- Entry *entry_array;
- int *entry_indices;
+ Entry *entry_array = nullptr;
+ int *entry_indices = nullptr;
int entry_max;
int entry_count;
- uint8_t *pool;
- void *mem_ptr;
+ uint8_t *pool = nullptr;
+ void *mem_ptr = nullptr;
int pool_size;
int free_mem;
diff --git a/core/string/string_name.h b/core/string/string_name.h
index 6f08d32981..f4233854ac 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -70,7 +70,7 @@ class StringName {
_Data *_data = nullptr;
union _HashUnion {
- _Data *ptr;
+ _Data *ptr = nullptr;
uint32_t hash;
};
diff --git a/core/templates/command_queue_mt.h b/core/templates/command_queue_mt.h
index 1ecb81c2a2..0aa1cfd541 100644
--- a/core/templates/command_queue_mt.h
+++ b/core/templates/command_queue_mt.h
@@ -311,7 +311,7 @@ class CommandQueueMT {
};
struct SyncCommand : public CommandBase {
- SyncSemaphore *sync_sem;
+ SyncSemaphore *sync_sem = nullptr;
virtual void post() {
sync_sem->sem.post();
diff --git a/core/templates/map.h b/core/templates/map.h
index f228640a1e..c54da1dc03 100644
--- a/core/templates/map.h
+++ b/core/templates/map.h
@@ -178,7 +178,7 @@ public:
private:
struct _Data {
Element *_root = nullptr;
- Element *_nil;
+ Element *_nil = nullptr;
int size_cache = 0;
_FORCE_INLINE_ _Data() {
@@ -344,7 +344,7 @@ private:
void _insert_rb_fix(Element *p_new_node) {
Element *node = p_new_node;
Element *nparent = node->parent;
- Element *ngrand_parent;
+ Element *ngrand_parent = nullptr;
while (nparent->color == RED) {
ngrand_parent = nparent->parent;
@@ -500,7 +500,7 @@ private:
Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- Element *sibling;
+ Element *sibling = nullptr;
if (rp == rp->parent->left) {
rp->parent->left = node;
sibling = rp->parent->right;
diff --git a/core/templates/oa_hash_map.h b/core/templates/oa_hash_map.h
index 4e712fccf2..e4d9323c45 100644
--- a/core/templates/oa_hash_map.h
+++ b/core/templates/oa_hash_map.h
@@ -306,7 +306,7 @@ public:
bool valid;
const TKey *key;
- TValue *value;
+ TValue *value = nullptr;
private:
uint32_t pos;
diff --git a/core/templates/safe_list.h b/core/templates/safe_list.h
index 53fc3fe5f9..ae31525dd0 100644
--- a/core/templates/safe_list.h
+++ b/core/templates/safe_list.h
@@ -75,8 +75,8 @@ public:
class Iterator {
friend class SafeList;
- SafeListNode *cursor;
- SafeList *list;
+ SafeListNode *cursor = nullptr;
+ SafeList *list = nullptr;
Iterator(SafeListNode *p_cursor, SafeList *p_list) :
cursor(p_cursor), list(p_list) {
@@ -253,8 +253,8 @@ public:
class Iterator {
friend class SafeList;
- SafeListNode *cursor;
- SafeList *list;
+ SafeListNode *cursor = nullptr;
+ SafeList *list = nullptr;
public:
Iterator(SafeListNode *p_cursor, SafeList *p_list) :
diff --git a/core/templates/self_list.h b/core/templates/self_list.h
index 7f2236fa3a..719b5f2e63 100644
--- a/core/templates/self_list.h
+++ b/core/templates/self_list.h
@@ -108,7 +108,7 @@ public:
private:
List *_root = nullptr;
- T *_self;
+ T *_self = nullptr;
SelfList<T> *_next = nullptr;
SelfList<T> *_prev = nullptr;
diff --git a/core/templates/set.h b/core/templates/set.h
index cdc6e8447d..a8a0a77712 100644
--- a/core/templates/set.h
+++ b/core/templates/set.h
@@ -328,7 +328,7 @@ private:
void _insert_rb_fix(Element *p_new_node) {
Element *node = p_new_node;
Element *nparent = node->parent;
- Element *ngrand_parent;
+ Element *ngrand_parent = nullptr;
while (nparent->color == RED) {
ngrand_parent = nparent->parent;
@@ -482,7 +482,7 @@ private:
Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
- Element *sibling;
+ Element *sibling = nullptr;
if (rp == rp->parent->left) {
rp->parent->left = node;
sibling = rp->parent->right;
diff --git a/core/templates/thread_work_pool.h b/core/templates/thread_work_pool.h
index 957af44f48..d364ac4fd8 100644
--- a/core/templates/thread_work_pool.h
+++ b/core/templates/thread_work_pool.h
@@ -68,7 +68,7 @@ class ThreadWorkPool {
Semaphore start;
Semaphore completed;
std::atomic<bool> exit;
- BaseWork *work;
+ BaseWork *work = nullptr;
};
ThreadData *threads = nullptr;
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index 4836f48a57..c1e28ffba3 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -61,6 +61,8 @@
<member name="dialog_autowrap" type="bool" setter="set_autowrap" getter="has_autowrap" default="false">
Sets autowrapping for the text in the dialog.
</member>
+ <member name="dialog_close_on_escape" type="bool" setter="set_close_on_escape" getter="get_close_on_escape" default="true">
+ </member>
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" default="true">
If [code]true[/code], the dialog is hidden when the OK button is pressed. You can set it to [code]false[/code] if you want to do e.g. input validation when receiving the [signal confirmed] signal, and handle hiding the dialog in your own logic.
[b]Note:[/b] Some nodes derived from this class can have a different default value, and potentially their own built-in logic overriding this setting. For example [FileDialog] defaults to [code]false[/code], and has its own input validation code that is called when you press OK, which eventually hides the dialog if the input is valid. As such, this property can't be used in [FileDialog] to disable hiding the dialog when pressing OK.
diff --git a/doc/classes/EditorFileSystemImportFormatSupportQuery.xml b/doc/classes/EditorFileSystemImportFormatSupportQuery.xml
new file mode 100644
index 0000000000..8431a3a7ef
--- /dev/null
+++ b/doc/classes/EditorFileSystemImportFormatSupportQuery.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorFileSystemImportFormatSupportQuery" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Used to query and configure import format support.
+ </brief_description>
+ <description>
+ This class is used to query and configure a certain import format. It is used in conjuntion with asset format import plugins.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="_get_file_extensions" qualifiers="virtual const">
+ <return type="PackedStringArray" />
+ <description>
+ Return the file extensions supported.
+ </description>
+ </method>
+ <method name="_is_active" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ Return whether this importer is active.
+ </description>
+ </method>
+ <method name="_query" qualifiers="virtual const">
+ <return type="bool" />
+ <description>
+ Query support. Return false if import must not continue.
+ </description>
+ </method>
+ </methods>
+</class>
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index b7b23a1097..baab91569a 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -90,6 +90,9 @@
<member name="max_speed" type="float" setter="set_max_speed" getter="get_max_speed" default="200.0">
The maximum speed that an agent can move.
</member>
+ <member name="navigable_layers" type="int" setter="set_navigable_layers" getter="get_navigable_layers" default="1">
+ A bitfield determining what layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new layers.
+ </member>
<member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="500.0">
The distance to search for other agents.
</member>
diff --git a/doc/classes/NavigationAgent3D.xml b/doc/classes/NavigationAgent3D.xml
index 18886ac33e..04b148c70d 100644
--- a/doc/classes/NavigationAgent3D.xml
+++ b/doc/classes/NavigationAgent3D.xml
@@ -96,6 +96,9 @@
<member name="max_speed" type="float" setter="set_max_speed" getter="get_max_speed" default="10.0">
The maximum speed that an agent can move.
</member>
+ <member name="navigable_layers" type="int" setter="set_navigable_layers" getter="get_navigable_layers" default="1">
+ A bitfield determining what layers of navigation regions this agent will use to calculate path. Changing it runtime will clear current navigation path and generate new one, according to new layers.
+ </member>
<member name="neighbor_dist" type="float" setter="set_neighbor_dist" getter="get_neighbor_dist" default="50.0">
The distance to search for other agents.
</member>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index 44b16de0cf..ee32677b3a 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -512,7 +512,7 @@
</member>
<member name="display/window/size/resizable" type="bool" setter="" getter="" default="true">
Allows the window to be resizable by default.
- [b]Note:[/b] This setting is ignored on iOS and Android.
+ [b]Note:[/b] This setting is ignored on iOS.
</member>
<member name="display/window/size/viewport_height" type="int" setter="" getter="" default="600">
Sets the game's main viewport height. On desktop platforms, this is also the initial window height.
@@ -553,9 +553,9 @@
<member name="editor/script/templates_search_path" type="String" setter="" getter="" default="&quot;res://script_templates&quot;">
Search path for project-specific script templates. Godot will search for script templates both in the editor-specific path and in this project-specific path.
</member>
- <member name="filesystem/import/blend/enabled" type="bool" setter="" getter="" default="true">
+ <member name="filesystem/import/blender/enabled" type="bool" setter="" getter="" default="true">
If [code]true[/code], Blender 3D scene files with the [code].blend[/code] extension will be imported by converting them to glTF 2.0.
- This requires configuring a path to a Blender executable in the editor settings at [code]filesystem/import/blend/blender_path[/code]. Blender 3.0 or later is required.
+ This requires configuring a path to a Blender executable in the editor settings at [code]filesystem/import/blender/blender3_path[/code]. Blender 3.0 or later is required.
</member>
<member name="filesystem/import/fbx/enabled" type="bool" setter="" getter="" default="true">
If [code]true[/code], Autodesk FBX 3D scene files with the [code].fbx[/code] extension will be imported by converting them to glTF 2.0.
@@ -1923,7 +1923,7 @@
</member>
<member name="rendering/vulkan/staging_buffer/texture_upload_region_size_px" type="int" setter="" getter="" default="64">
</member>
- <member name="xr/openxr/default_action_map" type="String" setter="" getter="" default="&quot;res://default_action_map.tres&quot;">
+ <member name="xr/openxr/default_action_map" type="String" setter="" getter="" default="&quot;res://openxr_action_map.tres&quot;">
Action map configuration to load by default.
</member>
<member name="xr/openxr/enabled" type="bool" setter="" getter="" default="false">
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index e805d3469c..a882a6c66f 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -49,6 +49,12 @@
Clears the tag stack and sets [member text] to an empty string.
</description>
</method>
+ <method name="deselect">
+ <return type="void" />
+ <description>
+ Clears the current selection.
+ </description>
+ </method>
<method name="get_character_line">
<return type="int" />
<argument index="0" name="character" type="int" />
diff --git a/doc/classes/ScriptLanguageExtension.xml b/doc/classes/ScriptLanguageExtension.xml
index 7225d93030..d66bb6a7c7 100644
--- a/doc/classes/ScriptLanguageExtension.xml
+++ b/doc/classes/ScriptLanguageExtension.xml
@@ -378,6 +378,18 @@
</constant>
<constant name="LOOKUP_RESULT_MAX" value="7" enum="LookupResultType">
</constant>
+ <constant name="LOCATION_LOCAL" value="0" enum="CodeCompletionLocation">
+ The option is local to the location of the code completion query - e.g. a local variable.
+ </constant>
+ <constant name="LOCATION_PARENT_MASK" value="256" enum="CodeCompletionLocation">
+ The option is from the containing class or a parent class, relative to the location of the code completion query. Perform a bitwise OR with the class depth (e.g. 0 for the local class, 1 for the parent, 2 for the grandparent, etc) to store the depth of an option in a the class or a parent class.
+ </constant>
+ <constant name="LOCATION_OTHER_USER_CODE" value="512" enum="CodeCompletionLocation">
+ The option is from user code which is not local and not in a derived class (e.g. Autoload Singletons).
+ </constant>
+ <constant name="LOCATION_OTHER" value="1024" enum="CodeCompletionLocation">
+ The option is from other engine code, not covered by the other enum constants - e.g. built-in classes.
+ </constant>
<constant name="CODE_COMPLETION_KIND_CLASS" value="0" enum="CodeCompletionKind">
</constant>
<constant name="CODE_COMPLETION_KIND_FUNCTION" value="1" enum="CodeCompletionKind">
diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml
index 5e3eb0c9f8..e84f9c38ff 100644
--- a/doc/classes/SpinBox.xml
+++ b/doc/classes/SpinBox.xml
@@ -25,6 +25,7 @@
The above code will create a [SpinBox], disable context menu on it and set the text alignment to right.
See [Range] class for more options over the [SpinBox].
[b]Note:[/b] [SpinBox] relies on an underlying [LineEdit] node. To theme a [SpinBox]'s background, add theme items for [LineEdit] and customize them.
+ [b]Note:[/b] If you want to implement drag and drop for the underlying [LineEdit], you can use [method Control.set_drag_forwarding] on the node returned by [method get_line_edit].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index 8108c5eb46..1f3d5596aa 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -341,7 +341,6 @@
print("1.7".is_valid_float()) # Prints "true"
print("24".is_valid_float()) # Prints "true"
print("7e3".is_valid_float()) # Prints "true"
- print("24".is_valid_float()) # Prints "true"
print("Hello".is_valid_float()) # Prints "false"
[/codeblock]
</description>
@@ -678,7 +677,7 @@
<return type="float" />
<argument index="0" name="text" type="String" />
<description>
- Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sorensen-Dice coefficient[/url]) this string compared to another. 1.0 means totally similar and 0.0 means totally dissimilar.
+ Returns the similarity index ([url=https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient]Sorensen-Dice coefficient[/url]) of this string compared to another. A result of 1.0 means totally similar, while 0.0 means totally dissimilar.
[codeblock]
print("ABC123".similarity("ABC123")) # Prints "1"
print("ABC123".similarity("XYZ456")) # Prints "0"
diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml
index c506152546..011b716dfc 100644
--- a/doc/classes/TabContainer.xml
+++ b/doc/classes/TabContainer.xml
@@ -30,6 +30,13 @@
Returns the previously active tab index.
</description>
</method>
+ <method name="get_tab_button_icon" qualifiers="const">
+ <return type="Texture2D" />
+ <argument index="0" name="tab_idx" type="int" />
+ <description>
+ Returns the button icon from the tab at index [code]tab_idx[/code].
+ </description>
+ </method>
<method name="get_tab_control" qualifiers="const">
<return type="Control" />
<argument index="0" name="tab_idx" type="int" />
@@ -92,6 +99,14 @@
If set on a [Popup] node instance, a popup menu icon appears in the top-right corner of the [TabContainer] (setting it to [code]null[/code] will make it go away). Clicking it will expand the [Popup] node.
</description>
</method>
+ <method name="set_tab_button_icon">
+ <return type="void" />
+ <argument index="0" name="tab_idx" type="int" />
+ <argument index="1" name="icon" type="Texture2D" />
+ <description>
+ Sets the button icon from the tab at index [code]tab_idx[/code].
+ </description>
+ </method>
<method name="set_tab_disabled">
<return type="void" />
<argument index="0" name="tab_idx" type="int" />
@@ -158,6 +173,12 @@
Emitted when the [TabContainer]'s [Popup] button is clicked. See [method set_popup] for details.
</description>
</signal>
+ <signal name="tab_button_pressed">
+ <argument index="0" name="tab" type="int" />
+ <description>
+ Emitted when the user clicks on the button icon on this tab.
+ </description>
+ </signal>
<signal name="tab_changed">
<argument index="0" name="tab" type="int" />
<description>
diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index 2c152410ce..72f32f39c2 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -72,6 +72,13 @@
[b]Note:[/b] The [Tween] will become invalid after finished, but you can call [method stop] after the step, to keep it and reset.
</description>
</method>
+ <method name="get_total_elapsed_time" qualifiers="const">
+ <return type="float" />
+ <description>
+ Returns the total time in seconds the [Tween] has been animating (i.e. time since it started, not counting pauses etc.). The time is affected by [method set_speed_scale] and [method stop] will reset it to [code]0[/code].
+ [b]Note:[/code] As it results from accumulating frame deltas, the time returned after the [Tween] has finished animating will be slightly greater than the actual [Tween] duration.
+ </description>
+ </method>
<method name="interpolate_value">
<return type="Variant" />
<argument index="0" name="initial_value" type="Variant" />
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 4e825ab8b2..70066c5e2a 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -169,7 +169,7 @@ public:
LocalVector<GLsync> fences;
uint32_t current_buffer = 0;
- InstanceData *instance_data_array;
+ InstanceData *instance_data_array = nullptr;
bool canvas_texscreen_used;
CanvasShaderGLES3 canvas_shader;
RID canvas_shader_current_version;
@@ -198,7 +198,7 @@ public:
bool end_batch = false;
Transform3D vp;
- Light *using_light;
+ Light *using_light = nullptr;
bool using_shadow;
bool using_transparent_rt;
@@ -220,9 +220,9 @@ public:
typedef void Texture;
- RasterizerSceneGLES3 *scene_render;
+ RasterizerSceneGLES3 *scene_render = nullptr;
- RasterizerStorageGLES3 *storage;
+ RasterizerStorageGLES3 *storage = nullptr;
void _set_uniforms();
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 55ee54e992..2279a502a2 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -41,6 +41,7 @@
#include "storage/config.h"
#include "storage/decal_atlas_storage.h"
#include "storage/material_storage.h"
+#include "storage/mesh_storage.h"
#include "storage/render_target_storage.h"
#include "storage/texture_storage.h"
@@ -57,6 +58,7 @@ protected:
GLES3::TextureStorage texture_storage;
GLES3::DecalAtlasStorage decal_atlas_storage;
GLES3::MaterialStorage material_storage;
+ GLES3::MeshStorage mesh_storage;
RasterizerStorageGLES3 storage;
RasterizerCanvasGLES3 canvas;
RasterizerSceneGLES3 scene;
@@ -66,6 +68,7 @@ protected:
public:
RendererCanvasTextureStorage *get_canvas_texture_storage() { return &canvas_texture_storage; }
RendererMaterialStorage *get_material_storage() { return &material_storage; }
+ RendererMeshStorage *get_mesh_storage() { return &mesh_storage; }
RendererTextureStorage *get_texture_storage() { return &texture_storage; }
RendererDecalAtlasStorage *get_decal_atlas_storage() { return &decal_atlas_storage; }
RendererStorage *get_storage() { return &storage; }
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index c71423a45d..3517d985f0 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -58,202 +58,6 @@ RID RasterizerStorageGLES3::sky_create() {
void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) {
}
-/* MESH API */
-
-RID RasterizerStorageGLES3::mesh_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::mesh_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
-}
-
-bool RasterizerStorageGLES3::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
- return false;
-}
-
-RID RasterizerStorageGLES3::mesh_instance_create(RID p_base) {
- return RID();
-}
-
-void RasterizerStorageGLES3::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
-}
-
-void RasterizerStorageGLES3::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
-}
-
-void RasterizerStorageGLES3::mesh_instance_check_for_update(RID p_mesh_instance) {
-}
-
-void RasterizerStorageGLES3::update_mesh_instances() {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
-}
-
-float RasterizerStorageGLES3::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
- return 0.0;
-}
-
-void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
-}
-
-int RasterizerStorageGLES3::mesh_get_blend_shape_count(RID p_mesh) const {
- return 0;
-}
-
-void RasterizerStorageGLES3::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
-}
-
-RS::BlendShapeMode RasterizerStorageGLES3::mesh_get_blend_shape_mode(RID p_mesh) const {
- return RS::BLEND_SHAPE_MODE_NORMALIZED;
-}
-
-void RasterizerStorageGLES3::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
-}
-
-void RasterizerStorageGLES3::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
-}
-
-void RasterizerStorageGLES3::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
-}
-
-void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
-}
-
-RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const {
- return RID();
-}
-
-RS::SurfaceData RasterizerStorageGLES3::mesh_get_surface(RID p_mesh, int p_surface) const {
- return RS::SurfaceData();
-}
-
-int RasterizerStorageGLES3::mesh_get_surface_count(RID p_mesh) const {
- return 1;
-}
-
-void RasterizerStorageGLES3::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
-}
-
-AABB RasterizerStorageGLES3::mesh_get_custom_aabb(RID p_mesh) const {
- return AABB();
-}
-
-AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
- return AABB();
-}
-
-void RasterizerStorageGLES3::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
-}
-
-void RasterizerStorageGLES3::mesh_clear(RID p_mesh) {
-}
-
-/* MULTIMESH API */
-
-RID RasterizerStorageGLES3::multimesh_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::multimesh_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
-}
-
-int RasterizerStorageGLES3::multimesh_get_instance_count(RID p_multimesh) const {
- return 0;
-}
-
-void RasterizerStorageGLES3::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
-}
-
-void RasterizerStorageGLES3::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
-}
-
-void RasterizerStorageGLES3::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
-}
-
-void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
-}
-
-void RasterizerStorageGLES3::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
-}
-
-RID RasterizerStorageGLES3::multimesh_get_mesh(RID p_multimesh) const {
- return RID();
-}
-
-AABB RasterizerStorageGLES3::multimesh_get_aabb(RID p_multimesh) const {
- return AABB();
-}
-
-Transform3D RasterizerStorageGLES3::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
- return Transform3D();
-}
-
-Transform2D RasterizerStorageGLES3::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
- return Transform2D();
-}
-
-Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
- return Color();
-}
-
-Color RasterizerStorageGLES3::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
- return Color();
-}
-
-void RasterizerStorageGLES3::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
-}
-
-Vector<float> RasterizerStorageGLES3::multimesh_get_buffer(RID p_multimesh) const {
- return Vector<float>();
-}
-
-void RasterizerStorageGLES3::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
-}
-
-int RasterizerStorageGLES3::multimesh_get_visible_instances(RID p_multimesh) const {
- return 0;
-}
-
-/* SKELETON API */
-
-RID RasterizerStorageGLES3::skeleton_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::skeleton_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
-}
-
-void RasterizerStorageGLES3::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
-}
-
-int RasterizerStorageGLES3::skeleton_get_bone_count(RID p_skeleton) const {
- return 0;
-}
-
-void RasterizerStorageGLES3::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
-}
-
-Transform3D RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
- return Transform3D();
-}
-
-void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
-}
-
-Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
- return Transform2D();
-}
-
/* Light API */
RID RasterizerStorageGLES3::directional_light_allocate() {
@@ -450,7 +254,11 @@ bool RasterizerStorageGLES3::reflection_probe_renders_shadows(RID p_probe) const
void RasterizerStorageGLES3::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
}
-void RasterizerStorageGLES3::skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) {
+void RasterizerStorageGLES3::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
+}
+
+float RasterizerStorageGLES3::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
+ return 0.0;
}
/* VOXEL GI API */
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index b9022142dd..105529ee3d 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -132,143 +132,6 @@ public:
RID sky_create();
void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
- /* MESH API */
-
- RID mesh_allocate() override;
- void mesh_initialize(RID p_rid) override;
- void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override;
- bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override;
- RID mesh_instance_create(RID p_base) override;
- void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
- void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
- void mesh_instance_check_for_update(RID p_mesh_instance) override;
- void update_mesh_instances() override;
- void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
- float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
-
- void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override;
-
- int mesh_get_blend_shape_count(RID p_mesh) const override;
-
- void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override;
- RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override;
-
- void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
- void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
- void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
-
- void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override;
- RID mesh_surface_get_material(RID p_mesh, int p_surface) const override;
-
- RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override;
- int mesh_get_surface_count(RID p_mesh) const override;
-
- void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override;
- AABB mesh_get_custom_aabb(RID p_mesh) const override;
-
- AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override;
- void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
- void mesh_clear(RID p_mesh) override;
-
- /* MULTIMESH API */
-
- struct MultiMesh {
- RID mesh;
- int instances = 0;
- RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
- bool uses_colors = false;
- bool uses_custom_data = false;
- int visible_instances = -1;
- AABB aabb;
- bool aabb_dirty = false;
- bool buffer_set = false;
- uint32_t stride_cache = 0;
- uint32_t color_offset_cache = 0;
- uint32_t custom_data_offset_cache = 0;
-
- Vector<float> data_cache; //used if individual setting is used
- bool *data_cache_dirty_regions = nullptr;
- uint32_t data_cache_used_dirty_regions = 0;
-
- RID buffer; //storage buffer
- RID uniform_set_3d;
- RID uniform_set_2d;
-
- bool dirty = false;
- MultiMesh *dirty_list = nullptr;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<MultiMesh, true> multimesh_owner;
-
- MultiMesh *multimesh_dirty_list = nullptr;
-
- _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
- _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
- void _update_dirty_multimeshes();
-
- RID multimesh_allocate() override;
- void multimesh_initialize(RID p_rid) override;
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
- int multimesh_get_instance_count(RID p_multimesh) const override;
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
-
- RID multimesh_get_mesh(RID p_multimesh) const override;
- AABB multimesh_get_aabb(RID p_multimesh) const override;
-
- Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
- Vector<float> multimesh_get_buffer(RID p_multimesh) const override;
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
- int multimesh_get_visible_instances(RID p_multimesh) const override;
-
- _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->xform_format;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_colors;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_custom_data;
- }
-
- _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (multimesh->visible_instances >= 0) {
- return multimesh->visible_instances;
- }
- return multimesh->instances;
- }
-
- /* SKELETON API */
-
- RID skeleton_allocate() override;
- void skeleton_initialize(RID p_rid) override;
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override;
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override;
- int skeleton_get_bone_count(RID p_skeleton) const override;
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override;
- Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override;
- void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
- Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
-
/* Light API */
RID directional_light_allocate() override;
@@ -328,6 +191,8 @@ public:
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override;
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override;
void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
+ void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+ float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
AABB reflection_probe_get_aabb(RID p_probe) const override;
RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
@@ -338,7 +203,6 @@ public:
bool reflection_probe_renders_shadows(RID p_probe) const override;
void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
- void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override;
/* VOXEL GI API */
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index bf17e66c2f..450ee7191f 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -66,7 +66,7 @@ struct Shader {
RID self;
RS::ShaderMode mode;
- ShaderGLES3 *shader;
+ ShaderGLES3 *shader = nullptr;
String code;
SelfList<Material>::List materials;
@@ -185,7 +185,7 @@ struct Shader {
struct Material {
RID self;
- Shader *shader;
+ Shader *shader = nullptr;
Map<StringName, Variant> params;
SelfList<Material> list;
SelfList<Material> dirty_list;
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
new file mode 100644
index 0000000000..c2a431aff1
--- /dev/null
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -0,0 +1,257 @@
+/*************************************************************************/
+/* mesh_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifdef GLES3_ENABLED
+
+#include "mesh_storage.h"
+
+using namespace GLES3;
+
+MeshStorage *MeshStorage::singleton = nullptr;
+
+MeshStorage *MeshStorage::get_singleton() {
+ return singleton;
+}
+
+MeshStorage::MeshStorage() {
+ singleton = this;
+}
+
+MeshStorage::~MeshStorage() {
+ singleton = nullptr;
+}
+
+/* MESH API */
+
+RID MeshStorage::mesh_allocate() {
+ return RID();
+}
+
+void MeshStorage::mesh_initialize(RID p_rid) {
+}
+
+void MeshStorage::mesh_free(RID p_rid) {
+}
+
+void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
+}
+
+bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
+ return false;
+}
+
+void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
+}
+
+int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const {
+ return 0;
+}
+
+void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
+}
+
+RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const {
+ return RS::BLEND_SHAPE_MODE_NORMALIZED;
+}
+
+void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+}
+
+void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+}
+
+void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+}
+
+void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
+}
+
+RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const {
+ return RID();
+}
+
+RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
+ return RS::SurfaceData();
+}
+
+int MeshStorage::mesh_get_surface_count(RID p_mesh) const {
+ return 1;
+}
+
+void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
+}
+
+AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const {
+ return AABB();
+}
+
+AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
+ return AABB();
+}
+
+void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
+}
+
+void MeshStorage::mesh_clear(RID p_mesh) {
+}
+
+/* MESH INSTANCE API */
+
+RID MeshStorage::mesh_instance_create(RID p_base) {
+ return RID();
+}
+
+void MeshStorage::mesh_instance_free(RID p_rid) {
+}
+
+void MeshStorage::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
+}
+
+void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
+}
+
+void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
+}
+
+void MeshStorage::update_mesh_instances() {
+}
+
+/* MULTIMESH API */
+
+RID MeshStorage::multimesh_allocate() {
+ return RID();
+}
+
+void MeshStorage::multimesh_initialize(RID p_rid) {
+}
+
+void MeshStorage::multimesh_free(RID p_rid) {
+}
+
+void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+}
+
+int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
+ return 0;
+}
+
+void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
+}
+
+void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
+}
+
+void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
+}
+
+void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
+}
+
+void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
+}
+
+RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
+ return RID();
+}
+
+AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const {
+ return AABB();
+}
+
+Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
+ return Transform3D();
+}
+
+Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
+ return Transform2D();
+}
+
+Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
+ return Color();
+}
+
+Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
+ return Color();
+}
+
+void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
+}
+
+Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
+ return Vector<float>();
+}
+
+void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
+}
+
+int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
+ return 0;
+}
+
+/* SKELETON API */
+
+RID MeshStorage::skeleton_allocate() {
+ return RID();
+}
+
+void MeshStorage::skeleton_initialize(RID p_rid) {
+}
+
+void MeshStorage::skeleton_free(RID p_rid) {
+}
+
+void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
+}
+
+void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
+}
+
+int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const {
+ return 0;
+}
+
+void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
+}
+
+Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
+ return Transform3D();
+}
+
+void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
+}
+
+Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
+ return Transform2D();
+}
+
+void MeshStorage::skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) {
+}
+
+#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
new file mode 100644
index 0000000000..3f44908049
--- /dev/null
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -0,0 +1,204 @@
+/*************************************************************************/
+/* mesh_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MESH_STORAGE_GLES3_H
+#define MESH_STORAGE_GLES3_H
+
+#ifdef GLES3_ENABLED
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/storage/mesh_storage.h"
+
+namespace GLES3 {
+
+class MeshStorage : public RendererMeshStorage {
+private:
+ static MeshStorage *singleton;
+
+public:
+ static MeshStorage *get_singleton();
+
+ MeshStorage();
+ virtual ~MeshStorage();
+
+ /* MESH API */
+
+ virtual RID mesh_allocate() override;
+ virtual void mesh_initialize(RID p_rid) override;
+ virtual void mesh_free(RID p_rid) override;
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override;
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override;
+
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override;
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const override;
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override;
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override;
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override;
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override;
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override;
+ virtual int mesh_get_surface_count(RID p_mesh) const override;
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const override;
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override;
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
+ virtual void mesh_clear(RID p_mesh) override;
+
+ /* MESH INSTANCE API */
+
+ virtual RID mesh_instance_create(RID p_base) override;
+ virtual void mesh_instance_free(RID p_rid) override;
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
+ virtual void update_mesh_instances() override;
+
+ /* MULTIMESH API */
+
+ struct MultiMesh {
+ RID mesh;
+ int instances = 0;
+ RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
+ bool uses_colors = false;
+ bool uses_custom_data = false;
+ int visible_instances = -1;
+ AABB aabb;
+ bool aabb_dirty = false;
+ bool buffer_set = false;
+ uint32_t stride_cache = 0;
+ uint32_t color_offset_cache = 0;
+ uint32_t custom_data_offset_cache = 0;
+
+ Vector<float> data_cache; //used if individual setting is used
+ bool *data_cache_dirty_regions = nullptr;
+ uint32_t data_cache_used_dirty_regions = 0;
+
+ RID buffer; //storage buffer
+ RID uniform_set_3d;
+ RID uniform_set_2d;
+
+ bool dirty = false;
+ MultiMesh *dirty_list = nullptr;
+
+ RendererStorage::Dependency dependency;
+ };
+
+ mutable RID_Owner<MultiMesh, true> multimesh_owner;
+
+ MultiMesh *multimesh_dirty_list = nullptr;
+
+ _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
+ _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
+ void _update_dirty_multimeshes();
+
+ virtual RID multimesh_allocate() override;
+ virtual void multimesh_initialize(RID p_rid) override;
+ virtual void multimesh_free(RID p_rid) override;
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
+ virtual int multimesh_get_instance_count(RID p_multimesh) const override;
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const override;
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override;
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const override;
+
+ _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->xform_format;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_colors;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_custom_data;
+ }
+
+ _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh->visible_instances >= 0) {
+ return multimesh->visible_instances;
+ }
+ return multimesh->instances;
+ }
+
+ /* SKELETON API */
+
+ virtual RID skeleton_allocate() override;
+ virtual void skeleton_initialize(RID p_rid) override;
+ virtual void skeleton_free(RID p_rid) override;
+
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override;
+ virtual int skeleton_get_bone_count(RID p_skeleton) const override;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
+
+ virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override;
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !MESH_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 8a921fbe10..7656cdf67e 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -93,7 +93,7 @@ enum OpenGLTextureFlags {
struct Texture {
RID self;
- Texture *proxy;
+ Texture *proxy = nullptr;
Set<Texture *> proxy_owners;
String path;
@@ -125,20 +125,20 @@ struct Texture {
uint16_t stored_cube_sides;
- RenderTarget *render_target;
+ RenderTarget *render_target = nullptr;
Vector<Ref<Image>> images;
bool redraw_if_visible;
RS::TextureDetectCallback detect_3d;
- void *detect_3d_ud;
+ void *detect_3d_ud = nullptr;
RS::TextureDetectCallback detect_srgb;
- void *detect_srgb_ud;
+ void *detect_srgb_ud = nullptr;
RS::TextureDetectCallback detect_normal;
- void *detect_normal_ud;
+ void *detect_normal_ud = nullptr;
CanvasTexture *canvas_texture = nullptr;
diff --git a/drivers/gles3/texture_loader_gles3.cpp b/drivers/gles3/texture_loader_gles3.cpp
index f8d4cfdc61..8c8724686d 100644
--- a/drivers/gles3/texture_loader_gles3.cpp
+++ b/drivers/gles3/texture_loader_gles3.cpp
@@ -52,7 +52,7 @@ RES ResourceFormatGLES2Texture::load(const String &p_path, const String &p_origi
uint8_t **row_p = memnew_arr(uint8_t *, height);
for (unsigned int i = 0; i < height; i++) {
- row_p[i] = 0; //No colors any more, I want them to turn black
+ row_p[i] = nullptr; // No colors any more, I want them to turn black.
}
memdelete_arr(row_p);
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index f90f55605c..b4dc012db2 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -41,7 +41,7 @@
#include <unistd.h>
class DirAccessUnix : public DirAccess {
- DIR *dir_stream;
+ DIR *dir_stream = nullptr;
static DirAccess *create_fs();
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 84ca7dbfc2..f7c2fcb88a 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -3364,8 +3364,14 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
attachment_last_pass.resize(p_attachments.size());
Vector<VkAttachmentDescription> attachments;
+ Vector<int> attachment_remap;
for (int i = 0; i < p_attachments.size(); i++) {
+ if (p_attachments[i].usage_flags == AttachmentFormat::UNUSED_ATTACHMENT) {
+ attachment_remap.push_back(VK_ATTACHMENT_UNUSED);
+ continue;
+ }
+
ERR_FAIL_INDEX_V(p_attachments[i].format, DATA_FORMAT_MAX, VK_NULL_HANDLE);
ERR_FAIL_INDEX_V(p_attachments[i].samples, TEXTURE_SAMPLES_MAX, VK_NULL_HANDLE);
ERR_FAIL_COND_V_MSG(!(p_attachments[i].usage_flags & (TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | TEXTURE_USAGE_INPUT_ATTACHMENT_BIT)),
@@ -3567,7 +3573,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
}
attachment_last_pass[i] = -1;
-
+ attachment_remap.push_back(attachments.size());
attachments.push_back(description);
}
@@ -3612,7 +3618,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
} else {
ERR_FAIL_COND_V_MSG(texture_samples != p_attachments[attachment].samples, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), if an attachment is marked as multisample, all of them should be multisample and use the same number of samples.");
}
- reference.attachment = attachment;
+ reference.attachment = attachment_remap[attachment];
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
attachment_last_pass[attachment] = i;
}
@@ -3631,7 +3637,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), input attachment (" + itos(j) + ").");
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_INPUT_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it isn't marked as an input texture.");
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
- reference.attachment = attachment;
+ reference.attachment = attachment_remap[attachment];
reference.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
attachment_last_pass[attachment] = i;
}
@@ -3657,7 +3663,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
bool multisample = p_attachments[attachment].samples > TEXTURE_SAMPLES_1;
ERR_FAIL_COND_V_MSG(multisample, VK_NULL_HANDLE, "Invalid framebuffer format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), resolve attachments can't be multisample.");
- reference.attachment = attachment;
+ reference.attachment = attachment_remap[attachment];
reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
attachment_last_pass[attachment] = i;
}
@@ -3671,7 +3677,7 @@ VkRenderPass RenderingDeviceVulkan::_render_pass_create(const Vector<AttachmentF
ERR_FAIL_INDEX_V_MSG(attachment, p_attachments.size(), VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), depth attachment.");
ERR_FAIL_COND_V_MSG(!(p_attachments[attachment].usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT), VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it's marked as depth, but it's not a depth attachment.");
ERR_FAIL_COND_V_MSG(attachment_last_pass[attachment] == i, VK_NULL_HANDLE, "Invalid framebuffer depth format attachment(" + itos(attachment) + "), in pass (" + itos(i) + "), it already was used for something else before in this pass.");
- depth_stencil_reference.attachment = attachment;
+ depth_stencil_reference.attachment = attachment_remap[attachment];
depth_stencil_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachment_last_pass[attachment] = i;
@@ -3958,14 +3964,13 @@ RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attac
for (int i = 0; i < p_texture_attachments.size(); i++) {
Texture *texture = texture_owner.get_or_null(p_texture_attachments[i]);
- ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture index supplied for framebuffer (" + itos(i) + ") is not a valid texture.");
- ERR_FAIL_COND_V_MSG(texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer");
+ ERR_FAIL_COND_V_MSG(texture && texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer");
- if (texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ if (texture && texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
pass.depth_attachment = i;
} else {
- pass.color_attachments.push_back(i);
+ pass.color_attachments.push_back(texture ? i : FramebufferPass::ATTACHMENT_UNUSED);
}
}
@@ -3979,29 +3984,35 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
_THREAD_SAFE_METHOD_
Vector<AttachmentFormat> attachments;
+ attachments.resize(p_texture_attachments.size());
Size2i size;
-
+ bool size_set = false;
for (int i = 0; i < p_texture_attachments.size(); i++) {
+ AttachmentFormat af;
Texture *texture = texture_owner.get_or_null(p_texture_attachments[i]);
- ERR_FAIL_COND_V_MSG(!texture, RID(), "Texture index supplied for framebuffer (" + itos(i) + ") is not a valid texture.");
+ if (!texture) {
+ af.usage_flags = AttachmentFormat::UNUSED_ATTACHMENT;
+ } else {
+ ERR_FAIL_COND_V_MSG(texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer");
- ERR_FAIL_COND_V_MSG(texture->layers != p_view_count, RID(), "Layers of our texture doesn't match view count for this framebuffer");
+ if (!size_set) {
+ size.width = texture->width;
+ size.height = texture->height;
+ size_set = true;
+ } else {
+ ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(),
+ "All textures in a framebuffer should be the same size.");
+ }
- if (i == 0) {
- size.width = texture->width;
- size.height = texture->height;
- } else {
- ERR_FAIL_COND_V_MSG((uint32_t)size.width != texture->width || (uint32_t)size.height != texture->height, RID(),
- "All textures in a framebuffer should be the same size.");
+ af.format = texture->format;
+ af.samples = texture->samples;
+ af.usage_flags = texture->usage_flags;
}
-
- AttachmentFormat af;
- af.format = texture->format;
- af.samples = texture->samples;
- af.usage_flags = texture->usage_flags;
- attachments.push_back(af);
+ attachments.write[i] = af;
}
+ ERR_FAIL_COND_V_MSG(!size_set, RID(), "All attachments unused.");
+
FramebufferFormatID format_id = framebuffer_format_create_multipass(attachments, p_passes, p_view_count);
if (format_id == INVALID_ID) {
return RID();
@@ -4019,7 +4030,9 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
RID id = framebuffer_owner.make_rid(framebuffer);
for (int i = 0; i < p_texture_attachments.size(); i++) {
- _add_dependency(id, p_texture_attachments[i]);
+ if (p_texture_attachments[i].is_valid()) {
+ _add_dependency(id, p_texture_attachments[i]);
+ }
}
return id;
@@ -6417,49 +6430,55 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
Vector<VkPipelineColorBlendAttachmentState> attachment_states;
{
const FramebufferPass &pass = fb_format.E->key().passes[p_for_render_pass];
-
+ attachment_states.resize(pass.color_attachments.size());
+ ERR_FAIL_COND_V(p_blend_state.attachments.size() < pass.color_attachments.size(), RID());
for (int i = 0; i < pass.color_attachments.size(); i++) {
- if (pass.color_attachments[i] != FramebufferPass::ATTACHMENT_UNUSED) {
- int idx = attachment_states.size();
-
- ERR_FAIL_INDEX_V(idx, p_blend_state.attachments.size(), RID());
- VkPipelineColorBlendAttachmentState state;
- state.blendEnable = p_blend_state.attachments[idx].enable_blend;
-
- ERR_FAIL_INDEX_V(p_blend_state.attachments[idx].src_color_blend_factor, BLEND_FACTOR_MAX, RID());
- state.srcColorBlendFactor = blend_factors[p_blend_state.attachments[idx].src_color_blend_factor];
- ERR_FAIL_INDEX_V(p_blend_state.attachments[idx].dst_color_blend_factor, BLEND_FACTOR_MAX, RID());
- state.dstColorBlendFactor = blend_factors[p_blend_state.attachments[idx].dst_color_blend_factor];
- ERR_FAIL_INDEX_V(p_blend_state.attachments[idx].color_blend_op, BLEND_OP_MAX, RID());
- state.colorBlendOp = blend_operations[p_blend_state.attachments[idx].color_blend_op];
-
- ERR_FAIL_INDEX_V(p_blend_state.attachments[idx].src_alpha_blend_factor, BLEND_FACTOR_MAX, RID());
- state.srcAlphaBlendFactor = blend_factors[p_blend_state.attachments[idx].src_alpha_blend_factor];
- ERR_FAIL_INDEX_V(p_blend_state.attachments[idx].dst_alpha_blend_factor, BLEND_FACTOR_MAX, RID());
- state.dstAlphaBlendFactor = blend_factors[p_blend_state.attachments[idx].dst_alpha_blend_factor];
- ERR_FAIL_INDEX_V(p_blend_state.attachments[idx].alpha_blend_op, BLEND_OP_MAX, RID());
- state.alphaBlendOp = blend_operations[p_blend_state.attachments[idx].alpha_blend_op];
+ VkPipelineColorBlendAttachmentState state;
+ if (pass.color_attachments[i] == FramebufferPass::ATTACHMENT_UNUSED) {
+ state.blendEnable = false;
+
+ state.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
+ state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
+ state.colorBlendOp = VK_BLEND_OP_ADD;
+
+ state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
+ state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
+ state.alphaBlendOp = VK_BLEND_OP_ADD;
+
+ state.colorWriteMask = 0;
+ } else {
+ state.blendEnable = p_blend_state.attachments[i].enable_blend;
+
+ ERR_FAIL_INDEX_V(p_blend_state.attachments[i].src_color_blend_factor, BLEND_FACTOR_MAX, RID());
+ state.srcColorBlendFactor = blend_factors[p_blend_state.attachments[i].src_color_blend_factor];
+ ERR_FAIL_INDEX_V(p_blend_state.attachments[i].dst_color_blend_factor, BLEND_FACTOR_MAX, RID());
+ state.dstColorBlendFactor = blend_factors[p_blend_state.attachments[i].dst_color_blend_factor];
+ ERR_FAIL_INDEX_V(p_blend_state.attachments[i].color_blend_op, BLEND_OP_MAX, RID());
+ state.colorBlendOp = blend_operations[p_blend_state.attachments[i].color_blend_op];
+
+ ERR_FAIL_INDEX_V(p_blend_state.attachments[i].src_alpha_blend_factor, BLEND_FACTOR_MAX, RID());
+ state.srcAlphaBlendFactor = blend_factors[p_blend_state.attachments[i].src_alpha_blend_factor];
+ ERR_FAIL_INDEX_V(p_blend_state.attachments[i].dst_alpha_blend_factor, BLEND_FACTOR_MAX, RID());
+ state.dstAlphaBlendFactor = blend_factors[p_blend_state.attachments[i].dst_alpha_blend_factor];
+ ERR_FAIL_INDEX_V(p_blend_state.attachments[i].alpha_blend_op, BLEND_OP_MAX, RID());
+ state.alphaBlendOp = blend_operations[p_blend_state.attachments[i].alpha_blend_op];
state.colorWriteMask = 0;
- if (p_blend_state.attachments[idx].write_r) {
+ if (p_blend_state.attachments[i].write_r) {
state.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
}
- if (p_blend_state.attachments[idx].write_g) {
+ if (p_blend_state.attachments[i].write_g) {
state.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
}
- if (p_blend_state.attachments[idx].write_b) {
+ if (p_blend_state.attachments[i].write_b) {
state.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
}
- if (p_blend_state.attachments[idx].write_a) {
+ if (p_blend_state.attachments[i].write_a) {
state.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
}
-
- attachment_states.push_back(state);
- idx++;
}
+ attachment_states.write[i] = state;
}
-
- ERR_FAIL_COND_V(attachment_states.size() != p_blend_state.attachments.size(), RID());
}
color_blend_state_create_info.attachmentCount = attachment_states.size();
@@ -6863,10 +6882,11 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu
Vector<VkImageView> attachments;
for (int i = 0; i < p_framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.get_or_null(p_framebuffer->texture_ids[i]);
- ERR_FAIL_COND_V(!texture, ERR_BUG);
- attachments.push_back(texture->view);
- ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG);
- ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG);
+ if (texture) {
+ attachments.push_back(texture->view);
+ ERR_FAIL_COND_V(texture->width != p_framebuffer->size.width, ERR_BUG);
+ ERR_FAIL_COND_V(texture->height != p_framebuffer->size.height, ERR_BUG);
+ }
}
framebuffer_create_info.attachmentCount = attachments.size();
framebuffer_create_info.pAttachments = attachments.ptr();
@@ -6910,13 +6930,18 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
Vector<VkClearValue> clear_values;
clear_values.resize(framebuffer->texture_ids.size());
-
+ int clear_values_count = 0;
{
int color_index = 0;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
- Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
VkClearValue clear_value;
+ Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
+ if (!texture) {
+ color_index++;
+ continue;
+ }
+
if (color_index < p_clear_colors.size() && texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
ERR_FAIL_INDEX_V(color_index, p_clear_colors.size(), ERR_BUG); //a bug
Color clear_color = p_clear_colors[color_index];
@@ -6934,15 +6959,18 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
clear_value.color.float32[2] = 0;
clear_value.color.float32[3] = 0;
}
- clear_values.write[i] = clear_value;
+ clear_values.write[clear_values_count++] = clear_value;
}
}
- render_pass_begin.clearValueCount = clear_values.size();
+ render_pass_begin.clearValueCount = clear_values_count;
render_pass_begin.pClearValues = clear_values.ptr();
for (int i = 0; i < p_storage_textures.size(); i++) {
Texture *texture = texture_owner.get_or_null(p_storage_textures[i]);
+ if (!texture) {
+ continue;
+ }
ERR_CONTINUE_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), "Supplied storage texture " + itos(i) + " for draw list is not set to be used for storage.");
if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) {
@@ -6981,6 +7009,9 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
+ if (!texture) {
+ continue;
+ }
texture->bound = true;
draw_list_bound_textures.push_back(framebuffer->texture_ids[i]);
}
@@ -6989,15 +7020,21 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff
}
void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil) {
+ ERR_FAIL_COND_MSG(p_clear_color && p_clear_colors.size() != framebuffer->texture_ids.size(), "Clear color values supplied (" + itos(p_clear_colors.size()) + ") differ from the amount required for framebuffer color attachments (" + itos(framebuffer->texture_ids.size()) + ").");
Vector<VkClearAttachment> clear_attachments;
int color_index = 0;
+ int texture_index = 0;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
- VkClearAttachment clear_at = {};
+ if (!texture) {
+ texture_index++;
+ continue;
+ }
+
+ VkClearAttachment clear_at = {};
if (p_clear_color && texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
- ERR_FAIL_INDEX(color_index, p_clear_colors.size()); //a bug
- Color clear_color = p_clear_colors[color_index];
+ Color clear_color = p_clear_colors[texture_index++];
clear_at.clearValue.color.float32[0] = clear_color.r;
clear_at.clearValue.color.float32[1] = clear_color.g;
clear_at.clearValue.color.float32[2] = clear_color.b;
@@ -7073,18 +7110,14 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu
}
if (p_initial_color_action == INITIAL_ACTION_CLEAR) { //check clear values
-
int color_count = 0;
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
-
- if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ if (!texture || !(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
color_count++;
}
}
-
- ERR_FAIL_COND_V_MSG(p_clear_color_values.size() != color_count, INVALID_ID,
- "Clear color values supplied (" + itos(p_clear_color_values.size()) + ") differ from the amount required for framebuffer color attachments (" + itos(color_count) + ").");
+ ERR_FAIL_COND_V_MSG(p_clear_color_values.size() != color_count, INVALID_ID, "Clear color values supplied (" + itos(p_clear_color_values.size()) + ") differ from the amount required for framebuffer color attachments (" + itos(color_count) + ").");
}
VkFramebuffer vkframebuffer;
@@ -7176,7 +7209,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p
for (int i = 0; i < framebuffer->texture_ids.size(); i++) {
Texture *texture = texture_owner.get_or_null(framebuffer->texture_ids[i]);
- if (texture->usage_flags & TEXTURE_USAGE_COLOR_ATTACHMENT_BIT) {
+ if (!texture || !(texture->usage_flags & TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
color_count++;
}
}
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index 34c70c942e..e96139e070 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -63,24 +63,24 @@ private:
Ref<InputEvent> event = Ref<InputEvent>();
- TabContainer *tab_container;
+ TabContainer *tab_container = nullptr;
// Listening for input
- Label *event_as_text;
- ColorRect *mouse_detection_rect;
+ Label *event_as_text = nullptr;
+ ColorRect *mouse_detection_rect = nullptr;
// List of All Key/Mouse/Joypad input options.
int allowed_input_types;
- Tree *input_list_tree;
- LineEdit *input_list_search;
+ Tree *input_list_tree = nullptr;
+ LineEdit *input_list_search = nullptr;
// Additional Options, shown depending on event selected
- VBoxContainer *additional_options_container;
+ VBoxContainer *additional_options_container = nullptr;
- HBoxContainer *device_container;
- OptionButton *device_id_option;
+ HBoxContainer *device_container = nullptr;
+ OptionButton *device_id_option = nullptr;
- HBoxContainer *mod_container; // Contains the subcontainer and the store command checkbox.
+ HBoxContainer *mod_container = nullptr; // Contains the subcontainer and the store command checkbox.
enum ModCheckbox {
MOD_ALT,
@@ -93,9 +93,9 @@ private:
String mods[MOD_MAX] = { "Alt", "Shift", "Command", "Ctrl", "Metakey" };
CheckBox *mod_checkboxes[MOD_MAX];
- CheckBox *store_command_checkbox;
+ CheckBox *store_command_checkbox = nullptr;
- CheckBox *physical_key_checkbox;
+ CheckBox *physical_key_checkbox = nullptr;
void _set_event(const Ref<InputEvent> &p_event);
@@ -149,7 +149,7 @@ private:
};
Vector<ActionInfo> actions_cache;
- Tree *action_tree;
+ Tree *action_tree = nullptr;
// Storing which action/event is currently being edited in the InputEventConfigurationDialog.
@@ -159,17 +159,17 @@ private:
// Popups
- InputEventConfigurationDialog *event_config_dialog;
- AcceptDialog *message;
+ InputEventConfigurationDialog *event_config_dialog = nullptr;
+ AcceptDialog *message = nullptr;
// Filtering and Adding actions
bool show_builtin_actions = false;
- CheckButton *show_builtin_actions_checkbutton;
- LineEdit *action_list_search;
+ CheckButton *show_builtin_actions_checkbutton = nullptr;
+ LineEdit *action_list_search = nullptr;
- HBoxContainer *add_hbox;
- LineEdit *add_edit;
+ HBoxContainer *add_hbox = nullptr;
+ LineEdit *add_edit = nullptr;
void _event_config_confirmed();
diff --git a/editor/animation_bezier_editor.h b/editor/animation_bezier_editor.h
index fa6fc405f2..dcb6502440 100644
--- a/editor/animation_bezier_editor.h
+++ b/editor/animation_bezier_editor.h
@@ -49,7 +49,7 @@ class AnimationBezierTrackEdit : public Control {
AnimationTimelineEdit *timeline = nullptr;
UndoRedo *undo_redo = nullptr;
Node *root = nullptr;
- Control *play_position; //separate control used to draw so updates for only position changed are much faster
+ Control *play_position = nullptr; //separate control used to draw so updates for only position changed are much faster
float play_position_pos = 0;
Ref<Animation> animation;
@@ -130,7 +130,7 @@ class AnimationBezierTrackEdit : public Control {
float transition = 0;
};
- AnimationTrackEditor *editor;
+ AnimationTrackEditor *editor = nullptr;
struct EditPoint {
Rect2 point_rect;
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index 1baebc469e..d025dd3d26 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -54,27 +54,27 @@ class AnimationTimelineEdit : public Range {
GDCLASS(AnimationTimelineEdit, Range);
Ref<Animation> animation;
- AnimationTrackEdit *track_edit;
+ AnimationTrackEdit *track_edit = nullptr;
int name_limit;
- Range *zoom;
- Range *h_scroll;
+ Range *zoom = nullptr;
+ Range *h_scroll = nullptr;
float play_position_pos;
- HBoxContainer *len_hb;
- EditorSpinSlider *length;
- Button *loop;
- TextureRect *time_icon;
+ HBoxContainer *len_hb = nullptr;
+ EditorSpinSlider *length = nullptr;
+ Button *loop = nullptr;
+ TextureRect *time_icon = nullptr;
- MenuButton *add_track;
- Control *play_position; //separate control used to draw so updates for only position changed are much faster
- HScrollBar *hscroll;
+ MenuButton *add_track = nullptr;
+ Control *play_position = nullptr; //separate control used to draw so updates for only position changed are much faster
+ HScrollBar *hscroll = nullptr;
void _zoom_changed(double);
void _anim_length_changed(double p_new_len);
void _anim_loop_pressed();
void _play_position_draw();
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
Rect2 hsize_rect;
bool editing = false;
@@ -146,12 +146,12 @@ class AnimationTrackEdit : public Control {
MENU_KEY_ADD_RESET,
MENU_KEY_DELETE
};
- AnimationTimelineEdit *timeline;
- UndoRedo *undo_redo;
- Popup *path_popup;
- LineEdit *path;
- Node *root;
- Control *play_position; //separate control used to draw so updates for only position changed are much faster
+ AnimationTimelineEdit *timeline = nullptr;
+ UndoRedo *undo_redo = nullptr;
+ Popup *path_popup = nullptr;
+ LineEdit *path = nullptr;
+ Node *root = nullptr;
+ Control *play_position = nullptr; //separate control used to draw so updates for only position changed are much faster
float play_position_pos;
NodePath node_path;
@@ -169,7 +169,7 @@ class AnimationTrackEdit : public Control {
Ref<Texture2D> type_icon;
Ref<Texture2D> selected_icon;
- PopupMenu *menu;
+ PopupMenu *menu = nullptr;
bool clicking_on_name = false;
@@ -194,7 +194,7 @@ class AnimationTrackEdit : public Control {
float moving_selection_from_ofs;
bool in_group = false;
- AnimationTrackEditor *editor;
+ AnimationTrackEditor *editor = nullptr;
protected:
static void _bind_methods();
@@ -285,27 +285,27 @@ class AnimationTrackEditor : public VBoxContainer {
GDCLASS(AnimationTrackEditor, VBoxContainer);
Ref<Animation> animation;
- Node *root;
-
- MenuButton *edit;
+ Node *root = nullptr;
- PanelContainer *main_panel;
- HScrollBar *hscroll;
- ScrollContainer *scroll;
- VBoxContainer *track_vbox;
- AnimationBezierTrackEdit *bezier_edit;
+ MenuButton *edit = nullptr;
- Label *info_message;
+ PanelContainer *main_panel = nullptr;
+ HScrollBar *hscroll = nullptr;
+ ScrollContainer *scroll = nullptr;
+ VBoxContainer *track_vbox = nullptr;
+ AnimationBezierTrackEdit *bezier_edit = nullptr;
- AnimationTimelineEdit *timeline;
- HSlider *zoom;
- EditorSpinSlider *step;
- TextureRect *zoom_icon;
- Button *snap;
- Button *bezier_edit_icon;
- OptionButton *snap_mode;
+ Label *info_message = nullptr;
- Button *imported_anim_warning;
+ AnimationTimelineEdit *timeline = nullptr;
+ HSlider *zoom = nullptr;
+ EditorSpinSlider *step = nullptr;
+ TextureRect *zoom_icon = nullptr;
+ Button *snap = nullptr;
+ Button *bezier_edit_icon = nullptr;
+ OptionButton *snap_mode = nullptr;
+
+ Button *imported_anim_warning = nullptr;
void _show_imported_anim_warning();
void _snap_mode_changed(int p_mode);
@@ -323,7 +323,7 @@ class AnimationTrackEditor : public VBoxContainer {
void _track_remove_request(int p_track);
void _track_grab_focus(int p_track);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
void _update_scroll(double);
void _update_step(double p_new_step);
@@ -336,9 +336,9 @@ class AnimationTrackEditor : public VBoxContainer {
void _update_step_spinbox();
- PropertySelector *prop_selector;
- PropertySelector *method_selector;
- SceneTreeDialog *pick_track;
+ PropertySelector *prop_selector = nullptr;
+ PropertySelector *method_selector = nullptr;
+ SceneTreeDialog *pick_track = nullptr;
int adding_track_type;
NodePath adding_track_path;
@@ -353,10 +353,10 @@ class AnimationTrackEditor : public VBoxContainer {
bool advance = false;
}; /* insert_data;*/
- Label *insert_confirm_text;
- CheckBox *insert_confirm_bezier;
- CheckBox *insert_confirm_reset;
- ConfirmationDialog *insert_confirm;
+ Label *insert_confirm_text = nullptr;
+ CheckBox *insert_confirm_bezier = nullptr;
+ CheckBox *insert_confirm_reset = nullptr;
+ ConfirmationDialog *insert_confirm = nullptr;
bool insert_queue = false;
List<InsertData> insert_data;
@@ -419,13 +419,13 @@ class AnimationTrackEditor : public VBoxContainer {
void _move_selection_commit();
void _move_selection_cancel();
- AnimationTrackKeyEdit *key_edit;
- AnimationMultiTrackKeyEdit *multi_key_edit;
+ AnimationTrackKeyEdit *key_edit = nullptr;
+ AnimationMultiTrackKeyEdit *multi_key_edit = nullptr;
void _update_key_edit();
void _clear_key_edit();
- Control *box_selection;
+ Control *box_selection = nullptr;
void _box_selection_draw();
bool box_selecting = false;
Vector2 box_selecting_from;
@@ -440,18 +440,18 @@ class AnimationTrackEditor : public VBoxContainer {
////////////// edit menu stuff
- ConfirmationDialog *optimize_dialog;
- SpinBox *optimize_linear_error;
- SpinBox *optimize_angular_error;
- SpinBox *optimize_max_angle;
+ ConfirmationDialog *optimize_dialog = nullptr;
+ SpinBox *optimize_linear_error = nullptr;
+ SpinBox *optimize_angular_error = nullptr;
+ SpinBox *optimize_max_angle = nullptr;
- ConfirmationDialog *cleanup_dialog;
- CheckBox *cleanup_keys;
- CheckBox *cleanup_tracks;
- CheckBox *cleanup_all;
+ ConfirmationDialog *cleanup_dialog = nullptr;
+ CheckBox *cleanup_keys = nullptr;
+ CheckBox *cleanup_tracks = nullptr;
+ CheckBox *cleanup_all = nullptr;
- ConfirmationDialog *scale_dialog;
- SpinBox *scale;
+ ConfirmationDialog *scale_dialog = nullptr;
+ SpinBox *scale = nullptr;
void _select_all_tracks_for_copy();
@@ -464,13 +464,13 @@ class AnimationTrackEditor : public VBoxContainer {
void _anim_duplicate_keys(bool transpose);
void _view_group_toggle();
- Button *view_group;
- Button *selected_filter;
+ Button *view_group = nullptr;
+ Button *selected_filter = nullptr;
void _selection_changed();
- ConfirmationDialog *track_copy_dialog;
- Tree *track_copy_select;
+ ConfirmationDialog *track_copy_dialog = nullptr;
+ Tree *track_copy_select = nullptr;
struct TrackClipboard {
NodePath full_path;
diff --git a/editor/code_editor.h b/editor/code_editor.h
index bbc45d6ec0..d52f57860c 100644
--- a/editor/code_editor.h
+++ b/editor/code_editor.h
@@ -43,10 +43,10 @@
class GotoLineDialog : public ConfirmationDialog {
GDCLASS(GotoLineDialog, ConfirmationDialog);
- Label *line_label;
- LineEdit *line;
+ Label *line_label = nullptr;
+ LineEdit *line = nullptr;
- CodeEdit *text_editor;
+ CodeEdit *text_editor = nullptr;
virtual void ok_pressed() override;
@@ -62,25 +62,25 @@ class CodeTextEditor;
class FindReplaceBar : public HBoxContainer {
GDCLASS(FindReplaceBar, HBoxContainer);
- LineEdit *search_text;
- Label *matches_label;
- Button *find_prev;
- Button *find_next;
- CheckBox *case_sensitive;
- CheckBox *whole_words;
- TextureButton *hide_button;
+ LineEdit *search_text = nullptr;
+ Label *matches_label = nullptr;
+ Button *find_prev = nullptr;
+ Button *find_next = nullptr;
+ CheckBox *case_sensitive = nullptr;
+ CheckBox *whole_words = nullptr;
+ TextureButton *hide_button = nullptr;
- LineEdit *replace_text;
- Button *replace;
- Button *replace_all;
- CheckBox *selection_only;
+ LineEdit *replace_text = nullptr;
+ Button *replace = nullptr;
+ Button *replace_all = nullptr;
+ CheckBox *selection_only = nullptr;
- VBoxContainer *vbc_lineedit;
- HBoxContainer *hbc_button_replace;
- HBoxContainer *hbc_option_replace;
+ VBoxContainer *vbc_lineedit = nullptr;
+ HBoxContainer *hbc_button_replace = nullptr;
+ HBoxContainer *hbc_option_replace = nullptr;
CodeTextEditor *base_text_editor = nullptr;
- CodeEdit *text_editor;
+ CodeEdit *text_editor = nullptr;
int result_line;
int result_col;
@@ -139,25 +139,25 @@ typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code,
class CodeTextEditor : public VBoxContainer {
GDCLASS(CodeTextEditor, VBoxContainer);
- CodeEdit *text_editor;
+ CodeEdit *text_editor = nullptr;
FindReplaceBar *find_replace_bar = nullptr;
- HBoxContainer *status_bar;
+ HBoxContainer *status_bar = nullptr;
- Button *toggle_scripts_button;
- Button *error_button;
- Button *warning_button;
+ Button *toggle_scripts_button = nullptr;
+ Button *error_button = nullptr;
+ Button *warning_button = nullptr;
- Label *line_and_col_txt;
+ Label *line_and_col_txt = nullptr;
- Label *info;
- Timer *idle;
- Timer *code_complete_timer;
+ Label *info = nullptr;
+ Timer *idle = nullptr;
+ Timer *code_complete_timer = nullptr;
- Timer *font_resize_timer;
+ Timer *font_resize_timer = nullptr;
int font_resize_val;
real_t font_size;
- Label *error;
+ Label *error = nullptr;
int error_line;
int error_column;
@@ -181,7 +181,7 @@ class CodeTextEditor : public VBoxContainer {
Color completion_string_color;
Color completion_comment_color;
CodeTextEditorCodeCompleteFunc code_complete_func;
- void *code_complete_ud;
+ void *code_complete_ud = nullptr;
void _error_button_pressed();
void _warning_button_pressed();
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 58c584b8b2..4b1b8363dd 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -105,27 +105,27 @@ public:
};
private:
- Label *connect_to_label;
- LineEdit *from_signal;
- Node *source;
+ Label *connect_to_label = nullptr;
+ LineEdit *from_signal = nullptr;
+ Node *source = nullptr;
StringName signal;
- LineEdit *dst_method;
- ConnectDialogBinds *cdbinds;
+ LineEdit *dst_method = nullptr;
+ ConnectDialogBinds *cdbinds = nullptr;
bool edit_mode;
NodePath dst_path;
- VBoxContainer *vbc_right;
-
- SceneTreeEditor *tree;
- AcceptDialog *error;
- SpinBox *unbind_count;
- EditorInspector *bind_editor;
- OptionButton *type_list;
- CheckBox *deferred;
- CheckBox *oneshot;
- CheckButton *advanced;
+ VBoxContainer *vbc_right = nullptr;
+
+ SceneTreeEditor *tree = nullptr;
+ AcceptDialog *error = nullptr;
+ SpinBox *unbind_count = nullptr;
+ EditorInspector *bind_editor = nullptr;
+ OptionButton *type_list = nullptr;
+ CheckBox *deferred = nullptr;
+ CheckBox *oneshot = nullptr;
+ CheckButton *advanced = nullptr;
Vector<Control *> bind_controls;
- Label *error_label;
+ Label *error_label = nullptr;
void ok_pressed() override;
void _cancel_pressed();
@@ -186,16 +186,16 @@ class ConnectionsDock : public VBoxContainer {
DISCONNECT
};
- Node *selected_node;
- ConnectionsDockTree *tree;
+ Node *selected_node = nullptr;
+ ConnectionsDockTree *tree = nullptr;
- ConfirmationDialog *disconnect_all_dialog;
- ConnectDialog *connect_dialog;
- Button *connect_button;
- PopupMenu *signal_menu;
- PopupMenu *slot_menu;
- UndoRedo *undo_redo;
- LineEdit *search_box;
+ ConfirmationDialog *disconnect_all_dialog = nullptr;
+ ConnectDialog *connect_dialog = nullptr;
+ Button *connect_button = nullptr;
+ PopupMenu *signal_menu = nullptr;
+ PopupMenu *slot_menu = nullptr;
+ UndoRedo *undo_redo = nullptr;
+ LineEdit *search_box = nullptr;
Map<StringName, Map<StringName, String>> descr_cache;
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index fe7c89c059..31761be6fe 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -47,18 +47,18 @@ class CreateDialog : public ConfirmationDialog {
OTHER_TYPE
};
- LineEdit *search_box;
- Tree *search_options;
+ LineEdit *search_box = nullptr;
+ Tree *search_options = nullptr;
String base_type;
String icon_fallback;
String preferred_search_result_type;
- Button *favorite;
+ Button *favorite = nullptr;
Vector<String> favorite_list;
- Tree *favorites;
- ItemList *recent;
- EditorHelpBit *help_bit;
+ Tree *favorites = nullptr;
+ ItemList *recent = nullptr;
+ EditorHelpBit *help_bit = nullptr;
HashMap<String, TreeItem *> search_options_types;
HashMap<String, String> custom_type_parents;
diff --git a/editor/debugger/debug_adapter/debug_adapter_protocol.h b/editor/debugger/debug_adapter/debug_adapter_protocol.h
index b54a5f1f3f..e4760bea54 100644
--- a/editor/debugger/debug_adapter/debug_adapter_protocol.h
+++ b/editor/debugger/debug_adapter/debug_adapter_protocol.h
@@ -76,7 +76,7 @@ class DebugAdapterProtocol : public Object {
private:
static DebugAdapterProtocol *singleton;
- DebugAdapterParser *parser;
+ DebugAdapterParser *parser = nullptr;
List<Ref<DAPeer>> clients;
Ref<TCPServer> server;
diff --git a/editor/debugger/editor_debugger_inspector.h b/editor/debugger/editor_debugger_inspector.h
index 5cdc4417d0..8f523bfbdc 100644
--- a/editor/debugger/editor_debugger_inspector.h
+++ b/editor/debugger/editor_debugger_inspector.h
@@ -70,7 +70,7 @@ private:
ObjectID inspected_object_id;
Map<ObjectID, EditorDebuggerRemoteObject *> remote_objects;
Set<RES> remote_dependencies;
- EditorDebuggerRemoteObject *variables;
+ EditorDebuggerRemoteObject *variables = nullptr;
void _object_selected(ObjectID p_object);
void _object_edited(ObjectID p_id, const String &p_prop, const Variant &p_value);
diff --git a/editor/debugger/editor_network_profiler.h b/editor/debugger/editor_network_profiler.h
index 3e95eb0de6..3a604f5564 100644
--- a/editor/debugger/editor_network_profiler.h
+++ b/editor/debugger/editor_network_profiler.h
@@ -42,13 +42,13 @@ class EditorNetworkProfiler : public VBoxContainer {
GDCLASS(EditorNetworkProfiler, VBoxContainer)
private:
- Button *activate;
- Button *clear_button;
- Tree *counters_display;
- LineEdit *incoming_bandwidth_text;
- LineEdit *outgoing_bandwidth_text;
+ Button *activate = nullptr;
+ Button *clear_button = nullptr;
+ Tree *counters_display = nullptr;
+ LineEdit *incoming_bandwidth_text = nullptr;
+ LineEdit *outgoing_bandwidth_text = nullptr;
- Timer *frame_delay;
+ Timer *frame_delay = nullptr;
Map<ObjectID, SceneDebugger::RPCNodeInfo> nodes_data;
diff --git a/editor/debugger/editor_performance_profiler.h b/editor/debugger/editor_performance_profiler.h
index 998ecc5bb6..a917ddbe28 100644
--- a/editor/debugger/editor_performance_profiler.h
+++ b/editor/debugger/editor_performance_profiler.h
@@ -62,9 +62,9 @@ private:
OrderedHashMap<StringName, Monitor> monitors;
Map<StringName, TreeItem *> base_map;
- Tree *monitor_tree;
- Control *monitor_draw;
- Label *info_message;
+ Tree *monitor_tree = nullptr;
+ Control *monitor_draw = nullptr;
+ Label *info_message = nullptr;
StringName marker_key;
int marker_frame;
const int MARGIN = 4;
diff --git a/editor/debugger/editor_profiler.h b/editor/debugger/editor_profiler.h
index 45f7ac39c1..34f34be7c3 100644
--- a/editor/debugger/editor_profiler.h
+++ b/editor/debugger/editor_profiler.h
@@ -90,20 +90,20 @@ public:
};
private:
- Button *activate;
- Button *clear_button;
- TextureRect *graph;
+ Button *activate = nullptr;
+ Button *clear_button = nullptr;
+ TextureRect *graph = nullptr;
Ref<ImageTexture> graph_texture;
Vector<uint8_t> graph_image;
- Tree *variables;
- HSplitContainer *h_split;
+ Tree *variables = nullptr;
+ HSplitContainer *h_split = nullptr;
Set<StringName> plot_sigs;
- OptionButton *display_mode;
- OptionButton *display_time;
+ OptionButton *display_mode = nullptr;
+ OptionButton *display_time = nullptr;
- SpinBox *cursor_metric_edit;
+ SpinBox *cursor_metric_edit = nullptr;
Vector<Metric> frame_metrics;
int total_metrics;
@@ -119,8 +119,8 @@ private:
bool seeking;
- Timer *frame_delay;
- Timer *plot_delay;
+ Timer *frame_delay = nullptr;
+ Timer *plot_delay = nullptr;
void _update_frame();
diff --git a/editor/debugger/editor_visual_profiler.h b/editor/debugger/editor_visual_profiler.h
index 55ba725ae8..14eacca02d 100644
--- a/editor/debugger/editor_visual_profiler.h
+++ b/editor/debugger/editor_visual_profiler.h
@@ -67,20 +67,20 @@ public:
};
private:
- Button *activate;
- Button *clear_button;
+ Button *activate = nullptr;
+ Button *clear_button = nullptr;
- TextureRect *graph;
+ TextureRect *graph = nullptr;
Ref<ImageTexture> graph_texture;
Vector<uint8_t> graph_image;
- Tree *variables;
- HSplitContainer *h_split;
- CheckBox *frame_relative;
- CheckBox *linked;
+ Tree *variables = nullptr;
+ HSplitContainer *h_split = nullptr;
+ CheckBox *frame_relative = nullptr;
+ CheckBox *linked = nullptr;
- OptionButton *display_mode;
+ OptionButton *display_mode = nullptr;
- SpinBox *cursor_metric_edit;
+ SpinBox *cursor_metric_edit = nullptr;
Vector<Metric> frame_metrics;
int last_metric;
@@ -99,8 +99,8 @@ private:
bool seeking;
- Timer *frame_delay;
- Timer *plot_delay;
+ Timer *frame_delay = nullptr;
+ Timer *plot_delay = nullptr;
void _update_frame(bool p_focus_selected = false);
diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h
index 486ac26ef7..ad90e63c16 100644
--- a/editor/debugger/script_editor_debugger.h
+++ b/editor/debugger/script_editor_debugger.h
@@ -85,26 +85,26 @@ private:
ACTION_DELETE_ALL_BREAKPOINTS,
};
- AcceptDialog *msgdialog;
-
- LineEdit *clicked_ctrl;
- LineEdit *clicked_ctrl_type;
- LineEdit *live_edit_root;
- Button *le_set;
- Button *le_clear;
- Button *export_csv;
-
- VBoxContainer *errors_tab;
- Tree *error_tree;
- Button *expand_all_button;
- Button *collapse_all_button;
- Button *clear_button;
- PopupMenu *item_menu;
-
- Tree *breakpoints_tree;
- PopupMenu *breakpoints_menu;
-
- EditorFileDialog *file_dialog;
+ AcceptDialog *msgdialog = nullptr;
+
+ LineEdit *clicked_ctrl = nullptr;
+ LineEdit *clicked_ctrl_type = nullptr;
+ LineEdit *live_edit_root = nullptr;
+ Button *le_set = nullptr;
+ Button *le_clear = nullptr;
+ Button *export_csv = nullptr;
+
+ VBoxContainer *errors_tab = nullptr;
+ Tree *error_tree = nullptr;
+ Button *expand_all_button = nullptr;
+ Button *collapse_all_button = nullptr;
+ Button *clear_button = nullptr;
+ PopupMenu *item_menu = nullptr;
+
+ Tree *breakpoints_tree = nullptr;
+ PopupMenu *breakpoints_menu = nullptr;
+
+ EditorFileDialog *file_dialog = nullptr;
enum FileDialogPurpose {
SAVE_MONITORS_CSV,
SAVE_VRAM_CSV,
@@ -117,31 +117,31 @@ private:
bool skip_breakpoints_value = false;
Ref<Script> stack_script;
- TabContainer *tabs;
+ TabContainer *tabs = nullptr;
- Label *reason;
+ Label *reason = nullptr;
- Button *skip_breakpoints;
- Button *copy;
- Button *step;
- Button *next;
- Button *dobreak;
- Button *docontinue;
+ Button *skip_breakpoints = nullptr;
+ Button *copy = nullptr;
+ Button *step = nullptr;
+ Button *next = nullptr;
+ Button *dobreak = nullptr;
+ Button *docontinue = nullptr;
// Reference to "Remote" tab in scene tree. Needed by _live_edit_set and buttons state.
// Each debugger should have it's tree in the future I guess.
const Tree *editor_remote_tree = nullptr;
Map<int, String> profiler_signature;
- Tree *vmem_tree;
- Button *vmem_refresh;
- Button *vmem_export;
- LineEdit *vmem_total;
+ Tree *vmem_tree = nullptr;
+ Button *vmem_refresh = nullptr;
+ Button *vmem_export = nullptr;
+ LineEdit *vmem_total = nullptr;
- Tree *stack_dump;
+ Tree *stack_dump = nullptr;
LineEdit *search = nullptr;
- EditorDebuggerInspector *inspector;
- SceneDebuggerTree *scene_tree;
+ EditorDebuggerInspector *inspector = nullptr;
+ SceneDebuggerTree *scene_tree = nullptr;
Ref<RemoteDebuggerPeer> peer;
@@ -149,10 +149,10 @@ private:
int last_path_id;
Map<String, int> res_path_cache;
- EditorProfiler *profiler;
- EditorVisualProfiler *visual_profiler;
- EditorNetworkProfiler *network_profiler;
- EditorPerformanceProfiler *performance_profiler;
+ EditorProfiler *profiler = nullptr;
+ EditorVisualProfiler *visual_profiler = nullptr;
+ EditorNetworkProfiler *network_profiler = nullptr;
+ EditorPerformanceProfiler *performance_profiler = nullptr;
OS::ProcessID remote_pid = 0;
bool breaked = false;
diff --git a/editor/dependency_editor.h b/editor/dependency_editor.h
index 84642edd79..d1dc470c79 100644
--- a/editor/dependency_editor.h
+++ b/editor/dependency_editor.h
@@ -42,10 +42,10 @@ class EditorFileSystemDirectory;
class DependencyEditor : public AcceptDialog {
GDCLASS(DependencyEditor, AcceptDialog);
- Tree *tree;
- Button *fixdeps;
+ Tree *tree = nullptr;
+ Button *fixdeps = nullptr;
- EditorFileDialog *search;
+ EditorFileDialog *search = nullptr;
String replacing;
String editing;
@@ -71,8 +71,8 @@ public:
class DependencyEditorOwners : public AcceptDialog {
GDCLASS(DependencyEditorOwners, AcceptDialog);
- ItemList *owners;
- PopupMenu *file_options;
+ ItemList *owners = nullptr;
+ PopupMenu *file_options = nullptr;
String editing;
void _fill_owners(EditorFileSystemDirectory *efsd);
@@ -95,8 +95,8 @@ public:
class DependencyRemoveDialog : public ConfirmationDialog {
GDCLASS(DependencyRemoveDialog, ConfirmationDialog);
- Label *text;
- Tree *owners;
+ Label *text = nullptr;
+ Tree *owners = nullptr;
Map<String, String> all_remove_files;
Vector<String> dirs_to_delete;
@@ -142,9 +142,9 @@ public:
private:
String for_file;
Mode mode;
- Button *fdep;
- Label *text;
- Tree *files;
+ Button *fdep = nullptr;
+ Label *text = nullptr;
+ Tree *files = nullptr;
void ok_pressed() override;
void custom_action(const String &) override;
@@ -156,9 +156,9 @@ public:
class OrphanResourcesDialog : public ConfirmationDialog {
GDCLASS(OrphanResourcesDialog, ConfirmationDialog);
- DependencyEditor *dep_edit;
- Tree *files;
- ConfirmationDialog *delete_confirm;
+ DependencyEditor *dep_edit = nullptr;
+ Tree *files = nullptr;
+ ConfirmationDialog *delete_confirm = nullptr;
void ok_pressed() override;
bool _fill_owners(EditorFileSystemDirectory *efsd, HashMap<String, int> &refs, TreeItem *p_parent);
diff --git a/editor/editor_about.h b/editor/editor_about.h
index 5a3b1e1987..6f05700582 100644
--- a/editor/editor_about.h
+++ b/editor/editor_about.h
@@ -56,11 +56,11 @@ private:
void _version_button_pressed();
ScrollContainer *_populate_list(const String &p_name, const List<String> &p_sections, const char *const *const p_src[], const int p_flag_single_column = 0);
- LinkButton *version_btn;
- Tree *_tpl_tree;
- RichTextLabel *_license_text;
- RichTextLabel *_tpl_text;
- TextureRect *_logo;
+ LinkButton *version_btn = nullptr;
+ Tree *_tpl_tree = nullptr;
+ RichTextLabel *_license_text = nullptr;
+ RichTextLabel *_tpl_text = nullptr;
+ TextureRect *_logo = nullptr;
void _theme_changed();
diff --git a/editor/editor_asset_installer.h b/editor/editor_asset_installer.h
index 58c232f351..deb320e7fa 100644
--- a/editor/editor_asset_installer.h
+++ b/editor/editor_asset_installer.h
@@ -36,11 +36,11 @@
class EditorAssetInstaller : public ConfirmationDialog {
GDCLASS(EditorAssetInstaller, ConfirmationDialog);
- Tree *tree;
- Label *asset_contents;
+ Tree *tree = nullptr;
+ Label *asset_contents = nullptr;
String package_path;
String asset_name;
- AcceptDialog *error;
+ AcceptDialog *error = nullptr;
Map<String, TreeItem *> status_map;
bool updating = false;
void _item_edited();
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index 0020b61370..81a6e5b86d 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -52,9 +52,9 @@ class EditorAudioBus : public PanelContainer {
GDCLASS(EditorAudioBus, PanelContainer);
Ref<Texture2D> disabled_vu;
- LineEdit *track_name;
- MenuButton *bus_options;
- VSlider *slider;
+ LineEdit *track_name = nullptr;
+ MenuButton *bus_options = nullptr;
+ VSlider *slider = nullptr;
int cc;
static const int CHANNELS_MAX = 4;
@@ -69,21 +69,21 @@ class EditorAudioBus : public PanelContainer {
TextureProgressBar *vu_r = nullptr;
} channel[CHANNELS_MAX];
- OptionButton *send;
+ OptionButton *send = nullptr;
- PopupMenu *effect_options;
- PopupMenu *bus_popup;
- PopupMenu *delete_effect_popup;
+ PopupMenu *effect_options = nullptr;
+ PopupMenu *bus_popup = nullptr;
+ PopupMenu *delete_effect_popup = nullptr;
- Panel *audio_value_preview_box;
- Label *audio_value_preview_label;
- Timer *preview_timer;
+ Panel *audio_value_preview_box = nullptr;
+ Label *audio_value_preview_label = nullptr;
+ Timer *preview_timer = nullptr;
- Button *solo;
- Button *mute;
- Button *bypass;
+ Button *solo = nullptr;
+ Button *mute = nullptr;
+ Button *bypass = nullptr;
- Tree *effects;
+ Tree *effects = nullptr;
bool updating_bus = false;
bool is_master;
@@ -121,7 +121,7 @@ class EditorAudioBus : public PanelContainer {
friend class EditorAudioBuses;
- EditorAudioBuses *buses;
+ EditorAudioBuses *buses = nullptr;
protected:
static void _bind_methods();
@@ -153,22 +153,22 @@ public:
class EditorAudioBuses : public VBoxContainer {
GDCLASS(EditorAudioBuses, VBoxContainer);
- HBoxContainer *top_hb;
+ HBoxContainer *top_hb = nullptr;
- ScrollContainer *bus_scroll;
- HBoxContainer *bus_hb;
+ ScrollContainer *bus_scroll = nullptr;
+ HBoxContainer *bus_hb = nullptr;
- EditorAudioBusDrop *drop_end;
+ EditorAudioBusDrop *drop_end = nullptr;
- Label *file;
+ Label *file = nullptr;
- Button *add;
- Button *load;
- Button *save_as;
- Button *_default;
- Button *_new;
+ Button *add = nullptr;
+ Button *load = nullptr;
+ Button *save_as = nullptr;
+ Button *_default = nullptr;
+ Button *_new = nullptr;
- Timer *save_timer;
+ Timer *save_timer = nullptr;
String edited_path;
void _add_bus();
@@ -191,7 +191,7 @@ class EditorAudioBuses : public VBoxContainer {
void _load_default_layout();
void _new_layout();
- EditorFileDialog *file_dialog;
+ EditorFileDialog *file_dialog = nullptr;
bool new_layout;
void _file_dialog_callback(const String &p_string);
@@ -262,7 +262,7 @@ public:
class AudioBusesEditorPlugin : public EditorPlugin {
GDCLASS(AudioBusesEditorPlugin, EditorPlugin);
- EditorAudioBuses *audio_bus_editor;
+ EditorAudioBuses *audio_bus_editor = nullptr;
public:
virtual String get_name() const override { return "SampleLibrary"; }
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index b37b06748d..49bf24f864 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -406,7 +406,7 @@ Node *EditorAutoloadSettings::_create_autoload(const String &p_path) {
} else if (script.is_valid()) {
StringName ibt = script->get_instance_base_type();
bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_FAIL_COND_V_MSG(!valid_type, nullptr, "Script does not inherit a Node: " + p_path + ".");
+ ERR_FAIL_COND_V_MSG(!valid_type, nullptr, "Script does not inherit from Node: " + p_path + ".");
Object *obj = ClassDB::instantiate(ibt);
diff --git a/editor/editor_command_palette.h b/editor/editor_command_palette.h
index 41141af0c3..124703cca4 100644
--- a/editor/editor_command_palette.h
+++ b/editor/editor_command_palette.h
@@ -40,8 +40,8 @@ class EditorCommandPalette : public ConfirmationDialog {
GDCLASS(EditorCommandPalette, ConfirmationDialog);
static EditorCommandPalette *singleton;
- LineEdit *command_search_box;
- Tree *search_options;
+ LineEdit *command_search_box = nullptr;
+ Tree *search_options = nullptr;
struct Command {
Callable callable;
diff --git a/editor/editor_dir_dialog.h b/editor/editor_dir_dialog.h
index e97b5ce8af..9baa37793b 100644
--- a/editor/editor_dir_dialog.h
+++ b/editor/editor_dir_dialog.h
@@ -39,14 +39,14 @@
class EditorDirDialog : public ConfirmationDialog {
GDCLASS(EditorDirDialog, ConfirmationDialog);
- ConfirmationDialog *makedialog;
- LineEdit *makedirname;
- AcceptDialog *mkdirerr;
+ ConfirmationDialog *makedialog = nullptr;
+ LineEdit *makedirname = nullptr;
+ AcceptDialog *mkdirerr = nullptr;
- Button *makedir;
+ Button *makedir = nullptr;
Set<String> opened_paths;
- Tree *tree;
+ Tree *tree = nullptr;
bool updating = false;
void _item_collapsed(Object *p_item);
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 7c61e7cff6..4d5aebc770 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -380,7 +380,7 @@ class EditorExport : public Node {
StringName _export_presets_updated;
- Timer *save_timer;
+ Timer *save_timer = nullptr;
bool block_save = false;
static EditorExport *singleton;
diff --git a/editor/editor_feature_profile.h b/editor/editor_feature_profile.h
index 881f14638f..19df8a9686 100644
--- a/editor/editor_feature_profile.h
+++ b/editor/editor_feature_profile.h
@@ -117,25 +117,25 @@ class EditorFeatureProfileManager : public AcceptDialog {
CLASS_OPTION_DISABLE_EDITOR
};
- ConfirmationDialog *erase_profile_dialog;
- ConfirmationDialog *new_profile_dialog;
- LineEdit *new_profile_name;
+ ConfirmationDialog *erase_profile_dialog = nullptr;
+ ConfirmationDialog *new_profile_dialog = nullptr;
+ LineEdit *new_profile_name = nullptr;
- LineEdit *current_profile_name;
- OptionButton *profile_list;
+ LineEdit *current_profile_name = nullptr;
+ OptionButton *profile_list = nullptr;
Button *profile_actions[PROFILE_MAX];
- HSplitContainer *h_split;
+ HSplitContainer *h_split = nullptr;
- VBoxContainer *class_list_vbc;
- Tree *class_list;
- VBoxContainer *property_list_vbc;
- Tree *property_list;
- EditorHelpBit *description_bit;
- Label *no_profile_selected_help;
+ VBoxContainer *class_list_vbc = nullptr;
+ Tree *class_list = nullptr;
+ VBoxContainer *property_list_vbc = nullptr;
+ Tree *property_list = nullptr;
+ EditorHelpBit *description_bit = nullptr;
+ Label *no_profile_selected_help = nullptr;
- EditorFileDialog *import_profiles;
- EditorFileDialog *export_profile;
+ EditorFileDialog *import_profiles = nullptr;
+ EditorFileDialog *export_profile = nullptr;
void _profile_action(int p_action);
void _profile_selected(int p_what);
@@ -163,7 +163,7 @@ class EditorFeatureProfileManager : public AcceptDialog {
void _property_item_edited();
void _save_and_update();
- Timer *update_timer;
+ Timer *update_timer = nullptr;
void _emit_current_profile_changed();
static EditorFeatureProfileManager *singleton;
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index a747255ce8..07af8c5435 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -84,50 +84,50 @@ private:
ITEM_MENU_SHOW_IN_EXPLORER
};
- ConfirmationDialog *makedialog;
- LineEdit *makedirname;
+ ConfirmationDialog *makedialog = nullptr;
+ LineEdit *makedirname = nullptr;
- Button *makedir;
+ Button *makedir = nullptr;
Access access;
- VBoxContainer *vbox;
+ VBoxContainer *vbox = nullptr;
FileMode mode;
bool can_create_dir;
- LineEdit *dir;
-
- Button *dir_prev;
- Button *dir_next;
- Button *dir_up;
-
- HBoxContainer *drives_container;
- HBoxContainer *shortcuts_container;
- OptionButton *drives;
- ItemList *item_list;
- PopupMenu *item_menu;
- TextureRect *preview;
- VBoxContainer *preview_vb;
- HSplitContainer *list_hb;
- HBoxContainer *file_box;
- LineEdit *file;
- OptionButton *filter;
- AcceptDialog *error_dialog;
- DirAccess *dir_access;
- ConfirmationDialog *confirm_save;
- DependencyRemoveDialog *dep_remove_dialog;
- ConfirmationDialog *global_remove_dialog;
-
- Button *mode_thumbnails;
- Button *mode_list;
-
- Button *refresh;
- Button *favorite;
- Button *show_hidden;
-
- Button *fav_up;
- Button *fav_down;
-
- ItemList *favorites;
- ItemList *recent;
+ LineEdit *dir = nullptr;
+
+ Button *dir_prev = nullptr;
+ Button *dir_next = nullptr;
+ Button *dir_up = nullptr;
+
+ HBoxContainer *drives_container = nullptr;
+ HBoxContainer *shortcuts_container = nullptr;
+ OptionButton *drives = nullptr;
+ ItemList *item_list = nullptr;
+ PopupMenu *item_menu = nullptr;
+ TextureRect *preview = nullptr;
+ VBoxContainer *preview_vb = nullptr;
+ HSplitContainer *list_hb = nullptr;
+ HBoxContainer *file_box = nullptr;
+ LineEdit *file = nullptr;
+ OptionButton *filter = nullptr;
+ AcceptDialog *error_dialog = nullptr;
+ DirAccess *dir_access = nullptr;
+ ConfirmationDialog *confirm_save = nullptr;
+ DependencyRemoveDialog *dep_remove_dialog = nullptr;
+ ConfirmationDialog *global_remove_dialog = nullptr;
+
+ Button *mode_thumbnails = nullptr;
+ Button *mode_list = nullptr;
+
+ Button *refresh = nullptr;
+ Button *favorite = nullptr;
+ Button *show_hidden = nullptr;
+
+ Button *fav_up = nullptr;
+ Button *fav_down = nullptr;
+
+ ItemList *favorites = nullptr;
+ ItemList *recent = nullptr;
Vector<String> local_history;
int local_history_pos;
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index f3d9449c6c..2b98a4b02a 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -520,6 +520,45 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
return false; //nothing changed
}
+bool EditorFileSystem::_scan_import_support(Vector<String> reimports) {
+ if (import_support_queries.size() == 0) {
+ return false;
+ }
+ Map<String, int> import_support_test;
+ Vector<bool> import_support_tested;
+ import_support_tested.resize(import_support_queries.size());
+ for (int i = 0; i < import_support_queries.size(); i++) {
+ import_support_tested.write[i] = false;
+ if (import_support_queries[i]->is_active()) {
+ Vector<String> extensions = import_support_queries[i]->get_file_extensions();
+ for (int j = 0; j < extensions.size(); j++) {
+ import_support_test.insert(extensions[j], i);
+ }
+ }
+ }
+
+ if (import_support_test.size() == 0) {
+ return false; //well nothing to do
+ }
+
+ for (int i = 0; i < reimports.size(); i++) {
+ Map<String, int>::Element *E = import_support_test.find(reimports[i].get_extension());
+ if (E) {
+ import_support_tested.write[E->get()] = true;
+ }
+ }
+
+ for (int i = 0; i < import_support_tested.size(); i++) {
+ if (import_support_tested[i]) {
+ if (import_support_queries.write[i]->query()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
bool EditorFileSystem::_update_scan_actions() {
sources_changed.clear();
@@ -612,7 +651,7 @@ bool EditorFileSystem::_update_scan_actions() {
if (_scan_extensions()) {
//needs editor restart
//extensions also may provide filetypes to be imported, so they must run before importing
- if (EditorNode::immediate_confirmation_dialog(TTR("Some extensions need the editor to restart to take effect."), first_scan ? TTR("Restart") : TTR("Save&Restart"), TTR("Continue"))) {
+ if (EditorNode::immediate_confirmation_dialog(TTR("Some extensions need the editor to restart to take effect."), first_scan ? TTR("Restart") : TTR("Save & Restart"), TTR("Continue"))) {
if (!first_scan) {
EditorNode::get_singleton()->save_all_scenes();
}
@@ -621,7 +660,12 @@ bool EditorFileSystem::_update_scan_actions() {
return true;
}
}
+
if (reimports.size()) {
+ if (_scan_import_support(reimports)) {
+ return true;
+ }
+
reimport_files(reimports);
} else {
//reimport files will update the uid cache file so if nothing was reimported, update it manually
@@ -2274,6 +2318,7 @@ static void _scan_extensions_dir(EditorFileSystemDirectory *d, Set<String> &exte
bool EditorFileSystem::_scan_extensions() {
EditorFileSystemDirectory *d = get_filesystem();
Set<String> extensions;
+
_scan_extensions_dir(d, extensions);
//verify against loaded extensions
@@ -2374,6 +2419,14 @@ void EditorFileSystem::_update_extensions() {
}
}
+void EditorFileSystem::add_import_format_support_query(Ref<EditorFileSystemImportFormatSupportQuery> p_query) {
+ ERR_FAIL_COND(import_support_queries.find(p_query) != -1);
+ import_support_queries.push_back(p_query);
+}
+void EditorFileSystem::remove_import_format_support_query(Ref<EditorFileSystemImportFormatSupportQuery> p_query) {
+ import_support_queries.erase(p_query);
+}
+
EditorFileSystem::EditorFileSystem() {
ResourceLoader::import = _resource_import;
reimport_on_missing_imported_files = GLOBAL_DEF("editor/import/reimport_missing_imported_files", true);
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index 0ec0094030..05b55d4e1b 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -49,7 +49,7 @@ class EditorFileSystemDirectory : public Object {
uint64_t modified_time;
bool verified = false; //used for checking changes
- EditorFileSystemDirectory *parent;
+ EditorFileSystemDirectory *parent = nullptr;
Vector<EditorFileSystemDirectory *> subdirs;
struct FileInfo {
@@ -109,6 +109,37 @@ public:
~EditorFileSystemDirectory();
};
+class EditorFileSystemImportFormatSupportQuery : public RefCounted {
+ GDCLASS(EditorFileSystemImportFormatSupportQuery, RefCounted);
+
+protected:
+ GDVIRTUAL0RC(bool, _is_active)
+ GDVIRTUAL0RC(Vector<String>, _get_file_extensions)
+ GDVIRTUAL0RC(bool, _query)
+ static void _bind_methods() {
+ GDVIRTUAL_BIND(_is_active);
+ GDVIRTUAL_BIND(_get_file_extensions);
+ GDVIRTUAL_BIND(_query);
+ }
+
+public:
+ virtual bool is_active() const {
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_is_active, ret);
+ return ret;
+ }
+ virtual Vector<String> get_file_extensions() const {
+ Vector<String> ret;
+ GDVIRTUAL_REQUIRED_CALL(_get_file_extensions, ret);
+ return ret;
+ }
+ virtual bool query() {
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_query, ret);
+ return ret;
+ }
+};
+
class EditorFileSystem : public Node {
GDCLASS(EditorFileSystem, Node);
@@ -136,7 +167,7 @@ class EditorFileSystem : public Node {
Thread thread;
static void _thread_func(void *_userdata);
- EditorFileSystemDirectory *new_filesystem;
+ EditorFileSystemDirectory *new_filesystem = nullptr;
bool abort_scan = false;
bool scanning = false;
@@ -153,7 +184,7 @@ class EditorFileSystem : public Node {
void _save_late_updated_files();
- EditorFileSystemDirectory *filesystem;
+ EditorFileSystemDirectory *filesystem = nullptr;
static EditorFileSystem *singleton;
@@ -257,6 +288,9 @@ class EditorFileSystem : public Node {
static ResourceUID::ID _resource_saver_get_resource_id_for_path(const String &p_path, bool p_generate);
bool _scan_extensions();
+ bool _scan_import_support(Vector<String> reimports);
+
+ Vector<Ref<EditorFileSystemImportFormatSupportQuery>> import_support_queries;
protected:
void _notification(int p_what);
@@ -289,6 +323,8 @@ public:
static bool _should_skip_directory(const String &p_path);
+ void add_import_format_support_query(Ref<EditorFileSystemImportFormatSupportQuery> p_query);
+ void remove_import_format_support_query(Ref<EditorFileSystemImportFormatSupportQuery> p_query);
EditorFileSystem();
~EditorFileSystem();
};
diff --git a/editor/editor_help.h b/editor/editor_help.h
index b40d1709b6..054fd84af6 100644
--- a/editor/editor_help.h
+++ b/editor/editor_help.h
@@ -47,14 +47,14 @@
class FindBar : public HBoxContainer {
GDCLASS(FindBar, HBoxContainer);
- LineEdit *search_text;
- Button *find_prev;
- Button *find_next;
- Label *matches_label;
- TextureButton *hide_button;
+ LineEdit *search_text = nullptr;
+ Button *find_prev = nullptr;
+ Button *find_next = nullptr;
+ Label *matches_label = nullptr;
+ TextureButton *hide_button = nullptr;
String prev_search;
- RichTextLabel *rich_text_label;
+ RichTextLabel *rich_text_label = nullptr;
int results_count;
@@ -114,15 +114,15 @@ class EditorHelp : public VBoxContainer {
Map<String, Map<String, int>> enum_values_line;
int description_line;
- RichTextLabel *class_desc;
- HSplitContainer *h_split;
+ RichTextLabel *class_desc = nullptr;
+ HSplitContainer *h_split = nullptr;
static DocTools *doc;
- ConfirmationDialog *search_dialog;
- LineEdit *search;
- FindBar *find_bar;
- HBoxContainer *status_bar;
- Button *toggle_scripts_button;
+ ConfirmationDialog *search_dialog = nullptr;
+ LineEdit *search = nullptr;
+ FindBar *find_bar = nullptr;
+ HBoxContainer *status_bar = nullptr;
+ Button *toggle_scripts_button = nullptr;
String base_path;
@@ -210,7 +210,7 @@ public:
class EditorHelpBit : public MarginContainer {
GDCLASS(EditorHelpBit, MarginContainer);
- RichTextLabel *rich_text;
+ RichTextLabel *rich_text = nullptr;
void _go_to_help(String p_what);
void _meta_clicked(String p_select);
diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h
index bf69fe1693..d89bb0959c 100644
--- a/editor/editor_help_search.h
+++ b/editor/editor_help_search.h
@@ -55,11 +55,11 @@ class EditorHelpSearch : public ConfirmationDialog {
SEARCH_SHOW_HIERARCHY = 1 << 30
};
- LineEdit *search_box;
- Button *case_sensitive_button;
- Button *hierarchy_button;
- OptionButton *filter_combo;
- Tree *results_tree;
+ LineEdit *search_box = nullptr;
+ Button *case_sensitive_button = nullptr;
+ Button *hierarchy_button = nullptr;
+ OptionButton *filter_combo = nullptr;
+ Tree *results_tree = nullptr;
bool old_search = false;
String old_term;
@@ -114,8 +114,8 @@ class EditorHelpSearch::Runner : public RefCounted {
}
};
- Control *ui_service;
- Tree *results_tree;
+ Control *ui_service = nullptr;
+ Tree *results_tree = nullptr;
String term;
int search_flags;
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index 87703564b9..c9e8a1672e 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -68,7 +68,7 @@ private:
String label;
int text_size;
friend class EditorInspector;
- Object *object;
+ Object *object = nullptr;
StringName property;
String property_path;
@@ -111,9 +111,9 @@ private:
float split_ratio;
Vector<Control *> focusables;
- Control *label_reference;
- Control *bottom_editor;
- PopupMenu *menu;
+ Control *label_reference = nullptr;
+ Control *bottom_editor = nullptr;
+ PopupMenu *menu = nullptr;
mutable String tooltip_text;
@@ -269,14 +269,14 @@ class EditorInspectorSection : public Container {
bool foldable = false;
int indent_depth = 0;
- Timer *dropping_unfold_timer;
+ Timer *dropping_unfold_timer = nullptr;
bool dropping = false;
void _test_unfold();
protected:
Object *object = nullptr;
- VBoxContainer *vbox;
+ VBoxContainer *vbox = nullptr;
void _notification(int p_what);
static void _bind_methods();
@@ -297,7 +297,7 @@ public:
class EditorInspectorArray : public EditorInspectorSection {
GDCLASS(EditorInspectorArray, EditorInspectorSection);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
enum Mode {
MODE_NONE,
@@ -309,16 +309,16 @@ class EditorInspectorArray : public EditorInspectorSection {
int count = 0;
- VBoxContainer *elements_vbox;
+ VBoxContainer *elements_vbox = nullptr;
- Control *control_dropping;
+ Control *control_dropping = nullptr;
bool dropping = false;
- Button *add_button;
+ Button *add_button = nullptr;
- AcceptDialog *resize_dialog;
+ AcceptDialog *resize_dialog = nullptr;
int new_size = 0;
- LineEdit *new_size_line_edit;
+ LineEdit *new_size_line_edit = nullptr;
// Pagination
int page_length = 5;
@@ -337,14 +337,14 @@ class EditorInspectorArray : public EditorInspectorSection {
OPTION_RESIZE_ARRAY,
};
int popup_array_index_pressed = -1;
- PopupMenu *rmb_popup;
+ PopupMenu *rmb_popup = nullptr;
struct ArrayElement {
- PanelContainer *panel;
- MarginContainer *margin;
- HBoxContainer *hbox;
- TextureRect *move_texture_rect;
- VBoxContainer *vbox;
+ PanelContainer *panel = nullptr;
+ MarginContainer *margin = nullptr;
+ HBoxContainer *hbox = nullptr;
+ TextureRect *move_texture_rect = nullptr;
+ VBoxContainer *vbox = nullptr;
};
LocalVector<ArrayElement> array_elements;
@@ -399,12 +399,12 @@ class EditorPaginator : public HBoxContainer {
int page = 0;
int max_page = 0;
- Button *first_page_button;
- Button *prev_page_button;
- LineEdit *page_line_edit;
- Label *page_count_label;
- Button *next_page_button;
- Button *last_page_button;
+ Button *first_page_button = nullptr;
+ Button *prev_page_button = nullptr;
+ LineEdit *page_line_edit = nullptr;
+ Label *page_count_label = nullptr;
+ Button *next_page_button = nullptr;
+ Button *last_page_button = nullptr;
void _first_page_button_pressed();
void _prev_page_button_pressed();
@@ -425,14 +425,14 @@ public:
class EditorInspector : public ScrollContainer {
GDCLASS(EditorInspector, ScrollContainer);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
enum {
MAX_PLUGINS = 1024
};
static Ref<EditorInspectorPlugin> inspector_plugins[MAX_PLUGINS];
static int inspector_plugin_count;
- VBoxContainer *main_vbox;
+ VBoxContainer *main_vbox = nullptr;
//map use to cache the instantiated editors
Map<StringName, List<EditorProperty *>> editor_property_map;
@@ -440,11 +440,11 @@ class EditorInspector : public ScrollContainer {
Set<StringName> pending;
void _clear();
- Object *object;
+ Object *object = nullptr;
//
- LineEdit *search_box;
+ LineEdit *search_box = nullptr;
bool show_categories = false;
bool hide_script = true;
bool hide_metadata = true;
diff --git a/editor/editor_layouts_dialog.h b/editor/editor_layouts_dialog.h
index bbdffd6722..a597ac38cc 100644
--- a/editor/editor_layouts_dialog.h
+++ b/editor/editor_layouts_dialog.h
@@ -39,9 +39,9 @@ class ItemList;
class EditorLayoutsDialog : public ConfirmationDialog {
GDCLASS(EditorLayoutsDialog, ConfirmationDialog);
- LineEdit *name;
- ItemList *layout_names;
- VBoxContainer *makevb;
+ LineEdit *name = nullptr;
+ ItemList *layout_names = nullptr;
+ VBoxContainer *makevb = nullptr;
void _line_gui_input(const Ref<InputEvent> &p_event);
diff --git a/editor/editor_log.h b/editor/editor_log.h
index e66b732ffe..267ad406d4 100644
--- a/editor/editor_log.h
+++ b/editor/editor_log.h
@@ -117,23 +117,23 @@ private:
// Maps MessageTypes to LogFilters for convenient access and storage (don't need 1 member per filter).
Map<MessageType, LogFilter *> type_filter_map;
- RichTextLabel *log;
+ RichTextLabel *log = nullptr;
- Button *clear_button;
- Button *copy_button;
+ Button *clear_button = nullptr;
+ Button *copy_button = nullptr;
- Button *collapse_button;
+ Button *collapse_button = nullptr;
bool collapse = false;
- Button *show_search_button;
- LineEdit *search_box;
+ Button *show_search_button = nullptr;
+ LineEdit *search_box = nullptr;
// Reference to the "Output" button on the toolbar so we can update it's icon when
// Warnings or Errors are encounetered.
- Button *tool_button;
+ Button *tool_button = nullptr;
bool is_loading_state = false; // Used to disable saving requests while loading (some signals from buttons will try trigger a save, which happens during loading).
- Timer *save_state_timer;
+ Timer *save_state_timer = nullptr;
static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 25e3bc8d6a..52f7366dd7 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -3920,6 +3920,7 @@ void EditorNode::register_editor_types() {
GDREGISTER_CLASS(EditorScriptPicker);
GDREGISTER_ABSTRACT_CLASS(FileSystemDock);
+ GDREGISTER_VIRTUAL_CLASS(EditorFileSystemImportFormatSupportQuery);
GDREGISTER_CLASS(EditorScenePostImport);
GDREGISTER_CLASS(EditorCommandPalette);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 7d24cfe758..5f09d4e518 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -275,161 +275,161 @@ private:
bool _initializing_plugins = false;
Map<String, EditorPlugin *> addon_name_to_plugin;
- PanelContainer *scene_root_parent;
- Control *theme_base;
- Control *gui_base;
- VBoxContainer *main_vbox;
- OptionButton *rendering_driver;
+ PanelContainer *scene_root_parent = nullptr;
+ Control *theme_base = nullptr;
+ Control *gui_base = nullptr;
+ VBoxContainer *main_vbox = nullptr;
+ OptionButton *rendering_driver = nullptr;
- ConfirmationDialog *video_restart_dialog;
+ ConfirmationDialog *video_restart_dialog = nullptr;
int rendering_driver_current;
String rendering_driver_request;
// Split containers.
- HSplitContainer *left_l_hsplit;
- VSplitContainer *left_l_vsplit;
- HSplitContainer *left_r_hsplit;
- VSplitContainer *left_r_vsplit;
- HSplitContainer *main_hsplit;
- HSplitContainer *right_hsplit;
- VSplitContainer *right_l_vsplit;
- VSplitContainer *right_r_vsplit;
- VSplitContainer *center_split;
+ HSplitContainer *left_l_hsplit = nullptr;
+ VSplitContainer *left_l_vsplit = nullptr;
+ HSplitContainer *left_r_hsplit = nullptr;
+ VSplitContainer *left_r_vsplit = nullptr;
+ HSplitContainer *main_hsplit = nullptr;
+ HSplitContainer *right_hsplit = nullptr;
+ VSplitContainer *right_l_vsplit = nullptr;
+ VSplitContainer *right_r_vsplit = nullptr;
+ VSplitContainer *center_split = nullptr;
// To access those easily by index.
Vector<VSplitContainer *> vsplits;
Vector<HSplitContainer *> hsplits;
// Main tabs.
- TabBar *scene_tabs;
- PopupMenu *scene_tabs_context_menu;
- Panel *tab_preview_panel;
- TextureRect *tab_preview;
+ TabBar *scene_tabs = nullptr;
+ PopupMenu *scene_tabs_context_menu = nullptr;
+ Panel *tab_preview_panel = nullptr;
+ TextureRect *tab_preview = nullptr;
int tab_closing_idx;
bool exiting = false;
bool dimmed = false;
int old_split_ofs;
- VSplitContainer *top_split;
- HBoxContainer *bottom_hb;
- Control *vp_base;
-
- HBoxContainer *menu_hb;
- Control *main_control;
- MenuButton *file_menu;
- MenuButton *project_menu;
- MenuButton *debug_menu;
- MenuButton *settings_menu;
- MenuButton *help_menu;
- PopupMenu *tool_menu;
- Button *export_button;
- Button *prev_scene;
- Button *play_button;
- Button *pause_button;
- Button *stop_button;
- Button *run_settings_button;
- Button *play_scene_button;
- Button *play_custom_scene_button;
- Button *search_button;
- TextureProgressBar *audio_vu;
-
- Timer *screenshot_timer;
-
- PluginConfigDialog *plugin_config_dialog;
-
- RichTextLabel *load_errors;
- AcceptDialog *load_error_dialog;
-
- RichTextLabel *execute_outputs;
- AcceptDialog *execute_output_dialog;
+ VSplitContainer *top_split = nullptr;
+ HBoxContainer *bottom_hb = nullptr;
+ Control *vp_base = nullptr;
+
+ HBoxContainer *menu_hb = nullptr;
+ Control *main_control = nullptr;
+ MenuButton *file_menu = nullptr;
+ MenuButton *project_menu = nullptr;
+ MenuButton *debug_menu = nullptr;
+ MenuButton *settings_menu = nullptr;
+ MenuButton *help_menu = nullptr;
+ PopupMenu *tool_menu = nullptr;
+ Button *export_button = nullptr;
+ Button *prev_scene = nullptr;
+ Button *play_button = nullptr;
+ Button *pause_button = nullptr;
+ Button *stop_button = nullptr;
+ Button *run_settings_button = nullptr;
+ Button *play_scene_button = nullptr;
+ Button *play_custom_scene_button = nullptr;
+ Button *search_button = nullptr;
+ TextureProgressBar *audio_vu = nullptr;
+
+ Timer *screenshot_timer = nullptr;
+
+ PluginConfigDialog *plugin_config_dialog = nullptr;
+
+ RichTextLabel *load_errors = nullptr;
+ AcceptDialog *load_error_dialog = nullptr;
+
+ RichTextLabel *execute_outputs = nullptr;
+ AcceptDialog *execute_output_dialog = nullptr;
Ref<Theme> theme;
- PopupMenu *recent_scenes;
+ PopupMenu *recent_scenes = nullptr;
String _recent_scene;
List<String> previous_scenes;
String defer_load_scene;
- Node *_last_instantiated_scene;
-
- ConfirmationDialog *confirmation;
- ConfirmationDialog *save_confirmation;
- ConfirmationDialog *import_confirmation;
- ConfirmationDialog *pick_main_scene;
- Button *select_current_scene_button;
- AcceptDialog *accept;
- AcceptDialog *save_accept;
- EditorAbout *about;
- AcceptDialog *warning;
+ Node *_last_instantiated_scene = nullptr;
+
+ ConfirmationDialog *confirmation = nullptr;
+ ConfirmationDialog *save_confirmation = nullptr;
+ ConfirmationDialog *import_confirmation = nullptr;
+ ConfirmationDialog *pick_main_scene = nullptr;
+ Button *select_current_scene_button = nullptr;
+ AcceptDialog *accept = nullptr;
+ AcceptDialog *save_accept = nullptr;
+ EditorAbout *about = nullptr;
+ AcceptDialog *warning = nullptr;
int overridden_default_layout;
Ref<ConfigFile> default_layout;
- PopupMenu *editor_layouts;
- EditorLayoutsDialog *layout_dialog;
-
- ConfirmationDialog *custom_build_manage_templates;
- ConfirmationDialog *install_android_build_template;
- ConfirmationDialog *remove_android_build_template;
-
- PopupMenu *vcs_actions_menu;
- EditorFileDialog *file;
- ExportTemplateManager *export_template_manager;
- EditorFeatureProfileManager *feature_profile_manager;
- EditorFileDialog *file_templates;
- EditorFileDialog *file_export_lib;
- EditorFileDialog *file_script;
- EditorFileDialog *file_android_build_source;
- CheckBox *file_export_lib_merge;
- CheckBox *file_export_lib_apply_xforms;
+ PopupMenu *editor_layouts = nullptr;
+ EditorLayoutsDialog *layout_dialog = nullptr;
+
+ ConfirmationDialog *custom_build_manage_templates = nullptr;
+ ConfirmationDialog *install_android_build_template = nullptr;
+ ConfirmationDialog *remove_android_build_template = nullptr;
+
+ PopupMenu *vcs_actions_menu = nullptr;
+ EditorFileDialog *file = nullptr;
+ ExportTemplateManager *export_template_manager = nullptr;
+ EditorFeatureProfileManager *feature_profile_manager = nullptr;
+ EditorFileDialog *file_templates = nullptr;
+ EditorFileDialog *file_export_lib = nullptr;
+ EditorFileDialog *file_script = nullptr;
+ EditorFileDialog *file_android_build_source = nullptr;
+ CheckBox *file_export_lib_merge = nullptr;
+ CheckBox *file_export_lib_apply_xforms = nullptr;
String current_path;
- MenuButton *update_spinner;
+ MenuButton *update_spinner = nullptr;
- HBoxContainer *main_editor_button_vb;
+ HBoxContainer *main_editor_button_vb = nullptr;
Vector<Button *> main_editor_buttons;
Vector<EditorPlugin *> editor_table;
- AudioStreamPreviewGenerator *audio_preview_gen;
- ProgressDialog *progress_dialog;
- BackgroundProgress *progress_hb;
+ AudioStreamPreviewGenerator *audio_preview_gen = nullptr;
+ ProgressDialog *progress_dialog = nullptr;
+ BackgroundProgress *progress_hb = nullptr;
- DependencyErrorDialog *dependency_error;
+ DependencyErrorDialog *dependency_error = nullptr;
Map<String, Set<String>> dependency_errors;
- DependencyEditor *dependency_fixer;
- OrphanResourcesDialog *orphan_resources;
- ConfirmationDialog *open_imported;
- Button *new_inherited_button;
+ DependencyEditor *dependency_fixer = nullptr;
+ OrphanResourcesDialog *orphan_resources = nullptr;
+ ConfirmationDialog *open_imported = nullptr;
+ Button *new_inherited_button = nullptr;
String open_import_request;
Vector<Control *> floating_docks;
- Button *dock_float;
- Button *dock_tab_move_left;
- Button *dock_tab_move_right;
- Control *dock_select;
- PopupPanel *dock_select_popup;
+ Button *dock_float = nullptr;
+ Button *dock_tab_move_left = nullptr;
+ Button *dock_tab_move_right = nullptr;
+ Control *dock_select = nullptr;
+ PopupPanel *dock_select_popup = nullptr;
Rect2 dock_select_rect[DOCK_SLOT_MAX];
TabContainer *dock_slot[DOCK_SLOT_MAX];
- Timer *dock_drag_timer;
+ Timer *dock_drag_timer = nullptr;
bool docks_visible = true;
int dock_popup_selected_idx;
int dock_select_rect_over_idx;
- HBoxContainer *tabbar_container;
- Button *distraction_free;
- Button *scene_tab_add;
- Control *scene_tab_add_ph;
+ HBoxContainer *tabbar_container = nullptr;
+ Button *distraction_free = nullptr;
+ Button *scene_tab_add = nullptr;
+ Control *scene_tab_add_ph = nullptr;
Vector<BottomPanelItem> bottom_panel_items;
- PanelContainer *bottom_panel;
- HBoxContainer *bottom_panel_hb;
- HBoxContainer *bottom_panel_hb_editors;
- VBoxContainer *bottom_panel_vb;
- EditorToaster *editor_toaster;
- LinkButton *version_btn;
- Button *bottom_panel_raise;
+ PanelContainer *bottom_panel = nullptr;
+ HBoxContainer *bottom_panel_hb = nullptr;
+ HBoxContainer *bottom_panel_hb_editors = nullptr;
+ VBoxContainer *bottom_panel_vb = nullptr;
+ EditorToaster *editor_toaster = nullptr;
+ LinkButton *version_btn = nullptr;
+ Button *bottom_panel_raise = nullptr;
- Tree *disk_changed_list;
- ConfirmationDialog *disk_changed;
+ Tree *disk_changed_list = nullptr;
+ ConfirmationDialog *disk_changed = nullptr;
bool scene_distraction_free = false;
bool script_distraction_free = false;
@@ -447,8 +447,8 @@ private:
int current_menu_option;
- SubViewport *scene_root; // Root of the scene being edited.
- Object *current;
+ SubViewport *scene_root = nullptr; // Root of the scene being edited.
+ Object *current = nullptr;
Ref<Resource> saving_resource;
@@ -464,8 +464,8 @@ private:
uint64_t saved_version;
uint64_t last_checked_version;
- DynamicFontImportSettings *fontdata_import_settings;
- SceneImportSettings *scene_import_settings;
+ DynamicFontImportSettings *fontdata_import_settings = nullptr;
+ SceneImportSettings *scene_import_settings = nullptr;
String import_reload_fn;
diff --git a/editor/editor_path.h b/editor/editor_path.h
index 1e19344d9e..afc7a20bad 100644
--- a/editor/editor_path.h
+++ b/editor/editor_path.h
@@ -42,12 +42,12 @@ class EditorSelectionHistory;
class EditorPath : public Button {
GDCLASS(EditorPath, Button);
- EditorSelectionHistory *history;
+ EditorSelectionHistory *history = nullptr;
- TextureRect *current_object_icon;
- Label *current_object_label;
- TextureRect *sub_objects_icon;
- PopupMenu *sub_objects_menu;
+ TextureRect *current_object_icon = nullptr;
+ Label *current_object_label = nullptr;
+ TextureRect *sub_objects_icon = nullptr;
+ PopupMenu *sub_objects_menu = nullptr;
Vector<ObjectID> objects;
diff --git a/editor/editor_plugin_settings.h b/editor/editor_plugin_settings.h
index c239b735de..826bb8c00f 100644
--- a/editor/editor_plugin_settings.h
+++ b/editor/editor_plugin_settings.h
@@ -44,10 +44,10 @@ class EditorPluginSettings : public VBoxContainer {
BUTTON_PLUGIN_EDIT
};
- PluginConfigDialog *plugin_config_dialog;
- Button *create_plugin;
- Button *update_list;
- Tree *plugin_list;
+ PluginConfigDialog *plugin_config_dialog = nullptr;
+ Button *create_plugin = nullptr;
+ Button *update_list = nullptr;
+ Tree *plugin_list = nullptr;
bool updating = false;
void _plugin_activity_changed();
diff --git a/editor/editor_properties.h b/editor/editor_properties.h
index c21e0e0b4d..1f40a7fe7b 100644
--- a/editor/editor_properties.h
+++ b/editor/editor_properties.h
@@ -52,7 +52,7 @@ public:
class EditorPropertyText : public EditorProperty {
GDCLASS(EditorPropertyText, EditorProperty);
- LineEdit *text;
+ LineEdit *text = nullptr;
bool updating = false;
bool string_name = false;
@@ -72,11 +72,11 @@ public:
class EditorPropertyMultilineText : public EditorProperty {
GDCLASS(EditorPropertyMultilineText, EditorProperty);
- TextEdit *text;
+ TextEdit *text = nullptr;
- AcceptDialog *big_text_dialog;
- TextEdit *big_text;
- Button *open_big_text;
+ AcceptDialog *big_text_dialog = nullptr;
+ TextEdit *big_text = nullptr;
+ Button *open_big_text = nullptr;
void _big_text_changed();
void _text_changed();
@@ -95,15 +95,15 @@ public:
class EditorPropertyTextEnum : public EditorProperty {
GDCLASS(EditorPropertyTextEnum, EditorProperty);
- HBoxContainer *default_layout;
- HBoxContainer *edit_custom_layout;
+ HBoxContainer *default_layout = nullptr;
+ HBoxContainer *edit_custom_layout = nullptr;
- OptionButton *option_button;
- Button *edit_button;
+ OptionButton *option_button = nullptr;
+ Button *edit_button = nullptr;
- LineEdit *custom_value_edit;
- Button *accept_button;
- Button *cancel_button;
+ LineEdit *custom_value_edit = nullptr;
+ Button *accept_button = nullptr;
+ Button *cancel_button = nullptr;
Vector<String> options;
bool string_name = false;
@@ -134,9 +134,9 @@ class EditorPropertyPath : public EditorProperty {
bool folder = false;
bool global = false;
bool save_mode = false;
- EditorFileDialog *dialog;
- LineEdit *path;
- Button *path_edit;
+ EditorFileDialog *dialog = nullptr;
+ LineEdit *path = nullptr;
+ Button *path_edit = nullptr;
void _path_selected(const String &p_path);
void _path_pressed();
@@ -156,9 +156,9 @@ public:
class EditorPropertyLocale : public EditorProperty {
GDCLASS(EditorPropertyLocale, EditorProperty);
- EditorLocaleDialog *dialog;
- LineEdit *locale;
- Button *locale_edit;
+ EditorLocaleDialog *dialog = nullptr;
+ LineEdit *locale = nullptr;
+ Button *locale_edit = nullptr;
void _locale_selected(const String &p_locale);
void _locale_pressed();
@@ -178,8 +178,8 @@ class EditorPropertyClassName : public EditorProperty {
GDCLASS(EditorPropertyClassName, EditorProperty);
private:
- CreateDialog *dialog;
- Button *property;
+ CreateDialog *dialog = nullptr;
+ Button *property = nullptr;
String selected_type;
String base_type;
void _property_selected();
@@ -212,8 +212,8 @@ public:
private:
Type hint;
- PropertySelector *selector;
- Button *property;
+ PropertySelector *selector = nullptr;
+ Button *property = nullptr;
String hint_text;
void _property_selected(const String &p_selected);
@@ -231,7 +231,7 @@ public:
class EditorPropertyCheck : public EditorProperty {
GDCLASS(EditorPropertyCheck, EditorProperty);
- CheckBox *checkbox;
+ CheckBox *checkbox = nullptr;
void _checkbox_pressed();
@@ -246,7 +246,7 @@ public:
class EditorPropertyEnum : public EditorProperty {
GDCLASS(EditorPropertyEnum, EditorProperty);
- OptionButton *options;
+ OptionButton *options = nullptr;
void _option_selected(int p_which);
@@ -263,7 +263,7 @@ public:
class EditorPropertyFlags : public EditorProperty {
GDCLASS(EditorPropertyFlags, EditorProperty);
- VBoxContainer *vbox;
+ VBoxContainer *vbox = nullptr;
Vector<CheckBox *> flags;
Vector<int> flag_indices;
@@ -293,9 +293,9 @@ private:
int hovered_index = -1;
bool read_only = false;
int renamed_layer_index = -1;
- PopupMenu *layer_rename;
- ConfirmationDialog *rename_dialog;
- LineEdit *rename_dialog_text;
+ PopupMenu *layer_rename = nullptr;
+ ConfirmationDialog *rename_dialog = nullptr;
+ LineEdit *rename_dialog_text = nullptr;
void _rename_pressed(int p_menu);
void _rename_operation_confirm();
@@ -334,12 +334,12 @@ public:
};
private:
- EditorPropertyLayersGrid *grid;
+ EditorPropertyLayersGrid *grid = nullptr;
void _grid_changed(uint32_t p_grid);
String basename;
LayerType layer_type;
- PopupMenu *layers;
- Button *button;
+ PopupMenu *layers = nullptr;
+ Button *button = nullptr;
void _button_pressed();
void _menu_pressed(int p_menu);
@@ -358,7 +358,7 @@ public:
class EditorPropertyInteger : public EditorProperty {
GDCLASS(EditorPropertyInteger, EditorProperty);
- EditorSpinSlider *spin;
+ EditorSpinSlider *spin = nullptr;
bool setting = false;
void _value_changed(int64_t p_val);
@@ -374,7 +374,7 @@ public:
class EditorPropertyObjectID : public EditorProperty {
GDCLASS(EditorPropertyObjectID, EditorProperty);
- Button *edit;
+ Button *edit = nullptr;
String base_type;
void _edit_pressed();
@@ -390,7 +390,7 @@ public:
class EditorPropertyFloat : public EditorProperty {
GDCLASS(EditorPropertyFloat, EditorProperty);
- EditorSpinSlider *spin;
+ EditorSpinSlider *spin = nullptr;
bool setting = false;
bool angle_in_radians = false;
void _value_changed(double p_val);
@@ -407,9 +407,9 @@ public:
class EditorPropertyEasing : public EditorProperty {
GDCLASS(EditorPropertyEasing, EditorProperty);
- Control *easing_draw;
- PopupMenu *preset;
- EditorSpinSlider *spin;
+ Control *easing_draw = nullptr;
+ PopupMenu *preset = nullptr;
+ EditorSpinSlider *spin = nullptr;
bool setting = false;
bool dragging = false;
@@ -657,7 +657,7 @@ public:
class EditorPropertyColor : public EditorProperty {
GDCLASS(EditorPropertyColor, EditorProperty);
- ColorPickerButton *picker;
+ ColorPickerButton *picker = nullptr;
void _color_changed(const Color &p_color);
void _popup_closed();
void _picker_created();
@@ -677,9 +677,9 @@ public:
class EditorPropertyNodePath : public EditorProperty {
GDCLASS(EditorPropertyNodePath, EditorProperty);
- Button *assign;
- Button *clear;
- SceneTreeDialog *scene_tree;
+ Button *assign = nullptr;
+ Button *clear = nullptr;
+ SceneTreeDialog *scene_tree = nullptr;
NodePath base_hint;
bool use_path_from_scene_root = false;
@@ -705,7 +705,7 @@ public:
class EditorPropertyRID : public EditorProperty {
GDCLASS(EditorPropertyRID, EditorProperty);
- Label *label;
+ Label *label = nullptr;
public:
virtual void update_property() override;
diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h
index 3d9fe90b20..070353c538 100644
--- a/editor/editor_properties_array_dict.h
+++ b/editor/editor_properties_array_dict.h
@@ -80,7 +80,7 @@ public:
class EditorPropertyArray : public EditorProperty {
GDCLASS(EditorPropertyArray, EditorProperty);
- PopupMenu *change_type;
+ PopupMenu *change_type = nullptr;
bool updating = false;
bool dropping = false;
@@ -88,12 +88,12 @@ class EditorPropertyArray : public EditorProperty {
int page_length = 20;
int page_index = 0;
int changing_type_index;
- Button *edit;
- VBoxContainer *vbox;
- VBoxContainer *property_vbox;
- EditorSpinSlider *size_slider;
- Button *button_add_item;
- EditorPaginator *paginator;
+ Button *edit = nullptr;
+ VBoxContainer *vbox = nullptr;
+ VBoxContainer *property_vbox = nullptr;
+ EditorSpinSlider *size_slider = nullptr;
+ Button *button_add_item = nullptr;
+ EditorPaginator *paginator = nullptr;
Variant::Type array_type;
Variant::Type subtype;
PropertyHint subtype_hint;
@@ -138,19 +138,19 @@ public:
class EditorPropertyDictionary : public EditorProperty {
GDCLASS(EditorPropertyDictionary, EditorProperty);
- PopupMenu *change_type;
+ PopupMenu *change_type = nullptr;
bool updating = false;
Ref<EditorPropertyDictionaryObject> object;
int page_length = 20;
int page_index = 0;
int changing_type_index;
- Button *edit;
- VBoxContainer *vbox;
- VBoxContainer *property_vbox;
- EditorSpinSlider *size_slider;
- Button *button_add_item;
- EditorPaginator *paginator;
+ Button *edit = nullptr;
+ VBoxContainer *vbox = nullptr;
+ VBoxContainer *property_vbox = nullptr;
+ EditorSpinSlider *size_slider = nullptr;
+ Button *button_add_item = nullptr;
+ EditorPaginator *paginator = nullptr;
void _page_changed(int p_page);
void _edit_pressed();
@@ -173,19 +173,19 @@ public:
class EditorPropertyLocalizableString : public EditorProperty {
GDCLASS(EditorPropertyLocalizableString, EditorProperty);
- EditorLocaleDialog *locale_select;
+ EditorLocaleDialog *locale_select = nullptr;
bool updating;
Ref<EditorPropertyDictionaryObject> object;
int page_length = 20;
int page_index = 0;
- Button *edit;
- VBoxContainer *vbox;
- VBoxContainer *property_vbox;
- EditorSpinSlider *size_slider;
- Button *button_add_item;
- EditorPaginator *paginator;
+ Button *edit = nullptr;
+ VBoxContainer *vbox = nullptr;
+ VBoxContainer *property_vbox = nullptr;
+ EditorSpinSlider *size_slider = nullptr;
+ Button *button_add_item = nullptr;
+ EditorPaginator *paginator = nullptr;
void _page_changed(int p_page);
void _edit_pressed();
diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp
index 5e6c35806c..5b5d451df9 100644
--- a/editor/editor_property_name_processor.cpp
+++ b/editor/editor_property_name_processor.cpp
@@ -117,17 +117,23 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["bvh"] = "BVH";
capitalize_string_remaps["ca"] = "CA";
capitalize_string_remaps["cd"] = "CD";
+ capitalize_string_remaps["commentfocus"] = "Comment Focus";
capitalize_string_remaps["cpu"] = "CPU";
capitalize_string_remaps["csg"] = "CSG";
capitalize_string_remaps["db"] = "dB";
+ capitalize_string_remaps["defaultfocus"] = "Default Focus";
+ capitalize_string_remaps["defaultframe"] = "Default Frame";
capitalize_string_remaps["dof"] = "DoF";
capitalize_string_remaps["dpi"] = "DPI";
capitalize_string_remaps["dtls"] = "DTLS";
+ capitalize_string_remaps["eol"] = "EOL";
capitalize_string_remaps["erp"] = "ERP";
capitalize_string_remaps["etc"] = "ETC";
capitalize_string_remaps["etc2"] = "ETC2";
capitalize_string_remaps["fbx"] = "FBX";
+ capitalize_string_remaps["fbx2gltf"] = "FBX2glTF";
capitalize_string_remaps["fft"] = "FFT";
+ capitalize_string_remaps["fg"] = "FG";
capitalize_string_remaps["fov"] = "FOV";
capitalize_string_remaps["fps"] = "FPS";
capitalize_string_remaps["fs"] = "FS";
@@ -145,6 +151,8 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["hdr"] = "HDR";
capitalize_string_remaps["hidpi"] = "hiDPI";
capitalize_string_remaps["hipass"] = "High-pass";
+ capitalize_string_remaps["hl"] = "HL";
+ capitalize_string_remaps["hseparation"] = "H Separation";
capitalize_string_remaps["hsv"] = "HSV";
capitalize_string_remaps["html"] = "HTML";
capitalize_string_remaps["http"] = "HTTP";
@@ -177,6 +185,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["msaa"] = "MSAA";
capitalize_string_remaps["nfc"] = "NFC";
capitalize_string_remaps["normalmap"] = "Normal Map";
+ capitalize_string_remaps["ofs"] = "Offset";
capitalize_string_remaps["ok"] = "OK";
capitalize_string_remaps["opengl"] = "OpenGL";
capitalize_string_remaps["opentype"] = "OpenType";
@@ -195,6 +204,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["sdfgi"] = "SDFGI";
capitalize_string_remaps["sdk"] = "SDK";
capitalize_string_remaps["sec"] = "(sec)"; // Unit.
+ capitalize_string_remaps["selectedframe"] = "Selected Frame";
capitalize_string_remaps["sms"] = "SMS";
capitalize_string_remaps["srgb"] = "sRGB";
capitalize_string_remaps["ssao"] = "SSAO";
@@ -203,6 +213,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["ssl"] = "SSL";
capitalize_string_remaps["stderr"] = "stderr";
capitalize_string_remaps["stdout"] = "stdout";
+ capitalize_string_remaps["sv"] = "SV";
capitalize_string_remaps["svg"] = "SVG";
capitalize_string_remaps["tcp"] = "TCP";
capitalize_string_remaps["ui"] = "UI";
@@ -216,9 +227,11 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() {
capitalize_string_remaps["uv1"] = "UV1";
capitalize_string_remaps["uv2"] = "UV2";
capitalize_string_remaps["uwp"] = "UWP";
+ capitalize_string_remaps["vadjust"] = "V Adjust";
capitalize_string_remaps["vector2"] = "Vector2";
capitalize_string_remaps["vpn"] = "VPN";
capitalize_string_remaps["vram"] = "VRAM";
+ capitalize_string_remaps["vseparation"] = "V Separation";
capitalize_string_remaps["vsync"] = "V-Sync";
capitalize_string_remaps["wap"] = "WAP";
capitalize_string_remaps["webp"] = "WebP";
diff --git a/editor/editor_resource_picker.h b/editor/editor_resource_picker.h
index a6eff760e7..cd7e507984 100644
--- a/editor/editor_resource_picker.h
+++ b/editor/editor_resource_picker.h
@@ -52,9 +52,9 @@ class EditorResourcePicker : public HBoxContainer {
Vector<String> inheritors_array;
- Button *assign_button;
- TextureRect *preview_rect;
- Button *edit_button;
+ Button *assign_button = nullptr;
+ TextureRect *preview_rect = nullptr;
+ Button *edit_button = nullptr;
EditorFileDialog *file_dialog = nullptr;
EditorQuickOpen *quick_open = nullptr;
diff --git a/editor/editor_run_script.h b/editor/editor_run_script.h
index 28a854aaeb..a2399bd780 100644
--- a/editor/editor_run_script.h
+++ b/editor/editor_run_script.h
@@ -39,7 +39,7 @@ class EditorNode;
class EditorScript : public RefCounted {
GDCLASS(EditorScript, RefCounted);
- EditorNode *editor;
+ EditorNode *editor = nullptr;
protected:
static void _bind_methods();
diff --git a/editor/editor_sectioned_inspector.h b/editor/editor_sectioned_inspector.h
index 7c21e00c03..0ccffa0048 100644
--- a/editor/editor_sectioned_inspector.h
+++ b/editor/editor_sectioned_inspector.h
@@ -42,11 +42,11 @@ class SectionedInspector : public HSplitContainer {
ObjectID obj;
- Tree *sections;
- SectionedInspectorFilter *filter;
+ Tree *sections = nullptr;
+ SectionedInspectorFilter *filter = nullptr;
Map<String, TreeItem *> section_map;
- EditorInspector *inspector;
+ EditorInspector *inspector = nullptr;
LineEdit *search_box = nullptr;
String selected_category;
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 1364f7891e..461f640578 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -542,7 +542,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/behavior/navigation/move_caret_on_right_click", true);
_initial_set("text_editor/behavior/navigation/scroll_past_end_of_file", false);
_initial_set("text_editor/behavior/navigation/smooth_scrolling", true);
- _initial_set("text_editor/behavior/navigation/v_scroll_speed", 80);
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "text_editor/behavior/navigation/v_scroll_speed", 80, "1,10000,1")
// Behavior: Indent
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "text_editor/behavior/indent/type", 0, "Tabs,Spaces")
@@ -1365,7 +1365,7 @@ String EditorSettings::get_editor_layouts_config() const {
}
float EditorSettings::get_auto_display_scale() const {
-#ifdef OSX_ENABLED
+#if defined(OSX_ENABLED) || defined(ANDROID_ENABLED)
return DisplayServer::get_singleton()->screen_get_max_scale();
#else
const int screen = DisplayServer::get_singleton()->window_get_current_screen();
diff --git a/editor/editor_settings_dialog.h b/editor/editor_settings_dialog.h
index e3139bb07a..42831c9ebd 100644
--- a/editor/editor_settings_dialog.h
+++ b/editor/editor_settings_dialog.h
@@ -45,13 +45,13 @@ class EditorSettingsDialog : public AcceptDialog {
bool updating = false;
- TabContainer *tabs;
- Control *tab_general;
- Control *tab_shortcuts;
+ TabContainer *tabs = nullptr;
+ Control *tab_general = nullptr;
+ Control *tab_shortcuts = nullptr;
- LineEdit *search_box;
- LineEdit *shortcut_search_box;
- SectionedInspector *inspector;
+ LineEdit *search_box = nullptr;
+ LineEdit *shortcut_search_box = nullptr;
+ SectionedInspector *inspector = nullptr;
// Shortcuts
enum ShortcutButton {
@@ -61,19 +61,19 @@ class EditorSettingsDialog : public AcceptDialog {
SHORTCUT_REVERT
};
- Tree *shortcuts;
+ Tree *shortcuts = nullptr;
String shortcut_filter;
- InputEventConfigurationDialog *shortcut_editor;
+ InputEventConfigurationDialog *shortcut_editor = nullptr;
bool is_editing_action = false;
String current_edited_identifier;
Array current_events;
int current_event_index = -1;
- Timer *timer;
+ Timer *timer = nullptr;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
virtual void cancel_pressed() override;
virtual void ok_pressed() override;
@@ -110,10 +110,10 @@ class EditorSettingsDialog : public AcceptDialog {
static void _undo_redo_callback(void *p_self, const String &p_name);
- Label *restart_label;
- TextureRect *restart_icon;
- PanelContainer *restart_container;
- Button *restart_close_button;
+ Label *restart_label = nullptr;
+ TextureRect *restart_icon = nullptr;
+ PanelContainer *restart_container = nullptr;
+ Button *restart_close_button = nullptr;
void _editor_restart_request();
void _editor_restart();
diff --git a/editor/editor_spin_slider.h b/editor/editor_spin_slider.h
index 405c3bfc22..fc9f6b8722 100644
--- a/editor/editor_spin_slider.h
+++ b/editor/editor_spin_slider.h
@@ -44,7 +44,7 @@ class EditorSpinSlider : public Range {
bool hover_updown = false;
bool mouse_hover = false;
- TextureRect *grabber;
+ TextureRect *grabber = nullptr;
int grabber_range;
bool mouse_over_spin = false;
diff --git a/editor/editor_toaster.h b/editor/editor_toaster.h
index 059245ce66..791a146a8d 100644
--- a/editor/editor_toaster.h
+++ b/editor/editor_toaster.h
@@ -61,11 +61,11 @@ private:
Ref<StyleBoxFlat> warning_panel_style_progress;
Ref<StyleBoxFlat> error_panel_style_progress;
- Button *main_button;
- PanelContainer *disable_notifications_panel;
- Button *disable_notifications_button;
+ Button *main_button = nullptr;
+ PanelContainer *disable_notifications_panel = nullptr;
+ Button *disable_notifications_button = nullptr;
- VBoxContainer *vbox_container;
+ VBoxContainer *vbox_container = nullptr;
const int max_temporary_count = 5;
struct Toast {
Severity severity = SEVERITY_INFO;
diff --git a/editor/editor_zoom_widget.h b/editor/editor_zoom_widget.h
index bf8358ff1a..4690a57a2b 100644
--- a/editor/editor_zoom_widget.h
+++ b/editor/editor_zoom_widget.h
@@ -37,9 +37,9 @@
class EditorZoomWidget : public HBoxContainer {
GDCLASS(EditorZoomWidget, HBoxContainer);
- Button *zoom_minus;
- Button *zoom_reset;
- Button *zoom_plus;
+ Button *zoom_minus = nullptr;
+ Button *zoom_reset = nullptr;
+ Button *zoom_plus = nullptr;
float zoom = 1.0;
void _update_zoom_label();
diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h
index cf7585635d..61df212f1f 100644
--- a/editor/export_template_manager.h
+++ b/editor/export_template_manager.h
@@ -51,42 +51,42 @@ class ExportTemplateManager : public AcceptDialog {
bool is_downloading_templates = false;
float update_countdown = 0;
- Label *current_value;
- Label *current_missing_label;
- Label *current_installed_label;
+ Label *current_value = nullptr;
+ Label *current_missing_label = nullptr;
+ Label *current_installed_label = nullptr;
- HBoxContainer *current_installed_hb;
- LineEdit *current_installed_path;
- Button *current_open_button;
- Button *current_uninstall_button;
+ HBoxContainer *current_installed_hb = nullptr;
+ LineEdit *current_installed_path = nullptr;
+ Button *current_open_button = nullptr;
+ Button *current_uninstall_button = nullptr;
- VBoxContainer *install_options_vb;
- OptionButton *mirrors_list;
+ VBoxContainer *install_options_vb = nullptr;
+ OptionButton *mirrors_list = nullptr;
enum MirrorAction {
VISIT_WEB_MIRROR,
COPY_MIRROR_URL,
};
- MenuButton *mirror_options_button;
- HBoxContainer *download_progress_hb;
- ProgressBar *download_progress_bar;
- Label *download_progress_label;
- HTTPRequest *download_templates;
- Button *install_file_button;
- HTTPRequest *request_mirrors;
+ MenuButton *mirror_options_button = nullptr;
+ HBoxContainer *download_progress_hb = nullptr;
+ ProgressBar *download_progress_bar = nullptr;
+ Label *download_progress_label = nullptr;
+ HTTPRequest *download_templates = nullptr;
+ Button *install_file_button = nullptr;
+ HTTPRequest *request_mirrors = nullptr;
enum TemplatesAction {
OPEN_TEMPLATE_FOLDER,
UNINSTALL_TEMPLATE,
};
- Tree *installed_table;
+ Tree *installed_table = nullptr;
- ConfirmationDialog *uninstall_confirm;
+ ConfirmationDialog *uninstall_confirm = nullptr;
String uninstall_version;
- FileDialog *install_file_dialog;
- AcceptDialog *hide_dialog_accept;
+ FileDialog *install_file_dialog = nullptr;
+ AcceptDialog *hide_dialog_accept = nullptr;
void _update_template_status();
diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h
index 7807e72800..a1bb7ecf4e 100644
--- a/editor/fileserver/editor_file_server.h
+++ b/editor/fileserver/editor_file_server.h
@@ -47,7 +47,7 @@ class EditorFileServer : public Object {
};
struct ClientData {
- Thread *thread;
+ Thread *thread = nullptr;
Ref<StreamPeerTCP> connection;
Map<int, FileAccess *> files;
EditorFileServer *efs = nullptr;
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 92dac374ec..15fade2d95 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -102,57 +102,57 @@ private:
FileSortOption file_sort = FILE_SORT_NAME;
- VBoxContainer *scanning_vb;
- ProgressBar *scanning_progress;
- VSplitContainer *split_box;
- VBoxContainer *file_list_vb;
+ VBoxContainer *scanning_vb = nullptr;
+ ProgressBar *scanning_progress = nullptr;
+ VSplitContainer *split_box = nullptr;
+ VBoxContainer *file_list_vb = nullptr;
Set<String> favorites;
- Button *button_toggle_display_mode;
- Button *button_reload;
- Button *button_file_list_display_mode;
- Button *button_hist_next;
- Button *button_hist_prev;
- LineEdit *current_path;
+ Button *button_toggle_display_mode = nullptr;
+ Button *button_reload = nullptr;
+ Button *button_file_list_display_mode = nullptr;
+ Button *button_hist_next = nullptr;
+ Button *button_hist_prev = nullptr;
+ LineEdit *current_path = nullptr;
- HBoxContainer *toolbar2_hbc;
- LineEdit *tree_search_box;
- MenuButton *tree_button_sort;
+ HBoxContainer *toolbar2_hbc = nullptr;
+ LineEdit *tree_search_box = nullptr;
+ MenuButton *tree_button_sort = nullptr;
- LineEdit *file_list_search_box;
- MenuButton *file_list_button_sort;
+ LineEdit *file_list_search_box = nullptr;
+ MenuButton *file_list_button_sort = nullptr;
String searched_string;
Vector<String> uncollapsed_paths_before_search;
- TextureRect *search_icon;
- HBoxContainer *path_hb;
+ TextureRect *search_icon = nullptr;
+ HBoxContainer *path_hb = nullptr;
FileListDisplayMode file_list_display_mode;
DisplayMode display_mode;
DisplayMode old_display_mode;
- PopupMenu *file_list_popup;
- PopupMenu *tree_popup;
-
- DependencyEditor *deps_editor;
- DependencyEditorOwners *owners_editor;
- DependencyRemoveDialog *remove_dialog;
-
- EditorDirDialog *move_dialog;
- ConfirmationDialog *rename_dialog;
- LineEdit *rename_dialog_text;
- ConfirmationDialog *duplicate_dialog;
- LineEdit *duplicate_dialog_text;
- ConfirmationDialog *make_dir_dialog;
- LineEdit *make_dir_dialog_text;
- ConfirmationDialog *make_scene_dialog;
- LineEdit *make_scene_dialog_text;
- ConfirmationDialog *overwrite_dialog;
- ScriptCreateDialog *make_script_dialog;
- ShaderCreateDialog *make_shader_dialog;
- CreateDialog *new_resource_dialog;
+ PopupMenu *file_list_popup = nullptr;
+ PopupMenu *tree_popup = nullptr;
+
+ DependencyEditor *deps_editor = nullptr;
+ DependencyEditorOwners *owners_editor = nullptr;
+ DependencyRemoveDialog *remove_dialog = nullptr;
+
+ EditorDirDialog *move_dialog = nullptr;
+ ConfirmationDialog *rename_dialog = nullptr;
+ LineEdit *rename_dialog_text = nullptr;
+ ConfirmationDialog *duplicate_dialog = nullptr;
+ LineEdit *duplicate_dialog_text = nullptr;
+ ConfirmationDialog *make_dir_dialog = nullptr;
+ LineEdit *make_dir_dialog_text = nullptr;
+ ConfirmationDialog *make_scene_dialog = nullptr;
+ LineEdit *make_scene_dialog_text = nullptr;
+ ConfirmationDialog *overwrite_dialog = nullptr;
+ ScriptCreateDialog *make_script_dialog = nullptr;
+ ShaderCreateDialog *make_shader_dialog = nullptr;
+ CreateDialog *new_resource_dialog = nullptr;
bool always_show_folders = false;
@@ -181,8 +181,8 @@ private:
bool updating_tree = false;
int tree_update_id;
- Tree *tree;
- ItemList *files;
+ Tree *tree = nullptr;
+ ItemList *files = nullptr;
bool import_dock_needs_update = false;
bool holding_branch = false;
diff --git a/editor/find_in_files.h b/editor/find_in_files.h
index cf14f3d5c3..9def190b5b 100644
--- a/editor/find_in_files.h
+++ b/editor/find_in_files.h
@@ -132,18 +132,18 @@ private:
void _on_replace_text_submitted(String text);
FindInFilesMode _mode;
- LineEdit *_search_text_line_edit;
-
- Label *_replace_label;
- LineEdit *_replace_text_line_edit;
-
- LineEdit *_folder_line_edit;
- CheckBox *_match_case_checkbox;
- CheckBox *_whole_words_checkbox;
- Button *_find_button;
- Button *_replace_button;
- FileDialog *_folder_dialog;
- HBoxContainer *_filters_container;
+ LineEdit *_search_text_line_edit = nullptr;
+
+ Label *_replace_label = nullptr;
+ LineEdit *_replace_text_line_edit = nullptr;
+
+ LineEdit *_folder_line_edit = nullptr;
+ CheckBox *_match_case_checkbox = nullptr;
+ CheckBox *_whole_words_checkbox = nullptr;
+ Button *_find_button = nullptr;
+ Button *_replace_button = nullptr;
+ FileDialog *_folder_dialog = nullptr;
+ HBoxContainer *_filters_container = nullptr;
HashMap<String, bool> _filters_preferences;
};
@@ -201,20 +201,20 @@ private:
void set_progress_visible(bool visible);
void clear();
- FindInFiles *_finder;
- Label *_search_text_label;
- Tree *_results_display;
- Label *_status_label;
- Button *_refresh_button;
- Button *_cancel_button;
- ProgressBar *_progress_bar;
+ FindInFiles *_finder = nullptr;
+ Label *_search_text_label = nullptr;
+ Tree *_results_display = nullptr;
+ Label *_status_label = nullptr;
+ Button *_refresh_button = nullptr;
+ Button *_cancel_button = nullptr;
+ ProgressBar *_progress_bar = nullptr;
Map<String, TreeItem *> _file_items;
Map<TreeItem *, Result> _result_items;
bool _with_replace = false;
- HBoxContainer *_replace_container;
- LineEdit *_replace_line_edit;
- Button *_replace_all_button;
+ HBoxContainer *_replace_container = nullptr;
+ LineEdit *_replace_line_edit = nullptr;
+ Button *_replace_all_button = nullptr;
};
#endif // FIND_IN_FILES_H
diff --git a/editor/groups_editor.h b/editor/groups_editor.h
index aa70ac5bc4..b6a6204013 100644
--- a/editor/groups_editor.h
+++ b/editor/groups_editor.h
@@ -43,32 +43,32 @@
class GroupDialog : public AcceptDialog {
GDCLASS(GroupDialog, AcceptDialog);
- ConfirmationDialog *error;
+ ConfirmationDialog *error = nullptr;
- SceneTree *scene_tree;
- TreeItem *groups_root;
+ SceneTree *scene_tree = nullptr;
+ TreeItem *groups_root = nullptr;
- LineEdit *add_group_text;
- Button *add_group_button;
+ LineEdit *add_group_text = nullptr;
+ Button *add_group_button = nullptr;
- Tree *groups;
+ Tree *groups = nullptr;
- Tree *nodes_to_add;
- TreeItem *add_node_root;
- LineEdit *add_filter;
+ Tree *nodes_to_add = nullptr;
+ TreeItem *add_node_root = nullptr;
+ LineEdit *add_filter = nullptr;
- Tree *nodes_to_remove;
- TreeItem *remove_node_root;
- LineEdit *remove_filter;
+ Tree *nodes_to_remove = nullptr;
+ TreeItem *remove_node_root = nullptr;
+ LineEdit *remove_filter = nullptr;
- Label *group_empty;
+ Label *group_empty = nullptr;
- Button *add_button;
- Button *remove_button;
+ Button *add_button = nullptr;
+ Button *remove_button = nullptr;
String selected_group;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
void _group_selected();
@@ -111,15 +111,15 @@ public:
class GroupsEditor : public VBoxContainer {
GDCLASS(GroupsEditor, VBoxContainer);
- Node *node;
+ Node *node = nullptr;
- GroupDialog *group_dialog;
+ GroupDialog *group_dialog = nullptr;
- LineEdit *group_name;
- Button *add;
- Tree *tree;
+ LineEdit *group_name = nullptr;
+ Button *add = nullptr;
+ Tree *tree = nullptr;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
void update_tree();
void _add_group(const String &p_group = "");
diff --git a/editor/import/dynamic_font_import_settings.h b/editor/import/dynamic_font_import_settings.h
index 7b2a9184a4..c1e868403f 100644
--- a/editor/import/dynamic_font_import_settings.h
+++ b/editor/import/dynamic_font_import_settings.h
@@ -66,7 +66,7 @@ class DynamicFontImportSettings : public ConfirmationDialog {
List<ResourceImporter::ImportOption> options_variations;
List<ResourceImporter::ImportOption> options_general;
- EditorLocaleDialog *locale_select;
+ EditorLocaleDialog *locale_select = nullptr;
Vector<String> script_codes;
// Root layout
diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h
index b51f342729..3cf708740b 100644
--- a/editor/import/scene_import_settings.h
+++ b/editor/import/scene_import_settings.h
@@ -62,26 +62,26 @@ class SceneImportSettings : public ConfirmationDialog {
Node *scene = nullptr;
- HSplitContainer *tree_split;
- HSplitContainer *property_split;
- TabContainer *data_mode;
- Tree *scene_tree;
- Tree *mesh_tree;
- Tree *material_tree;
+ HSplitContainer *tree_split = nullptr;
+ HSplitContainer *property_split = nullptr;
+ TabContainer *data_mode = nullptr;
+ Tree *scene_tree = nullptr;
+ Tree *mesh_tree = nullptr;
+ Tree *material_tree = nullptr;
- EditorInspector *inspector;
+ EditorInspector *inspector = nullptr;
- SubViewport *base_viewport;
+ SubViewport *base_viewport = nullptr;
- Camera3D *camera;
+ Camera3D *camera = nullptr;
bool first_aabb = false;
AABB contents_aabb;
- DirectionalLight3D *light;
+ DirectionalLight3D *light = nullptr;
Ref<ArrayMesh> selection_mesh;
- MeshInstance3D *node_selected;
+ MeshInstance3D *node_selected = nullptr;
- MeshInstance3D *mesh_preview;
+ MeshInstance3D *mesh_preview = nullptr;
Ref<SphereMesh> material_preview;
Ref<StandardMaterial3D> collider_mat;
@@ -95,9 +95,9 @@ class SceneImportSettings : public ConfirmationDialog {
struct MaterialData {
bool has_import_id;
Ref<Material> material;
- TreeItem *scene_node;
- TreeItem *mesh_node;
- TreeItem *material_node;
+ TreeItem *scene_node = nullptr;
+ TreeItem *mesh_node = nullptr;
+ TreeItem *material_node = nullptr;
float cam_rot_x = -Math_PI / 4;
float cam_rot_y = -Math_PI / 4;
@@ -110,8 +110,8 @@ class SceneImportSettings : public ConfirmationDialog {
struct MeshData {
bool has_import_id;
Ref<Mesh> mesh;
- TreeItem *scene_node;
- TreeItem *mesh_node;
+ TreeItem *scene_node = nullptr;
+ TreeItem *mesh_node = nullptr;
float cam_rot_x = -Math_PI / 4;
float cam_rot_y = -Math_PI / 4;
@@ -122,14 +122,14 @@ class SceneImportSettings : public ConfirmationDialog {
struct AnimationData {
Ref<Animation> animation;
- TreeItem *scene_node;
+ TreeItem *scene_node = nullptr;
Map<StringName, Variant> settings;
};
Map<String, AnimationData> animation_map;
struct NodeData {
- Node *node;
- TreeItem *scene_node;
+ Node *node = nullptr;
+ TreeItem *scene_node = nullptr;
Map<StringName, Variant> settings;
};
Map<String, NodeData> node_map;
@@ -158,20 +158,20 @@ class SceneImportSettings : public ConfirmationDialog {
Map<StringName, Variant> defaults;
- SceneImportSettingsData *scene_import_settings_data;
+ SceneImportSettingsData *scene_import_settings_data = nullptr;
void _re_import();
String base_path;
- MenuButton *action_menu;
+ MenuButton *action_menu = nullptr;
- ConfirmationDialog *external_paths;
- Tree *external_path_tree;
- EditorFileDialog *save_path;
- OptionButton *external_extension_type;
+ ConfirmationDialog *external_paths = nullptr;
+ Tree *external_path_tree = nullptr;
+ EditorFileDialog *save_path = nullptr;
+ OptionButton *external_extension_type = nullptr;
- EditorFileDialog *item_save_path;
+ EditorFileDialog *item_save_path = nullptr;
void _menu_callback(int p_id);
void _save_dir_callback(const String &p_path);
diff --git a/editor/import_defaults_editor.h b/editor/import_defaults_editor.h
index ed94fe6156..f0433f6065 100644
--- a/editor/import_defaults_editor.h
+++ b/editor/import_defaults_editor.h
@@ -41,13 +41,13 @@ class EditorInspector;
class ImportDefaultsEditor : public VBoxContainer {
GDCLASS(ImportDefaultsEditor, VBoxContainer)
- OptionButton *importers;
- Button *save_defaults;
- Button *reset_defaults;
+ OptionButton *importers = nullptr;
+ Button *save_defaults = nullptr;
+ Button *reset_defaults = nullptr;
- EditorInspector *inspector;
+ EditorInspector *inspector = nullptr;
- ImportDefaultsEditorSettings *settings;
+ ImportDefaultsEditorSettings *settings = nullptr;
void _update_importer();
void _importer_selected(int p_index);
diff --git a/editor/import_dock.h b/editor/import_dock.h
index c5cdc4ac40..f522b0bced 100644
--- a/editor/import_dock.h
+++ b/editor/import_dock.h
@@ -45,25 +45,25 @@ class ImportDockParameters;
class ImportDock : public VBoxContainer {
GDCLASS(ImportDock, VBoxContainer);
- Label *imported;
- OptionButton *import_as;
- MenuButton *preset;
- EditorInspector *import_opts;
+ Label *imported = nullptr;
+ OptionButton *import_as = nullptr;
+ MenuButton *preset = nullptr;
+ EditorInspector *import_opts = nullptr;
List<PropertyInfo> properties;
Map<StringName, Variant> property_values;
- ConfirmationDialog *reimport_confirm;
- Label *label_warning;
- Button *import;
+ ConfirmationDialog *reimport_confirm = nullptr;
+ Label *label_warning = nullptr;
+ Button *import = nullptr;
- Control *advanced_spacer;
- Button *advanced;
+ Control *advanced_spacer = nullptr;
+ Button *advanced = nullptr;
- ImportDockParameters *params;
+ ImportDockParameters *params = nullptr;
- VBoxContainer *content;
- Label *select_a_resource;
+ VBoxContainer *content = nullptr;
+ Label *select_a_resource = nullptr;
void _preset_selected(int p_idx);
void _importer_selected(int i_idx);
diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h
index 7e653c4750..86733c992d 100644
--- a/editor/inspector_dock.h
+++ b/editor/inspector_dock.h
@@ -70,34 +70,34 @@ class InspectorDock : public VBoxContainer {
OBJECT_METHOD_BASE = 500
};
- EditorData *editor_data;
+ EditorData *editor_data = nullptr;
- EditorInspector *inspector;
+ EditorInspector *inspector = nullptr;
- Object *current;
+ Object *current = nullptr;
- Button *backward_button;
- Button *forward_button;
+ Button *backward_button = nullptr;
+ Button *forward_button = nullptr;
- EditorFileDialog *load_resource_dialog;
- CreateDialog *new_resource_dialog;
- Button *resource_new_button;
- Button *resource_load_button;
- MenuButton *resource_save_button;
- MenuButton *resource_extra_button;
- MenuButton *history_menu;
- LineEdit *search;
+ EditorFileDialog *load_resource_dialog = nullptr;
+ CreateDialog *new_resource_dialog = nullptr;
+ Button *resource_new_button = nullptr;
+ Button *resource_load_button = nullptr;
+ MenuButton *resource_save_button = nullptr;
+ MenuButton *resource_extra_button = nullptr;
+ MenuButton *history_menu = nullptr;
+ LineEdit *search = nullptr;
- Button *open_docs_button;
- MenuButton *object_menu;
- EditorPath *editor_path;
+ Button *open_docs_button = nullptr;
+ MenuButton *object_menu = nullptr;
+ EditorPath *editor_path = nullptr;
- Button *warning;
- AcceptDialog *warning_dialog;
+ Button *warning = nullptr;
+ AcceptDialog *warning_dialog = nullptr;
int current_option = -1;
- ConfirmationDialog *unique_resources_confirmation;
- Tree *unique_resources_list_tree;
+ ConfirmationDialog *unique_resources_confirmation = nullptr;
+ Tree *unique_resources_list_tree = nullptr;
EditorPropertyNameProcessor::Style property_name_style;
diff --git a/editor/localization_editor.h b/editor/localization_editor.h
index 3424ba7c55..966ef0f36e 100644
--- a/editor/localization_editor.h
+++ b/editor/localization_editor.h
@@ -40,22 +40,22 @@ class EditorFileDialog;
class LocalizationEditor : public VBoxContainer {
GDCLASS(LocalizationEditor, VBoxContainer);
- Tree *translation_list;
+ Tree *translation_list = nullptr;
- EditorLocaleDialog *locale_select;
- EditorFileDialog *translation_file_open;
+ EditorLocaleDialog *locale_select = nullptr;
+ EditorFileDialog *translation_file_open = nullptr;
- Button *translation_res_option_add_button;
- EditorFileDialog *translation_res_file_open_dialog;
- EditorFileDialog *translation_res_option_file_open_dialog;
- Tree *translation_remap;
- Tree *translation_remap_options;
+ Button *translation_res_option_add_button = nullptr;
+ EditorFileDialog *translation_res_file_open_dialog = nullptr;
+ EditorFileDialog *translation_res_option_file_open_dialog = nullptr;
+ Tree *translation_remap = nullptr;
+ Tree *translation_remap_options = nullptr;
- Tree *translation_pot_list;
- EditorFileDialog *pot_file_open_dialog;
- EditorFileDialog *pot_generate_dialog;
+ Tree *translation_pot_list = nullptr;
+ EditorFileDialog *pot_file_open_dialog = nullptr;
+ EditorFileDialog *pot_generate_dialog = nullptr;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
bool updating_translations = false;
String localization_changed;
diff --git a/editor/node_dock.h b/editor/node_dock.h
index 4c814ab65f..35af1a8121 100644
--- a/editor/node_dock.h
+++ b/editor/node_dock.h
@@ -38,15 +38,15 @@ class ConnectionsDock;
class NodeDock : public VBoxContainer {
GDCLASS(NodeDock, VBoxContainer);
- Button *connections_button;
- Button *groups_button;
+ Button *connections_button = nullptr;
+ Button *groups_button = nullptr;
- ConnectionsDock *connections;
- GroupsEditor *groups;
+ ConnectionsDock *connections = nullptr;
+ GroupsEditor *groups = nullptr;
- HBoxContainer *mode_hb;
+ HBoxContainer *mode_hb = nullptr;
- Label *select_a_node;
+ Label *select_a_node = nullptr;
private:
static NodeDock *singleton;
diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h
index 0dc2e84a98..76fec636f3 100644
--- a/editor/plugin_config_dialog.h
+++ b/editor/plugin_config_dialog.h
@@ -41,18 +41,18 @@
class PluginConfigDialog : public ConfirmationDialog {
GDCLASS(PluginConfigDialog, ConfirmationDialog);
- LineEdit *name_edit;
- LineEdit *subfolder_edit;
- TextEdit *desc_edit;
- LineEdit *author_edit;
- LineEdit *version_edit;
- OptionButton *script_option_edit;
- LineEdit *script_edit;
- CheckBox *active_edit;
+ LineEdit *name_edit = nullptr;
+ LineEdit *subfolder_edit = nullptr;
+ TextEdit *desc_edit = nullptr;
+ LineEdit *author_edit = nullptr;
+ LineEdit *version_edit = nullptr;
+ OptionButton *script_option_edit = nullptr;
+ LineEdit *script_edit = nullptr;
+ CheckBox *active_edit = nullptr;
- TextureRect *name_validation;
- TextureRect *subfolder_validation;
- TextureRect *script_validation;
+ TextureRect *name_validation = nullptr;
+ TextureRect *subfolder_validation = nullptr;
+ TextureRect *script_validation = nullptr;
bool _edit_mode;
diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h
index c0e7c1be2e..b0483cbb62 100644
--- a/editor/plugins/abstract_polygon_2d_editor.h
+++ b/editor/plugins/abstract_polygon_2d_editor.h
@@ -40,9 +40,9 @@ class CanvasItemEditor;
class AbstractPolygon2DEditor : public HBoxContainer {
GDCLASS(AbstractPolygon2DEditor, HBoxContainer);
- Button *button_create;
- Button *button_edit;
- Button *button_delete;
+ Button *button_create = nullptr;
+ Button *button_edit = nullptr;
+ Button *button_delete = nullptr;
struct Vertex {
Vertex() {}
@@ -85,9 +85,9 @@ class AbstractPolygon2DEditor : public HBoxContainer {
bool _polygon_editing_enabled;
- CanvasItemEditor *canvas_item_editor;
- Panel *panel;
- ConfirmationDialog *create_resource;
+ CanvasItemEditor *canvas_item_editor = nullptr;
+ Panel *panel = nullptr;
+ ConfirmationDialog *create_resource = nullptr;
protected:
enum {
@@ -99,7 +99,7 @@ protected:
int mode;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
virtual void _menu_option(int p_option);
void _wip_changed();
@@ -149,7 +149,7 @@ public:
class AbstractPolygon2DEditorPlugin : public EditorPlugin {
GDCLASS(AbstractPolygon2DEditorPlugin, EditorPlugin);
- AbstractPolygon2DEditor *polygon_editor;
+ AbstractPolygon2DEditor *polygon_editor = nullptr;
String klass;
public:
diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h
index 54cded6048..816c2555ca 100644
--- a/editor/plugins/animation_blend_space_1d_editor.h
+++ b/editor/plugins/animation_blend_space_1d_editor.h
@@ -45,36 +45,36 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
Ref<AnimationNodeBlendSpace1D> blend_space;
- HBoxContainer *goto_parent_hb;
- Button *goto_parent;
-
- PanelContainer *panel;
- Button *tool_blend;
- Button *tool_select;
- Button *tool_create;
- VSeparator *tool_erase_sep;
- Button *tool_erase;
- Button *snap;
- SpinBox *snap_value;
-
- LineEdit *label_value;
- SpinBox *max_value;
- SpinBox *min_value;
-
- HBoxContainer *edit_hb;
- SpinBox *edit_value;
- Button *open_editor;
+ HBoxContainer *goto_parent_hb = nullptr;
+ Button *goto_parent = nullptr;
+
+ PanelContainer *panel = nullptr;
+ Button *tool_blend = nullptr;
+ Button *tool_select = nullptr;
+ Button *tool_create = nullptr;
+ VSeparator *tool_erase_sep = nullptr;
+ Button *tool_erase = nullptr;
+ Button *snap = nullptr;
+ SpinBox *snap_value = nullptr;
+
+ LineEdit *label_value = nullptr;
+ SpinBox *max_value = nullptr;
+ SpinBox *min_value = nullptr;
+
+ HBoxContainer *edit_hb = nullptr;
+ SpinBox *edit_value = nullptr;
+ Button *open_editor = nullptr;
int selected_point;
- Control *blend_space_draw;
+ Control *blend_space_draw = nullptr;
- PanelContainer *error_panel;
- Label *error_label;
+ PanelContainer *error_panel = nullptr;
+ Label *error_label = nullptr;
bool updating;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
static AnimationNodeBlendSpace1DEditor *singleton;
@@ -87,8 +87,8 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
void _labels_changed(String);
void _snap_toggled();
- PopupMenu *menu;
- PopupMenu *animations_menu;
+ PopupMenu *menu = nullptr;
+ PopupMenu *animations_menu = nullptr;
Vector<String> animations_to_add;
float add_point_pos;
Vector<real_t> points;
@@ -108,7 +108,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin {
void _edit_point_pos(double);
void _open_editor();
- EditorFileDialog *open_file;
+ EditorFileDialog *open_file = nullptr;
Ref<AnimationNode> file_loaded;
void _file_opened(const String &p_file);
diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h
index 933d2bd96d..db54e84254 100644
--- a/editor/plugins/animation_blend_space_2d_editor.h
+++ b/editor/plugins/animation_blend_space_2d_editor.h
@@ -45,43 +45,43 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
Ref<AnimationNodeBlendSpace2D> blend_space;
- PanelContainer *panel;
- Button *tool_blend;
- Button *tool_select;
- Button *tool_create;
- Button *tool_triangle;
- VSeparator *tool_erase_sep;
- Button *tool_erase;
- Button *snap;
- SpinBox *snap_x;
- SpinBox *snap_y;
- OptionButton *interpolation;
-
- Button *auto_triangles;
-
- LineEdit *label_x;
- LineEdit *label_y;
- SpinBox *max_x_value;
- SpinBox *min_x_value;
- SpinBox *max_y_value;
- SpinBox *min_y_value;
-
- HBoxContainer *edit_hb;
- SpinBox *edit_x;
- SpinBox *edit_y;
- Button *open_editor;
+ PanelContainer *panel = nullptr;
+ Button *tool_blend = nullptr;
+ Button *tool_select = nullptr;
+ Button *tool_create = nullptr;
+ Button *tool_triangle = nullptr;
+ VSeparator *tool_erase_sep = nullptr;
+ Button *tool_erase = nullptr;
+ Button *snap = nullptr;
+ SpinBox *snap_x = nullptr;
+ SpinBox *snap_y = nullptr;
+ OptionButton *interpolation = nullptr;
+
+ Button *auto_triangles = nullptr;
+
+ LineEdit *label_x = nullptr;
+ LineEdit *label_y = nullptr;
+ SpinBox *max_x_value = nullptr;
+ SpinBox *min_x_value = nullptr;
+ SpinBox *max_y_value = nullptr;
+ SpinBox *min_y_value = nullptr;
+
+ HBoxContainer *edit_hb = nullptr;
+ SpinBox *edit_x = nullptr;
+ SpinBox *edit_y = nullptr;
+ Button *open_editor = nullptr;
int selected_point;
int selected_triangle;
- Control *blend_space_draw;
+ Control *blend_space_draw = nullptr;
- PanelContainer *error_panel;
- Label *error_label;
+ PanelContainer *error_panel = nullptr;
+ Label *error_label = nullptr;
bool updating;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
static AnimationNodeBlendSpace2DEditor *singleton;
@@ -94,8 +94,8 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
void _labels_changed(String);
void _snap_toggled();
- PopupMenu *menu;
- PopupMenu *animations_menu;
+ PopupMenu *menu = nullptr;
+ PopupMenu *animations_menu = nullptr;
Vector<String> animations_to_add;
Vector2 add_point_pos;
Vector<Vector2> points;
@@ -123,7 +123,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin {
StringName get_blend_position_path() const;
- EditorFileDialog *open_file;
+ EditorFileDialog *open_file = nullptr;
Ref<AnimationNode> file_loaded;
void _file_opened(const String &p_file);
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h
index c111f9245e..cacf8379f9 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.h
+++ b/editor/plugins/animation_blend_tree_editor_plugin.h
@@ -47,19 +47,19 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin);
Ref<AnimationNodeBlendTree> blend_tree;
- GraphEdit *graph;
- MenuButton *add_node;
+ GraphEdit *graph = nullptr;
+ MenuButton *add_node = nullptr;
Vector2 position_from_popup_menu;
bool use_position_from_popup_menu;
- PanelContainer *error_panel;
- Label *error_label;
+ PanelContainer *error_panel = nullptr;
+ Label *error_label = nullptr;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
- AcceptDialog *filter_dialog;
- Tree *filters;
- CheckBox *filter_enabled;
+ AcceptDialog *filter_dialog = nullptr;
+ Tree *filters = nullptr;
+ CheckBox *filter_enabled = nullptr;
Map<StringName, ProgressBar *> animations;
Vector<EditorProperty *> visible_properties;
@@ -122,7 +122,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin {
void _update_editor_settings();
void _update_theme();
- EditorFileDialog *open_file;
+ EditorFileDialog *open_file = nullptr;
Ref<AnimationNode> file_loaded;
void _file_opened(const String &p_file);
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 5bb32e25e6..850751e47a 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -46,8 +46,8 @@ class AnimationPlayerEditorPlugin;
class AnimationPlayerEditor : public VBoxContainer {
GDCLASS(AnimationPlayerEditor, VBoxContainer);
- AnimationPlayerEditorPlugin *plugin;
- AnimationPlayer *player;
+ AnimationPlayerEditorPlugin *plugin = nullptr;
+ AnimationPlayer *player = nullptr;
enum {
TOOL_NEW_ANIM,
@@ -88,31 +88,31 @@ class AnimationPlayerEditor : public VBoxContainer {
RESOURCE_SAVE
};
- OptionButton *animation;
- Button *stop;
- Button *play;
- Button *play_from;
- Button *play_bw;
- Button *play_bw_from;
- Button *autoplay;
-
- MenuButton *tool_anim;
- Button *onion_toggle;
- MenuButton *onion_skinning;
- Button *pin;
- SpinBox *frame;
- LineEdit *scale;
- LineEdit *name;
- Label *name_title;
- UndoRedo *undo_redo;
+ OptionButton *animation = nullptr;
+ Button *stop = nullptr;
+ Button *play = nullptr;
+ Button *play_from = nullptr;
+ Button *play_bw = nullptr;
+ Button *play_bw_from = nullptr;
+ Button *autoplay = nullptr;
+
+ MenuButton *tool_anim = nullptr;
+ Button *onion_toggle = nullptr;
+ MenuButton *onion_skinning = nullptr;
+ Button *pin = nullptr;
+ SpinBox *frame = nullptr;
+ LineEdit *scale = nullptr;
+ LineEdit *name = nullptr;
+ Label *name_title = nullptr;
+ UndoRedo *undo_redo = nullptr;
Ref<Texture2D> autoplay_icon;
Ref<Texture2D> reset_icon;
Ref<ImageTexture> autoplay_reset_icon;
bool last_active;
float timeline_position;
- EditorFileDialog *file;
- ConfirmationDialog *delete_dialog;
+ EditorFileDialog *file = nullptr;
+ ConfirmationDialog *delete_dialog = nullptr;
struct BlendEditor {
AcceptDialog *dialog = nullptr;
@@ -121,14 +121,14 @@ class AnimationPlayerEditor : public VBoxContainer {
} blend_editor;
- ConfirmationDialog *name_dialog;
- ConfirmationDialog *error_dialog;
+ ConfirmationDialog *name_dialog = nullptr;
+ ConfirmationDialog *error_dialog = nullptr;
int name_dialog_op = TOOL_NEW_ANIM;
bool updating;
bool updating_blends;
- AnimationTrackEditor *track_editor;
+ AnimationTrackEditor *track_editor = nullptr;
static AnimationPlayerEditor *singleton;
// Onion skinning.
@@ -250,7 +250,7 @@ public:
class AnimationPlayerEditorPlugin : public EditorPlugin {
GDCLASS(AnimationPlayerEditorPlugin, EditorPlugin);
- AnimationPlayerEditor *anim_editor;
+ AnimationPlayerEditor *anim_editor = nullptr;
protected:
void _notification(int p_what);
diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h
index 03991d00f9..bf3f7e93cf 100644
--- a/editor/plugins/animation_state_machine_editor.h
+++ b/editor/plugins/animation_state_machine_editor.h
@@ -47,36 +47,36 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
Ref<AnimationNodeStateMachine> state_machine;
- Button *tool_select;
- Button *tool_create;
- Button *tool_connect;
- Popup *name_edit_popup;
- LineEdit *name_edit;
+ Button *tool_select = nullptr;
+ Button *tool_create = nullptr;
+ Button *tool_connect = nullptr;
+ Popup *name_edit_popup = nullptr;
+ LineEdit *name_edit = nullptr;
- HBoxContainer *tool_erase_hb;
- Button *tool_erase;
- Button *tool_autoplay;
- Button *tool_end;
+ HBoxContainer *tool_erase_hb = nullptr;
+ Button *tool_erase = nullptr;
+ Button *tool_autoplay = nullptr;
+ Button *tool_end = nullptr;
- OptionButton *transition_mode;
- OptionButton *play_mode;
+ OptionButton *transition_mode = nullptr;
+ OptionButton *play_mode = nullptr;
- PanelContainer *panel;
+ PanelContainer *panel = nullptr;
StringName selected_node;
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
+ HScrollBar *h_scroll = nullptr;
+ VScrollBar *v_scroll = nullptr;
- Control *state_machine_draw;
- Control *state_machine_play_pos;
+ Control *state_machine_draw = nullptr;
+ Control *state_machine_play_pos = nullptr;
- PanelContainer *error_panel;
- Label *error_label;
+ PanelContainer *error_panel = nullptr;
+ Label *error_label = nullptr;
bool updating;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
static AnimationNodeStateMachineEditor *singleton;
@@ -87,8 +87,8 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
void _update_graph();
- PopupMenu *menu;
- PopupMenu *animations_menu;
+ PopupMenu *menu = nullptr;
+ PopupMenu *animations_menu = nullptr;
Vector<String> animations_to_add;
Vector2 add_node_pos;
@@ -166,7 +166,7 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin {
float error_time;
String error_text;
- EditorFileDialog *open_file;
+ EditorFileDialog *open_file = nullptr;
Ref<AnimationNode> file_loaded;
void _file_opened(const String &p_file);
diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h
index 5442584a40..ab4ef5a001 100644
--- a/editor/plugins/animation_tree_editor_plugin.h
+++ b/editor/plugins/animation_tree_editor_plugin.h
@@ -52,11 +52,11 @@ public:
class AnimationTreeEditor : public VBoxContainer {
GDCLASS(AnimationTreeEditor, VBoxContainer);
- ScrollContainer *path_edit;
- HBoxContainer *path_hb;
+ ScrollContainer *path_edit = nullptr;
+ HBoxContainer *path_hb = nullptr;
- AnimationTree *tree;
- MarginContainer *editor_base;
+ AnimationTree *tree = nullptr;
+ MarginContainer *editor_base = nullptr;
Vector<String> button_path;
Vector<String> edited_path;
@@ -96,8 +96,8 @@ public:
class AnimationTreeEditorPlugin : public EditorPlugin {
GDCLASS(AnimationTreeEditorPlugin, EditorPlugin);
- AnimationTreeEditor *anim_tree_editor;
- Button *button;
+ AnimationTreeEditor *anim_tree_editor = nullptr;
+ Button *button = nullptr;
public:
virtual String get_name() const override { return "AnimationTree"; }
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 493ffc4033..2a04935c47 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -53,12 +53,12 @@
class EditorAssetLibraryItem : public PanelContainer {
GDCLASS(EditorAssetLibraryItem, PanelContainer);
- TextureButton *icon;
- LinkButton *title;
- LinkButton *category;
- LinkButton *author;
+ TextureButton *icon = nullptr;
+ LinkButton *title = nullptr;
+ LinkButton *category = nullptr;
+ LinkButton *author = nullptr;
TextureRect *stars[5];
- Label *price;
+ Label *price = nullptr;
int asset_id;
int category_id;
@@ -83,11 +83,11 @@ public:
class EditorAssetLibraryItemDescription : public ConfirmationDialog {
GDCLASS(EditorAssetLibraryItemDescription, ConfirmationDialog);
- EditorAssetLibraryItem *item;
- RichTextLabel *description;
- ScrollContainer *previews;
- HBoxContainer *preview_hb;
- PanelContainer *previews_bg;
+ EditorAssetLibraryItem *item = nullptr;
+ RichTextLabel *description = nullptr;
+ ScrollContainer *previews = nullptr;
+ HBoxContainer *preview_hb = nullptr;
+ PanelContainer *previews_bg = nullptr;
struct Preview {
int id = 0;
@@ -98,7 +98,7 @@ class EditorAssetLibraryItemDescription : public ConfirmationDialog {
};
Vector<Preview> preview_images;
- TextureRect *preview;
+ TextureRect *preview = nullptr;
void set_image(int p_type, int p_index, const Ref<Texture2D> &p_image);
@@ -130,19 +130,19 @@ public:
class EditorAssetLibraryItemDownload : public MarginContainer {
GDCLASS(EditorAssetLibraryItemDownload, MarginContainer);
- PanelContainer *panel;
- TextureRect *icon;
- Label *title;
- ProgressBar *progress;
- Button *install_button;
- Button *retry_button;
- TextureButton *dismiss_button;
+ PanelContainer *panel = nullptr;
+ TextureRect *icon = nullptr;
+ Label *title = nullptr;
+ ProgressBar *progress = nullptr;
+ Button *install_button = nullptr;
+ Button *retry_button = nullptr;
+ TextureButton *dismiss_button = nullptr;
- AcceptDialog *download_error;
- HTTPRequest *download;
+ AcceptDialog *download_error = nullptr;
+ HTTPRequest *download = nullptr;
String host;
String sha256;
- Label *status;
+ Label *status = nullptr;
int prev_status;
@@ -150,7 +150,7 @@ class EditorAssetLibraryItemDownload : public MarginContainer {
bool external_install;
- EditorAssetInstaller *asset_installer;
+ EditorAssetInstaller *asset_installer = nullptr;
void _close();
void _make_request();
@@ -176,35 +176,35 @@ class EditorAssetLibrary : public PanelContainer {
String host;
- EditorFileDialog *asset_open;
- EditorAssetInstaller *asset_installer;
+ EditorFileDialog *asset_open = nullptr;
+ EditorAssetInstaller *asset_installer = nullptr;
void _asset_open();
void _asset_file_selected(const String &p_file);
void _update_repository_options();
- PanelContainer *library_scroll_bg;
- ScrollContainer *library_scroll;
- VBoxContainer *library_vb;
- Label *library_loading;
- Label *library_error;
- LineEdit *filter;
- Timer *filter_debounce_timer;
- OptionButton *categories;
- OptionButton *repository;
- OptionButton *sort;
- HBoxContainer *error_hb;
- TextureRect *error_tr;
- Label *error_label;
- MenuButton *support;
-
- HBoxContainer *contents;
-
- HBoxContainer *asset_top_page;
- GridContainer *asset_items;
- HBoxContainer *asset_bottom_page;
-
- HTTPRequest *request;
+ PanelContainer *library_scroll_bg = nullptr;
+ ScrollContainer *library_scroll = nullptr;
+ VBoxContainer *library_vb = nullptr;
+ Label *library_loading = nullptr;
+ Label *library_error = nullptr;
+ LineEdit *filter = nullptr;
+ Timer *filter_debounce_timer = nullptr;
+ OptionButton *categories = nullptr;
+ OptionButton *repository = nullptr;
+ OptionButton *sort = nullptr;
+ HBoxContainer *error_hb = nullptr;
+ TextureRect *error_tr = nullptr;
+ Label *error_label = nullptr;
+ MenuButton *support = nullptr;
+
+ HBoxContainer *contents = nullptr;
+
+ HBoxContainer *asset_top_page = nullptr;
+ GridContainer *asset_items = nullptr;
+ HBoxContainer *asset_bottom_page = nullptr;
+
+ HTTPRequest *request = nullptr;
bool templates_only;
bool initial_loading;
@@ -260,7 +260,7 @@ class EditorAssetLibrary : public PanelContainer {
HBoxContainer *_make_pages(int p_page, int p_page_count, int p_page_len, int p_total_items, int p_current_items);
//
- EditorAssetLibraryItemDescription *description;
+ EditorAssetLibraryItemDescription *description = nullptr;
//
enum RequestType {
@@ -273,8 +273,8 @@ class EditorAssetLibrary : public PanelContainer {
RequestType requesting;
Dictionary category_map;
- ScrollContainer *downloads_scroll;
- HBoxContainer *downloads_hb;
+ ScrollContainer *downloads_scroll = nullptr;
+ HBoxContainer *downloads_hb = nullptr;
void _install_asset();
@@ -315,7 +315,7 @@ public:
class AssetLibraryEditorPlugin : public EditorPlugin {
GDCLASS(AssetLibraryEditorPlugin, EditorPlugin);
- EditorAssetLibrary *addon_library;
+ EditorAssetLibrary *addon_library = nullptr;
public:
virtual String get_name() const override { return "AssetLib"; }
diff --git a/editor/plugins/audio_stream_editor_plugin.h b/editor/plugins/audio_stream_editor_plugin.h
index 2478210430..0d927bddd5 100644
--- a/editor/plugins/audio_stream_editor_plugin.h
+++ b/editor/plugins/audio_stream_editor_plugin.h
@@ -75,7 +75,7 @@ public:
class AudioStreamEditorPlugin : public EditorPlugin {
GDCLASS(AudioStreamEditorPlugin, EditorPlugin);
- AudioStreamEditor *audio_editor;
+ AudioStreamEditor *audio_editor = nullptr;
public:
virtual String get_name() const override { return "Audio"; }
diff --git a/editor/plugins/camera_3d_editor_plugin.h b/editor/plugins/camera_3d_editor_plugin.h
index c1f71d3b1b..a8164f9b85 100644
--- a/editor/plugins/camera_3d_editor_plugin.h
+++ b/editor/plugins/camera_3d_editor_plugin.h
@@ -37,9 +37,9 @@
class Camera3DEditor : public Control {
GDCLASS(Camera3DEditor, Control);
- Panel *panel;
- Button *preview;
- Node *node;
+ Panel *panel = nullptr;
+ Button *preview = nullptr;
+ Node *node = nullptr;
void _pressed();
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 1a9d49a4a8..1b61cdc675 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -183,16 +183,16 @@ private:
bool selection_menu_additive_selection;
Tool tool = TOOL_SELECT;
- Control *viewport;
- Control *viewport_scrollable;
+ Control *viewport = nullptr;
+ Control *viewport_scrollable = nullptr;
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
- HBoxContainer *hb;
+ HScrollBar *h_scroll = nullptr;
+ VScrollBar *v_scroll = nullptr;
+ HBoxContainer *hb = nullptr;
// Used for secondary menu items which are displayed depending on the currently selected node
// (such as MeshInstance's "Mesh" menu).
- PanelContainer *context_menu_container;
- HBoxContainer *hbc_context_menu;
+ PanelContainer *context_menu_container = nullptr;
+ HBoxContainer *hbc_context_menu = nullptr;
Transform2D transform;
GridVisibility grid_visibility = GRID_VISIBILITY_SHOW_WHEN_SNAPPING;
@@ -293,47 +293,47 @@ private:
};
List<PoseClipboard> pose_clipboard;
- Button *select_button;
+ Button *select_button = nullptr;
- Button *move_button;
- Button *scale_button;
- Button *rotate_button;
+ Button *move_button = nullptr;
+ Button *scale_button = nullptr;
+ Button *rotate_button = nullptr;
- Button *list_select_button;
- Button *pivot_button;
- Button *pan_button;
+ Button *list_select_button = nullptr;
+ Button *pivot_button = nullptr;
+ Button *pan_button = nullptr;
- Button *ruler_button;
+ Button *ruler_button = nullptr;
- Button *smart_snap_button;
- Button *grid_snap_button;
- MenuButton *snap_config_menu;
- PopupMenu *smartsnap_config_popup;
+ Button *smart_snap_button = nullptr;
+ Button *grid_snap_button = nullptr;
+ MenuButton *snap_config_menu = nullptr;
+ PopupMenu *smartsnap_config_popup = nullptr;
- Button *lock_button;
- Button *unlock_button;
+ Button *lock_button = nullptr;
+ Button *unlock_button = nullptr;
- Button *group_button;
- Button *ungroup_button;
+ Button *group_button = nullptr;
+ Button *ungroup_button = nullptr;
- MenuButton *skeleton_menu;
- Button *override_camera_button;
- MenuButton *view_menu;
- PopupMenu *grid_menu;
- HBoxContainer *animation_hb;
- MenuButton *animation_menu;
+ MenuButton *skeleton_menu = nullptr;
+ Button *override_camera_button = nullptr;
+ MenuButton *view_menu = nullptr;
+ PopupMenu *grid_menu = nullptr;
+ HBoxContainer *animation_hb = nullptr;
+ MenuButton *animation_menu = nullptr;
- Button *key_loc_button;
- Button *key_rot_button;
- Button *key_scale_button;
- Button *key_insert_button;
- Button *key_auto_insert_button;
+ Button *key_loc_button = nullptr;
+ Button *key_rot_button = nullptr;
+ Button *key_scale_button = nullptr;
+ Button *key_insert_button = nullptr;
+ Button *key_auto_insert_button = nullptr;
- PopupMenu *selection_menu;
- PopupMenu *add_node_menu;
+ PopupMenu *selection_menu = nullptr;
+ PopupMenu *add_node_menu = nullptr;
- Control *top_ruler;
- Control *left_ruler;
+ Control *top_ruler = nullptr;
+ Control *left_ruler = nullptr;
Point2 drag_start_origin;
DragType drag_type = DRAG_NONE;
@@ -374,9 +374,9 @@ private:
void _find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append);
- ConfirmationDialog *snap_dialog;
+ ConfirmationDialog *snap_dialog = nullptr;
- CanvasItem *ref_item;
+ CanvasItem *ref_item = nullptr;
void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false);
void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false);
@@ -400,7 +400,7 @@ private:
void _prepare_grid_menu();
void _on_grid_menu_id_pressed(int p_id);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
List<CanvasItem *> _get_edited_canvas_items(bool retrieve_locked = false, bool remove_canvas_item_if_parent_in_selection = true);
Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list);
@@ -476,8 +476,8 @@ private:
const SnapTarget p_snap_target, List<const CanvasItem *> p_exceptions,
const Node *p_current);
- VBoxContainer *controls_vb;
- EditorZoomWidget *zoom_widget;
+ VBoxContainer *controls_vb = nullptr;
+ EditorZoomWidget *zoom_widget = nullptr;
void _update_zoom(real_t p_zoom);
void _shortcut_zoom_set(real_t p_zoom);
void _zoom_on_position(real_t p_zoom, Point2 p_position = Point2());
@@ -488,9 +488,9 @@ private:
void _update_override_camera_button(bool p_game_running);
- HSplitContainer *left_panel_split;
- HSplitContainer *right_panel_split;
- VSplitContainer *bottom_split;
+ HSplitContainer *left_panel_split = nullptr;
+ HSplitContainer *right_panel_split = nullptr;
+ VSplitContainer *bottom_split = nullptr;
void _update_context_menu_stylebox();
@@ -555,7 +555,7 @@ public:
void focus_selection();
- EditorSelection *editor_selection;
+ EditorSelection *editor_selection = nullptr;
CanvasItemEditor();
};
@@ -563,7 +563,7 @@ public:
class CanvasItemEditorPlugin : public EditorPlugin {
GDCLASS(CanvasItemEditorPlugin, EditorPlugin);
- CanvasItemEditor *canvas_item_editor;
+ CanvasItemEditor *canvas_item_editor = nullptr;
public:
virtual String get_name() const override { return "2D"; }
@@ -589,18 +589,18 @@ class CanvasItemEditorViewport : public Control {
Vector<String> texture_node_types;
Vector<String> selected_files;
- Node *target_node;
+ Node *target_node = nullptr;
Point2 drop_pos;
- EditorData *editor_data;
- CanvasItemEditor *canvas_item_editor;
- Control *preview_node;
- AcceptDialog *accept;
- AcceptDialog *selector;
- Label *selector_label;
- Label *label;
- Label *label_desc;
- VBoxContainer *btn_group;
+ EditorData *editor_data = nullptr;
+ CanvasItemEditor *canvas_item_editor = nullptr;
+ Control *preview_node = nullptr;
+ AcceptDialog *accept = nullptr;
+ AcceptDialog *selector = nullptr;
+ Label *selector_label = nullptr;
+ Label *label = nullptr;
+ Label *label_desc = nullptr;
+ VBoxContainer *btn_group = nullptr;
Ref<ButtonGroup> button_group;
void _on_mouse_exit();
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index 5d769e7987..f018376e4b 100644
--- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -38,10 +38,7 @@ void CollisionPolygon2DEditor::_set_node(Node *p_polygon) {
node = Object::cast_to<CollisionPolygon2D>(p_polygon);
}
-CollisionPolygon2DEditor::CollisionPolygon2DEditor() :
- AbstractPolygon2DEditor() {
- node = nullptr;
-}
+CollisionPolygon2DEditor::CollisionPolygon2DEditor() {}
CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin() :
AbstractPolygon2DEditorPlugin(memnew(CollisionPolygon2DEditor), "CollisionPolygon2D") {
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.h b/editor/plugins/collision_polygon_2d_editor_plugin.h
index bdd4228b3b..0225d5d620 100644
--- a/editor/plugins/collision_polygon_2d_editor_plugin.h
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.h
@@ -37,7 +37,7 @@
class CollisionPolygon2DEditor : public AbstractPolygon2DEditor {
GDCLASS(CollisionPolygon2DEditor, AbstractPolygon2DEditor);
- CollisionPolygon2D *node;
+ CollisionPolygon2D *node = nullptr;
protected:
virtual Node2D *_get_node() const override;
diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h
index 033ea3db93..da9e9f339f 100644
--- a/editor/plugins/collision_shape_2d_editor_plugin.h
+++ b/editor/plugins/collision_shape_2d_editor_plugin.h
@@ -61,9 +61,9 @@ class CollisionShape2DEditor : public Control {
Point2(1, -1),
};
- UndoRedo *undo_redo;
- CanvasItemEditor *canvas_item_editor;
- CollisionShape2D *node;
+ UndoRedo *undo_redo = nullptr;
+ CanvasItemEditor *canvas_item_editor = nullptr;
+ CollisionShape2D *node = nullptr;
Vector<Point2> handles;
@@ -96,7 +96,7 @@ public:
class CollisionShape2DEditorPlugin : public EditorPlugin {
GDCLASS(CollisionShape2DEditorPlugin, EditorPlugin);
- CollisionShape2DEditor *collision_shape_2d_editor;
+ CollisionShape2DEditor *collision_shape_2d_editor = nullptr;
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return collision_shape_2d_editor->forward_canvas_gui_input(p_event); }
diff --git a/editor/plugins/control_editor_plugin.h b/editor/plugins/control_editor_plugin.h
index 37d218abb9..96451f7dcf 100644
--- a/editor/plugins/control_editor_plugin.h
+++ b/editor/plugins/control_editor_plugin.h
@@ -70,7 +70,7 @@ public:
class EditorPropertyAnchorsPreset : public EditorProperty {
GDCLASS(EditorPropertyAnchorsPreset, EditorProperty);
- OptionButton *options;
+ OptionButton *options = nullptr;
void _option_selected(int p_which);
@@ -94,9 +94,9 @@ class EditorPropertySizeFlags : public EditorProperty {
SIZE_FLAGS_PRESET_CUSTOM,
};
- OptionButton *flag_presets;
- CheckBox *flag_expand;
- VBoxContainer *flag_options;
+ OptionButton *flag_presets = nullptr;
+ CheckBox *flag_expand = nullptr;
+ VBoxContainer *flag_options = nullptr;
Vector<CheckBox *> flag_checks;
bool vertical = false;
@@ -128,8 +128,8 @@ public:
class ControlEditorToolbar : public HBoxContainer {
GDCLASS(ControlEditorToolbar, HBoxContainer);
- UndoRedo *undo_redo;
- EditorSelection *editor_selection;
+ UndoRedo *undo_redo = nullptr;
+ EditorSelection *editor_selection = nullptr;
enum MenuOption {
ANCHORS_AND_OFFSETS_PRESET_TOP_LEFT,
@@ -198,12 +198,12 @@ class ControlEditorToolbar : public HBoxContainer {
CONTAINERS_V_PRESET_SHRINK_END,
};
- MenuButton *anchor_presets_menu;
- PopupMenu *anchors_popup;
- MenuButton *container_h_presets_menu;
- MenuButton *container_v_presets_menu;
+ MenuButton *anchor_presets_menu = nullptr;
+ PopupMenu *anchors_popup = nullptr;
+ MenuButton *container_h_presets_menu = nullptr;
+ MenuButton *container_v_presets_menu = nullptr;
- Button *anchor_mode_button;
+ Button *anchor_mode_button = nullptr;
bool anchors_mode = false;
@@ -239,7 +239,7 @@ public:
class ControlEditorPlugin : public EditorPlugin {
GDCLASS(ControlEditorPlugin, EditorPlugin);
- ControlEditorToolbar *toolbar;
+ ControlEditorToolbar *toolbar = nullptr;
public:
virtual String get_name() const override { return "Control"; }
diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.h b/editor/plugins/cpu_particles_2d_editor_plugin.h
index b10ed73e38..cc59bc924f 100644
--- a/editor/plugins/cpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_2d_editor_plugin.h
@@ -55,22 +55,22 @@ class CPUParticles2DEditorPlugin : public EditorPlugin {
EMISSION_MODE_BORDER_DIRECTED
};
- CPUParticles2D *particles;
+ CPUParticles2D *particles = nullptr;
- EditorFileDialog *file;
+ EditorFileDialog *file = nullptr;
- HBoxContainer *toolbar;
- MenuButton *menu;
+ HBoxContainer *toolbar = nullptr;
+ MenuButton *menu = nullptr;
- SpinBox *epoints;
+ SpinBox *epoints = nullptr;
- ConfirmationDialog *emission_mask;
- OptionButton *emission_mask_mode;
- CheckBox *emission_colors;
+ ConfirmationDialog *emission_mask = nullptr;
+ OptionButton *emission_mask_mode = nullptr;
+ CheckBox *emission_colors = nullptr;
String source_emission_file;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
void _file_selected(const String &p_file);
void _menu_callback(int p_idx);
void _generate_emission_mask();
diff --git a/editor/plugins/cpu_particles_3d_editor_plugin.h b/editor/plugins/cpu_particles_3d_editor_plugin.h
index 0501936574..70f2da4b2d 100644
--- a/editor/plugins/cpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/cpu_particles_3d_editor_plugin.h
@@ -44,7 +44,7 @@ class CPUParticles3DEditor : public GPUParticles3DEditorBase {
};
- CPUParticles3D *node;
+ CPUParticles3D *node = nullptr;
void _menu_option(int);
@@ -65,7 +65,7 @@ public:
class CPUParticles3DEditorPlugin : public EditorPlugin {
GDCLASS(CPUParticles3DEditorPlugin, EditorPlugin);
- CPUParticles3DEditor *particles_editor;
+ CPUParticles3DEditor *particles_editor = nullptr;
public:
virtual String get_name() const override { return "CPUParticles3D"; }
diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h
index 4aba2fffd0..5cf3b16a06 100644
--- a/editor/plugins/curve_editor_plugin.h
+++ b/editor/plugins/curve_editor_plugin.h
@@ -99,8 +99,8 @@ private:
Transform2D _world_to_view;
Ref<Curve> _curve_ref;
- PopupMenu *_context_menu;
- PopupMenu *_presets_menu;
+ PopupMenu *_context_menu = nullptr;
+ PopupMenu *_presets_menu = nullptr;
Array _undo_data;
bool _has_undo_data;
diff --git a/editor/plugins/debugger_editor_plugin.h b/editor/plugins/debugger_editor_plugin.h
index c024526285..10e1a27933 100644
--- a/editor/plugins/debugger_editor_plugin.h
+++ b/editor/plugins/debugger_editor_plugin.h
@@ -41,9 +41,9 @@ class DebuggerEditorPlugin : public EditorPlugin {
GDCLASS(DebuggerEditorPlugin, EditorPlugin);
private:
- MenuButton *debug_menu;
- EditorFileServer *file_server;
- PopupMenu *instances_menu;
+ MenuButton *debug_menu = nullptr;
+ EditorFileServer *file_server = nullptr;
+ PopupMenu *instances_menu = nullptr;
enum MenuOptions {
RUN_FILE_SERVER,
diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.h b/editor/plugins/gpu_particles_2d_editor_plugin.h
index f94ce632e9..75f68617d1 100644
--- a/editor/plugins/gpu_particles_2d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_2d_editor_plugin.h
@@ -56,26 +56,26 @@ class GPUParticles2DEditorPlugin : public EditorPlugin {
EMISSION_MODE_BORDER_DIRECTED
};
- GPUParticles2D *particles;
+ GPUParticles2D *particles = nullptr;
List<GPUParticles2D *> selected_particles;
- EditorFileDialog *file;
+ EditorFileDialog *file = nullptr;
- HBoxContainer *toolbar;
- MenuButton *menu;
+ HBoxContainer *toolbar = nullptr;
+ MenuButton *menu = nullptr;
- SpinBox *epoints;
+ SpinBox *epoints = nullptr;
- ConfirmationDialog *generate_visibility_rect;
- SpinBox *generate_seconds;
+ ConfirmationDialog *generate_visibility_rect = nullptr;
+ SpinBox *generate_seconds = nullptr;
- ConfirmationDialog *emission_mask;
- OptionButton *emission_mask_mode;
- CheckBox *emission_colors;
+ ConfirmationDialog *emission_mask = nullptr;
+ OptionButton *emission_mask_mode = nullptr;
+ CheckBox *emission_colors = nullptr;
String source_emission_file;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
void _file_selected(const String &p_file);
void _menu_callback(int p_idx);
void _generate_visibility_rect();
diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.h b/editor/plugins/gpu_particles_3d_editor_plugin.h
index 39aa596ece..190fb9954b 100644
--- a/editor/plugins/gpu_particles_3d_editor_plugin.h
+++ b/editor/plugins/gpu_particles_3d_editor_plugin.h
@@ -41,16 +41,16 @@ class GPUParticles3DEditorBase : public Control {
GDCLASS(GPUParticles3DEditorBase, Control);
protected:
- Node3D *base_node;
- Panel *panel;
- MenuButton *options;
- HBoxContainer *particles_editor_hb;
+ Node3D *base_node = nullptr;
+ Panel *panel = nullptr;
+ MenuButton *options = nullptr;
+ HBoxContainer *particles_editor_hb = nullptr;
- SceneTreeDialog *emission_tree_dialog;
+ SceneTreeDialog *emission_tree_dialog = nullptr;
- ConfirmationDialog *emission_dialog;
- SpinBox *emission_amount;
- OptionButton *emission_fill;
+ ConfirmationDialog *emission_dialog = nullptr;
+ SpinBox *emission_amount = nullptr;
+ OptionButton *emission_fill = nullptr;
Vector<Face3> geometry;
@@ -67,9 +67,9 @@ public:
class GPUParticles3DEditor : public GPUParticles3DEditorBase {
GDCLASS(GPUParticles3DEditor, GPUParticles3DEditorBase);
- ConfirmationDialog *generate_aabb;
- SpinBox *generate_seconds;
- GPUParticles3D *node;
+ ConfirmationDialog *generate_aabb = nullptr;
+ SpinBox *generate_seconds = nullptr;
+ GPUParticles3D *node = nullptr;
enum Menu {
MENU_OPTION_GENERATE_AABB,
@@ -101,7 +101,7 @@ public:
class GPUParticles3DEditorPlugin : public EditorPlugin {
GDCLASS(GPUParticles3DEditorPlugin, EditorPlugin);
- GPUParticles3DEditor *particles_editor;
+ GPUParticles3DEditor *particles_editor = nullptr;
public:
virtual String get_name() const override { return "GPUParticles3D"; }
diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
index f6e4fd3dec..684279039a 100644
--- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
+++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.h
@@ -41,12 +41,12 @@ class EditorFileDialog;
class GPUParticlesCollisionSDF3DEditorPlugin : public EditorPlugin {
GDCLASS(GPUParticlesCollisionSDF3DEditorPlugin, EditorPlugin);
- GPUParticlesCollisionSDF3D *col_sdf;
+ GPUParticlesCollisionSDF3D *col_sdf = nullptr;
- HBoxContainer *bake_hb;
- Button *bake;
+ HBoxContainer *bake_hb = nullptr;
+ Button *bake = nullptr;
- EditorFileDialog *probe_file;
+ EditorFileDialog *probe_file = nullptr;
static EditorProgress *tmp_progress;
static void bake_func_begin(int p_steps);
diff --git a/editor/plugins/gradient_editor_plugin.h b/editor/plugins/gradient_editor_plugin.h
index 9857ea018d..26bf76fecd 100644
--- a/editor/plugins/gradient_editor_plugin.h
+++ b/editor/plugins/gradient_editor_plugin.h
@@ -65,9 +65,9 @@ class GradientReverseButton : public BaseButton {
class EditorInspectorPluginGradient : public EditorInspectorPlugin {
GDCLASS(EditorInspectorPluginGradient, EditorInspectorPlugin);
- GradientEditor *editor;
- HBoxContainer *gradient_tools_hbox;
- GradientReverseButton *reverse_btn;
+ GradientEditor *editor = nullptr;
+ HBoxContainer *gradient_tools_hbox = nullptr;
+ GradientReverseButton *reverse_btn = nullptr;
void _reverse_button_pressed();
diff --git a/editor/plugins/input_event_editor_plugin.h b/editor/plugins/input_event_editor_plugin.h
index ab948462ab..3c658a86e9 100644
--- a/editor/plugins/input_event_editor_plugin.h
+++ b/editor/plugins/input_event_editor_plugin.h
@@ -38,11 +38,11 @@
class InputEventConfigContainer : public HBoxContainer {
GDCLASS(InputEventConfigContainer, HBoxContainer);
- Label *input_event_text;
- Button *open_config_button;
+ Label *input_event_text = nullptr;
+ Button *open_config_button = nullptr;
Ref<InputEvent> input_event;
- InputEventConfigurationDialog *config_dialog;
+ InputEventConfigurationDialog *config_dialog = nullptr;
void _config_dialog_confirmed();
void _configure_pressed();
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp
index 6a5ead58d0..4fbc8188b9 100644
--- a/editor/plugins/light_occluder_2d_editor_plugin.cpp
+++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp
@@ -102,10 +102,7 @@ void LightOccluder2DEditor::_create_resource() {
_menu_option(MODE_CREATE);
}
-LightOccluder2DEditor::LightOccluder2DEditor() :
- AbstractPolygon2DEditor() {
- node = nullptr;
-}
+LightOccluder2DEditor::LightOccluder2DEditor() {}
LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin() :
AbstractPolygon2DEditorPlugin(memnew(LightOccluder2DEditor), "LightOccluder2D") {
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h
index 557e8bf292..aeee12b5b6 100644
--- a/editor/plugins/light_occluder_2d_editor_plugin.h
+++ b/editor/plugins/light_occluder_2d_editor_plugin.h
@@ -37,7 +37,7 @@
class LightOccluder2DEditor : public AbstractPolygon2DEditor {
GDCLASS(LightOccluder2DEditor, AbstractPolygon2DEditor);
- LightOccluder2D *node;
+ LightOccluder2D *node = nullptr;
Ref<OccluderPolygon2D> _ensure_occluder() const;
diff --git a/editor/plugins/lightmap_gi_editor_plugin.h b/editor/plugins/lightmap_gi_editor_plugin.h
index e658230181..1202efe8fc 100644
--- a/editor/plugins/lightmap_gi_editor_plugin.h
+++ b/editor/plugins/lightmap_gi_editor_plugin.h
@@ -41,11 +41,11 @@ class EditorFileDialog;
class LightmapGIEditorPlugin : public EditorPlugin {
GDCLASS(LightmapGIEditorPlugin, EditorPlugin);
- LightmapGI *lightmap;
+ LightmapGI *lightmap = nullptr;
- Button *bake;
+ Button *bake = nullptr;
- EditorFileDialog *file_dialog;
+ EditorFileDialog *file_dialog = nullptr;
static EditorProgress *tmp_progress;
static bool bake_func_step(float p_progress, const String &p_description, void *, bool p_refresh);
static void bake_func_end(uint64_t p_time_started);
diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp
index 0f81b17cb3..31053f90b8 100644
--- a/editor/plugins/line_2d_editor_plugin.cpp
+++ b/editor/plugins/line_2d_editor_plugin.cpp
@@ -56,10 +56,7 @@ void Line2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, con
undo_redo->add_undo_method(node, "set_points", p_previous);
}
-Line2DEditor::Line2DEditor() :
- AbstractPolygon2DEditor() {
- node = nullptr;
-}
+Line2DEditor::Line2DEditor() {}
Line2DEditorPlugin::Line2DEditorPlugin() :
AbstractPolygon2DEditorPlugin(memnew(Line2DEditor), "Line2D") {
diff --git a/editor/plugins/line_2d_editor_plugin.h b/editor/plugins/line_2d_editor_plugin.h
index 307cf11207..0d407b3150 100644
--- a/editor/plugins/line_2d_editor_plugin.h
+++ b/editor/plugins/line_2d_editor_plugin.h
@@ -37,7 +37,7 @@
class Line2DEditor : public AbstractPolygon2DEditor {
GDCLASS(Line2DEditor, AbstractPolygon2DEditor);
- Line2D *node;
+ Line2D *node = nullptr;
protected:
virtual Node2D *_get_node() const override;
diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h
index 37464c98fe..3554b3c1e9 100644
--- a/editor/plugins/mesh_editor_plugin.h
+++ b/editor/plugins/mesh_editor_plugin.h
@@ -44,17 +44,17 @@ class MeshEditor : public SubViewportContainer {
float rot_x;
float rot_y;
- SubViewport *viewport;
- MeshInstance3D *mesh_instance;
- Node3D *rotation;
- DirectionalLight3D *light1;
- DirectionalLight3D *light2;
- Camera3D *camera;
+ SubViewport *viewport = nullptr;
+ MeshInstance3D *mesh_instance = nullptr;
+ Node3D *rotation = nullptr;
+ DirectionalLight3D *light1 = nullptr;
+ DirectionalLight3D *light2 = nullptr;
+ Camera3D *camera = nullptr;
Ref<Mesh> mesh;
- TextureButton *light_1_switch;
- TextureButton *light_2_switch;
+ TextureButton *light_1_switch = nullptr;
+ TextureButton *light_2_switch = nullptr;
void _button_pressed(Node *p_button);
bool first_enter;
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.h b/editor/plugins/mesh_instance_3d_editor_plugin.h
index 9c59c5fb9f..36d8eacd98 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.h
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.h
@@ -51,17 +51,17 @@ class MeshInstance3DEditor : public Control {
MENU_OPTION_DEBUG_UV2,
};
- MeshInstance3D *node;
+ MeshInstance3D *node = nullptr;
- MenuButton *options;
+ MenuButton *options = nullptr;
- ConfirmationDialog *outline_dialog;
- SpinBox *outline_size;
+ ConfirmationDialog *outline_dialog = nullptr;
+ SpinBox *outline_size = nullptr;
- AcceptDialog *err_dialog;
+ AcceptDialog *err_dialog = nullptr;
- AcceptDialog *debug_uv_dialog;
- Control *debug_uv;
+ AcceptDialog *debug_uv_dialog = nullptr;
+ Control *debug_uv = nullptr;
Vector<Vector2> uv_lines;
void _menu_option(int p_option);
@@ -84,7 +84,7 @@ public:
class MeshInstance3DEditorPlugin : public EditorPlugin {
GDCLASS(MeshInstance3DEditorPlugin, EditorPlugin);
- MeshInstance3DEditor *mesh_editor;
+ MeshInstance3DEditor *mesh_editor = nullptr;
public:
virtual String get_name() const override { return "MeshInstance3D"; }
diff --git a/editor/plugins/mesh_library_editor_plugin.h b/editor/plugins/mesh_library_editor_plugin.h
index 6bc992869b..85ead35534 100644
--- a/editor/plugins/mesh_library_editor_plugin.h
+++ b/editor/plugins/mesh_library_editor_plugin.h
@@ -43,10 +43,10 @@ class MeshLibraryEditor : public Control {
Ref<MeshLibrary> mesh_library;
- MenuButton *menu;
- ConfirmationDialog *cd_remove;
- ConfirmationDialog *cd_update;
- EditorFileDialog *file;
+ MenuButton *menu = nullptr;
+ ConfirmationDialog *cd_remove = nullptr;
+ ConfirmationDialog *cd_update = nullptr;
+ EditorFileDialog *file = nullptr;
bool apply_xforms;
int to_erase;
@@ -81,7 +81,7 @@ public:
class MeshLibraryEditorPlugin : public EditorPlugin {
GDCLASS(MeshLibraryEditorPlugin, EditorPlugin);
- MeshLibraryEditor *mesh_library_editor;
+ MeshLibraryEditor *mesh_library_editor = nullptr;
public:
virtual String get_name() const override { return "MeshLibrary"; }
diff --git a/editor/plugins/multimesh_editor_plugin.h b/editor/plugins/multimesh_editor_plugin.h
index 846e6d17f3..9f5e85216c 100644
--- a/editor/plugins/multimesh_editor_plugin.h
+++ b/editor/plugins/multimesh_editor_plugin.h
@@ -43,26 +43,26 @@ class MultiMeshEditor : public Control {
friend class MultiMeshEditorPlugin;
- AcceptDialog *err_dialog;
- MenuButton *options;
- MultiMeshInstance3D *_last_pp_node;
+ AcceptDialog *err_dialog = nullptr;
+ MenuButton *options = nullptr;
+ MultiMeshInstance3D *_last_pp_node = nullptr;
bool browsing_source;
- Panel *panel;
- MultiMeshInstance3D *node;
+ Panel *panel = nullptr;
+ MultiMeshInstance3D *node = nullptr;
- LineEdit *surface_source;
- LineEdit *mesh_source;
+ LineEdit *surface_source = nullptr;
+ LineEdit *mesh_source = nullptr;
- SceneTreeDialog *std;
+ SceneTreeDialog *std = nullptr;
- ConfirmationDialog *populate_dialog;
- OptionButton *populate_axis;
- HSlider *populate_rotate_random;
- HSlider *populate_tilt_random;
- SpinBox *populate_scale_random;
- SpinBox *populate_scale;
- SpinBox *populate_amount;
+ ConfirmationDialog *populate_dialog = nullptr;
+ OptionButton *populate_axis = nullptr;
+ HSlider *populate_rotate_random = nullptr;
+ HSlider *populate_tilt_random = nullptr;
+ SpinBox *populate_scale_random = nullptr;
+ SpinBox *populate_scale = nullptr;
+ SpinBox *populate_amount = nullptr;
enum Menu {
MENU_OPTION_POPULATE
@@ -85,7 +85,7 @@ public:
class MultiMeshEditorPlugin : public EditorPlugin {
GDCLASS(MultiMeshEditorPlugin, EditorPlugin);
- MultiMeshEditor *multimesh_editor;
+ MultiMeshEditor *multimesh_editor = nullptr;
public:
virtual String get_name() const override { return "MultiMesh"; }
diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp
index fe31f254df..17eaf45bb5 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -112,10 +112,7 @@ void NavigationPolygonEditor::_create_resource() {
_menu_option(MODE_CREATE);
}
-NavigationPolygonEditor::NavigationPolygonEditor() :
- AbstractPolygon2DEditor() {
- node = nullptr;
-}
+NavigationPolygonEditor::NavigationPolygonEditor() {}
NavigationPolygonEditorPlugin::NavigationPolygonEditorPlugin() :
AbstractPolygon2DEditorPlugin(memnew(NavigationPolygonEditor), "NavigationRegion2D") {
diff --git a/editor/plugins/navigation_polygon_editor_plugin.h b/editor/plugins/navigation_polygon_editor_plugin.h
index 16fbb241e9..7550b75fa3 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.h
+++ b/editor/plugins/navigation_polygon_editor_plugin.h
@@ -37,7 +37,7 @@
class NavigationPolygonEditor : public AbstractPolygon2DEditor {
GDCLASS(NavigationPolygonEditor, AbstractPolygon2DEditor);
- NavigationRegion2D *node;
+ NavigationRegion2D *node = nullptr;
Ref<NavigationPolygon> _ensure_navpoly() const;
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index fa55651d26..3b67b898e3 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -70,14 +70,14 @@ class EditorNode3DGizmo : public Node3DGizmo {
bool valid;
bool hidden;
Vector<Instance> instances;
- Node3D *spatial_node;
+ Node3D *spatial_node = nullptr;
void _set_spatial_node(Node *p_node) { set_spatial_node(Object::cast_to<Node3D>(p_node)); }
protected:
static void _bind_methods();
- EditorNode3DGizmoPlugin *gizmo_plugin;
+ EditorNode3DGizmoPlugin *gizmo_plugin = nullptr;
GDVIRTUAL0(_redraw)
GDVIRTUAL2RC(String, _get_handle_name, int, bool)
@@ -618,7 +618,7 @@ public:
class Joint3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(Joint3DGizmoPlugin, EditorNode3DGizmoPlugin);
- Timer *update_timer;
+ Timer *update_timer = nullptr;
uint64_t update_idx = 0;
void incremental_update_gizmos();
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 5c0bfab34e..5447befedd 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -190,27 +190,27 @@ private:
ViewType view_type;
void _menu_option(int p_option);
void _set_auto_orthogonal();
- Node3D *preview_node;
- AABB *preview_bounds;
+ Node3D *preview_node = nullptr;
+ AABB *preview_bounds = nullptr;
Vector<String> selected_files;
- AcceptDialog *accept;
+ AcceptDialog *accept = nullptr;
- Node *target_node;
+ Node *target_node = nullptr;
Point2 drop_pos;
- EditorData *editor_data;
- EditorSelection *editor_selection;
- UndoRedo *undo_redo;
+ EditorData *editor_data = nullptr;
+ EditorSelection *editor_selection = nullptr;
+ UndoRedo *undo_redo = nullptr;
- CheckBox *preview_camera;
- SubViewportContainer *subviewport_container;
+ CheckBox *preview_camera = nullptr;
+ SubViewportContainer *subviewport_container = nullptr;
- MenuButton *view_menu;
- PopupMenu *display_submenu;
+ MenuButton *view_menu = nullptr;
+ PopupMenu *display_submenu = nullptr;
- Control *surface;
- SubViewport *viewport;
- Camera3D *camera;
+ Control *surface = nullptr;
+ SubViewport *viewport = nullptr;
+ Camera3D *camera = nullptr;
bool transforming;
bool orthogonal;
bool auto_orthogonal;
@@ -221,17 +221,17 @@ private:
real_t freelook_speed;
Vector2 previous_mouse_position;
- Label *info_label;
- Label *cinema_label;
- Label *locked_label;
- Label *zoom_limit_label;
+ Label *info_label = nullptr;
+ Label *cinema_label = nullptr;
+ Label *locked_label = nullptr;
+ Label *zoom_limit_label = nullptr;
- VBoxContainer *top_right_vbox;
- ViewportRotationControl *rotation_control;
- Gradient *frame_time_gradient;
- Label *cpu_time_label;
- Label *gpu_time_label;
- Label *fps_label;
+ VBoxContainer *top_right_vbox = nullptr;
+ ViewportRotationControl *rotation_control = nullptr;
+ Gradient *frame_time_gradient = nullptr;
+ Label *cpu_time_label = nullptr;
+ Label *gpu_time_label = nullptr;
+ Label *fps_label = nullptr;
struct _RayResult {
Node3D *item = nullptr;
@@ -274,7 +274,7 @@ private:
bool clicked_wants_append;
bool selection_in_progress = false;
- PopupMenu *selection_menu;
+ PopupMenu *selection_menu = nullptr;
enum NavigationZoomStyle {
NAVIGATION_ZOOM_VERTICAL,
@@ -375,9 +375,9 @@ private:
void _sinput(const Ref<InputEvent> &p_event);
void _update_freelook(real_t delta);
- Node3DEditor *spatial_editor;
+ Node3DEditor *spatial_editor = nullptr;
- Camera3D *previewing;
+ Camera3D *previewing = nullptr;
Camera3D *preview = nullptr;
bool previewing_cinema;
@@ -455,7 +455,7 @@ public:
Transform3D original_local;
Transform3D last_xform; // last transform
bool last_xform_dirty;
- Node3D *sp;
+ Node3D *sp = nullptr;
RID sbox_instance;
RID sbox_instance_offset;
RID sbox_instance_xray;
@@ -537,13 +537,13 @@ public:
};
private:
- EditorSelection *editor_selection;
+ EditorSelection *editor_selection = nullptr;
- Node3DEditorViewportContainer *viewport_base;
+ Node3DEditorViewportContainer *viewport_base = nullptr;
Node3DEditorViewport *viewports[VIEWPORTS_COUNT];
- VSplitContainer *shader_split;
- HSplitContainer *left_panel_split;
- HSplitContainer *right_panel_split;
+ VSplitContainer *shader_split = nullptr;
+ HSplitContainer *left_panel_split = nullptr;
+ HSplitContainer *right_panel_split = nullptr;
/////
@@ -588,7 +588,7 @@ private:
Ref<StandardMaterial3D> cursor_material;
// Scene drag and drop support
- Node3D *preview_node;
+ Node3D *preview_node = nullptr;
AABB preview_bounds;
struct Gizmo {
@@ -628,31 +628,31 @@ private:
Button *tool_button[TOOL_MAX];
Button *tool_option_button[TOOL_OPT_MAX];
- MenuButton *transform_menu;
- PopupMenu *gizmos_menu;
- MenuButton *view_menu;
+ MenuButton *transform_menu = nullptr;
+ PopupMenu *gizmos_menu = nullptr;
+ MenuButton *view_menu = nullptr;
- AcceptDialog *accept;
+ AcceptDialog *accept = nullptr;
- ConfirmationDialog *snap_dialog;
- ConfirmationDialog *xform_dialog;
- ConfirmationDialog *settings_dialog;
+ ConfirmationDialog *snap_dialog = nullptr;
+ ConfirmationDialog *xform_dialog = nullptr;
+ ConfirmationDialog *settings_dialog = nullptr;
bool snap_enabled;
bool snap_key_enabled;
- LineEdit *snap_translate;
- LineEdit *snap_rotate;
- LineEdit *snap_scale;
+ LineEdit *snap_translate = nullptr;
+ LineEdit *snap_rotate = nullptr;
+ LineEdit *snap_scale = nullptr;
LineEdit *xform_translate[3];
LineEdit *xform_rotate[3];
LineEdit *xform_scale[3];
- OptionButton *xform_type;
+ OptionButton *xform_type = nullptr;
- VBoxContainer *settings_vbc;
- SpinBox *settings_fov;
- SpinBox *settings_znear;
- SpinBox *settings_zfar;
+ VBoxContainer *settings_vbc = nullptr;
+ SpinBox *settings_fov = nullptr;
+ SpinBox *settings_znear = nullptr;
+ SpinBox *settings_zfar = nullptr;
void _snap_changed();
void _snap_update();
@@ -662,14 +662,14 @@ private:
void _menu_gizmo_toggled(int p_option);
void _update_camera_override_button(bool p_game_running);
void _update_camera_override_viewport(Object *p_viewport);
- HBoxContainer *hbc_menu;
+ HBoxContainer *hbc_menu = nullptr;
// Used for secondary menu items which are displayed depending on the currently selected node
// (such as MeshInstance's "Mesh" menu).
- PanelContainer *context_menu_container;
- HBoxContainer *hbc_context_menu;
+ PanelContainer *context_menu_container = nullptr;
+ HBoxContainer *hbc_context_menu = nullptr;
void _generate_selection_boxes();
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
int camera_override_viewport_id;
@@ -683,13 +683,13 @@ private:
void _toggle_maximize_view(Object *p_viewport);
- Node *custom_camera;
+ Node *custom_camera = nullptr;
Object *_get_editor_data(Object *p_what);
Ref<Environment> viewport_environment;
- Node3D *selected;
+ Node3D *selected = nullptr;
void _request_gizmo(Object *p_obj);
void _set_subgizmo_selection(Object *p_obj, Ref<Node3DGizmo> p_gizmo, int p_id, Transform3D p_transform = Transform3D());
@@ -712,18 +712,18 @@ private:
uint32_t world_env_count = 0;
uint32_t directional_light_count = 0;
- Button *sun_button;
- Label *sun_state;
- Label *sun_title;
- VBoxContainer *sun_vb;
- Popup *sun_environ_popup;
- Control *sun_direction;
- EditorSpinSlider *sun_angle_altitude;
- EditorSpinSlider *sun_angle_azimuth;
- ColorPickerButton *sun_color;
- EditorSpinSlider *sun_energy;
- EditorSpinSlider *sun_max_distance;
- Button *sun_add_to_scene;
+ Button *sun_button = nullptr;
+ Label *sun_state = nullptr;
+ Label *sun_title = nullptr;
+ VBoxContainer *sun_vb = nullptr;
+ Popup *sun_environ_popup = nullptr;
+ Control *sun_direction = nullptr;
+ EditorSpinSlider *sun_angle_altitude = nullptr;
+ EditorSpinSlider *sun_angle_azimuth = nullptr;
+ ColorPickerButton *sun_color = nullptr;
+ EditorSpinSlider *sun_energy = nullptr;
+ EditorSpinSlider *sun_max_distance = nullptr;
+ Button *sun_add_to_scene = nullptr;
void _sun_direction_draw();
void _sun_direction_input(const Ref<InputEvent> &p_event);
@@ -734,23 +734,23 @@ private:
Ref<Shader> sun_direction_shader;
Ref<ShaderMaterial> sun_direction_material;
- Button *environ_button;
- Label *environ_state;
- Label *environ_title;
- VBoxContainer *environ_vb;
- ColorPickerButton *environ_sky_color;
- ColorPickerButton *environ_ground_color;
- EditorSpinSlider *environ_energy;
- Button *environ_ao_button;
- Button *environ_glow_button;
- Button *environ_tonemap_button;
- Button *environ_gi_button;
- Button *environ_add_to_scene;
-
- Button *sun_environ_settings;
-
- DirectionalLight3D *preview_sun;
- WorldEnvironment *preview_environment;
+ Button *environ_button = nullptr;
+ Label *environ_state = nullptr;
+ Label *environ_title = nullptr;
+ VBoxContainer *environ_vb = nullptr;
+ ColorPickerButton *environ_sky_color = nullptr;
+ ColorPickerButton *environ_ground_color = nullptr;
+ EditorSpinSlider *environ_energy = nullptr;
+ Button *environ_ao_button = nullptr;
+ Button *environ_glow_button = nullptr;
+ Button *environ_tonemap_button = nullptr;
+ Button *environ_gi_button = nullptr;
+ Button *environ_add_to_scene = nullptr;
+
+ Button *sun_environ_settings = nullptr;
+
+ DirectionalLight3D *preview_sun = nullptr;
+ WorldEnvironment *preview_environment = nullptr;
Ref<Environment> environment;
Ref<ProceduralSkyMaterial> sky_material;
@@ -868,7 +868,7 @@ public:
class Node3DEditorPlugin : public EditorPlugin {
GDCLASS(Node3DEditorPlugin, EditorPlugin);
- Node3DEditor *spatial_editor;
+ Node3DEditor *spatial_editor = nullptr;
public:
Node3DEditor *get_spatial_editor() { return spatial_editor; }
diff --git a/editor/plugins/occluder_instance_3d_editor_plugin.h b/editor/plugins/occluder_instance_3d_editor_plugin.h
index 24f31b2ea8..360b7297cf 100644
--- a/editor/plugins/occluder_instance_3d_editor_plugin.h
+++ b/editor/plugins/occluder_instance_3d_editor_plugin.h
@@ -40,11 +40,11 @@ class EditorFileDialog;
class OccluderInstance3DEditorPlugin : public EditorPlugin {
GDCLASS(OccluderInstance3DEditorPlugin, EditorPlugin);
- OccluderInstance3D *occluder_instance;
+ OccluderInstance3D *occluder_instance = nullptr;
- Button *bake;
+ Button *bake = nullptr;
- EditorFileDialog *file_dialog;
+ EditorFileDialog *file_dialog = nullptr;
void _bake_select_file(const String &p_file);
void _bake();
diff --git a/editor/plugins/ot_features_plugin.h b/editor/plugins/ot_features_plugin.h
index fcbc8692ca..6639148080 100644
--- a/editor/plugins/ot_features_plugin.h
+++ b/editor/plugins/ot_features_plugin.h
@@ -38,7 +38,7 @@
class OpenTypeFeaturesEditor : public EditorProperty {
GDCLASS(OpenTypeFeaturesEditor, EditorProperty);
- EditorSpinSlider *spin;
+ EditorSpinSlider *spin = nullptr;
bool setting = true;
void _value_changed(double p_val);
Button *button = nullptr;
diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h
index 926a859f8b..ff74aeedf7 100644
--- a/editor/plugins/path_2d_editor_plugin.h
+++ b/editor/plugins/path_2d_editor_plugin.h
@@ -40,14 +40,14 @@ class CanvasItemEditor;
class Path2DEditor : public HBoxContainer {
GDCLASS(Path2DEditor, HBoxContainer);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
- CanvasItemEditor *canvas_item_editor;
- Panel *panel;
- Path2D *node;
+ CanvasItemEditor *canvas_item_editor = nullptr;
+ Panel *panel = nullptr;
+ Path2D *node = nullptr;
- HBoxContainer *base_hb;
- Separator *sep;
+ HBoxContainer *base_hb = nullptr;
+ Separator *sep = nullptr;
enum Mode {
MODE_CREATE,
@@ -58,12 +58,12 @@ class Path2DEditor : public HBoxContainer {
};
Mode mode;
- Button *curve_create;
- Button *curve_edit;
- Button *curve_edit_curve;
- Button *curve_del;
- Button *curve_close;
- MenuButton *handle_menu;
+ Button *curve_create = nullptr;
+ Button *curve_edit = nullptr;
+ Button *curve_edit_curve = nullptr;
+ Button *curve_del = nullptr;
+ Button *curve_close = nullptr;
+ MenuButton *handle_menu = nullptr;
bool mirror_handle_angle;
bool mirror_handle_length;
@@ -110,7 +110,7 @@ public:
class Path2DEditorPlugin : public EditorPlugin {
GDCLASS(Path2DEditorPlugin, EditorPlugin);
- Path2DEditor *path2d_editor;
+ Path2DEditor *path2d_editor = nullptr;
public:
virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return path2d_editor->forward_gui_input(p_event); }
diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h
index 3c6ca65437..72c24732c0 100644
--- a/editor/plugins/path_3d_editor_plugin.h
+++ b/editor/plugins/path_3d_editor_plugin.h
@@ -40,7 +40,7 @@
class Path3DGizmo : public EditorNode3DGizmo {
GDCLASS(Path3DGizmo, EditorNode3DGizmo);
- Path3D *path;
+ Path3D *path = nullptr;
mutable Vector3 original;
mutable float orig_in_length;
mutable float orig_out_length;
@@ -70,14 +70,14 @@ public:
class Path3DEditorPlugin : public EditorPlugin {
GDCLASS(Path3DEditorPlugin, EditorPlugin);
- Separator *sep;
- Button *curve_create;
- Button *curve_edit;
- Button *curve_del;
- Button *curve_close;
- MenuButton *handle_menu;
+ Separator *sep = nullptr;
+ Button *curve_create = nullptr;
+ Button *curve_edit = nullptr;
+ Button *curve_del = nullptr;
+ Button *curve_close = nullptr;
+ MenuButton *handle_menu = nullptr;
- Path3D *path;
+ Path3D *path = nullptr;
void _update_theme();
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.cpp b/editor/plugins/physical_bone_3d_editor_plugin.cpp
index e815a9c9f6..9dc89133c4 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.cpp
+++ b/editor/plugins/physical_bone_3d_editor_plugin.cpp
@@ -82,8 +82,7 @@ void PhysicalBone3DEditor::show() {
spatial_editor_hb->show();
}
-PhysicalBone3DEditorPlugin::PhysicalBone3DEditorPlugin() :
- physical_bone_editor() {}
+PhysicalBone3DEditorPlugin::PhysicalBone3DEditorPlugin() {}
void PhysicalBone3DEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
diff --git a/editor/plugins/physical_bone_3d_editor_plugin.h b/editor/plugins/physical_bone_3d_editor_plugin.h
index 4051644b54..93e722a432 100644
--- a/editor/plugins/physical_bone_3d_editor_plugin.h
+++ b/editor/plugins/physical_bone_3d_editor_plugin.h
@@ -39,8 +39,8 @@
class PhysicalBone3DEditor : public Object {
GDCLASS(PhysicalBone3DEditor, Object);
- HBoxContainer *spatial_editor_hb;
- Button *button_transform_joint;
+ HBoxContainer *spatial_editor_hb = nullptr;
+ Button *button_transform_joint = nullptr;
PhysicalBone3D *selected = nullptr;
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 2812c4aaaf..8566e92b22 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -1228,9 +1228,7 @@ Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
return p_target;
}
-Polygon2DEditor::Polygon2DEditor() :
- AbstractPolygon2DEditor() {
- node = nullptr;
+Polygon2DEditor::Polygon2DEditor() {
snap_offset = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_offset", Vector2());
snap_step = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_step", Vector2(10, 10));
use_snap = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_enabled", false);
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index 0a5def902c..4403d1e9c7 100644
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -68,38 +68,38 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
Button *uv_edit_mode[4];
Ref<ButtonGroup> uv_edit_group;
- Polygon2D *node;
+ Polygon2D *node = nullptr;
UVMode uv_mode;
- AcceptDialog *uv_edit;
+ AcceptDialog *uv_edit = nullptr;
Button *uv_button[UV_MODE_MAX];
- Button *b_snap_enable;
- Button *b_snap_grid;
- Panel *uv_edit_draw;
- HSlider *uv_zoom;
- SpinBox *uv_zoom_value;
- HScrollBar *uv_hscroll;
- VScrollBar *uv_vscroll;
- MenuButton *uv_menu;
- TextureRect *uv_icon_zoom;
+ Button *b_snap_enable = nullptr;
+ Button *b_snap_grid = nullptr;
+ Panel *uv_edit_draw = nullptr;
+ HSlider *uv_zoom = nullptr;
+ SpinBox *uv_zoom_value = nullptr;
+ HScrollBar *uv_hscroll = nullptr;
+ VScrollBar *uv_vscroll = nullptr;
+ MenuButton *uv_menu = nullptr;
+ TextureRect *uv_icon_zoom = nullptr;
Ref<ViewPanner> uv_panner;
void _uv_scroll_callback(Vector2 p_scroll_vec, bool p_alt);
void _uv_pan_callback(Vector2 p_scroll_vec);
void _uv_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt);
- VBoxContainer *bone_scroll_main_vb;
- ScrollContainer *bone_scroll;
- VBoxContainer *bone_scroll_vb;
- Button *sync_bones;
- HSlider *bone_paint_strength;
- SpinBox *bone_paint_radius;
- Label *bone_paint_radius_label;
+ VBoxContainer *bone_scroll_main_vb = nullptr;
+ ScrollContainer *bone_scroll = nullptr;
+ VBoxContainer *bone_scroll_vb = nullptr;
+ Button *sync_bones = nullptr;
+ HSlider *bone_paint_strength = nullptr;
+ SpinBox *bone_paint_radius = nullptr;
+ Label *bone_paint_radius_label = nullptr;
bool bone_painting;
int bone_painting_bone;
Vector<float> prev_weights;
Vector2 bone_paint_pos;
- AcceptDialog *grid_settings;
+ AcceptDialog *grid_settings = nullptr;
void _sync_bones();
void _update_bone_list();
@@ -123,9 +123,9 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
Vector2 uv_drag_from;
bool updating_uv_scroll;
- AcceptDialog *error;
+ AcceptDialog *error = nullptr;
- Button *button_uv;
+ Button *button_uv = nullptr;
bool use_snap;
bool snap_show_grid;
diff --git a/editor/plugins/polygon_3d_editor_plugin.h b/editor/plugins/polygon_3d_editor_plugin.h
index e92dcaf319..3ad7a4df58 100644
--- a/editor/plugins/polygon_3d_editor_plugin.h
+++ b/editor/plugins/polygon_3d_editor_plugin.h
@@ -41,7 +41,7 @@ class CanvasItemEditor;
class Polygon3DEditor : public HBoxContainer {
GDCLASS(Polygon3DEditor, HBoxContainer);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
enum Mode {
MODE_CREATE,
MODE_EDIT,
@@ -50,21 +50,21 @@ class Polygon3DEditor : public HBoxContainer {
Mode mode;
- Button *button_create;
- Button *button_edit;
+ Button *button_create = nullptr;
+ Button *button_edit = nullptr;
Ref<StandardMaterial3D> line_material;
Ref<StandardMaterial3D> handle_material;
- Panel *panel;
- Node3D *node;
+ Panel *panel = nullptr;
+ Node3D *node = nullptr;
Ref<Resource> node_resource;
Ref<ImmediateMesh> imesh;
- MeshInstance3D *imgeom;
- MeshInstance3D *pointsm;
+ MeshInstance3D *imgeom = nullptr;
+ MeshInstance3D *pointsm = nullptr;
Ref<ArrayMesh> m;
- MenuButton *options;
+ MenuButton *options = nullptr;
int edited_point;
Vector2 edited_point_pos;
@@ -98,7 +98,7 @@ public:
class Polygon3DEditorPlugin : public EditorPlugin {
GDCLASS(Polygon3DEditorPlugin, EditorPlugin);
- Polygon3DEditor *polygon_editor;
+ Polygon3DEditor *polygon_editor = nullptr;
public:
virtual EditorPlugin::AfterGUIInput forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) override { return polygon_editor->forward_spatial_gui_input(p_camera, p_event); }
diff --git a/editor/plugins/replication_editor_plugin.h b/editor/plugins/replication_editor_plugin.h
index 46274d188c..08e86d1617 100644
--- a/editor/plugins/replication_editor_plugin.h
+++ b/editor/plugins/replication_editor_plugin.h
@@ -51,7 +51,7 @@ private:
Ref<SceneReplicationConfig> config;
NodePath deleting;
- Tree *tree;
+ Tree *tree = nullptr;
bool keying = false;
Ref<Texture2D> _get_class_icon(const Node *p_node);
@@ -84,7 +84,7 @@ class ReplicationEditorPlugin : public EditorPlugin {
GDCLASS(ReplicationEditorPlugin, EditorPlugin);
private:
- ReplicationEditor *repl_editor;
+ ReplicationEditor *repl_editor = nullptr;
void _node_removed(Node *p_node);
void _keying_changed();
diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h
index 8e81239f1b..0b799c13c6 100644
--- a/editor/plugins/resource_preloader_editor_plugin.h
+++ b/editor/plugins/resource_preloader_editor_plugin.h
@@ -47,16 +47,16 @@ class ResourcePreloaderEditor : public PanelContainer {
BUTTON_REMOVE
};
- Button *load;
- Button *paste;
- Tree *tree;
+ Button *load = nullptr;
+ Button *paste = nullptr;
+ Tree *tree = nullptr;
bool loading_scene;
- EditorFileDialog *file;
+ EditorFileDialog *file = nullptr;
- AcceptDialog *dialog;
+ AcceptDialog *dialog = nullptr;
- ResourcePreloader *preloader;
+ ResourcePreloader *preloader = nullptr;
void _load_pressed();
void _files_load_request(const Vector<String> &p_paths);
@@ -66,7 +66,7 @@ class ResourcePreloaderEditor : public PanelContainer {
void _cell_button_pressed(Object *p_item, int p_column, int p_id);
void _item_edited();
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
@@ -87,8 +87,8 @@ public:
class ResourcePreloaderEditorPlugin : public EditorPlugin {
GDCLASS(ResourcePreloaderEditorPlugin, EditorPlugin);
- ResourcePreloaderEditor *preloader_editor;
- Button *button;
+ ResourcePreloaderEditor *preloader_editor = nullptr;
+ Button *button = nullptr;
public:
virtual String get_name() const override { return "ResourcePreloader"; }
diff --git a/editor/plugins/root_motion_editor_plugin.h b/editor/plugins/root_motion_editor_plugin.h
index c2866f269b..5b8c1d77b3 100644
--- a/editor/plugins/root_motion_editor_plugin.h
+++ b/editor/plugins/root_motion_editor_plugin.h
@@ -38,12 +38,12 @@
class EditorPropertyRootMotion : public EditorProperty {
GDCLASS(EditorPropertyRootMotion, EditorProperty);
- Button *assign;
- Button *clear;
+ Button *assign = nullptr;
+ Button *clear = nullptr;
NodePath base_hint;
- ConfirmationDialog *filter_dialog;
- Tree *filters;
+ ConfirmationDialog *filter_dialog = nullptr;
+ Tree *filters = nullptr;
void _confirmed();
void _node_assign();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index bbaf2bef98..677b55bb88 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1232,9 +1232,6 @@ void ScriptEditor::_menu_option(int p_option) {
if (ResourceLoader::get_resource_type(res_path) == "PackedScene") {
if (!EditorNode::get_singleton()->is_scene_open(res_path)) {
EditorNode::get_singleton()->load_scene(res_path);
- script_editor->call_deferred(SNAME("_menu_option"), p_option);
- previous_scripts.push_back(path); //repeat the operation
- return;
}
} else {
EditorNode::get_singleton()->load_resource(res_path);
@@ -1250,7 +1247,6 @@ void ScriptEditor::_menu_option(int p_option) {
edit(scr);
file_dialog_option = -1;
- return;
} else {
Error error;
Ref<TextFile> text_file = _load_text_file(path, &error);
@@ -1261,7 +1257,6 @@ void ScriptEditor::_menu_option(int p_option) {
if (text_file.is_valid()) {
edit(text_file);
file_dialog_option = -1;
- return;
}
}
} break;
@@ -3960,7 +3955,7 @@ void ScriptEditorPlugin::edit(Object *p_object) {
Script *p_script = Object::cast_to<Script>(p_object);
String res_path = p_script->get_path().get_slice("::", 0);
- if (p_script->is_built_in()) {
+ if (p_script->is_built_in() && !res_path.is_empty()) {
if (ResourceLoader::get_resource_type(res_path) == "PackedScene") {
if (!EditorNode::get_singleton()->is_scene_open(res_path)) {
EditorNode::get_singleton()->load_scene(res_path);
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index a99e269d46..5eeca7a334 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -102,8 +102,8 @@ public:
class ScriptEditorQuickOpen : public ConfirmationDialog {
GDCLASS(ScriptEditorQuickOpen, ConfirmationDialog);
- LineEdit *search_box;
- Tree *search_options;
+ LineEdit *search_box = nullptr;
+ Tree *search_options = nullptr;
String function;
void _update_search();
@@ -242,55 +242,55 @@ class ScriptEditor : public PanelContainer {
DISPLAY_FULL_PATH,
};
- HBoxContainer *menu_hb;
- MenuButton *file_menu;
- MenuButton *edit_menu;
- MenuButton *script_search_menu;
- MenuButton *debug_menu;
- PopupMenu *context_menu;
- Timer *autosave_timer;
+ HBoxContainer *menu_hb = nullptr;
+ MenuButton *file_menu = nullptr;
+ MenuButton *edit_menu = nullptr;
+ MenuButton *script_search_menu = nullptr;
+ MenuButton *debug_menu = nullptr;
+ PopupMenu *context_menu = nullptr;
+ Timer *autosave_timer = nullptr;
uint64_t idle;
- PopupMenu *recent_scripts;
- PopupMenu *theme_submenu;
-
- Button *help_search;
- Button *site_search;
- EditorHelpSearch *help_search_dialog;
-
- ItemList *script_list;
- HSplitContainer *script_split;
- ItemList *members_overview;
- LineEdit *filter_scripts;
- LineEdit *filter_methods;
- VBoxContainer *scripts_vbox;
- VBoxContainer *overview_vbox;
- HBoxContainer *buttons_hbox;
- Label *filename;
- Button *members_overview_alphabeta_sort_button;
+ PopupMenu *recent_scripts = nullptr;
+ PopupMenu *theme_submenu = nullptr;
+
+ Button *help_search = nullptr;
+ Button *site_search = nullptr;
+ EditorHelpSearch *help_search_dialog = nullptr;
+
+ ItemList *script_list = nullptr;
+ HSplitContainer *script_split = nullptr;
+ ItemList *members_overview = nullptr;
+ LineEdit *filter_scripts = nullptr;
+ LineEdit *filter_methods = nullptr;
+ VBoxContainer *scripts_vbox = nullptr;
+ VBoxContainer *overview_vbox = nullptr;
+ HBoxContainer *buttons_hbox = nullptr;
+ Label *filename = nullptr;
+ Button *members_overview_alphabeta_sort_button = nullptr;
bool members_overview_enabled;
- ItemList *help_overview;
+ ItemList *help_overview = nullptr;
bool help_overview_enabled;
- VSplitContainer *list_split;
- TabContainer *tab_container;
- EditorFileDialog *file_dialog;
- AcceptDialog *error_dialog;
- ConfirmationDialog *erase_tab_confirm;
- ScriptCreateDialog *script_create_dialog;
- Button *scripts_visible;
- FindReplaceBar *find_replace_bar;
+ VSplitContainer *list_split = nullptr;
+ TabContainer *tab_container = nullptr;
+ EditorFileDialog *file_dialog = nullptr;
+ AcceptDialog *error_dialog = nullptr;
+ ConfirmationDialog *erase_tab_confirm = nullptr;
+ ScriptCreateDialog *script_create_dialog = nullptr;
+ Button *scripts_visible = nullptr;
+ FindReplaceBar *find_replace_bar = nullptr;
String current_theme;
- TextureRect *script_icon;
- Label *script_name_label;
+ TextureRect *script_icon = nullptr;
+ Label *script_name_label = nullptr;
- Button *script_back;
- Button *script_forward;
+ Button *script_back = nullptr;
+ Button *script_forward = nullptr;
- FindInFilesDialog *find_in_files_dialog;
- FindInFilesPanel *find_in_files;
- Button *find_in_files_button;
+ FindInFilesDialog *find_in_files_dialog = nullptr;
+ FindInFilesPanel *find_in_files = nullptr;
+ Button *find_in_files_button = nullptr;
enum {
SCRIPT_EDITOR_FUNC_MAX = 32,
@@ -320,8 +320,8 @@ class ScriptEditor : public PanelContainer {
bool _has_script_tab() const;
void _prepare_file_menu();
- Tree *disk_changed_list;
- ConfirmationDialog *disk_changed;
+ Tree *disk_changed_list = nullptr;
+ ConfirmationDialog *disk_changed = nullptr;
bool restoring_layout;
@@ -361,7 +361,7 @@ class ScriptEditor : public PanelContainer {
void _update_selected_editor_menu();
- EditorScriptCodeCompletionCache *completion_cache;
+ EditorScriptCodeCompletionCache *completion_cache = nullptr;
void _editor_stop();
@@ -528,7 +528,7 @@ public:
class ScriptEditorPlugin : public EditorPlugin {
GDCLASS(ScriptEditorPlugin, EditorPlugin);
- ScriptEditor *script_editor;
+ ScriptEditor *script_editor = nullptr;
public:
virtual String get_name() const override { return "Script"; }
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index c1b0a32fc7..4626f10b8d 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -699,6 +699,9 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
}
String hint;
Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint);
+
+ r_options->sort_custom_inplace<CodeCompletionOptionCompare>();
+
if (err == OK) {
code_editor->get_text_editor()->set_code_hint(hint);
}
diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h
index 5c3a66404e..c1c4b0af54 100644
--- a/editor/plugins/script_text_editor.h
+++ b/editor/plugins/script_text_editor.h
@@ -256,4 +256,51 @@ public:
~ScriptTextEditor();
};
+const int KIND_COUNT = 10;
+// The order in which to sort code completion options.
+const ScriptLanguage::CodeCompletionKind KIND_SORT_ORDER[KIND_COUNT] = {
+ ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE,
+ ScriptLanguage::CODE_COMPLETION_KIND_MEMBER,
+ ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION,
+ ScriptLanguage::CODE_COMPLETION_KIND_ENUM,
+ ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL,
+ ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT,
+ ScriptLanguage::CODE_COMPLETION_KIND_CLASS,
+ ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH,
+ ScriptLanguage::CODE_COMPLETION_KIND_FILE_PATH,
+ ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT,
+};
+
+// The custom comparer which will sort completion options.
+struct CodeCompletionOptionCompare {
+ _FORCE_INLINE_ bool operator()(const ScriptLanguage::CodeCompletionOption &l, const ScriptLanguage::CodeCompletionOption &r) const {
+ if (l.location == r.location) {
+ // If locations are same, sort on kind
+ if (l.kind == r.kind) {
+ // If kinds are same, sort alphanumeric
+ return l.display < r.display;
+ }
+
+ // Sort kinds based on the const sorting array defined above. Lower index = higher priority.
+ int l_index = -1;
+ int r_index = -1;
+ for (int i = 0; i < KIND_COUNT; i++) {
+ const ScriptLanguage::CodeCompletionKind kind = KIND_SORT_ORDER[i];
+ l_index = kind == l.kind ? i : l_index;
+ r_index = kind == r.kind ? i : r_index;
+
+ if (l_index != -1 && r_index != -1) {
+ return l_index < r_index;
+ }
+ }
+
+ // This return should never be hit unless something goes wrong.
+ // l and r should always have a Kind which is in the sort order array.
+ return l.display < r.display;
+ }
+
+ return l.location < r.location;
+ }
+};
+
#endif // SCRIPT_TEXT_EDITOR_H
diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h
index 600b14362e..067711c75c 100644
--- a/editor/plugins/shader_editor_plugin.h
+++ b/editor/plugins/shader_editor_plugin.h
@@ -108,19 +108,19 @@ class ShaderEditor : public PanelContainer {
HELP_DOCS,
};
- MenuButton *edit_menu;
- MenuButton *search_menu;
- PopupMenu *bookmarks_menu;
- MenuButton *help_menu;
- PopupMenu *context_menu;
+ MenuButton *edit_menu = nullptr;
+ MenuButton *search_menu = nullptr;
+ PopupMenu *bookmarks_menu = nullptr;
+ MenuButton *help_menu = nullptr;
+ PopupMenu *context_menu = nullptr;
RichTextLabel *warnings_panel = nullptr;
uint64_t idle;
- GotoLineDialog *goto_line_dialog;
- ConfirmationDialog *erase_tab_confirm;
- ConfirmationDialog *disk_changed;
+ GotoLineDialog *goto_line_dialog = nullptr;
+ ConfirmationDialog *erase_tab_confirm = nullptr;
+ ConfirmationDialog *disk_changed = nullptr;
- ShaderTextEditor *shader_editor;
+ ShaderTextEditor *shader_editor = nullptr;
void _menu_option(int p_option);
mutable Ref<Shader> shader;
@@ -161,8 +161,8 @@ class ShaderEditorPlugin : public EditorPlugin {
GDCLASS(ShaderEditorPlugin, EditorPlugin);
bool _2d;
- ShaderEditor *shader_editor;
- Button *button;
+ ShaderEditor *shader_editor = nullptr;
+ Button *button = nullptr;
public:
virtual String get_name() const override { return "Shader"; }
diff --git a/editor/plugins/shader_file_editor_plugin.h b/editor/plugins/shader_file_editor_plugin.h
index 5ee2d01dbf..1ebd644282 100644
--- a/editor/plugins/shader_file_editor_plugin.h
+++ b/editor/plugins/shader_file_editor_plugin.h
@@ -48,10 +48,10 @@ class ShaderFileEditor : public PanelContainer {
Ref<RDShaderFile> shader_file;
- HBoxContainer *stage_hb;
- ItemList *versions;
+ HBoxContainer *stage_hb = nullptr;
+ ItemList *versions = nullptr;
Button *stages[RD::SHADER_STAGE_MAX];
- RichTextLabel *error_text;
+ RichTextLabel *error_text = nullptr;
void _update_version(const StringName &p_version_txt, const RenderingDevice::ShaderStage p_stage);
void _version_selected(int p_stage);
@@ -74,8 +74,8 @@ public:
class ShaderFileEditorPlugin : public EditorPlugin {
GDCLASS(ShaderFileEditorPlugin, EditorPlugin);
- ShaderFileEditor *shader_editor;
- Button *button;
+ ShaderFileEditor *shader_editor = nullptr;
+ Button *button = nullptr;
public:
virtual String get_name() const override { return "ShaderFile"; }
diff --git a/editor/plugins/skeleton_2d_editor_plugin.h b/editor/plugins/skeleton_2d_editor_plugin.h
index 004dac7b05..295725b751 100644
--- a/editor/plugins/skeleton_2d_editor_plugin.h
+++ b/editor/plugins/skeleton_2d_editor_plugin.h
@@ -43,10 +43,10 @@ class Skeleton2DEditor : public Control {
MENU_OPTION_MAKE_REST,
};
- Skeleton2D *node;
+ Skeleton2D *node = nullptr;
- MenuButton *options;
- AcceptDialog *err_dialog;
+ MenuButton *options = nullptr;
+ AcceptDialog *err_dialog = nullptr;
void _menu_option(int p_option);
@@ -65,7 +65,7 @@ public:
class Skeleton2DEditorPlugin : public EditorPlugin {
GDCLASS(Skeleton2DEditorPlugin, EditorPlugin);
- Skeleton2DEditor *sprite_editor;
+ Skeleton2DEditor *sprite_editor = nullptr;
public:
virtual String get_name() const override { return "Skeleton2D"; }
diff --git a/editor/plugins/skeleton_3d_editor_plugin.h b/editor/plugins/skeleton_3d_editor_plugin.h
index 2dbb552428..911e39a34f 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_3d_editor_plugin.h
@@ -60,10 +60,10 @@ class BoneTransformEditor : public VBoxContainer {
Rect2 background_rects[5];
- Skeleton3D *skeleton;
+ Skeleton3D *skeleton = nullptr;
// String property;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
bool toggle_enabled = false;
bool updating = false;
@@ -108,26 +108,26 @@ class Skeleton3DEditor : public VBoxContainer {
Transform3D relative_rest; // Relative to skeleton node.
};
- EditorInspectorPluginSkeleton *editor_plugin;
+ EditorInspectorPluginSkeleton *editor_plugin = nullptr;
- Skeleton3D *skeleton;
+ Skeleton3D *skeleton = nullptr;
Tree *joint_tree = nullptr;
BoneTransformEditor *rest_editor = nullptr;
BoneTransformEditor *pose_editor = nullptr;
- VSeparator *separator;
+ VSeparator *separator = nullptr;
MenuButton *skeleton_options = nullptr;
- Button *edit_mode_button;
+ Button *edit_mode_button = nullptr;
bool edit_mode = false;
- HBoxContainer *animation_hb;
- Button *key_loc_button;
- Button *key_rot_button;
- Button *key_scale_button;
- Button *key_insert_button;
- Button *key_insert_all_button;
+ HBoxContainer *animation_hb = nullptr;
+ Button *key_loc_button = nullptr;
+ Button *key_rot_button = nullptr;
+ Button *key_scale_button = nullptr;
+ Button *key_insert_button = nullptr;
+ Button *key_insert_all_button = nullptr;
EditorFileDialog *file_dialog = nullptr;
@@ -163,7 +163,7 @@ class Skeleton3DEditor : public VBoxContainer {
void set_bone_options_enabled(const bool p_bone_options_enabled);
// Handle.
- MeshInstance3D *handles_mesh_instance;
+ MeshInstance3D *handles_mesh_instance = nullptr;
Ref<ImmediateMesh> handles_mesh;
Ref<ShaderMaterial> handle_material;
Ref<Shader> handle_shader;
@@ -220,7 +220,7 @@ class EditorInspectorPluginSkeleton : public EditorInspectorPlugin {
friend class Skeleton3DEditorPlugin;
- Skeleton3DEditor *skel_editor;
+ Skeleton3DEditor *skel_editor = nullptr;
public:
virtual bool can_handle(Object *p_object) override;
@@ -230,7 +230,7 @@ public:
class Skeleton3DEditorPlugin : public EditorPlugin {
GDCLASS(Skeleton3DEditorPlugin, EditorPlugin);
- EditorInspectorPluginSkeleton *skeleton_plugin;
+ EditorInspectorPluginSkeleton *skeleton_plugin = nullptr;
public:
virtual EditorPlugin::AfterGUIInput forward_spatial_gui_input(Camera3D *p_camera, const Ref<InputEvent> &p_event) override;
diff --git a/editor/plugins/skeleton_ik_3d_editor_plugin.h b/editor/plugins/skeleton_ik_3d_editor_plugin.h
index f71e788232..26aead6d67 100644
--- a/editor/plugins/skeleton_ik_3d_editor_plugin.h
+++ b/editor/plugins/skeleton_ik_3d_editor_plugin.h
@@ -38,9 +38,9 @@ class SkeletonIK3D;
class SkeletonIK3DEditorPlugin : public EditorPlugin {
GDCLASS(SkeletonIK3DEditorPlugin, EditorPlugin);
- SkeletonIK3D *skeleton_ik;
+ SkeletonIK3D *skeleton_ik = nullptr;
- Button *play_btn;
+ Button *play_btn = nullptr;
void _play();
diff --git a/editor/plugins/sprite_2d_editor_plugin.h b/editor/plugins/sprite_2d_editor_plugin.h
index 46953b0937..8e3dc19c7e 100644
--- a/editor/plugins/sprite_2d_editor_plugin.h
+++ b/editor/plugins/sprite_2d_editor_plugin.h
@@ -47,16 +47,16 @@ class Sprite2DEditor : public Control {
Menu selected_menu_item;
- Sprite2D *node;
+ Sprite2D *node = nullptr;
- MenuButton *options;
+ MenuButton *options = nullptr;
- ConfirmationDialog *outline_dialog;
+ ConfirmationDialog *outline_dialog = nullptr;
- AcceptDialog *err_dialog;
+ AcceptDialog *err_dialog = nullptr;
- ConfirmationDialog *debug_uv_dialog;
- Control *debug_uv;
+ ConfirmationDialog *debug_uv_dialog = nullptr;
+ Control *debug_uv = nullptr;
Vector<Vector2> uv_lines;
Vector<Vector<Vector2>> outline_lines;
Vector<Vector<Vector2>> computed_outline_lines;
@@ -64,10 +64,10 @@ class Sprite2DEditor : public Control {
Vector<Vector2> computed_uv;
Vector<int> computed_indices;
- SpinBox *simplification;
- SpinBox *grow_pixels;
- SpinBox *shrink_pixels;
- Button *update_preview;
+ SpinBox *simplification = nullptr;
+ SpinBox *grow_pixels = nullptr;
+ SpinBox *shrink_pixels = nullptr;
+ Button *update_preview = nullptr;
void _menu_option(int p_option);
@@ -98,7 +98,7 @@ public:
class Sprite2DEditorPlugin : public EditorPlugin {
GDCLASS(Sprite2DEditorPlugin, EditorPlugin);
- Sprite2DEditor *sprite_editor;
+ Sprite2DEditor *sprite_editor = nullptr;
public:
virtual String get_name() const override { return "Sprite2D"; }
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index 872a88e262..b0213012a2 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -48,48 +48,48 @@ class EditorFileDialog;
class SpriteFramesEditor : public HSplitContainer {
GDCLASS(SpriteFramesEditor, HSplitContainer);
- Button *load;
- Button *load_sheet;
- Button *_delete;
- Button *copy;
- Button *paste;
- Button *empty;
- Button *empty2;
- Button *move_up;
- Button *move_down;
- Button *zoom_out;
- Button *zoom_reset;
- Button *zoom_in;
- ItemList *tree;
+ Button *load = nullptr;
+ Button *load_sheet = nullptr;
+ Button *_delete = nullptr;
+ Button *copy = nullptr;
+ Button *paste = nullptr;
+ Button *empty = nullptr;
+ Button *empty2 = nullptr;
+ Button *move_up = nullptr;
+ Button *move_down = nullptr;
+ Button *zoom_out = nullptr;
+ Button *zoom_reset = nullptr;
+ Button *zoom_in = nullptr;
+ ItemList *tree = nullptr;
bool loading_scene;
int sel;
- Button *new_anim;
- Button *remove_anim;
+ Button *new_anim = nullptr;
+ Button *remove_anim = nullptr;
- Tree *animations;
- SpinBox *anim_speed;
- CheckButton *anim_loop;
+ Tree *animations = nullptr;
+ SpinBox *anim_speed = nullptr;
+ CheckButton *anim_loop = nullptr;
- EditorFileDialog *file;
+ EditorFileDialog *file = nullptr;
- AcceptDialog *dialog;
+ AcceptDialog *dialog = nullptr;
- SpriteFrames *frames;
+ SpriteFrames *frames = nullptr;
StringName edited_anim;
- ConfirmationDialog *delete_dialog;
-
- ConfirmationDialog *split_sheet_dialog;
- ScrollContainer *split_sheet_scroll;
- TextureRect *split_sheet_preview;
- SpinBox *split_sheet_h;
- SpinBox *split_sheet_v;
- Button *split_sheet_zoom_out;
- Button *split_sheet_zoom_reset;
- Button *split_sheet_zoom_in;
- EditorFileDialog *file_split_sheet;
+ ConfirmationDialog *delete_dialog = nullptr;
+
+ ConfirmationDialog *split_sheet_dialog = nullptr;
+ ScrollContainer *split_sheet_scroll = nullptr;
+ TextureRect *split_sheet_preview = nullptr;
+ SpinBox *split_sheet_h = nullptr;
+ SpinBox *split_sheet_v = nullptr;
+ Button *split_sheet_zoom_out = nullptr;
+ Button *split_sheet_zoom_reset = nullptr;
+ Button *split_sheet_zoom_in = nullptr;
+ EditorFileDialog *file_split_sheet = nullptr;
Set<int> frames_selected;
Set<int> frames_toggled_by_mouse_hover;
int last_frame_selected;
@@ -129,7 +129,7 @@ class SpriteFramesEditor : public HSplitContainer {
bool updating;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
@@ -164,8 +164,8 @@ public:
class SpriteFramesEditorPlugin : public EditorPlugin {
GDCLASS(SpriteFramesEditorPlugin, EditorPlugin);
- SpriteFramesEditor *frames_editor;
- Button *button;
+ SpriteFramesEditor *frames_editor = nullptr;
+ Button *button = nullptr;
public:
virtual String get_name() const override { return "SpriteFrames"; }
diff --git a/editor/plugins/style_box_editor_plugin.h b/editor/plugins/style_box_editor_plugin.h
index bdebebbe1c..663440ae31 100644
--- a/editor/plugins/style_box_editor_plugin.h
+++ b/editor/plugins/style_box_editor_plugin.h
@@ -40,7 +40,7 @@
class StyleBoxPreview : public VBoxContainer {
GDCLASS(StyleBoxPreview, VBoxContainer);
- Control *preview;
+ Control *preview = nullptr;
Ref<StyleBox> stylebox;
void _sb_changed();
diff --git a/editor/plugins/text_control_editor_plugin.h b/editor/plugins/text_control_editor_plugin.h
index 1349003a9c..a475f6eba3 100644
--- a/editor/plugins/text_control_editor_plugin.h
+++ b/editor/plugins/text_control_editor_plugin.h
@@ -100,7 +100,7 @@ public:
class TextControlEditorPlugin : public EditorPlugin {
GDCLASS(TextControlEditorPlugin, EditorPlugin);
- TextControlEditor *text_ctl_editor;
+ TextControlEditor *text_ctl_editor = nullptr;
public:
virtual String get_name() const override { return "TextControlFontEditor"; }
diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h
index d418032477..2f7f6f83bb 100644
--- a/editor/plugins/texture_3d_editor_plugin.h
+++ b/editor/plugins/texture_3d_editor_plugin.h
@@ -39,14 +39,14 @@
class Texture3DEditor : public Control {
GDCLASS(Texture3DEditor, Control);
- SpinBox *layer;
- Label *info;
+ SpinBox *layer = nullptr;
+ Label *info = nullptr;
Ref<Texture3D> texture;
Ref<Shader> shader;
Ref<ShaderMaterial> material;
- Control *texture_rect;
+ Control *texture_rect = nullptr;
void _make_shaders();
diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h
index 1c59ec4db0..830916e954 100644
--- a/editor/plugins/texture_layered_editor_plugin.h
+++ b/editor/plugins/texture_layered_editor_plugin.h
@@ -39,8 +39,8 @@
class TextureLayeredEditor : public Control {
GDCLASS(TextureLayeredEditor, Control);
- SpinBox *layer;
- Label *info;
+ SpinBox *layer = nullptr;
+ Label *info = nullptr;
Ref<TextureLayered> texture;
Ref<Shader> shaders[3];
@@ -48,7 +48,7 @@ class TextureLayeredEditor : public Control {
float x_rot = 0;
float y_rot = 0;
- Control *texture_rect;
+ Control *texture_rect = nullptr;
void _make_shaders();
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 041742c28a..1e1cc2b7b2 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -52,23 +52,23 @@ class TextureRegionEditor : public VBoxContainer {
};
friend class TextureRegionEditorPlugin;
- OptionButton *snap_mode_button;
- Button *zoom_in;
- Button *zoom_reset;
- Button *zoom_out;
- HBoxContainer *hb_grid; //For showing/hiding the grid controls when changing the SnapMode
- SpinBox *sb_step_y;
- SpinBox *sb_step_x;
- SpinBox *sb_off_y;
- SpinBox *sb_off_x;
- SpinBox *sb_sep_y;
- SpinBox *sb_sep_x;
- Panel *edit_draw;
-
- VScrollBar *vscroll;
- HScrollBar *hscroll;
-
- UndoRedo *undo_redo;
+ OptionButton *snap_mode_button = nullptr;
+ Button *zoom_in = nullptr;
+ Button *zoom_reset = nullptr;
+ Button *zoom_out = nullptr;
+ HBoxContainer *hb_grid = nullptr; //For showing/hiding the grid controls when changing the SnapMode
+ SpinBox *sb_step_y = nullptr;
+ SpinBox *sb_step_x = nullptr;
+ SpinBox *sb_off_y = nullptr;
+ SpinBox *sb_off_x = nullptr;
+ SpinBox *sb_sep_y = nullptr;
+ SpinBox *sb_sep_x = nullptr;
+ Panel *edit_draw = nullptr;
+
+ VScrollBar *vscroll = nullptr;
+ HScrollBar *hscroll = nullptr;
+
+ UndoRedo *undo_redo = nullptr;
Vector2 draw_ofs;
float draw_zoom;
@@ -79,9 +79,9 @@ class TextureRegionEditor : public VBoxContainer {
Vector2 snap_step;
Vector2 snap_separation;
- Sprite2D *node_sprite_2d;
- Sprite3D *node_sprite_3d;
- NinePatchRect *node_ninepatch;
+ Sprite2D *node_sprite_2d = nullptr;
+ Sprite3D *node_sprite_3d = nullptr;
+ NinePatchRect *node_ninepatch = nullptr;
Ref<StyleBoxTexture> obj_styleBox;
Ref<AtlasTexture> atlas_tex;
@@ -146,8 +146,8 @@ class TextureRegionEditorPlugin : public EditorPlugin {
GDCLASS(TextureRegionEditorPlugin, EditorPlugin);
bool manually_hidden;
- Button *texture_region_button;
- TextureRegionEditor *region_editor;
+ Button *texture_region_button = nullptr;
+ TextureRegionEditor *region_editor = nullptr;
protected:
static void _bind_methods();
diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h
index 7c1b0cda3e..4b49fbb186 100644
--- a/editor/plugins/theme_editor_plugin.h
+++ b/editor/plugins/theme_editor_plugin.h
@@ -75,9 +75,9 @@ class ThemeItemImportTree : public VBoxContainer {
Map<ThemeItem, ItemCheckedState> selected_items;
- LineEdit *import_items_filter;
+ LineEdit *import_items_filter = nullptr;
- Tree *import_items_tree;
+ Tree *import_items_tree = nullptr;
List<TreeItem *> tree_color_items;
List<TreeItem *> tree_constant_items;
List<TreeItem *> tree_font_items;
@@ -92,57 +92,57 @@ class ThemeItemImportTree : public VBoxContainer {
IMPORT_ITEM_DATA = 2,
};
- TextureRect *select_colors_icon;
- Label *select_colors_label;
- Button *select_all_colors_button;
- Button *select_full_colors_button;
- Button *deselect_all_colors_button;
- Label *total_selected_colors_label;
-
- TextureRect *select_constants_icon;
- Label *select_constants_label;
- Button *select_all_constants_button;
- Button *select_full_constants_button;
- Button *deselect_all_constants_button;
- Label *total_selected_constants_label;
-
- TextureRect *select_fonts_icon;
- Label *select_fonts_label;
- Button *select_all_fonts_button;
- Button *select_full_fonts_button;
- Button *deselect_all_fonts_button;
- Label *total_selected_fonts_label;
-
- TextureRect *select_font_sizes_icon;
- Label *select_font_sizes_label;
- Button *select_all_font_sizes_button;
- Button *select_full_font_sizes_button;
- Button *deselect_all_font_sizes_button;
- Label *total_selected_font_sizes_label;
-
- TextureRect *select_icons_icon;
- Label *select_icons_label;
- Button *select_all_icons_button;
- Button *select_full_icons_button;
- Button *deselect_all_icons_button;
- Label *total_selected_icons_label;
-
- TextureRect *select_styleboxes_icon;
- Label *select_styleboxes_label;
- Button *select_all_styleboxes_button;
- Button *select_full_styleboxes_button;
- Button *deselect_all_styleboxes_button;
- Label *total_selected_styleboxes_label;
-
- HBoxContainer *select_icons_warning_hb;
- TextureRect *select_icons_warning_icon;
- Label *select_icons_warning;
-
- Button *import_collapse_types_button;
- Button *import_expand_types_button;
- Button *import_select_all_button;
- Button *import_select_full_button;
- Button *import_deselect_all_button;
+ TextureRect *select_colors_icon = nullptr;
+ Label *select_colors_label = nullptr;
+ Button *select_all_colors_button = nullptr;
+ Button *select_full_colors_button = nullptr;
+ Button *deselect_all_colors_button = nullptr;
+ Label *total_selected_colors_label = nullptr;
+
+ TextureRect *select_constants_icon = nullptr;
+ Label *select_constants_label = nullptr;
+ Button *select_all_constants_button = nullptr;
+ Button *select_full_constants_button = nullptr;
+ Button *deselect_all_constants_button = nullptr;
+ Label *total_selected_constants_label = nullptr;
+
+ TextureRect *select_fonts_icon = nullptr;
+ Label *select_fonts_label = nullptr;
+ Button *select_all_fonts_button = nullptr;
+ Button *select_full_fonts_button = nullptr;
+ Button *deselect_all_fonts_button = nullptr;
+ Label *total_selected_fonts_label = nullptr;
+
+ TextureRect *select_font_sizes_icon = nullptr;
+ Label *select_font_sizes_label = nullptr;
+ Button *select_all_font_sizes_button = nullptr;
+ Button *select_full_font_sizes_button = nullptr;
+ Button *deselect_all_font_sizes_button = nullptr;
+ Label *total_selected_font_sizes_label = nullptr;
+
+ TextureRect *select_icons_icon = nullptr;
+ Label *select_icons_label = nullptr;
+ Button *select_all_icons_button = nullptr;
+ Button *select_full_icons_button = nullptr;
+ Button *deselect_all_icons_button = nullptr;
+ Label *total_selected_icons_label = nullptr;
+
+ TextureRect *select_styleboxes_icon = nullptr;
+ Label *select_styleboxes_label = nullptr;
+ Button *select_all_styleboxes_button = nullptr;
+ Button *select_full_styleboxes_button = nullptr;
+ Button *deselect_all_styleboxes_button = nullptr;
+ Label *total_selected_styleboxes_label = nullptr;
+
+ HBoxContainer *select_icons_warning_hb = nullptr;
+ TextureRect *select_icons_warning_icon = nullptr;
+ Label *select_icons_warning = nullptr;
+
+ Button *import_collapse_types_button = nullptr;
+ Button *import_expand_types_button = nullptr;
+ Button *import_select_all_button = nullptr;
+ Button *import_select_full_button = nullptr;
+ Button *import_deselect_all_button = nullptr;
void _update_items_tree();
void _toggle_type_items(bool p_collapse);
@@ -186,31 +186,31 @@ class ThemeTypeEditor;
class ThemeItemEditorDialog : public AcceptDialog {
GDCLASS(ThemeItemEditorDialog, AcceptDialog);
- ThemeTypeEditor *theme_type_editor;
+ ThemeTypeEditor *theme_type_editor = nullptr;
Ref<Theme> edited_theme;
- TabContainer *tc;
+ TabContainer *tc = nullptr;
enum TypesTreeAction {
TYPES_TREE_REMOVE_ITEM,
};
- Tree *edit_type_list;
- LineEdit *edit_add_type_value;
+ Tree *edit_type_list = nullptr;
+ LineEdit *edit_add_type_value = nullptr;
String edited_item_type;
- Button *edit_items_add_color;
- Button *edit_items_add_constant;
- Button *edit_items_add_font;
- Button *edit_items_add_font_size;
- Button *edit_items_add_icon;
- Button *edit_items_add_stylebox;
- Button *edit_items_remove_class;
- Button *edit_items_remove_custom;
- Button *edit_items_remove_all;
- Tree *edit_items_tree;
- Label *edit_items_message;
+ Button *edit_items_add_color = nullptr;
+ Button *edit_items_add_constant = nullptr;
+ Button *edit_items_add_font = nullptr;
+ Button *edit_items_add_font_size = nullptr;
+ Button *edit_items_add_icon = nullptr;
+ Button *edit_items_add_stylebox = nullptr;
+ Button *edit_items_remove_class = nullptr;
+ Button *edit_items_remove_custom = nullptr;
+ Button *edit_items_remove_all = nullptr;
+ Tree *edit_items_tree = nullptr;
+ Label *edit_items_message = nullptr;
enum ItemsTreeAction {
ITEMS_TREE_RENAME_ITEM,
@@ -218,10 +218,10 @@ class ThemeItemEditorDialog : public AcceptDialog {
ITEMS_TREE_REMOVE_DATA_TYPE,
};
- ConfirmationDialog *edit_theme_item_dialog;
- VBoxContainer *edit_theme_item_old_vb;
- Label *theme_item_old_name;
- LineEdit *theme_item_name;
+ ConfirmationDialog *edit_theme_item_dialog = nullptr;
+ VBoxContainer *edit_theme_item_old_vb = nullptr;
+ Label *theme_item_old_name = nullptr;
+ LineEdit *theme_item_name = nullptr;
enum ItemPopupMode {
CREATE_THEME_ITEM,
@@ -233,15 +233,15 @@ class ThemeItemEditorDialog : public AcceptDialog {
String edit_item_old_name;
Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX;
- ThemeItemImportTree *import_default_theme_items;
- ThemeItemImportTree *import_editor_theme_items;
- ThemeItemImportTree *import_other_theme_items;
+ ThemeItemImportTree *import_default_theme_items = nullptr;
+ ThemeItemImportTree *import_editor_theme_items = nullptr;
+ ThemeItemImportTree *import_other_theme_items = nullptr;
- LineEdit *import_another_theme_value;
- Button *import_another_theme_button;
- EditorFileDialog *import_another_theme_dialog;
+ LineEdit *import_another_theme_value = nullptr;
+ Button *import_another_theme_button = nullptr;
+ EditorFileDialog *import_another_theme_dialog = nullptr;
- ConfirmationDialog *confirm_closing_dialog;
+ ConfirmationDialog *confirm_closing_dialog = nullptr;
void ok_pressed() override;
void _close_dialog();
@@ -288,9 +288,9 @@ class ThemeTypeDialog : public ConfirmationDialog {
String pre_submitted_value;
- LineEdit *add_type_filter;
- ItemList *add_type_options;
- ConfirmationDialog *add_type_confirmation;
+ LineEdit *add_type_filter = nullptr;
+ ItemList *add_type_options = nullptr;
+ ConfirmationDialog *add_type_confirmation = nullptr;
void _dialog_about_to_show();
void ok_pressed() override;
@@ -332,22 +332,22 @@ class ThemeTypeEditor : public MarginContainer {
LeadingStylebox leading_stylebox;
- OptionButton *theme_type_list;
- Button *add_type_button;
+ OptionButton *theme_type_list = nullptr;
+ Button *add_type_button = nullptr;
- CheckButton *show_default_items_button;
+ CheckButton *show_default_items_button = nullptr;
- TabContainer *data_type_tabs;
- VBoxContainer *color_items_list;
- VBoxContainer *constant_items_list;
- VBoxContainer *font_items_list;
- VBoxContainer *font_size_items_list;
- VBoxContainer *icon_items_list;
- VBoxContainer *stylebox_items_list;
+ TabContainer *data_type_tabs = nullptr;
+ VBoxContainer *color_items_list = nullptr;
+ VBoxContainer *constant_items_list = nullptr;
+ VBoxContainer *font_items_list = nullptr;
+ VBoxContainer *font_size_items_list = nullptr;
+ VBoxContainer *icon_items_list = nullptr;
+ VBoxContainer *stylebox_items_list = nullptr;
- LineEdit *type_variation_edit;
- Button *type_variation_button;
- Label *type_variation_locked;
+ LineEdit *type_variation_edit = nullptr;
+ Button *type_variation_button = nullptr;
+ Label *type_variation_locked = nullptr;
enum TypeDialogMode {
ADD_THEME_TYPE,
@@ -355,10 +355,10 @@ class ThemeTypeEditor : public MarginContainer {
};
TypeDialogMode add_type_mode = ADD_THEME_TYPE;
- ThemeTypeDialog *add_type_dialog;
+ ThemeTypeDialog *add_type_dialog = nullptr;
Vector<Control *> focusables;
- Timer *update_debounce_timer;
+ Timer *update_debounce_timer = nullptr;
VBoxContainer *_create_item_list(Theme::DataType p_data_type);
void _update_type_list();
@@ -417,15 +417,15 @@ class ThemeEditor : public VBoxContainer {
Ref<Theme> theme;
- TabBar *preview_tabs;
- PanelContainer *preview_tabs_content;
- Button *add_preview_button;
- EditorFileDialog *preview_scene_dialog;
+ TabBar *preview_tabs = nullptr;
+ PanelContainer *preview_tabs_content = nullptr;
+ Button *add_preview_button = nullptr;
+ EditorFileDialog *preview_scene_dialog = nullptr;
- ThemeTypeEditor *theme_type_editor;
+ ThemeTypeEditor *theme_type_editor = nullptr;
- Label *theme_name;
- ThemeItemEditorDialog *theme_edit_dialog;
+ Label *theme_name = nullptr;
+ ThemeItemEditorDialog *theme_edit_dialog = nullptr;
void _theme_save_button_cbk(bool p_save_as);
void _theme_edit_button_cbk();
@@ -452,8 +452,8 @@ public:
class ThemeEditorPlugin : public EditorPlugin {
GDCLASS(ThemeEditorPlugin, EditorPlugin);
- ThemeEditor *theme_editor;
- Button *button;
+ ThemeEditor *theme_editor = nullptr;
+ Button *button = nullptr;
public:
virtual String get_name() const override { return "Theme"; }
diff --git a/editor/plugins/theme_editor_preview.h b/editor/plugins/theme_editor_preview.h
index 48111df399..d05916afae 100644
--- a/editor/plugins/theme_editor_preview.h
+++ b/editor/plugins/theme_editor_preview.h
@@ -41,10 +41,10 @@
class ThemeEditorPreview : public VBoxContainer {
GDCLASS(ThemeEditorPreview, VBoxContainer);
- ScrollContainer *preview_container;
- ColorRect *preview_bg;
- MarginContainer *preview_overlay;
- Control *picker_overlay;
+ ScrollContainer *preview_container = nullptr;
+ ColorRect *preview_bg = nullptr;
+ MarginContainer *preview_overlay = nullptr;
+ Control *picker_overlay = nullptr;
Control *hovered_control = nullptr;
struct ThemeCache {
@@ -69,9 +69,9 @@ class ThemeEditorPreview : public VBoxContainer {
void _reset_picker_overlay();
protected:
- HBoxContainer *preview_toolbar;
- MarginContainer *preview_content;
- Button *picker_button;
+ HBoxContainer *preview_toolbar = nullptr;
+ MarginContainer *preview_content = nullptr;
+ Button *picker_button = nullptr;
void add_preview_overlay(Control *p_overlay);
@@ -96,7 +96,7 @@ class SceneThemeEditorPreview : public ThemeEditorPreview {
Ref<PackedScene> loaded_scene;
- Button *reload_scene_button;
+ Button *reload_scene_button = nullptr;
void _reload_scene();
diff --git a/editor/plugins/tiles/atlas_merging_dialog.h b/editor/plugins/tiles/atlas_merging_dialog.h
index 6cf555247d..9502d93f6b 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.h
+++ b/editor/plugins/tiles/atlas_merging_dialog.h
@@ -49,19 +49,19 @@ private:
LocalVector<Map<Vector2i, Vector2i>> merged_mapping;
Ref<TileSet> tile_set;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
// 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;
+ ItemList *atlas_merging_atlases_list = nullptr;
+ EditorPropertyVector2i *texture_region_size_editor_property = nullptr;
+ EditorPropertyInteger *columns_editor_property = nullptr;
+ TextureRect *preview = nullptr;
+ Label *select_2_atlases_label = nullptr;
+ EditorFileDialog *editor_file_dialog = nullptr;
+ Button *merge_button = nullptr;
void _property_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h
index caf3ef9e4b..6e74858b08 100644
--- a/editor/plugins/tiles/tile_atlas_view.h
+++ b/editor/plugins/tiles/tile_atlas_view.h
@@ -45,8 +45,8 @@ class TileAtlasView : public Control {
GDCLASS(TileAtlasView, Control);
private:
- TileSet *tile_set;
- TileSetAtlasSource *tile_set_atlas_source;
+ TileSet *tile_set = nullptr;
+ TileSetAtlasSource *tile_set_atlas_source = nullptr;
int source_id = TileSet::INVALID_SOURCE;
enum DragType {
@@ -55,9 +55,9 @@ private:
};
DragType drag_type = DRAG_TYPE_NONE;
float previous_zoom = 1.0;
- EditorZoomWidget *zoom_widget;
- Button *button_center_view;
- CenterContainer *center_container;
+ EditorZoomWidget *zoom_widget = nullptr;
+ Button *button_center_view = nullptr;
+ CenterContainer *center_container = nullptr;
Vector2 panning;
void _update_zoom_and_panning(bool p_zoom_on_mouse_pos = false);
void _zoom_widget_changed();
@@ -72,41 +72,41 @@ private:
Map<Vector2, Map<int, Rect2i>> alternative_tiles_rect_cache;
void _update_alternative_tiles_rect_cache();
- MarginContainer *margin_container;
+ MarginContainer *margin_container = nullptr;
int margin_container_paddings[4] = { 0, 0, 0, 0 };
- HBoxContainer *hbox;
- Label *missing_source_label;
+ HBoxContainer *hbox = nullptr;
+ Label *missing_source_label = nullptr;
// Background
- Control *background_left;
+ Control *background_left = nullptr;
void _draw_background_left();
- Control *background_right;
+ Control *background_right = nullptr;
void _draw_background_right();
// Left side.
- Control *base_tiles_root_control;
+ Control *base_tiles_root_control = nullptr;
void _base_tiles_root_control_gui_input(const Ref<InputEvent> &p_event);
- Control *base_tiles_drawing_root;
+ Control *base_tiles_drawing_root = nullptr;
- Control *base_tiles_draw;
+ Control *base_tiles_draw = nullptr;
void _draw_base_tiles();
- Control *base_tiles_texture_grid;
+ Control *base_tiles_texture_grid = nullptr;
void _draw_base_tiles_texture_grid();
- Control *base_tiles_shape_grid;
+ Control *base_tiles_shape_grid = nullptr;
void _draw_base_tiles_shape_grid();
Size2i _compute_base_tiles_control_size();
// Right side.
- Control *alternative_tiles_root_control;
+ Control *alternative_tiles_root_control = nullptr;
void _alternative_tiles_root_control_gui_input(const Ref<InputEvent> &p_event);
- Control *alternative_tiles_drawing_root;
+ Control *alternative_tiles_drawing_root = nullptr;
- Control *alternatives_draw;
+ Control *alternatives_draw = nullptr;
void _draw_alternatives();
Size2i _compute_alternative_tiles_control_size();
diff --git a/editor/plugins/tiles/tile_data_editors.h b/editor/plugins/tiles/tile_data_editors.h
index 99724760a7..3ac9eacb05 100644
--- a/editor/plugins/tiles/tile_data_editors.h
+++ b/editor/plugins/tiles/tile_data_editors.h
@@ -93,7 +93,7 @@ private:
bool multiple_polygon_mode = false;
bool use_undo_redo = true;
- UndoRedo *editor_undo_redo;
+ UndoRedo *editor_undo_redo = nullptr;
// UI
int hovered_polygon_index = -1;
@@ -113,20 +113,20 @@ private:
Vector2 drag_last_pos;
PackedVector2Array drag_old_polygon;
- HBoxContainer *toolbar;
+ HBoxContainer *toolbar = nullptr;
Ref<ButtonGroup> tools_button_group;
- Button *button_create;
- Button *button_edit;
- Button *button_delete;
- Button *button_pixel_snap;
- MenuButton *button_advanced_menu;
+ Button *button_create = nullptr;
+ Button *button_edit = nullptr;
+ Button *button_delete = nullptr;
+ Button *button_pixel_snap = nullptr;
+ MenuButton *button_advanced_menu = nullptr;
Vector<Point2> in_creation_polygon;
- Panel *panel;
- Control *base_control;
- EditorZoomWidget *editor_zoom_widget;
- Button *button_center_view;
+ Panel *panel = nullptr;
+ Control *base_control = nullptr;
+ EditorZoomWidget *editor_zoom_widget = nullptr;
+ Button *button_center_view = nullptr;
Vector2 panning;
Ref<Texture2D> background_texture;
@@ -188,12 +188,12 @@ class TileDataDefaultEditor : public TileDataEditor {
private:
// Toolbar
HBoxContainer *toolbar = memnew(HBoxContainer);
- Button *picker_button;
+ Button *picker_button = nullptr;
// UI
Ref<Texture2D> tile_bool_checked;
Ref<Texture2D> tile_bool_unchecked;
- Label *label;
+ Label *label = nullptr;
EditorProperty *property_editor = nullptr;
@@ -214,7 +214,7 @@ private:
protected:
DummyObject *dummy_object = memnew(DummyObject);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
StringName type;
String property;
@@ -268,7 +268,7 @@ private:
int occlusion_layer = -1;
// UI
- GenericTilePolygonEditor *polygon_editor;
+ GenericTilePolygonEditor *polygon_editor = nullptr;
void _polygon_changed(PackedVector2Array p_polygon);
@@ -279,7 +279,7 @@ private:
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override;
protected:
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
virtual void _tile_set_changed() override;
@@ -299,7 +299,7 @@ class TileDataCollisionEditor : public TileDataDefaultEditor {
int physics_layer = -1;
// UI
- GenericTilePolygonEditor *polygon_editor;
+ GenericTilePolygonEditor *polygon_editor = nullptr;
DummyObject *dummy_object = memnew(DummyObject);
Map<StringName, EditorProperty *> property_editors;
@@ -314,7 +314,7 @@ class TileDataCollisionEditor : public TileDataDefaultEditor {
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override;
protected:
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
virtual void _tile_set_changed() override;
@@ -335,7 +335,7 @@ class TileDataTerrainsEditor : public TileDataEditor {
private:
// Toolbar
HBoxContainer *toolbar = memnew(HBoxContainer);
- Button *picker_button;
+ Button *picker_button = nullptr;
// Painting state.
enum DragType {
@@ -352,7 +352,7 @@ private:
Variant drag_painted_value;
// UI
- Label *label;
+ Label *label = nullptr;
DummyObject *dummy_object = memnew(DummyObject);
EditorPropertyEnum *terrain_set_property_editor = nullptr;
EditorPropertyEnum *terrain_property_editor = nullptr;
@@ -366,7 +366,7 @@ protected:
void _notification(int p_what);
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
public:
virtual Control *get_toolbar() override { return toolbar; };
@@ -388,7 +388,7 @@ private:
PackedVector2Array navigation_polygon;
// UI
- GenericTilePolygonEditor *polygon_editor;
+ GenericTilePolygonEditor *polygon_editor = nullptr;
void _polygon_changed(PackedVector2Array p_polygon);
@@ -399,7 +399,7 @@ private:
virtual void _setup_undo_redo_action(TileSetAtlasSource *p_tile_set_atlas_source, Map<TileMapCell, Variant> p_previous_values, Variant p_new_value) override;
protected:
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
virtual void _tile_set_changed() override;
diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h
index d09061015f..3a0293f48f 100644
--- a/editor/plugins/tiles/tile_map_editor.h
+++ b/editor/plugins/tiles/tile_map_editor.h
@@ -51,8 +51,8 @@ class UndoRedo;
class TileMapEditorPlugin : public Object {
public:
struct TabData {
- Control *toolbar;
- Control *panel;
+ Control *toolbar = nullptr;
+ Control *panel = nullptr;
};
virtual Vector<TabData> get_tabs() const {
@@ -69,33 +69,33 @@ class TileMapEditorTilesPlugin : public TileMapEditorPlugin {
GDCLASS(TileMapEditorTilesPlugin, TileMapEditorPlugin);
private:
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
ObjectID tile_map_id;
int tile_map_layer = -1;
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
///// Toolbar /////
- HBoxContainer *toolbar;
+ HBoxContainer *toolbar = nullptr;
Ref<ButtonGroup> tool_buttons_group;
- Button *select_tool_button;
- Button *paint_tool_button;
- Button *line_tool_button;
- Button *rect_tool_button;
- Button *bucket_tool_button;
+ Button *select_tool_button = nullptr;
+ Button *paint_tool_button = nullptr;
+ Button *line_tool_button = nullptr;
+ Button *rect_tool_button = nullptr;
+ Button *bucket_tool_button = nullptr;
- HBoxContainer *tools_settings;
+ HBoxContainer *tools_settings = nullptr;
- VSeparator *tools_settings_vsep;
- Button *picker_button;
- Button *erase_button;
+ VSeparator *tools_settings_vsep = nullptr;
+ Button *picker_button = nullptr;
+ Button *erase_button = nullptr;
- VSeparator *tools_settings_vsep_2;
- CheckBox *bucket_contiguous_checkbox;
- CheckBox *random_tile_checkbox;
+ VSeparator *tools_settings_vsep_2 = nullptr;
+ CheckBox *bucket_contiguous_checkbox = nullptr;
+ CheckBox *random_tile_checkbox = nullptr;
float scattering = 0.0;
- Label *scatter_label;
- SpinBox *scatter_spinbox;
+ Label *scatter_label = nullptr;
+ SpinBox *scatter_spinbox = nullptr;
void _on_random_tile_checkbox_toggled(bool p_pressed);
void _on_scattering_spinbox_changed(double p_value);
@@ -148,12 +148,12 @@ private:
void _tab_changed();
///// Bottom panel tiles ////
- VBoxContainer *tiles_bottom_panel;
- Label *missing_source_label;
- Label *invalid_source_label;
+ VBoxContainer *tiles_bottom_panel = nullptr;
+ Label *missing_source_label = nullptr;
+ Label *invalid_source_label = nullptr;
- ItemList *sources_list;
- MenuButton *source_sort_button;
+ ItemList *sources_list = nullptr;
+ MenuButton *source_sort_button = nullptr;
Ref<Texture2D> missing_atlas_texture_icon;
void _update_tile_set_sources_list();
@@ -162,18 +162,18 @@ private:
// Atlas sources.
TileMapCell hovered_tile;
- TileAtlasView *tile_atlas_view;
- HSplitContainer *atlas_sources_split_container;
+ TileAtlasView *tile_atlas_view = nullptr;
+ HSplitContainer *atlas_sources_split_container = nullptr;
bool tile_set_dragging_selection = false;
Vector2i tile_set_drag_start_mouse_pos;
- Control *tile_atlas_control;
+ Control *tile_atlas_control = nullptr;
void _tile_atlas_control_mouse_exited();
void _tile_atlas_control_gui_input(const Ref<InputEvent> &p_event);
void _tile_atlas_control_draw();
- Control *alternative_tiles_control;
+ Control *alternative_tiles_control = nullptr;
void _tile_alternatives_control_draw();
void _tile_alternatives_control_mouse_exited();
void _tile_alternatives_control_gui_input(const Ref<InputEvent> &p_event);
@@ -182,7 +182,7 @@ private:
void _set_source_sort(int p_sort);
// Scenes collection sources.
- ItemList *scene_tiles_list;
+ ItemList *scene_tiles_list = nullptr;
void _update_scenes_collection_view();
void _scene_thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, Variant p_ud);
@@ -190,9 +190,9 @@ private:
void _scenes_list_nothing_selected();
///// Bottom panel patterns ////
- VBoxContainer *patterns_bottom_panel;
- ItemList *patterns_item_list;
- Label *patterns_help_label;
+ VBoxContainer *patterns_bottom_panel = nullptr;
+ ItemList *patterns_item_list = nullptr;
+ Label *patterns_help_label = nullptr;
void _patterns_item_list_gui_input(const Ref<InputEvent> &p_event);
void _pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture);
bool select_last_pattern = false;
@@ -220,32 +220,32 @@ class TileMapEditorTerrainsPlugin : public TileMapEditorPlugin {
GDCLASS(TileMapEditorTerrainsPlugin, TileMapEditorPlugin);
private:
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
ObjectID tile_map_id;
int tile_map_layer = -1;
virtual void edit(ObjectID p_tile_map_id, int p_tile_map_layer) override;
// Toolbar.
- HBoxContainer *toolbar;
+ HBoxContainer *toolbar = nullptr;
Ref<ButtonGroup> tool_buttons_group;
- Button *paint_tool_button;
- Button *line_tool_button;
- Button *rect_tool_button;
- Button *bucket_tool_button;
+ Button *paint_tool_button = nullptr;
+ Button *line_tool_button = nullptr;
+ Button *rect_tool_button = nullptr;
+ Button *bucket_tool_button = nullptr;
- HBoxContainer *tools_settings;
+ HBoxContainer *tools_settings = nullptr;
- VSeparator *tools_settings_vsep;
- Button *picker_button;
- Button *erase_button;
+ VSeparator *tools_settings_vsep = nullptr;
+ Button *picker_button = nullptr;
+ Button *erase_button = nullptr;
- VSeparator *tools_settings_vsep_2;
- CheckBox *bucket_contiguous_checkbox;
+ VSeparator *tools_settings_vsep_2 = nullptr;
+ CheckBox *bucket_contiguous_checkbox = nullptr;
void _update_toolbar();
// Main vbox.
- VBoxContainer *main_vbox_container;
+ VBoxContainer *main_vbox_container = nullptr;
// TileMap editing.
bool has_mouse = false;
@@ -278,8 +278,8 @@ private:
void _update_selection();
// Bottom panel.
- Tree *terrains_tree;
- ItemList *terrains_tile_list;
+ Tree *terrains_tree = nullptr;
+ ItemList *terrains_tile_list = nullptr;
// Cache.
LocalVector<LocalVector<Set<TileSet::TerrainsPattern>>> per_terrain_terrains_patterns;
@@ -306,7 +306,7 @@ class TileMapEditor : public VBoxContainer {
GDCLASS(TileMapEditor, VBoxContainer);
private:
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
bool tileset_changed_needs_update = false;
ObjectID tile_map_id;
int tile_map_layer = -1;
@@ -315,24 +315,24 @@ private:
Vector<TileMapEditorPlugin *> tile_map_editor_plugins;
// Toolbar.
- HBoxContainer *tile_map_toolbar;
+ HBoxContainer *tile_map_toolbar = nullptr;
- PopupMenu *layers_selection_popup;
- Button *layers_selection_button;
- Button *toogle_highlight_selected_layer_button;
+ PopupMenu *layers_selection_popup = nullptr;
+ Button *layers_selection_button = nullptr;
+ Button *toogle_highlight_selected_layer_button = nullptr;
void _layers_selection_button_draw();
void _layers_selection_button_pressed();
void _layers_selection_id_pressed(int p_id);
- Button *toggle_grid_button;
+ Button *toggle_grid_button = nullptr;
void _on_grid_toggled(bool p_pressed);
- MenuButton *advanced_menu_button;
+ MenuButton *advanced_menu_button = nullptr;
void _advanced_menu_button_id_pressed(int p_id);
// Bottom panel.
- Label *missing_tileset_label;
- TabBar *tabs_bar;
+ Label *missing_tileset_label = nullptr;
+ TabBar *tabs_bar = nullptr;
LocalVector<TileMapEditorPlugin::TabData> tabs_data;
LocalVector<TileMapEditorPlugin *> tabs_plugins;
void _update_bottom_panel();
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.h b/editor/plugins/tiles/tile_proxies_manager_dialog.h
index 3f1461391e..00866544be 100644
--- a/editor/plugins/tiles/tile_proxies_manager_dialog.h
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.h
@@ -43,24 +43,24 @@ private:
int commited_actions_count = 0;
Ref<TileSet> tile_set;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
TileMapCell from;
TileMapCell to;
// GUI
- ItemList *source_level_list;
- ItemList *coords_level_list;
- ItemList *alternative_level_list;
+ ItemList *source_level_list = nullptr;
+ ItemList *coords_level_list = nullptr;
+ ItemList *alternative_level_list = nullptr;
- 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;
+ EditorPropertyInteger *source_from_property_editor = nullptr;
+ EditorPropertyVector2i *coords_from_property_editor = nullptr;
+ EditorPropertyInteger *alternative_from_property_editor = nullptr;
+ EditorPropertyInteger *source_to_property_editor = nullptr;
+ EditorPropertyVector2i *coords_to_property_editor = nullptr;
+ EditorPropertyInteger *alternative_to_property_editor = nullptr;
- PopupMenu *popup_menu;
+ PopupMenu *popup_menu = nullptr;
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();
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.h b/editor/plugins/tiles/tile_set_atlas_source_editor.h
index 4a90b821f8..b26b7edbfa 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.h
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.h
@@ -85,7 +85,7 @@ public:
GDCLASS(AtlasTileProxyObject, Object);
private:
- TileSetAtlasSourceEditor *tiles_set_atlas_source_editor;
+ TileSetAtlasSourceEditor *tiles_set_atlas_source_editor = nullptr;
TileSetAtlasSource *tile_set_atlas_source = nullptr;
Set<TileSelection> tiles = Set<TileSelection>();
@@ -114,16 +114,16 @@ private:
TileSetAtlasSource *tile_set_atlas_source = nullptr;
int tile_set_atlas_source_id = TileSet::INVALID_SOURCE;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
bool tile_set_changed_needs_update = false;
// -- Properties painting --
- VBoxContainer *tile_data_painting_editor_container;
- Label *tile_data_editors_label;
- Button *tile_data_editor_dropdown_button;
- Popup *tile_data_editors_popup;
- Tree *tile_data_editors_tree;
+ VBoxContainer *tile_data_painting_editor_container = nullptr;
+ Label *tile_data_editors_label = nullptr;
+ Button *tile_data_editor_dropdown_button = nullptr;
+ Popup *tile_data_editors_popup = nullptr;
+ Tree *tile_data_editors_tree = nullptr;
void _tile_data_editor_dropdown_button_draw();
void _tile_data_editor_dropdown_button_pressed();
@@ -135,21 +135,21 @@ private:
void _tile_data_editors_tree_selected();
// -- Inspector --
- AtlasTileProxyObject *tile_proxy_object;
- Label *tile_inspector_label;
- EditorInspector *tile_inspector;
- Label *tile_inspector_no_tile_selected_label;
+ AtlasTileProxyObject *tile_proxy_object = nullptr;
+ Label *tile_inspector_label = nullptr;
+ EditorInspector *tile_inspector = nullptr;
+ Label *tile_inspector_no_tile_selected_label = nullptr;
String selected_property;
void _inspector_property_selected(String p_property);
- TileSetAtlasSourceProxyObject *atlas_source_proxy_object;
- Label *atlas_source_inspector_label;
- EditorInspector *atlas_source_inspector;
+ TileSetAtlasSourceProxyObject *atlas_source_proxy_object = nullptr;
+ Label *atlas_source_inspector_label = nullptr;
+ EditorInspector *atlas_source_inspector = nullptr;
// -- Atlas view --
- HBoxContainer *toolbox;
- Label *tile_atlas_view_missing_source_label;
- TileAtlasView *tile_atlas_view;
+ HBoxContainer *toolbox = nullptr;
+ Label *tile_atlas_view_missing_source_label = nullptr;
+ TileAtlasView *tile_atlas_view = nullptr;
// Dragging
enum DragType {
@@ -202,17 +202,17 @@ private:
// Tool buttons.
Ref<ButtonGroup> tools_button_group;
- Button *tool_setup_atlas_source_button;
- Button *tool_select_button;
- Button *tool_paint_button;
- Label *tool_tile_id_label;
+ Button *tool_setup_atlas_source_button = nullptr;
+ Button *tool_select_button = nullptr;
+ Button *tool_paint_button = nullptr;
+ Label *tool_tile_id_label = nullptr;
// Tool settings.
- HBoxContainer *tool_settings;
- VSeparator *tool_settings_vsep;
- HBoxContainer *tool_settings_tile_data_toolbar_container;
- Button *tools_settings_erase_button;
- MenuButton *tool_advanced_menu_buttom;
+ HBoxContainer *tool_settings = nullptr;
+ VSeparator *tool_settings_vsep = nullptr;
+ HBoxContainer *tool_settings_tile_data_toolbar_container = nullptr;
+ Button *tools_settings_erase_button = nullptr;
+ MenuButton *tool_advanced_menu_buttom = nullptr;
// Selection.
Set<TileSelection> selection;
@@ -223,12 +223,12 @@ private:
// A control on the tile atlas to draw and handle input events.
Vector2i hovered_base_tile_coords = TileSetSource::INVALID_ATLAS_COORDS;
- PopupMenu *base_tile_popup_menu;
- PopupMenu *empty_base_tile_popup_menu;
+ PopupMenu *base_tile_popup_menu = nullptr;
+ PopupMenu *empty_base_tile_popup_menu = nullptr;
Ref<Texture2D> resize_handle;
Ref<Texture2D> resize_handle_disabled;
- Control *tile_atlas_control;
- Control *tile_atlas_control_unscaled;
+ Control *tile_atlas_control = nullptr;
+ Control *tile_atlas_control_unscaled = nullptr;
void _tile_atlas_control_draw();
void _tile_atlas_control_unscaled_draw();
void _tile_atlas_control_mouse_exited();
@@ -238,9 +238,9 @@ private:
// A control over the alternative tiles.
Vector3i hovered_alternative_tile_coords = Vector3i(TileSetSource::INVALID_ATLAS_COORDS.x, TileSetSource::INVALID_ATLAS_COORDS.y, TileSetSource::INVALID_TILE_ALTERNATIVE);
- PopupMenu *alternative_tile_popup_menu;
- Control *alternative_tiles_control;
- Control *alternative_tiles_control_unscaled;
+ PopupMenu *alternative_tile_popup_menu = nullptr;
+ Control *alternative_tiles_control = nullptr;
+ Control *alternative_tiles_control_unscaled = nullptr;
void _tile_alternatives_control_draw();
void _tile_alternatives_control_unscaled_draw();
void _tile_alternatives_control_mouse_exited();
@@ -264,7 +264,7 @@ private:
// -- Misc --
void _auto_create_tiles();
void _auto_remove_tiles();
- AcceptDialog *confirm_auto_create_tiles;
+ AcceptDialog *confirm_auto_create_tiles = nullptr;
void _tile_set_changed();
void _tile_proxy_object_changed(String p_what);
@@ -293,7 +293,7 @@ class EditorPropertyTilePolygon : public EditorProperty {
void _add_focusable_children(Node *p_node);
- GenericTilePolygonEditor *generic_tile_polygon_editor;
+ GenericTilePolygonEditor *generic_tile_polygon_editor = nullptr;
void _polygons_changed();
public:
diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h
index b79b37cf2e..e633de37b0 100644
--- a/editor/plugins/tiles/tile_set_editor.h
+++ b/editor/plugins/tiles/tile_set_editor.h
@@ -47,18 +47,18 @@ class TileSetEditor : public VBoxContainer {
private:
Ref<TileSet> tile_set;
bool tile_set_changed_needs_update = false;
- HSplitContainer *split_container;
+ HSplitContainer *split_container = nullptr;
// TabBar.
- HBoxContainer *tile_set_toolbar;
- TabBar *tabs_bar;
+ HBoxContainer *tile_set_toolbar = nullptr;
+ TabBar *tabs_bar = nullptr;
// Tiles.
- Label *no_source_selected_label;
- TileSetAtlasSourceEditor *tile_set_atlas_source_editor;
- TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor;
+ Label *no_source_selected_label = nullptr;
+ TileSetAtlasSourceEditor *tile_set_atlas_source_editor = nullptr;
+ TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor = nullptr;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
void _drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
@@ -66,11 +66,11 @@ private:
void _update_sources_list(int force_selected_id = -1);
// Sources management.
- Button *sources_delete_button;
- MenuButton *sources_add_button;
- MenuButton *source_sort_button;
- MenuButton *sources_advanced_menu_button;
- ItemList *sources_list;
+ Button *sources_delete_button = nullptr;
+ MenuButton *sources_add_button = nullptr;
+ MenuButton *source_sort_button = nullptr;
+ MenuButton *sources_advanced_menu_button = nullptr;
+ ItemList *sources_list = nullptr;
Ref<Texture2D> missing_texture_texture;
void _source_selected(int p_source_index);
void _source_delete_pressed();
@@ -78,12 +78,12 @@ private:
void _sources_advanced_menu_id_pressed(int p_id_pressed);
void _set_source_sort(int p_sort);
- AtlasMergingDialog *atlas_merging_dialog;
- TileProxiesManagerDialog *tile_proxies_manager_dialog;
+ AtlasMergingDialog *atlas_merging_dialog = nullptr;
+ TileProxiesManagerDialog *tile_proxies_manager_dialog = nullptr;
// Patterns.
- ItemList *patterns_item_list;
- Label *patterns_help_label;
+ ItemList *patterns_item_list = nullptr;
+ Label *patterns_help_label = nullptr;
void _patterns_item_list_gui_input(const Ref<InputEvent> &p_event);
void _pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture);
bool select_last_pattern = false;
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
index 8904e8524a..657bfca032 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h
@@ -70,7 +70,7 @@ private:
GDCLASS(SceneTileProxyObject, Object);
private:
- TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor;
+ TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor = nullptr;
TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
int source_id;
@@ -97,23 +97,23 @@ private:
TileSetScenesCollectionSource *tile_set_scenes_collection_source = nullptr;
int tile_set_source_id = -1;
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
bool tile_set_scenes_collection_source_changed_needs_update = false;
// Source inspector.
- TileSetScenesCollectionProxyObject *scenes_collection_source_proxy_object;
- Label *scenes_collection_source_inspector_label;
- EditorInspector *scenes_collection_source_inspector;
+ TileSetScenesCollectionProxyObject *scenes_collection_source_proxy_object = nullptr;
+ Label *scenes_collection_source_inspector_label = nullptr;
+ EditorInspector *scenes_collection_source_inspector = nullptr;
// Tile inspector.
- SceneTileProxyObject *tile_proxy_object;
- Label *tile_inspector_label;
- EditorInspector *tile_inspector;
+ SceneTileProxyObject *tile_proxy_object = nullptr;
+ Label *tile_inspector_label = nullptr;
+ EditorInspector *tile_inspector = nullptr;
- ItemList *scene_tiles_list;
- Button *scene_tile_add_button;
- Button *scene_tile_delete_button;
+ ItemList *scene_tiles_list = nullptr;
+ Button *scene_tile_add_button = nullptr;
+ Button *scene_tile_delete_button = nullptr;
void _tile_set_scenes_collection_source_changed();
void _scenes_collection_source_proxy_object_changed(String p_what);
diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h
index eeff4da4e9..a22e782b34 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.h
+++ b/editor/plugins/tiles/tiles_editor_plugin.h
@@ -57,11 +57,11 @@ private:
ObjectID tile_map_id;
Ref<TileSet> tile_set;
- Button *tilemap_editor_button;
- TileMapEditor *tilemap_editor;
+ Button *tilemap_editor_button = nullptr;
+ TileMapEditor *tilemap_editor = nullptr;
- Button *tileset_editor_button;
- TileSetEditor *tileset_editor;
+ Button *tileset_editor_button = nullptr;
+ TileSetEditor *tileset_editor = nullptr;
void _update_editors();
diff --git a/editor/plugins/version_control_editor_plugin.h b/editor/plugins/version_control_editor_plugin.h
index 956c5a334f..39a56de772 100644
--- a/editor/plugins/version_control_editor_plugin.h
+++ b/editor/plugins/version_control_editor_plugin.h
@@ -57,48 +57,48 @@ private:
int staged_files_count;
List<StringName> available_addons;
- PopupMenu *version_control_actions;
- ConfirmationDialog *metadata_dialog;
- OptionButton *metadata_selection;
- AcceptDialog *set_up_dialog;
- VBoxContainer *set_up_vbc;
- HBoxContainer *set_up_hbc;
- Label *set_up_vcs_label;
- OptionButton *set_up_choice;
- PanelContainer *set_up_init_settings;
- Button *set_up_init_button;
- RichTextLabel *set_up_vcs_status;
- Button *set_up_ok_button;
+ PopupMenu *version_control_actions = nullptr;
+ ConfirmationDialog *metadata_dialog = nullptr;
+ OptionButton *metadata_selection = nullptr;
+ AcceptDialog *set_up_dialog = nullptr;
+ VBoxContainer *set_up_vbc = nullptr;
+ HBoxContainer *set_up_hbc = nullptr;
+ Label *set_up_vcs_label = nullptr;
+ OptionButton *set_up_choice = nullptr;
+ PanelContainer *set_up_init_settings = nullptr;
+ Button *set_up_init_button = nullptr;
+ RichTextLabel *set_up_vcs_status = nullptr;
+ Button *set_up_ok_button = nullptr;
HashMap<ChangeType, String> change_type_to_strings;
HashMap<ChangeType, Color> change_type_to_color;
- VBoxContainer *version_commit_dock;
- VBoxContainer *commit_box_vbc;
- HSplitContainer *stage_tools;
- Tree *stage_files;
- TreeItem *new_files;
- TreeItem *modified_files;
- TreeItem *renamed_files;
- TreeItem *deleted_files;
- TreeItem *typechange_files;
- Label *staging_area_label;
- HSplitContainer *stage_buttons;
- Button *stage_all_button;
- Button *stage_selected_button;
- Button *refresh_button;
- TextEdit *commit_message;
- Button *commit_button;
- Label *commit_status;
-
- PanelContainer *version_control_dock;
- Button *version_control_dock_button;
- VBoxContainer *diff_vbc;
- HBoxContainer *diff_hbc;
- Button *diff_refresh_button;
- Label *diff_file_name;
- Label *diff_heading;
- RichTextLabel *diff;
+ VBoxContainer *version_commit_dock = nullptr;
+ VBoxContainer *commit_box_vbc = nullptr;
+ HSplitContainer *stage_tools = nullptr;
+ Tree *stage_files = nullptr;
+ TreeItem *new_files = nullptr;
+ TreeItem *modified_files = nullptr;
+ TreeItem *renamed_files = nullptr;
+ TreeItem *deleted_files = nullptr;
+ TreeItem *typechange_files = nullptr;
+ Label *staging_area_label = nullptr;
+ HSplitContainer *stage_buttons = nullptr;
+ Button *stage_all_button = nullptr;
+ Button *stage_selected_button = nullptr;
+ Button *refresh_button = nullptr;
+ TextEdit *commit_message = nullptr;
+ Button *commit_button = nullptr;
+ Label *commit_status = nullptr;
+
+ PanelContainer *version_control_dock = nullptr;
+ Button *version_control_dock_button = nullptr;
+ VBoxContainer *diff_vbc = nullptr;
+ HBoxContainer *diff_hbc = nullptr;
+ Button *diff_refresh_button = nullptr;
+ Label *diff_file_name = nullptr;
+ Label *diff_heading = nullptr;
+ RichTextLabel *diff = nullptr;
void _populate_available_vcs_names();
void _create_vcs_metadata_files();
diff --git a/editor/plugins/voxel_gi_editor_plugin.h b/editor/plugins/voxel_gi_editor_plugin.h
index 67bd1d5105..621e98beef 100644
--- a/editor/plugins/voxel_gi_editor_plugin.h
+++ b/editor/plugins/voxel_gi_editor_plugin.h
@@ -41,12 +41,12 @@ struct EditorProgress;
class VoxelGIEditorPlugin : public EditorPlugin {
GDCLASS(VoxelGIEditorPlugin, EditorPlugin);
- VoxelGI *voxel_gi;
+ VoxelGI *voxel_gi = nullptr;
- HBoxContainer *bake_hb;
- Button *bake;
+ HBoxContainer *bake_hb = nullptr;
+ Button *bake = nullptr;
- EditorFileDialog *probe_file;
+ EditorFileDialog *probe_file = nullptr;
static EditorProgress *tmp_progress;
static void bake_func_begin(int p_steps);
diff --git a/editor/progress_dialog.h b/editor/progress_dialog.h
index 880e6bc9d4..f395750165 100644
--- a/editor/progress_dialog.h
+++ b/editor/progress_dialog.h
@@ -74,11 +74,11 @@ class ProgressDialog : public PopupPanel {
ProgressBar *progress = nullptr;
Label *state = nullptr;
};
- HBoxContainer *cancel_hb;
- Button *cancel;
+ HBoxContainer *cancel_hb = nullptr;
+ Button *cancel = nullptr;
Map<String, Task> tasks;
- VBoxContainer *main;
+ VBoxContainer *main = nullptr;
uint64_t last_progress_tick;
static ProgressDialog *singleton;
diff --git a/editor/project_export.h b/editor/project_export.h
index 057fd31168..4d1719d6eb 100644
--- a/editor/project_export.h
+++ b/editor/project_export.h
@@ -58,46 +58,46 @@ class ProjectExportDialog : public ConfirmationDialog {
GDCLASS(ProjectExportDialog, ConfirmationDialog);
private:
- TabContainer *sections;
+ TabContainer *sections = nullptr;
- MenuButton *add_preset;
- Button *duplicate_preset;
- Button *delete_preset;
- ItemList *presets;
+ MenuButton *add_preset = nullptr;
+ Button *duplicate_preset = nullptr;
+ Button *delete_preset = nullptr;
+ ItemList *presets = nullptr;
- LineEdit *name;
- EditorPropertyPath *export_path;
- EditorInspector *parameters;
- CheckButton *runnable;
+ LineEdit *name = nullptr;
+ EditorPropertyPath *export_path = nullptr;
+ EditorInspector *parameters = nullptr;
+ CheckButton *runnable = nullptr;
- Button *button_export;
+ Button *button_export = nullptr;
bool updating = false;
- AcceptDialog *error_dialog;
- ConfirmationDialog *delete_confirm;
+ AcceptDialog *error_dialog = nullptr;
+ ConfirmationDialog *delete_confirm = nullptr;
- OptionButton *export_filter;
- LineEdit *include_filters;
- LineEdit *exclude_filters;
- Tree *include_files;
+ OptionButton *export_filter = nullptr;
+ LineEdit *include_filters = nullptr;
+ LineEdit *exclude_filters = nullptr;
+ Tree *include_files = nullptr;
- Label *include_label;
- MarginContainer *include_margin;
+ Label *include_label = nullptr;
+ MarginContainer *include_margin = nullptr;
- Button *export_button;
- Button *export_all_button;
- AcceptDialog *export_all_dialog;
+ Button *export_button = nullptr;
+ Button *export_all_button = nullptr;
+ AcceptDialog *export_all_dialog = nullptr;
- LineEdit *custom_features;
- RichTextLabel *custom_feature_display;
+ LineEdit *custom_features = nullptr;
+ RichTextLabel *custom_feature_display = nullptr;
- OptionButton *script_mode;
- LineEdit *script_key;
- Label *script_key_error;
+ OptionButton *script_mode = nullptr;
+ LineEdit *script_key = nullptr;
+ Label *script_key_error = nullptr;
- Label *export_error;
- Label *export_warning;
- HBoxContainer *export_templates_error;
+ Label *export_error = nullptr;
+ Label *export_warning = nullptr;
+ HBoxContainer *export_templates_error = nullptr;
String default_filename;
@@ -127,15 +127,15 @@ private:
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
- EditorFileDialog *export_pck_zip;
- EditorFileDialog *export_project;
- CheckBox *export_debug;
- CheckBox *export_pck_zip_debug;
+ EditorFileDialog *export_pck_zip = nullptr;
+ EditorFileDialog *export_project = nullptr;
+ CheckBox *export_debug = nullptr;
+ CheckBox *export_pck_zip_debug = nullptr;
- CheckButton *enc_pck;
- CheckButton *enc_directory;
- LineEdit *enc_in_filters;
- LineEdit *enc_ex_filters;
+ CheckButton *enc_pck = nullptr;
+ CheckButton *enc_directory = nullptr;
+ LineEdit *enc_in_filters = nullptr;
+ LineEdit *enc_ex_filters = nullptr;
void _open_export_template_manager();
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index 5dc1ddc0a8..c9d849abec 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -47,34 +47,34 @@ class ProjectSettingsEditor : public AcceptDialog {
GDCLASS(ProjectSettingsEditor, AcceptDialog);
static ProjectSettingsEditor *singleton;
- ProjectSettings *ps;
- Timer *timer;
-
- TabContainer *tab_container;
- SectionedInspector *general_settings_inspector;
- ActionMapEditor *action_map_editor;
- LocalizationEditor *localization_editor;
- EditorAutoloadSettings *autoload_settings;
- ShaderGlobalsEditor *shaders_global_variables_editor;
- EditorPluginSettings *plugin_settings;
-
- LineEdit *search_box;
- CheckButton *advanced;
-
- LineEdit *property_box;
- OptionButton *feature_box;
- OptionButton *type_box;
- Button *add_button;
- Button *del_button;
-
- Label *restart_label;
- TextureRect *restart_icon;
- PanelContainer *restart_container;
- Button *restart_close_button;
-
- ImportDefaultsEditor *import_defaults_editor;
- EditorData *data;
- UndoRedo *undo_redo;
+ ProjectSettings *ps = nullptr;
+ Timer *timer = nullptr;
+
+ TabContainer *tab_container = nullptr;
+ SectionedInspector *general_settings_inspector = nullptr;
+ ActionMapEditor *action_map_editor = nullptr;
+ LocalizationEditor *localization_editor = nullptr;
+ EditorAutoloadSettings *autoload_settings = nullptr;
+ ShaderGlobalsEditor *shaders_global_variables_editor = nullptr;
+ EditorPluginSettings *plugin_settings = nullptr;
+
+ LineEdit *search_box = nullptr;
+ CheckButton *advanced = nullptr;
+
+ LineEdit *property_box = nullptr;
+ OptionButton *feature_box = nullptr;
+ OptionButton *type_box = nullptr;
+ Button *add_button = nullptr;
+ Button *del_button = nullptr;
+
+ Label *restart_label = nullptr;
+ TextureRect *restart_icon = nullptr;
+ PanelContainer *restart_container = nullptr;
+ Button *restart_close_button = nullptr;
+
+ ImportDefaultsEditor *import_defaults_editor = nullptr;
+ EditorData *data = nullptr;
+ UndoRedo *undo_redo = nullptr;
void _advanced_toggled(bool p_button_pressed);
void _property_box_changed(const String &p_text);
diff --git a/editor/property_editor.h b/editor/property_editor.h
index 73306e0bc2..1a4d88f7fa 100644
--- a/editor/property_editor.h
+++ b/editor/property_editor.h
@@ -95,11 +95,11 @@ class CustomPropertyEditor : public PopupPanel {
EASING_OUT_IN
};
- PopupMenu *menu;
- SceneTreeDialog *scene_tree;
- EditorFileDialog *file;
- EditorLocaleDialog *locale;
- ConfirmationDialog *error;
+ PopupMenu *menu = nullptr;
+ SceneTreeDialog *scene_tree = nullptr;
+ EditorFileDialog *file = nullptr;
+ EditorLocaleDialog *locale = nullptr;
+ ConfirmationDialog *error = nullptr;
String name;
Variant::Type type;
Variant v;
@@ -107,34 +107,34 @@ class CustomPropertyEditor : public PopupPanel {
int hint;
String hint_text;
HBoxContainer *value_hboxes[MAX_VALUE_EDITORS / 4];
- VBoxContainer *value_vbox;
+ VBoxContainer *value_vbox = nullptr;
LineEdit *value_editor[MAX_VALUE_EDITORS];
int focused_value_editor;
Label *value_label[MAX_VALUE_EDITORS];
HScrollBar *scroll[4];
- HBoxContainer *action_hboxes;
+ HBoxContainer *action_hboxes = nullptr;
Button *action_buttons[MAX_ACTION_BUTTONS];
- MenuButton *type_button;
+ MenuButton *type_button = nullptr;
Vector<String> inheritors_array;
- TextureRect *texture_preview;
- ColorPicker *color_picker;
- TextEdit *text_edit;
+ TextureRect *texture_preview = nullptr;
+ ColorPicker *color_picker = nullptr;
+ TextEdit *text_edit = nullptr;
bool read_only = false;
bool picking_viewport;
- GridContainer *checks20gc;
+ GridContainer *checks20gc = nullptr;
CheckBox *checks20[20];
- SpinBox *spinbox;
- HSlider *slider;
+ SpinBox *spinbox = nullptr;
+ HSlider *slider = nullptr;
- Control *easing_draw;
- CreateDialog *create_dialog;
- PropertySelector *property_select;
+ Control *easing_draw = nullptr;
+ CreateDialog *create_dialog = nullptr;
+ PropertySelector *property_select = nullptr;
- Object *owner;
+ Object *owner = nullptr;
bool updating = false;
- PropertyValueEvaluator *evaluator;
+ PropertyValueEvaluator *evaluator = nullptr;
void _text_edit_changed();
void _file_selected(String p_file);
diff --git a/editor/property_selector.h b/editor/property_selector.h
index 7e629a847e..597804da31 100644
--- a/editor/property_selector.h
+++ b/editor/property_selector.h
@@ -38,8 +38,8 @@
class PropertySelector : public ConfirmationDialog {
GDCLASS(PropertySelector, ConfirmationDialog);
- LineEdit *search_box;
- Tree *search_options;
+ LineEdit *search_box = nullptr;
+ Tree *search_options = nullptr;
void _text_changed(const String &p_newtext);
void _sbox_input(const Ref<InputEvent> &p_ie);
@@ -48,14 +48,14 @@ class PropertySelector : public ConfirmationDialog {
void _item_selected();
void _hide_requested();
- EditorHelpBit *help_bit;
+ EditorHelpBit *help_bit = nullptr;
bool properties;
String selected;
Variant::Type type;
String base_type;
ObjectID script;
- Object *instance;
+ Object *instance = nullptr;
bool virtuals_only = false;
Vector<Variant::Type> type_filter;
diff --git a/editor/quick_open.h b/editor/quick_open.h
index f50f09604c..843ef47711 100644
--- a/editor/quick_open.h
+++ b/editor/quick_open.h
@@ -39,8 +39,8 @@
class EditorQuickOpen : public ConfirmationDialog {
GDCLASS(EditorQuickOpen, ConfirmationDialog);
- LineEdit *search_box;
- Tree *search_options;
+ LineEdit *search_box = nullptr;
+ Tree *search_options = nullptr;
StringName base_type;
bool allow_multi_select = false;
diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h
index c9747795f0..d05e80fc04 100644
--- a/editor/rename_dialog.h
+++ b/editor/rename_dialog.h
@@ -62,41 +62,41 @@ class RenameDialog : public ConfirmationDialog {
void _update_preview_int(int new_value = 0);
static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type);
- SceneTreeEditor *scene_tree_editor;
- UndoRedo *undo_redo;
+ SceneTreeEditor *scene_tree_editor = nullptr;
+ UndoRedo *undo_redo = nullptr;
int global_count;
- LineEdit *lne_search;
- LineEdit *lne_replace;
- LineEdit *lne_prefix;
- LineEdit *lne_suffix;
+ LineEdit *lne_search = nullptr;
+ LineEdit *lne_replace = nullptr;
+ LineEdit *lne_prefix = nullptr;
+ LineEdit *lne_suffix = nullptr;
- TabContainer *tabc_features;
+ TabContainer *tabc_features = nullptr;
- CheckBox *cbut_substitute;
- CheckButton *cbut_regex;
- CheckBox *cbut_process;
- CheckBox *chk_per_level_counter;
+ CheckBox *cbut_substitute = nullptr;
+ CheckButton *cbut_regex = nullptr;
+ CheckBox *cbut_process = nullptr;
+ CheckBox *chk_per_level_counter = nullptr;
- Button *but_insert_name;
- Button *but_insert_parent;
- Button *but_insert_type;
- Button *but_insert_scene;
- Button *but_insert_root;
- Button *but_insert_count;
+ Button *but_insert_name = nullptr;
+ Button *but_insert_parent = nullptr;
+ Button *but_insert_type = nullptr;
+ Button *but_insert_scene = nullptr;
+ Button *but_insert_root = nullptr;
+ Button *but_insert_count = nullptr;
- SpinBox *spn_count_start;
- SpinBox *spn_count_step;
- SpinBox *spn_count_padding;
+ SpinBox *spn_count_start = nullptr;
+ SpinBox *spn_count_step = nullptr;
+ SpinBox *spn_count_padding = nullptr;
- OptionButton *opt_style;
- OptionButton *opt_case;
+ OptionButton *opt_style = nullptr;
+ OptionButton *opt_case = nullptr;
- Label *lbl_preview_title;
- Label *lbl_preview;
+ Label *lbl_preview_title = nullptr;
+ Label *lbl_preview = nullptr;
List<Pair<NodePath, String>> to_rename;
- Node *preview_node;
+ Node *preview_node = nullptr;
bool lock_preview_update;
ErrorHandlerList eh;
bool has_errors;
diff --git a/editor/reparent_dialog.h b/editor/reparent_dialog.h
index 981829a871..121a86e9f0 100644
--- a/editor/reparent_dialog.h
+++ b/editor/reparent_dialog.h
@@ -41,8 +41,8 @@
class ReparentDialog : public ConfirmationDialog {
GDCLASS(ReparentDialog, ConfirmationDialog);
- SceneTreeEditor *tree;
- CheckBox *keep_transform;
+ SceneTreeEditor *tree = nullptr;
+ CheckBox *keep_transform = nullptr;
void _reparent();
void _cancel();
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 938f83725d..711ac5bc53 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -109,29 +109,29 @@ class SceneTreeDock : public VBoxContainer {
bool reset_create_dialog = false;
int current_option;
- CreateDialog *create_dialog;
+ CreateDialog *create_dialog = nullptr;
#ifdef MODULE_REGEX_ENABLED
- RenameDialog *rename_dialog;
+ RenameDialog *rename_dialog = nullptr;
#endif // MODULE_REGEX_ENABLED
- Button *button_add;
- Button *button_instance;
- Button *button_create_script;
- Button *button_detach_script;
- MenuButton *button_tree_menu;
+ Button *button_add = nullptr;
+ Button *button_instance = nullptr;
+ Button *button_create_script = nullptr;
+ Button *button_detach_script = nullptr;
+ MenuButton *button_tree_menu = nullptr;
- Button *button_2d;
- Button *button_3d;
- Button *button_ui;
- Button *button_custom;
- Button *button_clipboard;
+ Button *button_2d = nullptr;
+ Button *button_3d = nullptr;
+ Button *button_ui = nullptr;
+ Button *button_custom = nullptr;
+ Button *button_clipboard = nullptr;
- HBoxContainer *button_hb;
+ HBoxContainer *button_hb = nullptr;
Button *edit_local, *edit_remote;
- SceneTreeEditor *scene_tree;
- Control *remote_tree;
+ SceneTreeEditor *scene_tree = nullptr;
+ Control *remote_tree = nullptr;
- HBoxContainer *tool_hbc;
+ HBoxContainer *tool_hbc = nullptr;
void _tool_selected(int p_tool, bool p_confirm_override = false);
void _property_selected(int p_idx);
void _node_collapsed(Object *p_obj);
@@ -140,40 +140,40 @@ class SceneTreeDock : public VBoxContainer {
String resource_drop_path;
void _perform_property_drop(Node *p_node, String p_property, RES p_res);
- EditorData *editor_data;
- EditorSelection *editor_selection;
+ EditorData *editor_data = nullptr;
+ EditorSelection *editor_selection = nullptr;
List<Node *> node_clipboard;
String clipboard_source_scene;
HashMap<String, Map<RES, RES>> clipboard_resource_remap;
- ScriptCreateDialog *script_create_dialog;
- ShaderCreateDialog *shader_create_dialog;
- AcceptDialog *accept;
- ConfirmationDialog *delete_dialog;
- ConfirmationDialog *editable_instance_remove_dialog;
- ConfirmationDialog *placeholder_editable_instance_remove_dialog;
+ ScriptCreateDialog *script_create_dialog = nullptr;
+ ShaderCreateDialog *shader_create_dialog = nullptr;
+ AcceptDialog *accept = nullptr;
+ ConfirmationDialog *delete_dialog = nullptr;
+ ConfirmationDialog *editable_instance_remove_dialog = nullptr;
+ ConfirmationDialog *placeholder_editable_instance_remove_dialog = nullptr;
- ReparentDialog *reparent_dialog;
- EditorQuickOpen *quick_open;
- EditorFileDialog *new_scene_from_dialog;
+ ReparentDialog *reparent_dialog = nullptr;
+ EditorQuickOpen *quick_open = nullptr;
+ EditorFileDialog *new_scene_from_dialog = nullptr;
- LineEdit *filter;
- TextureRect *filter_icon;
+ LineEdit *filter = nullptr;
+ TextureRect *filter_icon = nullptr;
- PopupMenu *menu;
- PopupMenu *menu_subresources;
- PopupMenu *menu_properties;
- ConfirmationDialog *clear_inherit_confirm;
+ PopupMenu *menu = nullptr;
+ PopupMenu *menu_subresources = nullptr;
+ PopupMenu *menu_properties = nullptr;
+ ConfirmationDialog *clear_inherit_confirm = nullptr;
bool first_enter = true;
void _create();
void _do_create(Node *p_parent);
- Node *scene_root;
- Node *edited_scene;
+ Node *scene_root = nullptr;
+ Node *edited_scene = nullptr;
- VBoxContainer *create_root_dialog;
+ VBoxContainer *create_root_dialog = nullptr;
String selected_favorite_root;
Ref<ShaderMaterial> selected_shader_material;
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 2466b8576a..547a5b57ca 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -41,7 +41,7 @@
class SceneTreeEditor : public Control {
GDCLASS(SceneTreeEditor, Control);
- EditorSelection *editor_selection;
+ EditorSelection *editor_selection = nullptr;
enum SceneTreeEditorButton {
BUTTON_SUBSCENE = 0,
@@ -55,14 +55,14 @@ class SceneTreeEditor : public Control {
BUTTON_PIN = 8,
};
- Tree *tree;
- Node *selected;
+ Tree *tree = nullptr;
+ Node *selected = nullptr;
ObjectID instance_node;
String filter;
- AcceptDialog *error;
- AcceptDialog *warning;
+ AcceptDialog *error = nullptr;
+ AcceptDialog *warning = nullptr;
bool auto_expand_selected = true;
bool connect_to_script_mode = false;
@@ -96,7 +96,7 @@ class SceneTreeEditor : public Control {
bool show_enabled_subscene = false;
void _renamed();
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
Set<Node *> marked;
bool marked_selectable = false;
@@ -125,7 +125,7 @@ class SceneTreeEditor : public Control {
void _warning_changed(Node *p_for_node);
- Timer *update_timer;
+ Timer *update_timer = nullptr;
List<StringName> *script_types;
bool _is_script_type(const StringName &p_type) const;
@@ -166,10 +166,10 @@ public:
class SceneTreeDialog : public ConfirmationDialog {
GDCLASS(SceneTreeDialog, ConfirmationDialog);
- SceneTreeEditor *tree;
+ SceneTreeEditor *tree = nullptr;
//Button *select;
//Button *cancel;
- LineEdit *filter;
+ LineEdit *filter = nullptr;
void _select();
void _cancel();
diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h
index e9f634e2c0..c7d8cfc38a 100644
--- a/editor/script_create_dialog.h
+++ b/editor/script_create_dialog.h
@@ -45,27 +45,27 @@ class EditorFileDialog;
class ScriptCreateDialog : public ConfirmationDialog {
GDCLASS(ScriptCreateDialog, ConfirmationDialog);
- LineEdit *class_name;
- Label *error_label;
- Label *path_error_label;
- Label *builtin_warning_label;
- Label *script_name_warning_label;
- Label *template_info_label;
- PanelContainer *status_panel;
- LineEdit *parent_name;
- Button *parent_browse_button;
- Button *parent_search_button;
- OptionButton *language_menu;
- OptionButton *template_menu;
- LineEdit *file_path;
- LineEdit *internal_name;
- Button *path_button;
- EditorFileDialog *file_browse;
- CheckBox *internal;
- CheckBox *use_templates;
- VBoxContainer *path_vb;
- AcceptDialog *alert;
- CreateDialog *select_class;
+ LineEdit *class_name = nullptr;
+ Label *error_label = nullptr;
+ Label *path_error_label = nullptr;
+ Label *builtin_warning_label = nullptr;
+ Label *script_name_warning_label = nullptr;
+ Label *template_info_label = nullptr;
+ PanelContainer *status_panel = nullptr;
+ LineEdit *parent_name = nullptr;
+ Button *parent_browse_button = nullptr;
+ Button *parent_search_button = nullptr;
+ OptionButton *language_menu = nullptr;
+ OptionButton *template_menu = nullptr;
+ LineEdit *file_path = nullptr;
+ LineEdit *internal_name = nullptr;
+ Button *path_button = nullptr;
+ EditorFileDialog *file_browse = nullptr;
+ CheckBox *internal = nullptr;
+ CheckBox *use_templates = nullptr;
+ VBoxContainer *path_vb = nullptr;
+ AcceptDialog *alert = nullptr;
+ CreateDialog *select_class = nullptr;
bool is_browsing_parent = false;
String template_inactive_message;
String initial_bp;
@@ -89,7 +89,7 @@ class ScriptCreateDialog : public ConfirmationDialog {
Control *name_controls[2];
Vector<ScriptLanguage::ScriptTemplate> template_list;
- ScriptLanguage *language;
+ ScriptLanguage *language = nullptr;
String base_type;
diff --git a/editor/shader_globals_editor.h b/editor/shader_globals_editor.h
index 3b337e07de..d29052eaee 100644
--- a/editor/shader_globals_editor.h
+++ b/editor/shader_globals_editor.h
@@ -43,12 +43,12 @@ class ShaderGlobalsEditorInterface;
class ShaderGlobalsEditor : public VBoxContainer {
GDCLASS(ShaderGlobalsEditor, VBoxContainer)
- ShaderGlobalsEditorInterface *interface;
- EditorInspector *inspector;
+ ShaderGlobalsEditorInterface *interface = nullptr;
+ EditorInspector *inspector = nullptr;
- LineEdit *variable_name;
- OptionButton *variable_type;
- Button *variable_add;
+ LineEdit *variable_name = nullptr;
+ OptionButton *variable_type = nullptr;
+ Button *variable_add = nullptr;
void _variable_added();
void _variable_deleted(const String &p_variable);
diff --git a/editor/translations/extract.py b/editor/translations/extract.py
index cb918c0092..bd32fc01c7 100755
--- a/editor/translations/extract.py
+++ b/editor/translations/extract.py
@@ -3,6 +3,7 @@
import enum
import fnmatch
import os
+import os.path
import re
import shutil
import subprocess
@@ -128,6 +129,9 @@ message_patterns = {
re.compile(r'ADD_GROUP\("(?P<message>[^"]+?)", "(?P<prefix>[^"]*?)"\)'): ExtractType.GROUP,
re.compile(r'#define WRTC_\w+ "(?P<message>[^"]+?)"'): ExtractType.PROPERTY_PATH,
}
+theme_property_patterns = {
+ re.compile(r'set_(constant|font|font_size|stylebox|color|icon)\("(?P<message>[^"]+)", '): ExtractType.PROPERTY_PATH,
+}
# See String::camelcase_to_underscore().
@@ -200,6 +204,10 @@ def process_file(f, fname):
translator_comment = ""
current_group = ""
+ patterns = message_patterns
+ if os.path.basename(fname) == "default_theme.cpp":
+ patterns = {**message_patterns, **theme_property_patterns}
+
while l:
# Detect translator comments.
@@ -217,7 +225,7 @@ def process_file(f, fname):
translator_comment = translator_comment[:-1] # Remove extra \n at the end.
if not reading_translator_comment:
- for pattern, extract_type in message_patterns.items():
+ for pattern, extract_type in patterns.items():
for m in pattern.finditer(l):
location = os.path.relpath(fname).replace("\\", "/")
if line_nb:
diff --git a/main/main.cpp b/main/main.cpp
index 89b56a814e..c637d8748d 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1489,8 +1489,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF("input_devices/pointing/ios/touch_delay", 0.150);
// XR project settings.
- GLOBAL_DEF_BASIC("xr/openxr/enabled", false);
- GLOBAL_DEF_BASIC("xr/openxr/default_action_map", "res://default_action_map.tres");
+ GLOBAL_DEF_RST_BASIC("xr/openxr/enabled", false);
+ GLOBAL_DEF_BASIC("xr/openxr/default_action_map", "res://openxr_action_map.tres");
ProjectSettings::get_singleton()->set_custom_property_info("xr/openxr/default_action_map", PropertyInfo(Variant::STRING, "xr/openxr/default_action_map", PROPERTY_HINT_FILE, "*.tres"));
GLOBAL_DEF_BASIC("xr/openxr/form_factor", "0");
@@ -2336,7 +2336,7 @@ bool Main::start() {
} else if (script_res.is_valid()) {
StringName ibt = script_res->get_instance_base_type();
bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + info.path);
+ ERR_CONTINUE_MSG(!valid_type, "Script does not inherit from Node: " + info.path);
Object *obj = ClassDB::instantiate(ibt);
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index 4721d0c11c..b5d5f97cf3 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -368,7 +368,7 @@ private:
PathRotation path_rotation;
bool path_local;
- Path3D *path;
+ Path3D *path = nullptr;
bool smooth_faces;
bool path_continuous_u;
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index f7fa967883..82125610c2 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -265,7 +265,7 @@ class GDScriptInstance : public ScriptInstance {
friend struct GDScriptUtilityFunctionsDefinitions;
ObjectID owner_id;
- Object *owner;
+ Object *owner = nullptr;
Ref<GDScript> script;
#ifdef DEBUG_ENABLED
Map<StringName, int> member_indices_cache; //used only for hot script reloading
@@ -311,17 +311,17 @@ class GDScriptLanguage : public ScriptLanguage {
static GDScriptLanguage *singleton;
- Variant *_global_array;
+ Variant *_global_array = nullptr;
Vector<Variant> global_array;
Map<StringName, int> globals;
Map<StringName, Variant> named_globals;
struct CallLevel {
- Variant *stack;
- GDScriptFunction *function;
- GDScriptInstance *instance;
- int *ip;
- int *line;
+ Variant *stack = nullptr;
+ GDScriptFunction *function = nullptr;
+ GDScriptInstance *instance = nullptr;
+ int *ip = nullptr;
+ int *line = nullptr;
};
int _debug_parse_err_line;
@@ -329,7 +329,7 @@ class GDScriptLanguage : public ScriptLanguage {
String _debug_error;
int _debug_call_stack_pos;
int _debug_max_call_stack;
- CallLevel *_call_stack;
+ CallLevel *_call_stack = nullptr;
void _add_global(const StringName &p_name, const Variant &p_value);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 5ed4054c57..7f0ffb4586 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -485,6 +485,89 @@ struct GDScriptCompletionIdentifier {
const GDScriptParser::ExpressionNode *assigned_expression = nullptr;
};
+// LOCATION METHODS
+// These methods are used to populate the `CodeCompletionOption::location` integer.
+// For these methods, the location is based on the depth in the inheritance chain that the property
+// appears. For example, if you are completing code in a class that inherits Node2D, a property found on Node2D
+// will have a "better" (lower) location "score" than a property that is found on CanvasItem.
+
+static int _get_property_location(StringName p_class, StringName p_property) {
+ if (!ClassDB::has_property(p_class, p_property)) {
+ return ScriptLanguage::LOCATION_OTHER;
+ }
+
+ int depth = 0;
+ StringName class_test = p_class;
+ while (class_test && !ClassDB::has_property(class_test, p_property, true)) {
+ class_test = ClassDB::get_parent_class(class_test);
+ depth++;
+ }
+
+ return depth | ScriptLanguage::LOCATION_PARENT_MASK;
+}
+
+static int _get_constant_location(StringName p_class, StringName p_constant) {
+ if (!ClassDB::has_integer_constant(p_class, p_constant)) {
+ return ScriptLanguage::LOCATION_OTHER;
+ }
+
+ int depth = 0;
+ StringName class_test = p_class;
+ while (class_test && !ClassDB::has_integer_constant(class_test, p_constant, true)) {
+ class_test = ClassDB::get_parent_class(class_test);
+ depth++;
+ }
+
+ return depth | ScriptLanguage::LOCATION_PARENT_MASK;
+}
+
+static int _get_signal_location(StringName p_class, StringName p_signal) {
+ if (!ClassDB::has_signal(p_class, p_signal)) {
+ return ScriptLanguage::LOCATION_OTHER;
+ }
+
+ int depth = 0;
+ StringName class_test = p_class;
+ while (class_test && !ClassDB::has_signal(class_test, p_signal, true)) {
+ class_test = ClassDB::get_parent_class(class_test);
+ depth++;
+ }
+
+ return depth | ScriptLanguage::LOCATION_PARENT_MASK;
+}
+
+static int _get_method_location(StringName p_class, StringName p_method) {
+ if (!ClassDB::has_method(p_class, p_method)) {
+ return ScriptLanguage::LOCATION_OTHER;
+ }
+
+ int depth = 0;
+ StringName class_test = p_class;
+ while (class_test && !ClassDB::has_method(class_test, p_method, true)) {
+ class_test = ClassDB::get_parent_class(class_test);
+ depth++;
+ }
+
+ return depth | ScriptLanguage::LOCATION_PARENT_MASK;
+}
+
+static int _get_enum_constant_location(StringName p_class, StringName p_enum_constant) {
+ if (!ClassDB::get_integer_constant_enum(p_class, p_enum_constant)) {
+ return ScriptLanguage::LOCATION_OTHER;
+ }
+
+ int depth = 0;
+ StringName class_test = p_class;
+ while (class_test && !ClassDB::get_integer_constant_enum(class_test, p_enum_constant, true)) {
+ class_test = ClassDB::get_parent_class(class_test);
+ depth++;
+ }
+
+ return depth | ScriptLanguage::LOCATION_PARENT_MASK;
+}
+
+// END LOCATION METHODS
+
static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg = true) {
if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
String enum_name = p_info.class_name;
@@ -721,18 +804,18 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
const GDScriptParser::ClassNode::Member &member = current->members[i];
switch (member.type) {
case GDScriptParser::ClassNode::Member::CLASS: {
- ScriptLanguage::CodeCompletionOption option(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+ ScriptLanguage::CodeCompletionOption option(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_LOCAL);
r_result.insert(option.display, option);
} break;
case GDScriptParser::ClassNode::Member::ENUM: {
if (!p_inherit_only) {
- ScriptLanguage::CodeCompletionOption option(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM);
+ ScriptLanguage::CodeCompletionOption option(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM, ScriptLanguage::LOCATION_LOCAL);
r_result.insert(option.display, option);
}
} break;
case GDScriptParser::ClassNode::Member::CONSTANT: {
if (member.constant->get_datatype().is_meta_type && p_context.current_class->outer != nullptr) {
- ScriptLanguage::CodeCompletionOption option(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+ ScriptLanguage::CodeCompletionOption option(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_LOCAL);
r_result.insert(option.display, option);
}
} break;
@@ -748,7 +831,7 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes);
for (const StringName &E : global_classes) {
- ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+ ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
r_result.insert(option.display, option);
}
@@ -759,7 +842,7 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
if (!info.is_singleton || info.path.get_extension().to_lower() != "gd") {
continue;
}
- ScriptLanguage::CodeCompletionOption option(info.name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+ ScriptLanguage::CodeCompletionOption option(info.name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
r_result.insert(option.display, option);
}
}
@@ -768,10 +851,10 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite,
for (int i = 0; i < p_suite->locals.size(); i++) {
ScriptLanguage::CodeCompletionOption option;
if (p_suite->locals[i].type == GDScriptParser::SuiteNode::Local::CONSTANT) {
- option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, ScriptLanguage::LOCATION_LOCAL);
option.default_value = p_suite->locals[i].constant->initializer->reduced_value;
} else {
- option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE);
+ option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE, ScriptLanguage::LOCATION_LOCAL);
}
r_result.insert(option.display, option);
}
@@ -788,8 +871,10 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (!p_parent_only) {
bool outer = false;
const GDScriptParser::ClassNode *clss = p_class;
+ int classes_processed = 0;
while (clss) {
for (int i = 0; i < clss->members.size(); i++) {
+ const int location = (classes_processed + p_recursion_depth) | ScriptLanguage::LOCATION_PARENT_MASK;
const GDScriptParser::ClassNode::Member &member = clss->members[i];
ScriptLanguage::CodeCompletionOption option;
switch (member.type) {
@@ -797,7 +882,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (p_only_functions || outer || (p_static)) {
continue;
}
- option = ScriptLanguage::CodeCompletionOption(member.variable->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
+ option = ScriptLanguage::CodeCompletionOption(member.variable->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
break;
case GDScriptParser::ClassNode::Member::CONSTANT:
if (p_only_functions) {
@@ -806,7 +891,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (r_result.has(member.constant->identifier->name)) {
continue;
}
- option = ScriptLanguage::CodeCompletionOption(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ option = ScriptLanguage::CodeCompletionOption(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
if (member.constant->initializer) {
option.default_value = member.constant->initializer->reduced_value;
}
@@ -815,25 +900,25 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (p_only_functions) {
continue;
}
- option = ScriptLanguage::CodeCompletionOption(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+ option = ScriptLanguage::CodeCompletionOption(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, location);
break;
case GDScriptParser::ClassNode::Member::ENUM_VALUE:
if (p_only_functions) {
continue;
}
- option = ScriptLanguage::CodeCompletionOption(member.enum_value.identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ option = ScriptLanguage::CodeCompletionOption(member.enum_value.identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
break;
case GDScriptParser::ClassNode::Member::ENUM:
if (p_only_functions) {
continue;
}
- option = ScriptLanguage::CodeCompletionOption(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM);
+ option = ScriptLanguage::CodeCompletionOption(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM, location);
break;
case GDScriptParser::ClassNode::Member::FUNCTION:
if (outer || (p_static && !member.function->is_static) || member.function->identifier->name.operator String().begins_with("@")) {
continue;
}
- option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
+ option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (member.function->parameters.size() > 0) {
option.insert_text += "(";
} else {
@@ -844,7 +929,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (p_only_functions || outer) {
continue;
}
- option = ScriptLanguage::CodeCompletionOption(member.signal->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL);
+ option = ScriptLanguage::CodeCompletionOption(member.signal->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location);
break;
case GDScriptParser::ClassNode::Member::UNDEFINED:
break;
@@ -853,6 +938,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
}
outer = true;
clss = clss->outer;
+ classes_processed++;
}
}
@@ -891,21 +977,24 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
List<PropertyInfo> members;
scr->get_script_property_list(&members);
for (const PropertyInfo &E : members) {
- ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
+ int location = p_recursion_depth + _get_property_location(scr->get_class_name(), E.class_name);
+ ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
r_result.insert(option.display, option);
}
}
Map<StringName, Variant> constants;
scr->get_constants(&constants);
for (const KeyValue<StringName, Variant> &E : constants) {
- ScriptLanguage::CodeCompletionOption option(E.key.operator String(), ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ int location = p_recursion_depth + _get_constant_location(scr->get_class_name(), E.key);
+ ScriptLanguage::CodeCompletionOption option(E.key.operator String(), ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
r_result.insert(option.display, option);
}
List<MethodInfo> signals;
scr->get_script_signal_list(&signals);
for (const MethodInfo &E : signals) {
- ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL);
+ int location = p_recursion_depth + _get_signal_location(scr->get_class_name(), E.name);
+ ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location);
r_result.insert(option.display, option);
}
}
@@ -916,7 +1005,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (E.name.begins_with("@")) {
continue;
}
- ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
+ int location = p_recursion_depth + _get_method_location(scr->get_class_name(), E.name);
+ ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (E.arguments.size()) {
option.insert_text += "(";
} else {
@@ -946,7 +1036,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
List<String> constants;
ClassDB::get_integer_constant_list(type, &constants);
for (const String &E : constants) {
- ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ int location = p_recursion_depth + _get_constant_location(type, StringName(E));
+ ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
r_result.insert(option.display, option);
}
@@ -960,7 +1051,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (E.name.contains("/")) {
continue;
}
- ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER);
+ int location = p_recursion_depth + _get_property_location(type, E.class_name);
+ ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
r_result.insert(option.display, option);
}
}
@@ -973,7 +1065,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (E.name.begins_with("_")) {
continue;
}
- ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION);
+ int location = p_recursion_depth + _get_method_location(type, E.name);
+ ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (E.arguments.size()) {
option.insert_text += "(";
} else {
@@ -982,7 +1075,6 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
r_result.insert(option.display, option);
}
}
-
return;
} break;
case GDScriptParser::DataType::BUILTIN: {
@@ -2242,7 +2334,8 @@ static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_co
ClassDB::get_enum_constants(class_name, enum_name, &enum_constants);
for (const StringName &E : enum_constants) {
String candidate = class_name + "." + E;
- ScriptLanguage::CodeCompletionOption option(candidate, ScriptLanguage::CODE_COMPLETION_KIND_ENUM);
+ int location = _get_enum_constant_location(class_name, E);
+ ScriptLanguage::CodeCompletionOption option(candidate, ScriptLanguage::CODE_COMPLETION_KIND_ENUM, location);
r_result.insert(option.display, option);
}
}
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index eb7b2c0240..a0e584e525 100644
--- a/modules/gdscript/language_server/gdscript_text_document.h
+++ b/modules/gdscript/language_server/gdscript_text_document.h
@@ -40,7 +40,7 @@ class GDScriptTextDocument : public RefCounted {
protected:
static void _bind_methods();
- FileAccess *file_checker;
+ FileAccess *file_checker = nullptr;
void didOpen(const Variant &p_param);
void didClose(const Variant &p_param);
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index e8ddf90836..16c143f7d9 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -80,7 +80,7 @@ void init_autoloads() {
} else if (script.is_valid()) {
StringName ibt = script->get_instance_base_type();
bool valid_type = ClassDB::is_parent_class(ibt, "Node");
- ERR_CONTINUE_MSG(!valid_type, "Script does not inherit a Node: " + info.path);
+ ERR_CONTINUE_MSG(!valid_type, "Script does not inherit from Node: " + info.path);
Object *obj = ClassDB::instantiate(ibt);
diff --git a/modules/gdscript/tests/gdscript_test_runner.h b/modules/gdscript/tests/gdscript_test_runner.h
index 1a950c6898..d6c6419e21 100644
--- a/modules/gdscript/tests/gdscript_test_runner.h
+++ b/modules/gdscript/tests/gdscript_test_runner.h
@@ -63,8 +63,8 @@ public:
private:
struct ErrorHandlerData {
- TestResult *result;
- GDScriptTest *self;
+ TestResult *result = nullptr;
+ GDScriptTest *self = nullptr;
ErrorHandlerData(TestResult *p_result, GDScriptTest *p_this) {
result = p_result;
self = p_this;
diff --git a/modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml b/modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml
index 9c6c8e03c4..ca8eb9854f 100644
--- a/modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml
+++ b/modules/gltf/doc_classes/EditorSceneFormatImporterBlend.xml
@@ -5,8 +5,8 @@
</brief_description>
<description>
Imports Blender scenes in the [code].blend[/code] file format through the glTF 2.0 3D import pipeline. This importer requires Blender to be installed by the user, so that it can be used to export the scene as glTF 2.0.
- The location of the Blender binary is set via the [code]filesystem/import/blend/blender_path[/code] editor setting.
- This importer is only used if [member ProjectSettings.filesystem/import/blend/enabled] is enabled, otherwise [code].blend[/code] files present in the project folder are not imported.
+ The location of the Blender binary is set via the [code]filesystem/import/blender/blender3_path[/code] editor setting.
+ This importer is only used if [member ProjectSettings.filesystem/import/blender/enabled] is enabled, otherwise [code].blend[/code] files present in the project folder are not imported.
Blend import requires Blender 3.0.
Internally, the EditorSceneFormatImporterBlend uses the Blender glTF "Use Original" mode to reference external textures.
</description>
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index 6f5c8c8740..cdb22b7d19 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -30,16 +30,25 @@
#include "editor_scene_importer_blend.h"
-#if TOOLS_ENABLED
+#ifdef TOOLS_ENABLED
#include "../gltf_document.h"
#include "../gltf_state.h"
#include "core/config/project_settings.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "main/main.h"
#include "scene/main/node.h"
#include "scene/resources/animation.h"
+#ifdef WINDOWS_ENABLED
+// Code by Pedro Estebanez (https://github.com/godotengine/godot/pull/59766)
+#include <shlwapi.h>
+#endif
+
uint32_t EditorSceneFormatImporterBlend::get_import_flags() const {
return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION;
}
@@ -180,7 +189,13 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_
// Run script with configured Blender binary.
- String blender_path = EDITOR_GET("filesystem/import/blend/blender_path");
+ String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path");
+
+#ifdef WINDOWS_ENABLED
+ blender_path = blender_path.plus_file("blender.exe");
+#else
+ blender_path = blender_path.plus_file("blender");
+#endif
List<String> args;
args.push_back("--background");
@@ -264,4 +279,294 @@ void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, Li
#undef ADD_OPTION_ENUM
}
+///////////////////////////
+
+static bool _test_blender_path(const String &p_path, String *r_err = nullptr) {
+ String path = p_path;
+#ifdef WINDOWS_ENABLED
+ path = path.plus_file("blender.exe");
+#else
+ path = path.plus_file("blender");
+#endif
+
+#if defined(OSX_ENABLED)
+ if (!FileAccess::exists(path)) {
+ path = path.plus_file("Blender");
+ }
+#endif
+
+ if (!FileAccess::exists(path)) {
+ if (r_err) {
+ *r_err = TTR("Path does not contain a Blender installation.");
+ }
+ return false;
+ }
+ List<String> args;
+ args.push_back("--version");
+ String pipe;
+ Error err = OS::get_singleton()->execute(path, args, &pipe);
+ if (err != OK) {
+ if (r_err) {
+ *r_err = TTR("Can't excecute Blender binary.");
+ }
+ return false;
+ }
+
+ if (pipe.find("Blender ") != 0) {
+ if (r_err) {
+ *r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s"), path);
+ }
+ return false;
+ }
+ pipe = pipe.replace_first("Blender ", "");
+ int pp = pipe.find(".");
+ if (pp == -1) {
+ if (r_err) {
+ *r_err = TTR("Path supplied lacks a Blender binary.");
+ }
+ return false;
+ }
+ String v = pipe.substr(0, pp);
+ int version = v.to_int();
+ if (version < 3) {
+ if (r_err) {
+ *r_err = TTR("This Blender installation is too old for this importer (not 3.0+).");
+ }
+ return false;
+ }
+ if (version > 3) {
+ if (r_err) {
+ *r_err = TTR("This Blender installation is too new for this importer (not 3.x).");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool EditorFileSystemImportFormatSupportQueryBlend::is_active() const {
+ bool blend_enabled = GLOBAL_GET("filesystem/import/blender/enabled");
+
+ String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path");
+
+ if (blend_enabled && !_test_blender_path(blender_path)) {
+ // Intending to import Blender, but blend not configured.
+ return true;
+ }
+
+ return false;
+}
+Vector<String> EditorFileSystemImportFormatSupportQueryBlend::get_file_extensions() const {
+ Vector<String> ret;
+ ret.push_back("blend");
+ return ret;
+}
+
+void EditorFileSystemImportFormatSupportQueryBlend::_validate_path(String p_path) {
+ String error;
+ bool success = false;
+ if (p_path == "") {
+ error = TTR("Path is empty.");
+ } else {
+ if (_test_blender_path(p_path, &error)) {
+ success = true;
+ if (auto_detected_path == p_path) {
+ error = TTR("Path to Blender installation is valid (Autodetected).");
+ } else {
+ error = TTR("Path to Blender installation is valid.");
+ }
+ }
+ }
+
+ path_status->set_text(error);
+
+ if (success) {
+ path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("success_color"), SNAME("Editor")));
+ configure_blender_dialog->get_ok_button()->set_disabled(false);
+ } else {
+ path_status->add_theme_color_override("font_color", path_status->get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ configure_blender_dialog->get_ok_button()->set_disabled(true);
+ }
+}
+
+bool EditorFileSystemImportFormatSupportQueryBlend::_autodetect_path(String p_path) {
+ if (_test_blender_path(p_path)) {
+ auto_detected_path = p_path;
+ return true;
+ }
+ return false;
+}
+
+void EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed() {
+ confirmed = true;
+}
+
+void EditorFileSystemImportFormatSupportQueryBlend::_select_install(String p_path) {
+ blender_path->set_text(p_path);
+ _validate_path(p_path);
+}
+void EditorFileSystemImportFormatSupportQueryBlend::_browse_install() {
+ if (blender_path->get_text() != String()) {
+ browse_dialog->set_current_dir(blender_path->get_text());
+ }
+
+ browse_dialog->popup_centered_ratio();
+}
+
+bool EditorFileSystemImportFormatSupportQueryBlend::query() {
+ if (!configure_blender_dialog) {
+ configure_blender_dialog = memnew(ConfirmationDialog);
+ configure_blender_dialog->set_title(TTR("Configure Blender Importer"));
+ configure_blender_dialog->set_flag(Window::FLAG_BORDERLESS, true); // Avoid closing accidentally .
+ configure_blender_dialog->set_close_on_escape(false);
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+ vb->add_child(memnew(Label(TTR("Blender 3.0+ is required to import '.blend' files.\nPlease provide a valid path to a Blender installation:"))));
+
+ HBoxContainer *hb = memnew(HBoxContainer);
+
+ blender_path = memnew(LineEdit);
+ blender_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb->add_child(blender_path);
+ blender_path_browse = memnew(Button);
+ hb->add_child(blender_path_browse);
+ blender_path_browse->set_text(TTR("Browse"));
+ blender_path_browse->connect("pressed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_browse_install));
+ hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ hb->set_custom_minimum_size(Size2(400 * EDSCALE, 0));
+
+ vb->add_child(hb);
+
+ path_status = memnew(Label);
+ vb->add_child(path_status);
+
+ configure_blender_dialog->add_child(vb);
+
+ blender_path->connect("text_changed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_validate_path));
+
+ EditorNode::get_singleton()->get_gui_base()->add_child(configure_blender_dialog);
+
+ configure_blender_dialog->get_ok_button()->set_text(TTR("Confirm Path"));
+ configure_blender_dialog->get_cancel_button()->set_text(TTR("Disable '.blend' Import"));
+ configure_blender_dialog->get_cancel_button()->set_tooltip(TTR("Disables Blender '.blend' files import for this project. Can be re-enabled in Project Settings."));
+ configure_blender_dialog->connect("confirmed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed));
+
+ browse_dialog = memnew(EditorFileDialog);
+ browse_dialog->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ browse_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_DIR);
+ browse_dialog->connect("dir_selected", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_select_install));
+
+ EditorNode::get_singleton()->get_gui_base()->add_child(browse_dialog);
+ }
+
+ String path = EDITOR_GET("filesystem/import/blender/blender3_path");
+
+ if (path == "") {
+ // Autodetect
+ auto_detected_path = "";
+
+#if defined(OSX_ENABLED)
+
+ {
+ Vector<String> mdfind_paths;
+ {
+ List<String> mdfind_args;
+ mdfind_args.push_back("kMDItemCFBundleIdentifier=org.blenderfoundation.blender");
+
+ String output;
+ Error err = OS::get_singleton()->execute("mdfind", mdfind_args, &output);
+ if (err == OK) {
+ mdfind_paths = output.split("\n");
+ }
+ }
+
+ bool found = false;
+ for (const String &path : mdfind_paths) {
+ found = _autodetect_path(path.plus_file("Contents/MacOS"));
+ if (found) {
+ break;
+ }
+ }
+ if (!found) {
+ found = _autodetect_path("/opt/homebrew/bin");
+ }
+ if (!found) {
+ found = _autodetect_path("/opt/local/bin");
+ }
+ if (!found) {
+ found = _autodetect_path("/usr/local/bin");
+ }
+ if (!found) {
+ found = _autodetect_path("/usr/local/opt");
+ }
+ if (!found) {
+ found = _autodetect_path("/Applications/Blender.app/Contents/MacOS");
+ }
+ }
+#elif defined(WINDOWS_ENABLED)
+ {
+ char blender_opener_path[MAX_PATH];
+ DWORD path_len = MAX_PATH;
+ HRESULT res = AssocQueryString(0, ASSOCSTR_EXECUTABLE, ".blend", "open", blender_opener_path, &path_len);
+ if (res == S_OK && _autodetect_path(String(blender_opener_path).get_base_dir())) {
+ // Good.
+ } else if (_autodetect_path("C:\\Program Files\\Blender Foundation")) {
+ // Good.
+ } else {
+ _autodetect_path("C:\\Program Files (x86)\\Blender Foundation");
+ }
+ }
+
+#elif defined(UNIX_ENABLED)
+ if (_autodetect_path("/usr/bin")) {
+ // Good.
+ } else if (_autodetect_path("/usr/local/bin")) {
+ // Good
+ } else {
+ _autodetect_path("/opt/blender/bin");
+ }
+#endif
+ if (auto_detected_path != "") {
+ path = auto_detected_path;
+ }
+ }
+
+ blender_path->set_text(path);
+
+ _validate_path(path);
+
+ configure_blender_dialog->popup_centered();
+ confirmed = false;
+
+ while (true) {
+ OS::get_singleton()->delay_usec(1);
+ DisplayServer::get_singleton()->process_events();
+ Main::iteration();
+ if (!configure_blender_dialog->is_visible() || confirmed) {
+ break;
+ }
+ }
+
+ if (confirmed) {
+ // Can only confirm a valid path.
+ EditorSettings::get_singleton()->set("filesystem/import/blender/blender3_path", blender_path->get_text());
+ EditorSettings::get_singleton()->save();
+ } else {
+ // Disable Blender import
+ ProjectSettings::get_singleton()->set("filesystem/import/blender/enabled", false);
+ ProjectSettings::get_singleton()->save();
+
+ if (EditorNode::immediate_confirmation_dialog(TTR("Disabling '.blend' file import requires restarting the editor."), TTR("Save & Restart"), TTR("Restart"))) {
+ EditorNode::get_singleton()->save_all_scenes();
+ }
+ EditorNode::get_singleton()->restart_editor();
+ return true;
+ }
+
+ return false;
+}
+
+EditorFileSystemImportFormatSupportQueryBlend::EditorFileSystemImportFormatSupportQueryBlend() {
+}
+
#endif // TOOLS_ENABLED
diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h
index e10897297c..9a1b5f5803 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.h
+++ b/modules/gltf/editor/editor_scene_importer_blend.h
@@ -33,10 +33,12 @@
#ifdef TOOLS_ENABLED
+#include "editor/editor_file_system.h"
#include "editor/import/resource_importer_scene.h"
class Animation;
class Node;
+class ConfirmationDialog;
class EditorSceneFormatImporterBlend : public EditorSceneFormatImporter {
GDCLASS(EditorSceneFormatImporterBlend, EditorSceneFormatImporter);
@@ -74,6 +76,39 @@ public:
const Map<StringName, Variant> &p_options) override;
};
+class LineEdit;
+class Button;
+class EditorFileDialog;
+class Label;
+
+class EditorFileSystemImportFormatSupportQueryBlend : public EditorFileSystemImportFormatSupportQuery {
+ GDCLASS(EditorFileSystemImportFormatSupportQueryBlend, EditorFileSystemImportFormatSupportQuery);
+
+ ConfirmationDialog *configure_blender_dialog = nullptr;
+ LineEdit *blender_path = nullptr;
+ Button *blender_path_browse = nullptr;
+ EditorFileDialog *browse_dialog = nullptr;
+ Label *path_status = nullptr;
+ bool confirmed = false;
+
+ String auto_detected_path;
+ void _validate_path(String p_path);
+
+ bool _autodetect_path(String p_path);
+
+ void _path_confirmed();
+
+ void _select_install(String p_path);
+ void _browse_install();
+
+public:
+ virtual bool is_active() const override;
+ virtual Vector<String> get_file_extensions() const override;
+ virtual bool query() override;
+
+ EditorFileSystemImportFormatSupportQueryBlend();
+};
+
#endif // TOOLS_ENABLED
#endif // EDITOR_SCENE_IMPORTER_BLEND_H
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index 79b918dbc0..4166f92502 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -64,22 +64,19 @@ static void _editor_init() {
// Blend to glTF importer.
- bool blend_enabled = GLOBAL_GET("filesystem/import/blend/enabled");
+ bool blend_enabled = GLOBAL_GET("filesystem/import/blender/enabled");
// Defined here because EditorSettings doesn't exist in `register_gltf_types` yet.
- String blender_path = EDITOR_DEF_RST("filesystem/import/blend/blender_path", "");
+ EDITOR_DEF_RST("filesystem/import/blender/blender3_path", "");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,
- "filesystem/import/blend/blender_path", PROPERTY_HINT_GLOBAL_FILE));
+ "filesystem/import/blender/blender3_path", PROPERTY_HINT_GLOBAL_DIR));
if (blend_enabled) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (blender_path.is_empty()) {
- WARN_PRINT("Blend file import is enabled, but no Blender path is configured. Blend files will not be imported.");
- } else if (!da->file_exists(blender_path)) {
- WARN_PRINT("Blend file import is enabled, but the Blender path doesn't point to a valid Blender executable. Blend files will not be imported.");
- } else {
- Ref<EditorSceneFormatImporterBlend> importer;
- importer.instantiate();
- ResourceImporterScene::get_singleton()->add_importer(importer);
- }
+ Ref<EditorSceneFormatImporterBlend> importer;
+ importer.instantiate();
+ ResourceImporterScene::get_singleton()->add_importer(importer);
+
+ Ref<EditorFileSystemImportFormatSupportQueryBlend> blend_import_query;
+ blend_import_query.instantiate();
+ EditorFileSystem::get_singleton()->add_import_format_support_query(blend_import_query);
}
// FBX to glTF importer.
@@ -131,13 +128,14 @@ void register_gltf_types() {
EditorPlugins::add_by_type<SceneExporterGLTFPlugin>();
// Project settings defined here so doctool finds them.
- GLOBAL_DEF_RST("filesystem/import/blend/enabled", true);
+ GLOBAL_DEF_RST("filesystem/import/blender/enabled", true);
GLOBAL_DEF_RST("filesystem/import/fbx/enabled", true);
GDREGISTER_CLASS(EditorSceneFormatImporterBlend);
GDREGISTER_CLASS(EditorSceneFormatImporterFBX);
ClassDB::set_current_api(prev_api);
EditorNode::add_init_callback(_editor_init);
+
#endif // TOOLS_ENABLED
}
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h
index adb0da6e2c..3b29397502 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.h
+++ b/modules/gridmap/editor/grid_map_editor_plugin.h
@@ -62,21 +62,21 @@ class GridMapEditor : public VBoxContainer {
DISPLAY_LIST
};
- UndoRedo *undo_redo;
+ UndoRedo *undo_redo = nullptr;
InputAction input_action = INPUT_NONE;
- Panel *panel;
- MenuButton *options;
- SpinBox *floor;
+ Panel *panel = nullptr;
+ MenuButton *options = nullptr;
+ SpinBox *floor = nullptr;
double accumulated_floor_delta = 0.0;
- Button *mode_thumbnail;
- Button *mode_list;
- LineEdit *search_box;
- HSlider *size_slider;
- HBoxContainer *spatial_editor_hb;
- ConfirmationDialog *settings_dialog;
- VBoxContainer *settings_vbc;
- SpinBox *settings_pick_distance;
- Label *spin_box_label;
+ Button *mode_thumbnail = nullptr;
+ Button *mode_list = nullptr;
+ LineEdit *search_box = nullptr;
+ HSlider *size_slider = nullptr;
+ HBoxContainer *spatial_editor_hb = nullptr;
+ ConfirmationDialog *settings_dialog = nullptr;
+ VBoxContainer *settings_vbc = nullptr;
+ SpinBox *settings_pick_distance = nullptr;
+ Label *spin_box_label = nullptr;
struct SetItem {
Vector3i position;
@@ -89,7 +89,7 @@ class GridMapEditor : public VBoxContainer {
List<SetItem> set_items;
GridMap *node = nullptr;
- MeshLibrary *last_mesh_library;
+ MeshLibrary *last_mesh_library = nullptr;
Transform3D grid_xform;
Transform3D edit_grid_xform;
@@ -173,15 +173,15 @@ class GridMapEditor : public VBoxContainer {
};
- Node3DEditorPlugin *spatial_editor;
+ Node3DEditorPlugin *spatial_editor = nullptr;
struct AreaDisplay {
RID mesh;
RID instance;
};
- ItemList *mesh_library_palette;
- Label *info_message;
+ ItemList *mesh_library_palette = nullptr;
+ Label *info_message = nullptr;
void update_grid(); // Change which and where the grid is displayed
void _draw_grids(const Vector3 &cell_size);
@@ -234,7 +234,7 @@ public:
class GridMapEditorPlugin : public EditorPlugin {
GDCLASS(GridMapEditorPlugin, EditorPlugin);
- GridMapEditor *grid_map_editor;
+ GridMapEditor *grid_map_editor = nullptr;
protected:
void _notification(int p_what);
diff --git a/modules/mono/glue/arguments_vector.h b/modules/mono/glue/arguments_vector.h
index 7c991d87a4..4405809887 100644
--- a/modules/mono/glue/arguments_vector.h
+++ b/modules/mono/glue/arguments_vector.h
@@ -37,7 +37,7 @@ template <typename T, int POOL_SIZE = 5>
struct ArgumentsVector {
private:
T pool[POOL_SIZE];
- T *_ptr;
+ T *_ptr = nullptr;
int size;
ArgumentsVector() = delete;
diff --git a/modules/mono/managed_callable.h b/modules/mono/managed_callable.h
index ea7231f43b..d50a8a7b08 100644
--- a/modules/mono/managed_callable.h
+++ b/modules/mono/managed_callable.h
@@ -43,7 +43,7 @@
class ManagedCallable : public CallableCustom {
friend class CSharpLanguage;
MonoGCHandleData delegate_handle;
- GDMonoMethod *delegate_invoke;
+ GDMonoMethod *delegate_invoke = nullptr;
#ifdef GD_MONO_HOT_RELOAD
SelfList<ManagedCallable> self_instance = this;
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index aab0b31c37..51fd0f8483 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -94,16 +94,16 @@ private:
UnhandledExceptionPolicy unhandled_exception_policy;
- MonoDomain *root_domain;
- MonoDomain *scripts_domain;
+ MonoDomain *root_domain = nullptr;
+ MonoDomain *scripts_domain = nullptr;
HashMap<int32_t, HashMap<String, GDMonoAssembly *>> assemblies;
- GDMonoAssembly *corlib_assembly;
- GDMonoAssembly *project_assembly;
+ GDMonoAssembly *corlib_assembly = nullptr;
+ GDMonoAssembly *project_assembly = nullptr;
#ifdef TOOLS_ENABLED
- GDMonoAssembly *tools_assembly;
- GDMonoAssembly *tools_project_editor_assembly;
+ GDMonoAssembly *tools_assembly = nullptr;
+ GDMonoAssembly *tools_project_editor_assembly = nullptr;
#endif
LoadedApiAssembly core_api_assembly;
@@ -150,7 +150,7 @@ private:
void _init_godot_api_hashes();
void _init_exception_policy();
- GDMonoLog *gdmono_log;
+ GDMonoLog *gdmono_log = nullptr;
#if defined(WINDOWS_ENABLED) && defined(TOOLS_ENABLED)
MonoRegInfo mono_reg_info;
@@ -250,7 +250,7 @@ public:
namespace gdmono {
class ScopeDomain {
- MonoDomain *prev_domain;
+ MonoDomain *prev_domain = nullptr;
public:
ScopeDomain(MonoDomain *p_domain) {
@@ -270,7 +270,7 @@ public:
};
class ScopeExitDomainUnload {
- MonoDomain *domain;
+ MonoDomain *domain = nullptr;
public:
ScopeExitDomainUnload(MonoDomain *p_domain) :
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index b25d773be7..a96357b082 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -68,8 +68,8 @@ class GDMonoAssembly {
};
String name;
- MonoImage *image;
- MonoAssembly *assembly;
+ MonoImage *image = nullptr;
+ MonoAssembly *assembly = nullptr;
bool attrs_fetched = false;
MonoCustomAttrInfo *attributes = nullptr;
diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h
index 49f47b0a15..4000342c94 100644
--- a/modules/mono/mono_gd/gd_mono_cache.h
+++ b/modules/mono/mono_gd/gd_mono_cache.h
@@ -41,91 +41,91 @@ struct CachedData {
// corlib classes
// Let's use the no-namespace format for these too
- GDMonoClass *class_MonoObject; // object
- GDMonoClass *class_bool; // bool
- GDMonoClass *class_int8_t; // sbyte
- GDMonoClass *class_int16_t; // short
- GDMonoClass *class_int32_t; // int
- GDMonoClass *class_int64_t; // long
- GDMonoClass *class_uint8_t; // byte
- GDMonoClass *class_uint16_t; // ushort
- GDMonoClass *class_uint32_t; // uint
- GDMonoClass *class_uint64_t; // ulong
- GDMonoClass *class_float; // float
- GDMonoClass *class_double; // double
- GDMonoClass *class_String; // string
- GDMonoClass *class_IntPtr; // System.IntPtr
-
- GDMonoClass *class_System_Collections_IEnumerable;
- GDMonoClass *class_System_Collections_ICollection;
- GDMonoClass *class_System_Collections_IDictionary;
+ GDMonoClass *class_MonoObject = nullptr; // object
+ GDMonoClass *class_bool = nullptr; // bool
+ GDMonoClass *class_int8_t = nullptr; // sbyte
+ GDMonoClass *class_int16_t = nullptr; // short
+ GDMonoClass *class_int32_t = nullptr; // int
+ GDMonoClass *class_int64_t = nullptr; // long
+ GDMonoClass *class_uint8_t = nullptr; // byte
+ GDMonoClass *class_uint16_t = nullptr; // ushort
+ GDMonoClass *class_uint32_t = nullptr; // uint
+ GDMonoClass *class_uint64_t = nullptr; // ulong
+ GDMonoClass *class_float = nullptr; // float
+ GDMonoClass *class_double = nullptr; // double
+ GDMonoClass *class_String = nullptr; // string
+ GDMonoClass *class_IntPtr = nullptr; // System.IntPtr
+
+ GDMonoClass *class_System_Collections_IEnumerable = nullptr;
+ GDMonoClass *class_System_Collections_ICollection = nullptr;
+ GDMonoClass *class_System_Collections_IDictionary = nullptr;
#ifdef DEBUG_ENABLED
- GDMonoClass *class_System_Diagnostics_StackTrace;
+ GDMonoClass *class_System_Diagnostics_StackTrace = nullptr;
GDMonoMethodThunkR<MonoArray *, MonoObject *> methodthunk_System_Diagnostics_StackTrace_GetFrames;
- GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool;
- GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool;
+ GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool = nullptr;
+ GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool = nullptr;
#endif
- GDMonoClass *class_KeyNotFoundException;
+ GDMonoClass *class_KeyNotFoundException = nullptr;
- MonoClass *rawclass_Dictionary;
+ MonoClass *rawclass_Dictionary = nullptr;
// -----------------------------------------------
- GDMonoClass *class_Vector2;
- GDMonoClass *class_Vector2i;
- GDMonoClass *class_Rect2;
- GDMonoClass *class_Rect2i;
- GDMonoClass *class_Transform2D;
- GDMonoClass *class_Vector3;
- GDMonoClass *class_Vector3i;
- GDMonoClass *class_Basis;
- GDMonoClass *class_Quaternion;
- GDMonoClass *class_Transform3D;
- GDMonoClass *class_AABB;
- GDMonoClass *class_Color;
- GDMonoClass *class_Plane;
- GDMonoClass *class_StringName;
- GDMonoClass *class_NodePath;
- GDMonoClass *class_RID;
- GDMonoClass *class_GodotObject;
- GDMonoClass *class_GodotResource;
- GDMonoClass *class_Node;
- GDMonoClass *class_Control;
- GDMonoClass *class_Node3D;
- GDMonoClass *class_WeakRef;
- GDMonoClass *class_Callable;
- GDMonoClass *class_SignalInfo;
- GDMonoClass *class_Array;
- GDMonoClass *class_Dictionary;
- GDMonoClass *class_MarshalUtils;
- GDMonoClass *class_ISerializationListener;
+ GDMonoClass *class_Vector2 = nullptr;
+ GDMonoClass *class_Vector2i = nullptr;
+ GDMonoClass *class_Rect2 = nullptr;
+ GDMonoClass *class_Rect2i = nullptr;
+ GDMonoClass *class_Transform2D = nullptr;
+ GDMonoClass *class_Vector3 = nullptr;
+ GDMonoClass *class_Vector3i = nullptr;
+ GDMonoClass *class_Basis = nullptr;
+ GDMonoClass *class_Quaternion = nullptr;
+ GDMonoClass *class_Transform3D = nullptr;
+ GDMonoClass *class_AABB = nullptr;
+ GDMonoClass *class_Color = nullptr;
+ GDMonoClass *class_Plane = nullptr;
+ GDMonoClass *class_StringName = nullptr;
+ GDMonoClass *class_NodePath = nullptr;
+ GDMonoClass *class_RID = nullptr;
+ GDMonoClass *class_GodotObject = nullptr;
+ GDMonoClass *class_GodotResource = nullptr;
+ GDMonoClass *class_Node = nullptr;
+ GDMonoClass *class_Control = nullptr;
+ GDMonoClass *class_Node3D = nullptr;
+ GDMonoClass *class_WeakRef = nullptr;
+ GDMonoClass *class_Callable = nullptr;
+ GDMonoClass *class_SignalInfo = nullptr;
+ GDMonoClass *class_Array = nullptr;
+ GDMonoClass *class_Dictionary = nullptr;
+ GDMonoClass *class_MarshalUtils = nullptr;
+ GDMonoClass *class_ISerializationListener = nullptr;
#ifdef DEBUG_ENABLED
- GDMonoClass *class_DebuggingUtils;
+ GDMonoClass *class_DebuggingUtils = nullptr;
GDMonoMethodThunk<MonoObject *, MonoString **, int *, MonoString **> methodthunk_DebuggingUtils_GetStackFrameInfo;
#endif
- GDMonoClass *class_ExportAttribute;
- GDMonoField *field_ExportAttribute_hint;
- GDMonoField *field_ExportAttribute_hintString;
- GDMonoClass *class_SignalAttribute;
- GDMonoClass *class_ToolAttribute;
- GDMonoClass *class_AnyPeerAttribute;
- GDMonoClass *class_AuthorityAttribute;
- GDMonoClass *class_GodotMethodAttribute;
- GDMonoField *field_GodotMethodAttribute_methodName;
- GDMonoClass *class_ScriptPathAttribute;
- GDMonoField *field_ScriptPathAttribute_path;
- GDMonoClass *class_AssemblyHasScriptsAttribute;
- GDMonoField *field_AssemblyHasScriptsAttribute_requiresLookup;
- GDMonoField *field_AssemblyHasScriptsAttribute_scriptTypes;
-
- GDMonoField *field_GodotObject_ptr;
- GDMonoField *field_StringName_ptr;
- GDMonoField *field_NodePath_ptr;
- GDMonoField *field_Image_ptr;
- GDMonoField *field_RID_ptr;
+ GDMonoClass *class_ExportAttribute = nullptr;
+ GDMonoField *field_ExportAttribute_hint = nullptr;
+ GDMonoField *field_ExportAttribute_hintString = nullptr;
+ GDMonoClass *class_SignalAttribute = nullptr;
+ GDMonoClass *class_ToolAttribute = nullptr;
+ GDMonoClass *class_AnyPeerAttribute = nullptr;
+ GDMonoClass *class_AuthorityAttribute = nullptr;
+ GDMonoClass *class_GodotMethodAttribute = nullptr;
+ GDMonoField *field_GodotMethodAttribute_methodName = nullptr;
+ GDMonoClass *class_ScriptPathAttribute = nullptr;
+ GDMonoField *field_ScriptPathAttribute_path = nullptr;
+ GDMonoClass *class_AssemblyHasScriptsAttribute = nullptr;
+ GDMonoField *field_AssemblyHasScriptsAttribute_requiresLookup = nullptr;
+ GDMonoField *field_AssemblyHasScriptsAttribute_scriptTypes = nullptr;
+
+ GDMonoField *field_GodotObject_ptr = nullptr;
+ GDMonoField *field_StringName_ptr = nullptr;
+ GDMonoField *field_NodePath_ptr = nullptr;
+ GDMonoField *field_Image_ptr = nullptr;
+ GDMonoField *field_RID_ptr = nullptr;
GDMonoMethodThunk<MonoObject *> methodthunk_GodotObject_Dispose;
GDMonoMethodThunkR<Array *, MonoObject *> methodthunk_Array_GetPtr;
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index bfb5797d4b..b32d561f61 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -70,11 +70,11 @@ class GDMonoClass {
StringName namespace_name;
StringName class_name;
- MonoClass *mono_class;
- GDMonoAssembly *assembly;
+ MonoClass *mono_class = nullptr;
+ GDMonoAssembly *assembly = nullptr;
bool attrs_fetched;
- MonoCustomAttrInfo *attributes;
+ MonoCustomAttrInfo *attributes = nullptr;
// This contains both the original method names and remapped method names from the native Godot identifiers to the C# functions.
// Most method-related functions refer to this and it's possible this is unintuitive for outside users; this may be a prime location for refactoring or renaming.
diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h
index abcdef378c..87ef245f3f 100644
--- a/modules/mono/mono_gd/gd_mono_field.h
+++ b/modules/mono/mono_gd/gd_mono_field.h
@@ -36,14 +36,14 @@
#include "i_mono_class_member.h"
class GDMonoField : public IMonoClassMember {
- GDMonoClass *owner;
- MonoClassField *mono_field;
+ GDMonoClass *owner = nullptr;
+ MonoClassField *mono_field = nullptr;
StringName name;
ManagedType type;
bool attrs_fetched;
- MonoCustomAttrInfo *attributes;
+ MonoCustomAttrInfo *attributes = nullptr;
public:
virtual GDMonoClass *get_enclosing_class() const final { return owner; }
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 20d4743e5c..eb33c6119e 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -196,14 +196,14 @@ PackedVector3Array mono_array_to_PackedVector3Array(MonoArray *p_array);
#pragma pack(push, 1)
struct M_Callable {
- MonoObject *target;
- MonoObject *method_string_name;
- MonoDelegate *delegate;
+ MonoObject *target = nullptr;
+ MonoObject *method_string_name = nullptr;
+ MonoDelegate *delegate = nullptr;
};
struct M_SignalInfo {
- MonoObject *owner;
- MonoObject *name_string_name;
+ MonoObject *owner = nullptr;
+ MonoObject *name_string_name = nullptr;
};
#pragma pack(pop)
diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h
index 6e87a60ee2..be11ef5bfe 100644
--- a/modules/mono/mono_gd/gd_mono_method.h
+++ b/modules/mono/mono_gd/gd_mono_method.h
@@ -54,7 +54,7 @@ class GDMonoMethod : public IMonoClassMember {
friend class GDMonoClass;
- MonoMethod *mono_method;
+ MonoMethod *mono_method = nullptr;
public:
virtual GDMonoClass *get_enclosing_class() const final;
diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h
index 003bcf05e1..6fc681aeb5 100644
--- a/modules/mono/mono_gd/gd_mono_property.h
+++ b/modules/mono/mono_gd/gd_mono_property.h
@@ -36,14 +36,14 @@
#include "i_mono_class_member.h"
class GDMonoProperty : public IMonoClassMember {
- GDMonoClass *owner;
- MonoProperty *mono_property;
+ GDMonoClass *owner = nullptr;
+ MonoProperty *mono_property = nullptr;
StringName name;
ManagedType type;
bool attrs_fetched;
- MonoCustomAttrInfo *attributes;
+ MonoCustomAttrInfo *attributes = nullptr;
unsigned int param_buffer_size;
diff --git a/modules/mono/mono_gd/gd_mono_wasm_m2n.h b/modules/mono/mono_gd/gd_mono_wasm_m2n.h
index 68299aa984..83e2750e5a 100644
--- a/modules/mono/mono_gd/gd_mono_wasm_m2n.h
+++ b/modules/mono/mono_gd/gd_mono_wasm_m2n.h
@@ -47,11 +47,11 @@ struct Mono_InterpMethodArguments {
size_t ilen;
void **iargs;
size_t flen;
- double *fargs;
+ double *fargs = nullptr;
void **retval;
size_t is_float_ret;
//#ifdef TARGET_WASM
- void *sig;
+ void *sig = nullptr;
//#endif
};
} // extern "C"
diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h
index 1a62f36625..532aa3e327 100644
--- a/modules/mono/signal_awaiter_utils.h
+++ b/modules/mono/signal_awaiter_utils.h
@@ -68,7 +68,7 @@ public:
};
class EventSignalCallable : public CallableCustom {
- Object *owner;
+ Object *owner = nullptr;
const CSharpScript::EventSignal *event_signal;
public:
diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.h b/modules/navigation/editor/navigation_mesh_editor_plugin.h
index 3c3e804fd2..bc9e4185b7 100644
--- a/modules/navigation/editor/navigation_mesh_editor_plugin.h
+++ b/modules/navigation/editor/navigation_mesh_editor_plugin.h
@@ -42,14 +42,14 @@ class NavigationMeshEditor : public Control {
GDCLASS(NavigationMeshEditor, Control);
- AcceptDialog *err_dialog;
+ AcceptDialog *err_dialog = nullptr;
- HBoxContainer *bake_hbox;
- Button *button_bake;
- Button *button_reset;
- Label *bake_info;
+ HBoxContainer *bake_hbox = nullptr;
+ Button *button_bake = nullptr;
+ Button *button_reset = nullptr;
+ Label *bake_info = nullptr;
- NavigationRegion3D *node;
+ NavigationRegion3D *node = nullptr;
void _bake_pressed();
void _clear_pressed();
@@ -68,7 +68,7 @@ public:
class NavigationMeshEditorPlugin : public EditorPlugin {
GDCLASS(NavigationMeshEditorPlugin, EditorPlugin);
- NavigationMeshEditor *navigation_mesh_editor;
+ NavigationMeshEditor *navigation_mesh_editor = nullptr;
public:
virtual String get_name() const override { return "NavigationMesh"; }
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index f3da85063a..ca4fc4f628 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -109,9 +109,7 @@
} \
void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
-GodotNavigationServer::GodotNavigationServer() :
- NavigationServer3D() {
-}
+GodotNavigationServer::GodotNavigationServer() {}
GodotNavigationServer::~GodotNavigationServer() {
flush_queries();
diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h
index 0c02885b10..5b6c695ca4 100644
--- a/modules/navigation/nav_utils.h
+++ b/modules/navigation/nav_utils.h
@@ -89,7 +89,7 @@ struct Edge {
};
struct Polygon {
- NavRegion *owner;
+ NavRegion *owner = nullptr;
/// The points of this `Polygon`
std::vector<Point> points;
diff --git a/modules/noise/noise.h b/modules/noise/noise.h
index c05bc057da..767aa830e8 100644
--- a/modules/noise/noise.h
+++ b/modules/noise/noise.h
@@ -39,7 +39,7 @@ class Noise : public Resource {
// Helper struct for get_seamless_image(). See comments in .cpp for usage.
template <typename T>
struct img_buff {
- T *img;
+ T *img = nullptr;
int width; // Array dimensions & default modulo for image.
int height;
int offset_x; // Offset index location on image (wrapped by specified modulo).
diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub
index 32cab1bef1..d5df33b261 100644
--- a/modules/openxr/SCsub
+++ b/modules/openxr/SCsub
@@ -83,5 +83,9 @@ if env["vulkan"]:
env.modules_sources += module_obj
+if env["tools"]:
+ SConscript("editor/SCsub")
+
# Needed to force rebuilding the module files when the thirdparty library is updated.
env.Depends(module_obj, thirdparty_obj)
+
diff --git a/modules/openxr/action_map/openxr_action.cpp b/modules/openxr/action_map/openxr_action.cpp
index 59ee3f4292..359975a480 100644
--- a/modules/openxr/action_map/openxr_action.cpp
+++ b/modules/openxr/action_map/openxr_action.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "openxr_action.h"
+#include "openxr_action_set.h"
void OpenXRAction::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_localized_name", "localized_name"), &OpenXRAction::set_localized_name);
@@ -62,6 +63,16 @@ Ref<OpenXRAction> OpenXRAction::new_action(const char *p_name, const char *p_loc
return action;
}
+String OpenXRAction::get_name_with_set() const {
+ String name = get_name();
+
+ if (action_set != nullptr) {
+ name = action_set->get_name() + "/" + name;
+ }
+
+ return name;
+}
+
void OpenXRAction::set_localized_name(const String p_localized_name) {
localized_name = p_localized_name;
}
@@ -86,6 +97,18 @@ PackedStringArray OpenXRAction::get_toplevel_paths() const {
return toplevel_paths;
}
+void OpenXRAction::add_toplevel_path(const String p_toplevel_path) {
+ if (!toplevel_paths.has(p_toplevel_path)) {
+ toplevel_paths.push_back(p_toplevel_path);
+ }
+}
+
+void OpenXRAction::rem_toplevel_path(const String p_toplevel_path) {
+ if (toplevel_paths.has(p_toplevel_path)) {
+ toplevel_paths.erase(p_toplevel_path);
+ }
+}
+
void OpenXRAction::parse_toplevel_paths(const String p_toplevel_paths) {
toplevel_paths = p_toplevel_paths.split(",", false);
}
diff --git a/modules/openxr/action_map/openxr_action.h b/modules/openxr/action_map/openxr_action.h
index e2cfe79e64..5e57f89133 100644
--- a/modules/openxr/action_map/openxr_action.h
+++ b/modules/openxr/action_map/openxr_action.h
@@ -33,6 +33,8 @@
#include "core/io/resource.h"
+class OpenXRActionSet;
+
class OpenXRAction : public Resource {
GDCLASS(OpenXRAction, Resource);
@@ -43,6 +45,7 @@ public:
OPENXR_ACTION_VECTOR2,
OPENXR_ACTION_POSE,
OPENXR_ACTION_HAPTIC,
+ OPENXR_ACTION_MAX
};
private:
@@ -52,21 +55,31 @@ private:
PackedStringArray toplevel_paths;
protected:
+ friend class OpenXRActionSet;
+
+ OpenXRActionSet *action_set = nullptr; // action belongs to this action set.
+
static void _bind_methods();
public:
- static Ref<OpenXRAction> new_action(const char *p_name, const char *p_localized_name, const ActionType p_action_type, const char *p_toplevel_paths);
+ static Ref<OpenXRAction> new_action(const char *p_name, const char *p_localized_name, const ActionType p_action_type, const char *p_toplevel_paths); // Helper function to add and configure an action
+ OpenXRActionSet *get_action_set() const { return action_set; } // Get the action set this action belongs to
+
+ String get_name_with_set() const; // Retrieve the name of this action as <action_set>/<action>
+
+ void set_localized_name(const String p_localized_name); // Set the localized name of this action
+ String get_localized_name() const; // Get the localized name of this action
- void set_localized_name(const String p_localized_name);
- String get_localized_name() const;
+ void set_action_type(const ActionType p_action_type); // Set the type of this action
+ ActionType get_action_type() const; // Get the type of this action
- void set_action_type(const ActionType p_action_type);
- ActionType get_action_type() const;
+ void set_toplevel_paths(const PackedStringArray p_toplevel_paths); // Set the toplevel paths of this action
+ PackedStringArray get_toplevel_paths() const; // Get the toplevel paths of this action
- void set_toplevel_paths(const PackedStringArray p_toplevel_paths);
- PackedStringArray get_toplevel_paths() const;
+ void add_toplevel_path(const String p_toplevel_path); // Add a top level path to this action
+ void rem_toplevel_path(const String p_toplevel_path); // Remove a toplevel path from this action
- void parse_toplevel_paths(const String p_toplevel_paths);
+ void parse_toplevel_paths(const String p_toplevel_paths); // Parse and set the top level paths from a comma separated string
};
VARIANT_ENUM_CAST(OpenXRAction::ActionType);
diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp
index e14c68079d..1ea1346f61 100644
--- a/modules/openxr/action_map/openxr_action_map.cpp
+++ b/modules/openxr/action_map/openxr_action_map.cpp
@@ -35,6 +35,9 @@ void OpenXRActionMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_action_sets"), &OpenXRActionMap::get_action_sets);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "action_sets", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRActionSet", PROPERTY_USAGE_NO_EDITOR), "set_action_sets", "get_action_sets");
+ ClassDB::bind_method(D_METHOD("get_action_set_count"), &OpenXRActionMap::get_action_set_count);
+ ClassDB::bind_method(D_METHOD("find_action_set", "name"), &OpenXRActionMap::find_action_set);
+ ClassDB::bind_method(D_METHOD("get_action_set", "idx"), &OpenXRActionMap::get_action_set);
ClassDB::bind_method(D_METHOD("add_action_set", "action_set"), &OpenXRActionMap::add_action_set);
ClassDB::bind_method(D_METHOD("remove_action_set", "action_set"), &OpenXRActionMap::remove_action_set);
@@ -42,6 +45,9 @@ void OpenXRActionMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_interaction_profiles"), &OpenXRActionMap::get_interaction_profiles);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "interaction_profiles", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRInteractionProfile", PROPERTY_USAGE_NO_EDITOR), "set_interaction_profiles", "get_interaction_profiles");
+ ClassDB::bind_method(D_METHOD("get_interaction_profile_count"), &OpenXRActionMap::get_interaction_profile_count);
+ ClassDB::bind_method(D_METHOD("find_interaction_profile", "name"), &OpenXRActionMap::find_interaction_profile);
+ ClassDB::bind_method(D_METHOD("get_interaction_profile", "idx"), &OpenXRActionMap::get_interaction_profile);
ClassDB::bind_method(D_METHOD("add_interaction_profile", "interaction_profile"), &OpenXRActionMap::add_interaction_profile);
ClassDB::bind_method(D_METHOD("remove_interaction_profile", "interaction_profile"), &OpenXRActionMap::remove_interaction_profile);
@@ -56,6 +62,27 @@ Array OpenXRActionMap::get_action_sets() const {
return action_sets;
}
+int OpenXRActionMap::get_action_set_count() const {
+ return action_sets.size();
+}
+
+Ref<OpenXRActionSet> OpenXRActionMap::find_action_set(String p_name) const {
+ for (int i = 0; i < action_sets.size(); i++) {
+ Ref<OpenXRActionSet> action_set = action_sets[i];
+ if (action_set->get_name() == p_name) {
+ return action_set;
+ }
+ }
+
+ return Ref<OpenXRActionSet>();
+}
+
+Ref<OpenXRActionSet> OpenXRActionMap::get_action_set(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, action_sets.size(), Ref<OpenXRActionSet>());
+
+ return action_sets[p_idx];
+}
+
void OpenXRActionMap::add_action_set(Ref<OpenXRActionSet> p_action_set) {
ERR_FAIL_COND(p_action_set.is_null());
@@ -79,6 +106,27 @@ Array OpenXRActionMap::get_interaction_profiles() const {
return interaction_profiles;
}
+int OpenXRActionMap::get_interaction_profile_count() const {
+ return interaction_profiles.size();
+}
+
+Ref<OpenXRInteractionProfile> OpenXRActionMap::find_interaction_profile(String p_path) const {
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i];
+ if (interaction_profile->get_interaction_profile_path() == p_path) {
+ return interaction_profile;
+ }
+ }
+
+ return Ref<OpenXRInteractionProfile>();
+}
+
+Ref<OpenXRInteractionProfile> OpenXRActionMap::get_interaction_profile(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, interaction_profiles.size(), Ref<OpenXRInteractionProfile>());
+
+ return interaction_profiles[p_idx];
+}
+
void OpenXRActionMap::add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile) {
ERR_FAIL_COND(p_interaction_profile.is_null());
@@ -255,6 +303,69 @@ void OpenXRActionMap::create_editor_action_sets() {
// TODO implement
}
+Ref<OpenXRAction> OpenXRActionMap::get_action(const String p_path) const {
+ PackedStringArray paths = p_path.split("/", false);
+ ERR_FAIL_COND_V(paths.size() != 2, Ref<OpenXRAction>());
+
+ Ref<OpenXRActionSet> action_set = find_action_set(paths[0]);
+ if (action_set.is_valid()) {
+ return action_set->get_action(paths[1]);
+ }
+
+ return Ref<OpenXRAction>();
+}
+
+void OpenXRActionMap::remove_action(const String p_path) {
+ Ref<OpenXRAction> action = get_action(p_path);
+ if (action.is_valid()) {
+ OpenXRActionSet *action_set = action->get_action_set();
+ if (action_set != nullptr) {
+ // Remove the action from this action set
+ action_set->remove_action(action);
+ }
+
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ Ref<OpenXRInteractionProfile> interaction_profile = interaction_profiles[i];
+
+ // Remove any bindings for this action
+ interaction_profile->remove_binding_for_action(action);
+ }
+ }
+}
+
+PackedStringArray OpenXRActionMap::get_top_level_paths(Ref<OpenXRAction> p_action) {
+ PackedStringArray arr;
+
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ Ref<OpenXRInteractionProfile> ip = interaction_profiles[i];
+ const OpenXRDefs::InteractionProfile *profile = OpenXRDefs::get_profile(ip->get_interaction_profile_path());
+
+ if (profile != nullptr) {
+ for (int j = 0; j < ip->get_binding_count(); j++) {
+ Ref<OpenXRIPBinding> binding = ip->get_binding(j);
+ if (binding->get_action() == p_action) {
+ PackedStringArray paths = binding->get_paths();
+
+ for (int k = 0; k < paths.size(); k++) {
+ const OpenXRDefs::IOPath *io_path = profile->get_io_path(paths[k]);
+ if (io_path != nullptr) {
+ String top_path = String(io_path->top_level_path->openxr_path);
+
+ if (!arr.has(top_path)) {
+ arr.push_back(top_path);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ print_line("Toplevel paths for", p_action->get_name_with_set(), "are", arr);
+
+ return arr;
+}
+
OpenXRActionMap::~OpenXRActionMap() {
action_sets.clear();
interaction_profiles.clear();
diff --git a/modules/openxr/action_map/openxr_action_map.h b/modules/openxr/action_map/openxr_action_map.h
index 866e170468..dcd8fc71aa 100644
--- a/modules/openxr/action_map/openxr_action_map.h
+++ b/modules/openxr/action_map/openxr_action_map.h
@@ -33,6 +33,7 @@
#include "core/io/resource.h"
+#include "openxr_action.h"
#include "openxr_action_set.h"
#include "openxr_interaction_profile.h"
@@ -47,20 +48,33 @@ protected:
static void _bind_methods();
public:
- void set_action_sets(Array p_action_sets);
- Array get_action_sets() const;
+ void set_action_sets(Array p_action_sets); // Set our actions sets by providing an array with action sets (for loading from resource)
+ Array get_action_sets() const; // Get our action sets as an array (for saving to resource)
- void add_action_set(Ref<OpenXRActionSet> p_action_set);
- void remove_action_set(Ref<OpenXRActionSet> p_action_set);
+ int get_action_set_count() const; // Retrieve the number of action sets we have
+ Ref<OpenXRActionSet> find_action_set(String p_name) const; // Find an action set by name
+ Ref<OpenXRActionSet> get_action_set(int p_idx) const; // Retrieve an action set by index
+ void add_action_set(Ref<OpenXRActionSet> p_action_set); // Add an action set to our action map
+ void remove_action_set(Ref<OpenXRActionSet> p_action_set); // Remove an action set from our action map
- void set_interaction_profiles(Array p_interaction_profiles);
- Array get_interaction_profiles() const;
+ void set_interaction_profiles(Array p_interaction_profiles); // Set our interaction profiles by providing an array (for loading from resource)
+ Array get_interaction_profiles() const; // Get our interaction profiles as an array (for saving to resource)
- void add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile);
- void remove_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile);
+ int get_interaction_profile_count() const; // Retrieve the number of interaction profiles we have
+ Ref<OpenXRInteractionProfile> find_interaction_profile(String p_path) const; // Find an interaction profile by path
+ Ref<OpenXRInteractionProfile> get_interaction_profile(int p_idx) const; // Retrieve an interaction profile by index
+ void add_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile); // Add an interaction profile to our action map
+ void remove_interaction_profile(Ref<OpenXRInteractionProfile> p_interaction_profile); // remove an interaction profile from our action map
- void create_default_action_sets();
- void create_editor_action_sets();
+ void create_default_action_sets(); // Create our default action set for runtime
+ void create_editor_action_sets(); // Create our action set for the editor
+
+ // Helper functions for editor
+ Ref<OpenXRAction> get_action(const String p_path) const; // Retrieve an action using <action name>/<action> as our parameter
+ void remove_action(const String p_path); // Remove action from action set, also removes it from interaction profiles
+ PackedStringArray get_top_level_paths(Ref<OpenXRAction> p_action); // Determines the top level paths based on where an action is bound in interaction profiles
+
+ // TODO add validation to display in the interface that checks if we have action sets with the same name or if we have interaction profiles for the same path
~OpenXRActionMap();
};
diff --git a/modules/openxr/action_map/openxr_action_set.cpp b/modules/openxr/action_map/openxr_action_set.cpp
index 465a709b60..be45218300 100644
--- a/modules/openxr/action_map/openxr_action_set.cpp
+++ b/modules/openxr/action_map/openxr_action_set.cpp
@@ -39,6 +39,7 @@ void OpenXRActionSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_priority"), &OpenXRActionSet::get_priority);
ADD_PROPERTY(PropertyInfo(Variant::INT, "priority"), "set_priority", "get_priority");
+ ClassDB::bind_method(D_METHOD("get_action_count"), &OpenXRActionSet::get_action_count);
ClassDB::bind_method(D_METHOD("set_actions", "actions"), &OpenXRActionSet::set_actions);
ClassDB::bind_method(D_METHOD("get_actions"), &OpenXRActionSet::get_actions);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "actions", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRAction", PROPERTY_USAGE_NO_EDITOR), "set_actions", "get_actions");
@@ -75,18 +76,54 @@ int OpenXRActionSet::get_priority() const {
return priority;
}
+int OpenXRActionSet::get_action_count() const {
+ return actions.size();
+}
+
+void OpenXRActionSet::clear_actions() {
+ // Actions held within our action set should be released and destroyed but just in case they are still used some where else
+ for (int i = 0; i < actions.size(); i++) {
+ Ref<OpenXRAction> action = actions[i];
+ action->action_set = nullptr;
+ }
+ actions.clear();
+}
+
void OpenXRActionSet::set_actions(Array p_actions) {
- actions = p_actions;
+ // Any actions not retained in p_actions should be freed automatically, those held within our Array will have be relinked to our action set.
+ clear_actions();
+
+ for (int i = 0; i < p_actions.size(); i++) {
+ // add them anew so we verify our action_set pointer
+ add_action(p_actions[i]);
+ }
}
Array OpenXRActionSet::get_actions() const {
return actions;
}
+Ref<OpenXRAction> OpenXRActionSet::get_action(const String p_name) const {
+ for (int i = 0; i < actions.size(); i++) {
+ Ref<OpenXRAction> action = actions[i];
+ if (action->get_name() == p_name) {
+ return action;
+ }
+ }
+
+ return Ref<OpenXRAction>();
+}
+
void OpenXRActionSet::add_action(Ref<OpenXRAction> p_action) {
ERR_FAIL_COND(p_action.is_null());
if (actions.find(p_action) == -1) {
+ if (p_action->action_set && p_action->action_set != this) {
+ // action should only relate to our action set
+ p_action->action_set->remove_action(p_action);
+ }
+
+ p_action->action_set = this;
actions.push_back(p_action);
}
}
@@ -95,6 +132,9 @@ void OpenXRActionSet::remove_action(Ref<OpenXRAction> p_action) {
int idx = actions.find(p_action);
if (idx != -1) {
actions.remove_at(idx);
+
+ ERR_FAIL_COND_MSG(p_action->action_set != this, "Removing action that belongs to this action set but had incorrect action set pointer."); // this should never happen!
+ p_action->action_set = nullptr;
}
}
@@ -107,5 +147,5 @@ Ref<OpenXRAction> OpenXRActionSet::add_new_action(const char *p_name, const char
}
OpenXRActionSet::~OpenXRActionSet() {
- actions.clear();
+ clear_actions();
}
diff --git a/modules/openxr/action_map/openxr_action_set.h b/modules/openxr/action_map/openxr_action_set.h
index 012a088b1c..b1d7168894 100644
--- a/modules/openxr/action_map/openxr_action_set.h
+++ b/modules/openxr/action_map/openxr_action_set.h
@@ -43,26 +43,31 @@ private:
int priority = 0;
Array actions;
+ void clear_actions();
protected:
static void _bind_methods();
public:
- static Ref<OpenXRActionSet> new_action_set(const char *p_name, const char *p_localized_name, const int p_priority = 0);
+ static Ref<OpenXRActionSet> new_action_set(const char *p_name, const char *p_localized_name, const int p_priority = 0); // Helper function for adding and setting up an action set
- void set_localized_name(const String p_localized_name);
- String get_localized_name() const;
+ void set_localized_name(const String p_localized_name); // Set the localized name of this action set
+ String get_localized_name() const; // Get the localized name of this action set
- void set_priority(const int p_priority);
- int get_priority() const;
+ void set_priority(const int p_priority); // Set the priority of this action set
+ int get_priority() const; // Get the priority of this action set
- void set_actions(Array p_actions);
- Array get_actions() const;
+ int get_action_count() const; // Retrieve the number of actions in our action set
+ void set_actions(Array p_actions); // Set our actions using an array of actions (for loading a resource)
+ Array get_actions() const; // Get our actions as an array (for saving a resource)
- void add_action(Ref<OpenXRAction> p_action);
- void remove_action(Ref<OpenXRAction> p_action);
+ Ref<OpenXRAction> get_action(const String p_name) const; // Retrieve an action by name
+ void add_action(Ref<OpenXRAction> p_action); // Add a new action to our action set
+ void remove_action(Ref<OpenXRAction> p_action); // remove a action from our action set
- Ref<OpenXRAction> add_new_action(const char *p_name, const char *p_localized_name, const OpenXRAction::ActionType p_action_type, const char *p_toplevel_paths);
+ Ref<OpenXRAction> add_new_action(const char *p_name, const char *p_localized_name, const OpenXRAction::ActionType p_action_type, const char *p_toplevel_paths); // Helper function for adding and setting up an action
+
+ // TODO add validation to display in the interface that checks if we have duplicate action names within our action set
~OpenXRActionSet();
};
diff --git a/modules/openxr/action_map/openxr_defs.cpp b/modules/openxr/action_map/openxr_defs.cpp
new file mode 100644
index 0000000000..3358b03276
--- /dev/null
+++ b/modules/openxr/action_map/openxr_defs.cpp
@@ -0,0 +1,325 @@
+/*************************************************************************/
+/* openxr_defs.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_defs.h"
+
+// Our top level paths to which devices can be bound
+OpenXRDefs::TopLevelPath OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_TOP_LEVEL_PATH_MAX] = {
+ { "Left hand controller", "/user/hand/left" },
+ { "Right hand controller", "/user/hand/right" },
+};
+
+// Fallback Khronos simple controller
+OpenXRDefs::IOPath OpenXRDefs::simple_io_paths[] = {
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Select click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/select/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Select click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/select/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+};
+
+// Original HTC Vive wands
+OpenXRDefs::IOPath OpenXRDefs::vive_io_paths[] = {
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+};
+
+// Microsoft motion controller (original WMR controllers)
+OpenXRDefs::IOPath OpenXRDefs::motion_io_paths[] = {
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Squeeze click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Trackpad click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+};
+
+// HP MR controller (newer G2 controllers)
+OpenXRDefs::IOPath OpenXRDefs::hpmr_io_paths[] = {
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+};
+
+// Meta touch controller (original touch controllers, Quest 1 and Quest 2 controllers)
+OpenXRDefs::IOPath OpenXRDefs::touch_io_paths[] = {
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+
+ { "Menu click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/menu/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "X click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "X touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/x/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Y click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Y touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/y/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+};
+
+// Valve index controller
+OpenXRDefs::IOPath OpenXRDefs::index_io_paths[] = {
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Grip pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/grip/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+ { "Aim pose", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/aim/pose", OpenXRAction::OPENXR_ACTION_POSE },
+
+ { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "System click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/system/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "A click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "A touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/a/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "B click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "B touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/b/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trigger", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trigger click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trigger touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trigger/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Squeeze", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/value", OpenXRAction::OPENXR_ACTION_FLOAT },
+
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Thumbstick click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Thumbstick touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbstick/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Trackpad force", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/force", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Trackpad", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad", OpenXRAction::OPENXR_ACTION_VECTOR2 },
+ { "Trackpad force", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/force", OpenXRAction::OPENXR_ACTION_FLOAT },
+ { "Trackpad touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/trackpad/touch", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+ { "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
+};
+
+OpenXRDefs::InteractionProfile OpenXRDefs::available_interaction_profiles[] = {
+ {
+ "Simple controller", // display_name
+ "/interaction_profiles/khr/simple_controller", // openxr_path
+ simple_io_paths, // io_paths
+ sizeof(simple_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "HTC Vive wand", // display_name
+ "/interaction_profiles/htc/vive_controller", // openxr_path
+ vive_io_paths, // io_paths
+ sizeof(vive_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "MS Motion controller", // display_name
+ "/interaction_profiles/microsoft/motion_controller", // openxr_path
+ motion_io_paths, // io_paths
+ sizeof(motion_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "HPMR controller", // display_name
+ "/interaction_profiles/hp/mixed_reality_controller", // openxr_path
+ hpmr_io_paths, // io_paths
+ sizeof(hpmr_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "Touch controller", // display_name
+ "/interaction_profiles/oculus/touch_controller", // openxr_path
+ touch_io_paths, // io_paths
+ sizeof(touch_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "Index controller", // display_name
+ "/interaction_profiles/valve/index_controller", // openxr_path
+ index_io_paths, // io_paths
+ sizeof(index_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+};
+
+int OpenXRDefs::available_interaction_profile_count = sizeof(OpenXRDefs::available_interaction_profiles) / sizeof(OpenXRDefs::InteractionProfile);
+
+const OpenXRDefs::TopLevelPath *OpenXRDefs::get_top_level_path(const String p_top_level_path) {
+ for (int i = 0; i < OPENXR_TOP_LEVEL_PATH_MAX; i++) {
+ if (available_top_level_paths[i].openxr_path == p_top_level_path) {
+ return &OpenXRDefs::available_top_level_paths[i];
+ }
+ }
+
+ return nullptr;
+}
+
+const OpenXRDefs::InteractionProfile *OpenXRDefs::get_profile(const String p_interaction_profile_path) {
+ for (int i = 0; i < available_interaction_profile_count; i++) {
+ if (available_interaction_profiles[i].openxr_path == p_interaction_profile_path) {
+ return &available_interaction_profiles[i];
+ }
+ }
+
+ return nullptr;
+}
+
+const OpenXRDefs::IOPath *OpenXRDefs::InteractionProfile::get_io_path(const String p_io_path) const {
+ for (int i = 0; i < available_interaction_profiles[i].io_path_count; i++) {
+ if (io_paths[i].openxr_path == p_io_path) {
+ return &io_paths[i];
+ }
+ }
+
+ return nullptr;
+}
+
+const OpenXRDefs::IOPath *OpenXRDefs::get_io_path(const String p_interaction_profile_path, const String p_io_path) {
+ const OpenXRDefs::InteractionProfile *profile = OpenXRDefs::get_profile(p_interaction_profile_path);
+ if (profile != nullptr) {
+ return profile->get_io_path(p_io_path);
+ }
+
+ return nullptr;
+}
+
+PackedStringArray OpenXRDefs::get_interaction_profile_paths() {
+ PackedStringArray arr;
+
+ for (int i = 0; i < available_interaction_profile_count; i++) {
+ arr.push_back(available_interaction_profiles[i].openxr_path);
+ }
+
+ return arr;
+}
diff --git a/modules/openxr/action_map/openxr_defs.h b/modules/openxr/action_map/openxr_defs.h
new file mode 100644
index 0000000000..aa3b2a8f8a
--- /dev/null
+++ b/modules/openxr/action_map/openxr_defs.h
@@ -0,0 +1,99 @@
+/*************************************************************************/
+/* openxr_defs.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_DEFS_H
+#define OPENXR_DEFS_H
+
+#include "openxr_action.h"
+
+///////////////////////////////////////////////////////////////////////////
+// Stores available interaction profiles
+//
+// OpenXR defines and hardcodes all the supported input devices and their
+// paths as part of the OpenXR spec. When support for new devices is
+// introduced this often starts life as extensions that need to be enabled
+// until they are adopted into the core. As there is no interface to
+// enumerate the possibly paths, and that any OpenXR runtime would likely
+// limit such enumeration to those input devices supported by that runtime
+// there is no other option than to hardcode this.
+//
+// Note on action type that automatic conversions between boolean and float
+// are supported but otherwise action types should match between action and
+// input/output paths.
+
+class OpenXRDefs {
+public:
+ enum TOP_LEVEL_PATH {
+ OPENXR_LEFT_HAND,
+ OPENXR_RIGHT_HAND,
+ OPENXR_TOP_LEVEL_PATH_MAX
+ };
+
+ struct TopLevelPath {
+ const char *display_name; // User friendly display name (i.e. Left controller)
+ const char *openxr_path; // Path in OpenXR (i.e. /user/hand/left)
+ };
+
+ struct IOPath {
+ const char *display_name; // User friendly display name (i.e. Grip pose (left controller))
+ const TopLevelPath *top_level_path; // Top level path identifying the usage of the device in relation to this input/output
+ const char *openxr_path; // Path in OpenXR (i.e. /user/hand/left/input/grip/pose)
+ const OpenXRAction::ActionType action_type; // Type of input/output
+ };
+
+ struct InteractionProfile {
+ const char *display_name; // User friendly display name (i.e. Simple controller)
+ const char *openxr_path; // Path in OpenXR (i.e. /interaction_profiles/khr/simple_controller)
+ const IOPath *io_paths; // Inputs and outputs for this device
+ const int io_path_count; // Number of inputs and outputs for this device
+
+ const IOPath *get_io_path(const String p_io_path) const;
+ };
+
+private:
+ static TopLevelPath available_top_level_paths[OPENXR_TOP_LEVEL_PATH_MAX];
+ static IOPath simple_io_paths[];
+ static IOPath vive_io_paths[];
+ static IOPath motion_io_paths[];
+ static IOPath hpmr_io_paths[];
+ static IOPath touch_io_paths[];
+ static IOPath index_io_paths[];
+ static InteractionProfile available_interaction_profiles[];
+ static int available_interaction_profile_count;
+
+public:
+ static const TopLevelPath *get_top_level_path(const String p_top_level_path);
+ static const InteractionProfile *get_profile(const String p_interaction_profile_path);
+ static const IOPath *get_io_path(const String p_interaction_profile_path, const String p_io_path);
+
+ static PackedStringArray get_interaction_profile_paths();
+};
+
+#endif // !OPENXR_DEFS_H
diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp
index bc33814f17..342c36cdff 100644
--- a/modules/openxr/action_map/openxr_interaction_profile.cpp
+++ b/modules/openxr/action_map/openxr_interaction_profile.cpp
@@ -35,9 +35,14 @@ void OpenXRIPBinding::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_action"), &OpenXRIPBinding::get_action);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "action", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRAction"), "set_action", "get_action");
+ ClassDB::bind_method(D_METHOD("get_path_count"), &OpenXRIPBinding::get_path_count);
ClassDB::bind_method(D_METHOD("set_paths", "paths"), &OpenXRIPBinding::set_paths);
ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "paths", PROPERTY_HINT_ARRAY_TYPE, "STRING"), "set_paths", "get_paths");
+
+ ClassDB::bind_method(D_METHOD("has_path"), &OpenXRIPBinding::has_path);
+ ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path);
+ ClassDB::bind_method(D_METHOD("remove_path", "path"), &OpenXRIPBinding::remove_path);
}
Ref<OpenXRIPBinding> OpenXRIPBinding::new_binding(const Ref<OpenXRAction> p_action, const char *p_paths) {
@@ -59,6 +64,10 @@ Ref<OpenXRAction> OpenXRIPBinding::get_action() const {
return action;
}
+int OpenXRIPBinding::get_path_count() const {
+ return paths.size();
+}
+
void OpenXRIPBinding::set_paths(const PackedStringArray p_paths) {
paths = p_paths;
}
@@ -71,6 +80,22 @@ void OpenXRIPBinding::parse_paths(const String p_paths) {
paths = p_paths.split(",", false);
}
+bool OpenXRIPBinding::has_path(const String p_path) const {
+ return paths.has(p_path);
+}
+
+void OpenXRIPBinding::add_path(const String p_path) {
+ if (!paths.has(p_path)) {
+ paths.push_back(p_path);
+ }
+}
+
+void OpenXRIPBinding::remove_path(const String p_path) {
+ if (paths.has(p_path)) {
+ paths.erase(p_path);
+ }
+}
+
OpenXRIPBinding::~OpenXRIPBinding() {
action.unref();
}
@@ -80,6 +105,8 @@ void OpenXRInteractionProfile::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_interaction_profile_path"), &OpenXRInteractionProfile::get_interaction_profile_path);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "interaction_profile_path"), "set_interaction_profile_path", "get_interaction_profile_path");
+ ClassDB::bind_method(D_METHOD("get_binding_count"), &OpenXRInteractionProfile::get_binding_count);
+ ClassDB::bind_method(D_METHOD("get_binding", "index"), &OpenXRInteractionProfile::get_binding);
ClassDB::bind_method(D_METHOD("set_bindings", "bindings"), &OpenXRInteractionProfile::set_bindings);
ClassDB::bind_method(D_METHOD("get_bindings"), &OpenXRInteractionProfile::get_bindings);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "bindings", PROPERTY_HINT_RESOURCE_TYPE, "OpenXRIPBinding", PROPERTY_USAGE_NO_EDITOR), "set_bindings", "get_bindings");
@@ -101,18 +128,43 @@ String OpenXRInteractionProfile::get_interaction_profile_path() const {
return interaction_profile_path;
}
+int OpenXRInteractionProfile::get_binding_count() const {
+ return bindings.size();
+}
+
+Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, bindings.size(), Ref<OpenXRIPBinding>());
+
+ return bindings[p_index];
+}
+
void OpenXRInteractionProfile::set_bindings(Array p_bindings) {
bindings = p_bindings;
+
+ // TODO add check here that our bindings don't contain duplicate actions
}
Array OpenXRInteractionProfile::get_bindings() const {
return bindings;
}
+Ref<OpenXRIPBinding> OpenXRInteractionProfile::get_binding_for_action(const Ref<OpenXRAction> p_action) const {
+ for (int i = 0; i < bindings.size(); i++) {
+ Ref<OpenXRIPBinding> binding = bindings[i];
+ if (binding->get_action() == p_action) {
+ return binding;
+ }
+ }
+
+ return Ref<OpenXRIPBinding>();
+}
+
void OpenXRInteractionProfile::add_binding(Ref<OpenXRIPBinding> p_binding) {
ERR_FAIL_COND(p_binding.is_null());
if (bindings.find(p_binding) == -1) {
+ ERR_FAIL_COND_MSG(get_binding_for_action(p_binding->get_action()).is_valid(), "There is already a binding for this action in this interaction profile");
+
bindings.push_back(p_binding);
}
}
@@ -131,6 +183,15 @@ void OpenXRInteractionProfile::add_new_binding(const Ref<OpenXRAction> p_action,
add_binding(binding);
}
+void OpenXRInteractionProfile::remove_binding_for_action(const Ref<OpenXRAction> p_action) {
+ for (int i = bindings.size() - 1; i >= 0; i--) {
+ Ref<OpenXRIPBinding> binding = bindings[i];
+ if (binding->get_action() == p_action) {
+ remove_binding(binding);
+ }
+ }
+}
+
OpenXRInteractionProfile::~OpenXRInteractionProfile() {
bindings.clear();
}
diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h
index abbc429e7d..46b1bda50f 100644
--- a/modules/openxr/action_map/openxr_interaction_profile.h
+++ b/modules/openxr/action_map/openxr_interaction_profile.h
@@ -34,6 +34,7 @@
#include "core/io/resource.h"
#include "openxr_action.h"
+#include "openxr_defs.h"
class OpenXRIPBinding : public Resource {
GDCLASS(OpenXRIPBinding, Resource);
@@ -46,15 +47,22 @@ protected:
static void _bind_methods();
public:
- static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const char *p_paths);
+ static Ref<OpenXRIPBinding> new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Helper function for adding a new binding
- void set_action(const Ref<OpenXRAction> p_action);
- Ref<OpenXRAction> get_action() const;
+ void set_action(const Ref<OpenXRAction> p_action); // Set the action for this binding
+ Ref<OpenXRAction> get_action() const; // Get the action for this binding
- void set_paths(const PackedStringArray p_paths);
- PackedStringArray get_paths() const;
+ int get_path_count() const; // Get the number of io paths
+ void set_paths(const PackedStringArray p_paths); // Set our paths (for loading from resource)
+ PackedStringArray get_paths() const; // Get our paths (for saving to resource)
- void parse_paths(const String p_paths);
+ void parse_paths(const String p_paths); // Parse a comma separated string of io paths.
+
+ bool has_path(const String p_path) const; // Has this io path
+ void add_path(const String p_path); // Add an io path
+ void remove_path(const String p_path); // Remove an io path
+
+ // TODO add validation that we can display in the interface that checks if no two paths belong to the same top level path
~OpenXRIPBinding();
};
@@ -70,18 +78,22 @@ protected:
static void _bind_methods();
public:
- static Ref<OpenXRInteractionProfile> new_profile(const char *p_input_profile_path);
+ static Ref<OpenXRInteractionProfile> new_profile(const char *p_input_profile_path); // Helper function to create a new interaction profile
- void set_interaction_profile_path(const String p_input_profile_path);
- String get_interaction_profile_path() const;
+ void set_interaction_profile_path(const String p_input_profile_path); // Set our input profile path
+ String get_interaction_profile_path() const; // get our input profile path
- void set_bindings(Array p_bindings);
- Array get_bindings() const;
+ int get_binding_count() const; // Retrieve the number of bindings in this profile path
+ Ref<OpenXRIPBinding> get_binding(int p_index) const;
+ void set_bindings(Array p_bindings); // Set the bindings (for loading from a resource)
+ Array get_bindings() const; // Get the bindings (for saving to a resource)
- void add_binding(Ref<OpenXRIPBinding> p_binding);
- void remove_binding(Ref<OpenXRIPBinding> p_binding);
+ Ref<OpenXRIPBinding> get_binding_for_action(const Ref<OpenXRAction> p_action) const; // Get our binding record for a given action
+ void add_binding(Ref<OpenXRIPBinding> p_binding); // Add a binding object
+ void remove_binding(Ref<OpenXRIPBinding> p_binding); // Remove a binding object
- void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths);
+ void add_new_binding(const Ref<OpenXRAction> p_action, const char *p_paths); // Create a new binding for this profile
+ void remove_binding_for_action(const Ref<OpenXRAction> p_action); // Remove all bindings for this action
~OpenXRInteractionProfile();
};
diff --git a/modules/openxr/doc_classes/OpenXRActionMap.xml b/modules/openxr/doc_classes/OpenXRActionMap.xml
index 4dd2b83ca7..a29d10be41 100644
--- a/modules/openxr/doc_classes/OpenXRActionMap.xml
+++ b/modules/openxr/doc_classes/OpenXRActionMap.xml
@@ -31,6 +31,46 @@
Setup this action set with our default actions.
</description>
</method>
+ <method name="find_action_set" qualifiers="const">
+ <return type="OpenXRActionSet" />
+ <argument index="0" name="name" type="String" />
+ <description>
+ Retrieve an action set by name.
+ </description>
+ </method>
+ <method name="find_interaction_profile" qualifiers="const">
+ <return type="OpenXRInteractionProfile" />
+ <argument index="0" name="name" type="String" />
+ <description>
+ Find an interaction profile by its name (path).
+ </description>
+ </method>
+ <method name="get_action_set" qualifiers="const">
+ <return type="OpenXRActionSet" />
+ <argument index="0" name="idx" type="int" />
+ <description>
+ Retrieve the action set at this index.
+ </description>
+ </method>
+ <method name="get_action_set_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Retrieve the number of actions sets in our action map.
+ </description>
+ </method>
+ <method name="get_interaction_profile" qualifiers="const">
+ <return type="OpenXRInteractionProfile" />
+ <argument index="0" name="idx" type="int" />
+ <description>
+ Get the interaction profile at this index.
+ </description>
+ </method>
+ <method name="get_interaction_profile_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Retrieve the number of interaction profiles in our action map.
+ </description>
+ </method>
<method name="remove_action_set">
<return type="void" />
<argument index="0" name="action_set" type="OpenXRActionSet" />
@@ -48,8 +88,10 @@
</methods>
<members>
<member name="action_sets" type="Array" setter="set_action_sets" getter="get_action_sets" default="[]">
+ Collection of [OpenXRActionSet]s that are part of this action map.
</member>
<member name="interaction_profiles" type="Array" setter="set_interaction_profiles" getter="get_interaction_profiles" default="[]">
+ Collection of [OpenXRInteractionProfile]s that are part of this action map.
</member>
</members>
</class>
diff --git a/modules/openxr/doc_classes/OpenXRActionSet.xml b/modules/openxr/doc_classes/OpenXRActionSet.xml
index 5a87de463e..55cc0aaad4 100644
--- a/modules/openxr/doc_classes/OpenXRActionSet.xml
+++ b/modules/openxr/doc_classes/OpenXRActionSet.xml
@@ -5,8 +5,7 @@
</brief_description>
<description>
Action sets in OpenXR define a collection of actions that can be activated in unison. This allows games to easily change between different states that require different inputs or need to reinterpret inputs. For instance we could have an action set that is active when a menu is open, an action set that is active when the player is freely walking around and an action set that is active when the player is controlling a vehicle.
- Action sets can contain the same actions, or actions with the same name, if such action sets are active at the same time the action set with the highest priority defines which binding is active.
- Note that the name of the resource is used to identify the action set within OpenXR.
+ Action sets can contain the same action with the same name, if such action sets are active at the same time the action set with the highest priority defines which binding is active.
</description>
<tutorials>
</tutorials>
@@ -18,6 +17,12 @@
Add an action to this action set.
</description>
</method>
+ <method name="get_action_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Retrieve the number of actions in our action set.
+ </description>
+ </method>
<method name="remove_action">
<return type="void" />
<argument index="0" name="action" type="OpenXRAction" />
diff --git a/modules/openxr/doc_classes/OpenXRIPBinding.xml b/modules/openxr/doc_classes/OpenXRIPBinding.xml
index 3fdcde5eb5..9e1176874a 100644
--- a/modules/openxr/doc_classes/OpenXRIPBinding.xml
+++ b/modules/openxr/doc_classes/OpenXRIPBinding.xml
@@ -4,13 +4,42 @@
Defines a binding between an [OpenXRAction] and an XR input or output.
</brief_description>
<description>
- This binding resource binds an OpenXR action to inputs or outputs. As most controllers have left hand and right versions that are handled by the same interaction profile we can specify multiple bindings. For instance an action "Fire" could be bound to both "/user/hand/left/input/trigger" and "/user/hand/right/input/trigger".
+ This binding resource binds an [OpenXRAction] to inputs or outputs. As most controllers have left hand and right versions that are handled by the same interaction profile we can specify multiple bindings. For instance an action "Fire" could be bound to both "/user/hand/left/input/trigger" and "/user/hand/right/input/trigger".
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="add_path">
+ <return type="void" />
+ <argument index="0" name="path" type="String" />
+ <description>
+ Add an input/output path to this binding.
+ </description>
+ </method>
+ <method name="get_path_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Get the number of input/output paths in this binding.
+ </description>
+ </method>
+ <method name="has_path" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="arg0" type="String" />
+ <description>
+ Returns [code]true[/code] if this input/output path is part of this binding.
+ </description>
+ </method>
+ <method name="remove_path">
+ <return type="void" />
+ <argument index="0" name="path" type="String" />
+ <description>
+ Removes this input/output path from this binding.
+ </description>
+ </method>
+ </methods>
<members>
<member name="action" type="OpenXRAction" setter="set_action" getter="get_action">
- Action that is bound to these paths.
+ [OpenXRAction] that is bound to these paths.
</member>
<member name="paths" type="PackedStringArray" setter="set_paths" getter="get_paths" default="PackedStringArray()">
Paths that define the inputs or outputs bound on the device.
diff --git a/modules/openxr/doc_classes/OpenXRInteractionProfile.xml b/modules/openxr/doc_classes/OpenXRInteractionProfile.xml
index a8629caae4..71c0db44ed 100644
--- a/modules/openxr/doc_classes/OpenXRInteractionProfile.xml
+++ b/modules/openxr/doc_classes/OpenXRInteractionProfile.xml
@@ -9,6 +9,21 @@
</description>
<tutorials>
</tutorials>
+ <methods>
+ <method name="get_binding" qualifiers="const">
+ <return type="OpenXRIPBinding" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Retrieve the binding at this index.
+ </description>
+ </method>
+ <method name="get_binding_count" qualifiers="const">
+ <return type="int" />
+ <description>
+ Get the number of bindings in this interaction profile.
+ </description>
+ </method>
+ </methods>
<members>
<member name="bindings" type="Array" setter="set_bindings" getter="get_bindings" default="[]">
Action bindings for this interaction profile.
diff --git a/modules/openxr/editor/SCsub b/modules/openxr/editor/SCsub
new file mode 100644
index 0000000000..ccf67a80d0
--- /dev/null
+++ b/modules/openxr/editor/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.modules_sources, "*.cpp")
diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp
new file mode 100644
index 0000000000..e2a4f67f16
--- /dev/null
+++ b/modules/openxr/editor/openxr_action_editor.cpp
@@ -0,0 +1,112 @@
+/*************************************************************************/
+/* openxr_action_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_action_editor.h"
+
+void OpenXRActionEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_editor")));
+}
+
+void OpenXRActionEditor::_theme_changed() {
+ rem_action->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+}
+
+void OpenXRActionEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ _theme_changed();
+ } break;
+ }
+}
+
+void OpenXRActionEditor::_on_action_name_changed(const String p_new_text) {
+ // TODO validate if entry is allowed
+
+ // If our localized name matches our action name, set this too
+ if (action->get_name() == action->get_localized_name()) {
+ action->set_localized_name(p_new_text);
+ action_localized_name->set_text(p_new_text);
+ }
+ action->set_name(p_new_text);
+}
+
+void OpenXRActionEditor::_on_action_localized_name_changed(const String p_new_text) {
+ action->set_localized_name(p_new_text);
+}
+
+void OpenXRActionEditor::_on_item_selected(int p_idx) {
+ ERR_FAIL_COND(p_idx < 0);
+ ERR_FAIL_COND(p_idx >= OpenXRAction::OPENXR_ACTION_MAX);
+
+ action->set_action_type(OpenXRAction::ActionType(p_idx));
+}
+
+void OpenXRActionEditor::_on_remove_action() {
+ emit_signal("remove", this);
+}
+
+OpenXRActionEditor::OpenXRActionEditor(Ref<OpenXRAction> p_action) {
+ action = p_action;
+
+ set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ action_name = memnew(LineEdit);
+ action_name->set_text(action->get_name());
+ action_name->set_custom_minimum_size(Size2(150.0, 0.0));
+ action_name->connect("text_changed", callable_mp(this, &OpenXRActionEditor::_on_action_name_changed));
+ add_child(action_name);
+
+ action_localized_name = memnew(LineEdit);
+ action_localized_name->set_text(action->get_localized_name());
+ action_localized_name->set_custom_minimum_size(Size2(150.0, 0.0));
+ action_localized_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ action_localized_name->connect("text_changed", callable_mp(this, &OpenXRActionEditor::_on_action_localized_name_changed));
+ add_child(action_localized_name);
+
+ action_type = memnew(OptionButton);
+ action_type->add_item("Bool", OpenXRAction::OPENXR_ACTION_BOOL);
+ action_type->add_item("Float", OpenXRAction::OPENXR_ACTION_FLOAT);
+ action_type->add_item("Vector2", OpenXRAction::OPENXR_ACTION_VECTOR2);
+ action_type->add_item("Pose", OpenXRAction::OPENXR_ACTION_POSE);
+ action_type->add_item("Haptic", OpenXRAction::OPENXR_ACTION_HAPTIC);
+ action_type->select(int(action->get_action_type()));
+ action_type->set_custom_minimum_size(Size2(100.0, 0.0));
+ action_type->connect("item_selected", callable_mp(this, &OpenXRActionEditor::_on_item_selected));
+ add_child(action_type);
+
+ // maybe add dropdown to edit our toplevel paths, or do we deduce them from our suggested bindings?
+
+ rem_action = memnew(Button);
+ rem_action->set_tooltip(TTR("Remove action"));
+ rem_action->connect("pressed", callable_mp(this, &OpenXRActionEditor::_on_remove_action));
+ rem_action->set_flat(true);
+ add_child(rem_action);
+}
diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h
new file mode 100644
index 0000000000..6e1b7ab779
--- /dev/null
+++ b/modules/openxr/editor/openxr_action_editor.h
@@ -0,0 +1,67 @@
+/*************************************************************************/
+/* openxr_action_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_ACTION_EDITOR_H
+#define OPENXR_ACTION_EDITOR_H
+
+#include "../action_map/openxr_action.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/option_button.h"
+#include "scene/gui/text_edit.h"
+
+class OpenXRActionEditor : public HBoxContainer {
+ GDCLASS(OpenXRActionEditor, HBoxContainer);
+
+private:
+ Ref<OpenXRAction> action;
+
+ LineEdit *action_name = nullptr;
+ LineEdit *action_localized_name = nullptr;
+ OptionButton *action_type = nullptr;
+ Button *rem_action = nullptr;
+
+ void _theme_changed();
+ void _on_action_name_changed(const String p_new_text);
+ void _on_action_localized_name_changed(const String p_new_text);
+ void _on_item_selected(int p_idx);
+ void _on_remove_action();
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ Ref<OpenXRAction> get_action() { return action; };
+ OpenXRActionEditor(Ref<OpenXRAction> p_action);
+};
+
+#endif // !OPENXR_ACTION_EDITOR_H
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
new file mode 100644
index 0000000000..6e9a2e1b61
--- /dev/null
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -0,0 +1,370 @@
+/*************************************************************************/
+/* openxr_action_map_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_action_map_editor.h"
+
+#include "core/config/project_settings.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+
+// TODO implement redo/undo system
+
+void OpenXRActionMapEditor::_bind_methods() {
+ ClassDB::bind_method("_add_action_set_editor", &OpenXRActionMapEditor::_add_action_set_editor);
+ ClassDB::bind_method("_update_action_sets", &OpenXRActionMapEditor::_update_action_sets);
+
+ ClassDB::bind_method("_add_interaction_profile_editor", &OpenXRActionMapEditor::_add_interaction_profile_editor);
+ ClassDB::bind_method("_update_interaction_profiles", &OpenXRActionMapEditor::_update_interaction_profiles);
+
+ ClassDB::bind_method(D_METHOD("_add_action_set", "name"), &OpenXRActionMapEditor::_add_action_set);
+ ClassDB::bind_method(D_METHOD("_set_focus_on_action_set", "action_set"), &OpenXRActionMapEditor::_set_focus_on_action_set);
+ ClassDB::bind_method(D_METHOD("_remove_action_set", "name"), &OpenXRActionMapEditor::_remove_action_set);
+}
+
+void OpenXRActionMapEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ for (int i = 0; i < tabs->get_child_count(); i++) {
+ Control *tab = static_cast<Control *>(tabs->get_child(i));
+ if (tab) {
+ tab->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ }
+ }
+ } break;
+
+ case NOTIFICATION_READY: {
+ _update_action_sets();
+ _update_interaction_profiles();
+ } break;
+ }
+}
+
+OpenXRActionSetEditor *OpenXRActionMapEditor::_add_action_set_editor(Ref<OpenXRActionSet> p_action_set) {
+ ERR_FAIL_COND_V(p_action_set.is_null(), nullptr);
+
+ OpenXRActionSetEditor *action_set_editor = memnew(OpenXRActionSetEditor(action_map, p_action_set));
+ action_set_editor->connect("remove", callable_mp(this, &OpenXRActionMapEditor::_on_remove_action_set));
+ action_set_editor->connect("action_removed", callable_mp(this, &OpenXRActionMapEditor::_on_action_removed));
+ actionsets_vb->add_child(action_set_editor);
+
+ return action_set_editor;
+}
+
+void OpenXRActionMapEditor::_update_action_sets() {
+ // out with the old...
+ while (actionsets_vb->get_child_count() > 0) {
+ memdelete(actionsets_vb->get_child(0));
+ }
+
+ // in with the new...
+ if (action_map.is_valid()) {
+ Array action_sets = action_map->get_action_sets();
+ for (int i = 0; i < action_sets.size(); i++) {
+ Ref<OpenXRActionSet> action_set = action_sets[i];
+ _add_action_set_editor(action_set);
+ }
+ }
+}
+
+OpenXRInteractionProfileEditorBase *OpenXRActionMapEditor::_add_interaction_profile_editor(Ref<OpenXRInteractionProfile> p_interaction_profile) {
+ ERR_FAIL_COND_V(p_interaction_profile.is_null(), nullptr);
+
+ String profile_path = p_interaction_profile->get_interaction_profile_path();
+
+ // need to instance the correct editor for our profile
+ OpenXRInteractionProfileEditorBase *new_profile_editor = nullptr;
+ if (profile_path == "placeholder_text") {
+ // instance specific editor for this type
+ } else {
+ // instance generic editor
+ new_profile_editor = memnew(OpenXRInteractionProfileEditor(action_map, p_interaction_profile));
+ }
+
+ // now add it in..
+ ERR_FAIL_NULL_V(new_profile_editor, nullptr);
+ tabs->add_child(new_profile_editor);
+ new_profile_editor->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ tabs->set_tab_button_icon(tabs->get_tab_count() - 1, get_theme_icon(SNAME("close"), SNAME("TabBar")));
+
+ interaction_profiles.push_back(new_profile_editor);
+
+ return new_profile_editor;
+}
+
+void OpenXRActionMapEditor::_update_interaction_profiles() {
+ // out with the old...
+ while (interaction_profiles.size() > 0) {
+ Node *interaction_profile = interaction_profiles[0];
+ interaction_profiles.remove_at(0);
+
+ tabs->remove_child(interaction_profile);
+ interaction_profile->queue_delete();
+ }
+
+ // in with the new...
+ if (action_map.is_valid()) {
+ Array new_interaction_profiles = action_map->get_interaction_profiles();
+ for (int i = 0; i < new_interaction_profiles.size(); i++) {
+ Ref<OpenXRInteractionProfile> interaction_profile = new_interaction_profiles[i];
+ _add_interaction_profile_editor(interaction_profile);
+ }
+ }
+}
+
+OpenXRActionSetEditor *OpenXRActionMapEditor::_add_action_set(String p_name) {
+ ERR_FAIL_COND_V(action_map.is_null(), nullptr);
+ Ref<OpenXRActionSet> new_action_set;
+
+ // add our new action set
+ new_action_set.instantiate();
+ new_action_set->set_name(p_name);
+ new_action_set->set_localized_name(p_name);
+ action_map->add_action_set(new_action_set);
+
+ // update our editor right away
+ return _add_action_set_editor(new_action_set);
+}
+
+void OpenXRActionMapEditor::_remove_action_set(String p_name) {
+ ERR_FAIL_COND(action_map.is_null());
+ Ref<OpenXRActionSet> action_set = action_map->find_action_set(p_name);
+ ERR_FAIL_COND(action_set.is_null());
+
+ if (action_set->get_action_count() > 0) {
+ // we should remove these and add to our redo/undo step before calling _remove_action_set
+ WARN_PRINT("Action set still has associated actions before being removed!");
+ }
+
+ // now we remove it
+ action_map->remove_action_set(action_set);
+}
+
+void OpenXRActionMapEditor::_on_add_action_set() {
+ ERR_FAIL_COND(action_map.is_null());
+ String new_name = "New";
+ int count = 0;
+
+ while (action_map->find_action_set(new_name).is_valid()) {
+ new_name = "New_" + itos(count++);
+ }
+
+ OpenXRActionSetEditor *new_action_set_editor = _add_action_set(new_name);
+
+ // Make sure our action set is the current tab
+ tabs->set_current_tab(0);
+
+ call_deferred("_set_focus_on_action_set", new_action_set_editor);
+}
+
+void OpenXRActionMapEditor::_set_focus_on_action_set(OpenXRActionSetEditor *p_action_set_editor) {
+ // Scroll down to our new entry
+ actionsets_scroll->ensure_control_visible(p_action_set_editor);
+
+ // Set focus on this entry
+ p_action_set_editor->set_focus_on_entry();
+}
+
+void OpenXRActionMapEditor::_on_remove_action_set(Object *p_action_set_editor) {
+ ERR_FAIL_COND(action_map.is_null());
+
+ OpenXRActionSetEditor *action_set_editor = Object::cast_to<OpenXRActionSetEditor>(p_action_set_editor);
+ ERR_FAIL_NULL(action_set_editor);
+ ERR_FAIL_COND(action_set_editor->get_parent() != actionsets_vb);
+ Ref<OpenXRActionSet> action_set = action_set_editor->get_action_set();
+ ERR_FAIL_COND(action_set.is_null());
+
+ action_map->remove_action_set(action_set);
+ actionsets_vb->remove_child(action_set_editor);
+ action_set_editor->queue_delete();
+}
+
+void OpenXRActionMapEditor::_on_action_removed() {
+ // make sure our interaction profiles are updated
+ _update_interaction_profiles();
+}
+
+void OpenXRActionMapEditor::_on_add_interaction_profile() {
+ ERR_FAIL_COND(action_map.is_null());
+
+ PackedStringArray already_selected;
+
+ for (int i = 0; i < action_map->get_interaction_profile_count(); i++) {
+ already_selected.push_back(action_map->get_interaction_profile(i)->get_interaction_profile_path());
+ }
+
+ select_interaction_profile_dialog->open(already_selected);
+}
+
+void OpenXRActionMapEditor::_on_interaction_profile_selected(const String p_path) {
+ ERR_FAIL_COND(action_map.is_null());
+
+ Ref<OpenXRInteractionProfile> new_profile;
+ new_profile.instantiate();
+ new_profile->set_interaction_profile_path(p_path);
+ action_map->add_interaction_profile(new_profile);
+
+ _add_interaction_profile_editor(new_profile);
+
+ tabs->set_current_tab(tabs->get_tab_count() - 1);
+}
+
+void OpenXRActionMapEditor::_load_action_map(const String p_path, bool p_create_new_if_missing) {
+ action_map = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE);
+ if (action_map.is_null()) {
+ if (p_create_new_if_missing) {
+ action_map.instantiate();
+ action_map->create_default_action_sets();
+ } else {
+ EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an OpenXR action map."));
+
+ edited_path = "";
+ header_label->set_text("");
+ return;
+ }
+ }
+
+ edited_path = p_path;
+ header_label->set_text(TTR("OpenXR Action map:") + " " + p_path.get_file());
+}
+
+void OpenXRActionMapEditor::_on_save_action_map() {
+ Error err = ResourceSaver::save(edited_path, action_map);
+ if (err != OK) {
+ EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), edited_path));
+ return;
+ }
+
+ _update_action_sets();
+ _update_interaction_profiles();
+}
+
+void OpenXRActionMapEditor::_on_reset_to_default_layout() {
+ // create a new one
+ action_map.unref();
+ action_map.instantiate();
+ action_map->create_default_action_sets();
+
+ _update_action_sets();
+ _update_interaction_profiles();
+}
+
+void OpenXRActionMapEditor::_on_tabs_tab_changed(int p_tab) {
+}
+
+void OpenXRActionMapEditor::_on_tab_button_pressed(int p_tab) {
+ OpenXRInteractionProfileEditorBase *profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(p_tab));
+ ERR_FAIL_NULL(profile_editor);
+
+ Ref<OpenXRInteractionProfile> interaction_profile = profile_editor->get_interaction_profile();
+ ERR_FAIL_COND(interaction_profile.is_null());
+
+ action_map->remove_interaction_profile(interaction_profile);
+ tabs->remove_child(profile_editor);
+ profile_editor->queue_delete();
+}
+
+void OpenXRActionMapEditor::open_action_map(String p_path) {
+ EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+
+ _load_action_map(p_path);
+
+ _update_action_sets();
+ _update_interaction_profiles();
+}
+
+OpenXRActionMapEditor::OpenXRActionMapEditor() {
+ set_custom_minimum_size(Size2(0.0, 300.0));
+
+ top_hb = memnew(HBoxContainer);
+ add_child(top_hb);
+
+ header_label = memnew(Label);
+ header_label->set_text(String(TTR("Action Map")));
+ header_label->set_clip_text(true);
+ header_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ top_hb->add_child(header_label);
+
+ add_action_set = memnew(Button);
+ add_action_set->set_text(TTR("Add Action Set"));
+ add_action_set->set_tooltip(TTR("Add an action set."));
+ add_action_set->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_add_action_set));
+ top_hb->add_child(add_action_set);
+
+ add_interaction_profile = memnew(Button);
+ add_interaction_profile->set_text(TTR("Add profile"));
+ add_interaction_profile->set_tooltip(TTR("Add an interaction profile."));
+ add_interaction_profile->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_add_interaction_profile));
+ top_hb->add_child(add_interaction_profile);
+
+ VSeparator *vseparator = memnew(VSeparator);
+ top_hb->add_child(vseparator);
+
+ save_as = memnew(Button);
+ save_as->set_text(TTR("Save"));
+ save_as->set_tooltip(TTR("Save this OpenXR action map."));
+ save_as->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_save_action_map));
+ top_hb->add_child(save_as);
+
+ _default = memnew(Button);
+ _default->set_text(TTR("Reset to Default"));
+ _default->set_tooltip(TTR("Reset to default OpenXR action map."));
+ _default->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_reset_to_default_layout));
+ top_hb->add_child(_default);
+
+ tabs = memnew(TabContainer);
+ tabs->set_h_size_flags(SIZE_EXPAND_FILL);
+ tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ tabs->connect("tab_changed", callable_mp(this, &OpenXRActionMapEditor::_on_tabs_tab_changed));
+ tabs->connect("tab_button_pressed", callable_mp(this, &OpenXRActionMapEditor::_on_tab_button_pressed));
+ add_child(tabs);
+
+ actionsets_scroll = memnew(ScrollContainer);
+ actionsets_scroll->set_h_size_flags(SIZE_EXPAND_FILL);
+ actionsets_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
+ actionsets_scroll->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
+ tabs->add_child(actionsets_scroll);
+ actionsets_scroll->set_name(TTR("Action Sets"));
+
+ actionsets_vb = memnew(VBoxContainer);
+ actionsets_vb->set_h_size_flags(SIZE_EXPAND_FILL);
+ actionsets_scroll->add_child(actionsets_vb);
+
+ select_interaction_profile_dialog = memnew(OpenXRSelectInteractionProfileDialog);
+ select_interaction_profile_dialog->connect("interaction_profile_selected", callable_mp(this, &OpenXRActionMapEditor::_on_interaction_profile_selected));
+ add_child(select_interaction_profile_dialog);
+
+ _load_action_map(ProjectSettings::get_singleton()->get("xr/openxr/default_action_map"));
+}
+
+OpenXRActionMapEditor::~OpenXRActionMapEditor() {
+}
diff --git a/modules/openxr/editor/openxr_action_map_editor.h b/modules/openxr/editor/openxr_action_map_editor.h
new file mode 100644
index 0000000000..dfc941b500
--- /dev/null
+++ b/modules/openxr/editor/openxr_action_map_editor.h
@@ -0,0 +1,100 @@
+/*************************************************************************/
+/* openxr_action_map_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_ACTION_MAP_EDITOR_H
+#define OPENXR_ACTION_MAP_EDITOR_H
+
+#include "../action_map/openxr_action_map.h"
+#include "../editor/openxr_action_set_editor.h"
+#include "../editor/openxr_interaction_profile_editor.h"
+#include "../editor/openxr_select_interaction_profile_dialog.h"
+
+#include "editor/editor_plugin.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/label.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/tab_container.h"
+
+class OpenXRActionMapEditor : public VBoxContainer {
+ GDCLASS(OpenXRActionMapEditor, VBoxContainer);
+
+private:
+ String edited_path;
+ Ref<OpenXRActionMap> action_map;
+ Vector<Node *> interaction_profiles;
+
+ HBoxContainer *top_hb = nullptr;
+ Label *header_label = nullptr;
+ Button *add_action_set = nullptr;
+ Button *add_interaction_profile = nullptr;
+ Button *load = nullptr;
+ Button *save_as = nullptr;
+ Button *_default = nullptr;
+ TabContainer *tabs = nullptr;
+ ScrollContainer *actionsets_scroll = nullptr;
+ VBoxContainer *actionsets_vb = nullptr;
+ OpenXRSelectInteractionProfileDialog *select_interaction_profile_dialog = nullptr;
+
+ OpenXRActionSetEditor *_add_action_set_editor(Ref<OpenXRActionSet> p_action_set);
+ void _update_action_sets();
+ OpenXRInteractionProfileEditorBase *_add_interaction_profile_editor(Ref<OpenXRInteractionProfile> p_interaction_profile);
+ void _update_interaction_profiles();
+
+ OpenXRActionSetEditor *_add_action_set(String p_name);
+ void _remove_action_set(String p_name);
+
+ void _on_add_action_set();
+ void _set_focus_on_action_set(OpenXRActionSetEditor *p_action_set_editor);
+ void _on_remove_action_set(Object *p_action_set_editor);
+ void _on_action_removed();
+
+ void _on_add_interaction_profile();
+ void _on_interaction_profile_selected(const String p_path);
+
+ void _load_action_map(const String p_path, bool p_create_new_if_missing = false);
+ void _on_save_action_map();
+ void _on_reset_to_default_layout();
+
+ void _on_tabs_tab_changed(int p_tab);
+ void _on_tab_button_pressed(int p_tab);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ void open_action_map(String p_path);
+
+ OpenXRActionMapEditor();
+ ~OpenXRActionMapEditor();
+};
+
+#endif // !OPENXR_ACTION_MAP_EDITOR_H
diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp
new file mode 100644
index 0000000000..7bf8557c5b
--- /dev/null
+++ b/modules/openxr/editor/openxr_action_set_editor.cpp
@@ -0,0 +1,218 @@
+/*************************************************************************/
+/* openxr_action_set_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_action_set_editor.h"
+#include "openxr_action_editor.h"
+
+void OpenXRActionSetEditor::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_set_editor")));
+ ADD_SIGNAL(MethodInfo("action_removed"));
+}
+
+void OpenXRActionSetEditor::_set_fold_icon() {
+ if (is_expanded) {
+ fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), SNAME("EditorIcons")));
+ } else {
+ fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), SNAME("EditorIcons")));
+ }
+}
+
+void OpenXRActionSetEditor::_theme_changed() {
+ _set_fold_icon();
+ add_action->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ rem_action_set->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+}
+
+void OpenXRActionSetEditor::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ _theme_changed();
+ panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
+ } break;
+ }
+}
+
+OpenXRActionEditor *OpenXRActionSetEditor::_add_action_editor(Ref<OpenXRAction> p_action) {
+ OpenXRActionEditor *action_editor = memnew(OpenXRActionEditor(p_action));
+ action_editor->connect("remove", callable_mp(this, &OpenXRActionSetEditor::_on_remove_action));
+ actions_vb->add_child(action_editor);
+
+ return action_editor;
+}
+
+void OpenXRActionSetEditor::_update_actions() {
+ // out with the old...
+ while (actions_vb->get_child_count() > 0) {
+ memdelete(actions_vb->get_child(0));
+ }
+
+ // in with the new...
+ Array actions = action_set->get_actions();
+ for (int i = 0; i < actions.size(); i++) {
+ Ref<OpenXRAction> action = actions[i];
+ _add_action_editor(action);
+ }
+}
+
+void OpenXRActionSetEditor::_on_toggle_expand() {
+ is_expanded = !is_expanded;
+ actions_vb->set_visible(is_expanded);
+ _set_fold_icon();
+}
+
+void OpenXRActionSetEditor::_on_action_set_name_changed(const String p_new_text) {
+ // TODO validate if entry is allowed
+
+ // If our localized name matches our action set name, set this too
+ if (action_set->get_name() == action_set->get_localized_name()) {
+ action_set->set_localized_name(p_new_text);
+ action_set_localized_name->set_text(p_new_text);
+ }
+ action_set->set_name(p_new_text);
+}
+
+void OpenXRActionSetEditor::_on_action_set_localized_name_changed(const String p_new_text) {
+ action_set->set_localized_name(p_new_text);
+}
+
+void OpenXRActionSetEditor::_on_action_set_priority_changed(const String p_new_text) {
+ int64_t value = p_new_text.to_int();
+
+ action_set->set_priority(value);
+}
+
+void OpenXRActionSetEditor::_on_add_action() {
+ Ref<OpenXRAction> new_action;
+
+ new_action.instantiate();
+ new_action->set_name("New");
+ new_action->set_localized_name("New");
+ action_set->add_action(new_action);
+
+ _add_action_editor(new_action);
+
+ // TODO handle focus
+}
+
+void OpenXRActionSetEditor::_on_remove_action_set() {
+ emit_signal("remove", this);
+}
+
+void OpenXRActionSetEditor::_on_remove_action(Object *p_action_editor) {
+ OpenXRActionEditor *action_editor = Object::cast_to<OpenXRActionEditor>(p_action_editor);
+ ERR_FAIL_NULL(action_editor);
+ ERR_FAIL_COND(action_editor->get_parent() != actions_vb);
+ Ref<OpenXRAction> action = action_editor->get_action();
+ ERR_FAIL_COND(action.is_null());
+
+ // TODO add undo/redo action
+
+ // TODO find where this action is used by our interaction profiles and remove it there
+
+ // And remove it....
+ action_map->remove_action(action->get_name_with_set()); // remove it from the set and any interaction profile it relates to
+ actions_vb->remove_child(action_editor);
+ action_editor->queue_delete();
+
+ // Let action map editor know so we can update our interaction profiles
+ emit_signal("action_removed");
+}
+
+void OpenXRActionSetEditor::set_focus_on_entry() {
+ ERR_FAIL_NULL(action_set_name);
+ action_set_name->grab_focus();
+}
+
+OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set) {
+ action_map = p_action_map;
+ action_set = p_action_set;
+
+ set_h_size_flags(Control::SIZE_EXPAND_FILL);
+
+ panel = memnew(PanelContainer);
+ panel->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(panel);
+
+ HBoxContainer *panel_hb = memnew(HBoxContainer);
+ panel_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ panel->add_child(panel_hb);
+
+ fold_btn = memnew(Button);
+ fold_btn->set_v_size_flags(Control::SIZE_SHRINK_BEGIN);
+ fold_btn->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_toggle_expand));
+ fold_btn->set_flat(true);
+ panel_hb->add_child(fold_btn);
+
+ main_vb = memnew(VBoxContainer);
+ main_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ panel_hb->add_child(main_vb);
+
+ action_set_hb = memnew(HBoxContainer);
+ action_set_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ main_vb->add_child(action_set_hb);
+
+ action_set_name = memnew(LineEdit);
+ action_set_name->set_text(action_set->get_name());
+ action_set_name->set_custom_minimum_size(Size2(150.0, 0.0));
+ action_set_name->connect("text_changed", callable_mp(this, &OpenXRActionSetEditor::_on_action_set_name_changed));
+ action_set_hb->add_child(action_set_name);
+
+ action_set_localized_name = memnew(LineEdit);
+ action_set_localized_name->set_text(action_set->get_localized_name());
+ action_set_localized_name->set_custom_minimum_size(Size2(150.0, 0.0));
+ action_set_localized_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ action_set_localized_name->connect("text_changed", callable_mp(this, &OpenXRActionSetEditor::_on_action_set_localized_name_changed));
+ action_set_hb->add_child(action_set_localized_name);
+
+ action_set_priority = memnew(TextEdit);
+ action_set_priority->set_text(itos(action_set->get_priority()));
+ action_set_priority->set_custom_minimum_size(Size2(50.0, 0.0));
+ action_set_priority->connect("text_changed", callable_mp(this, &OpenXRActionSetEditor::_on_action_set_priority_changed));
+ action_set_hb->add_child(action_set_priority);
+
+ add_action = memnew(Button);
+ add_action->set_tooltip("Add Action.");
+ add_action->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_add_action));
+ add_action->set_flat(true);
+ action_set_hb->add_child(add_action);
+
+ rem_action_set = memnew(Button);
+ rem_action_set->set_tooltip("Remove Action Set.");
+ rem_action_set->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_remove_action_set));
+ rem_action_set->set_flat(true);
+ action_set_hb->add_child(rem_action_set);
+
+ actions_vb = memnew(VBoxContainer);
+ actions_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ main_vb->add_child(actions_vb);
+
+ _update_actions();
+}
diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h
new file mode 100644
index 0000000000..f3960dcbf9
--- /dev/null
+++ b/modules/openxr/editor/openxr_action_set_editor.h
@@ -0,0 +1,88 @@
+/*************************************************************************/
+/* openxr_action_set_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_ACTION_SET_EDITOR_H
+#define OPENXR_ACTION_SET_EDITOR_H
+
+#include "../action_map/openxr_action_map.h"
+#include "../action_map/openxr_action_set.h"
+#include "openxr_action_editor.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/text_edit.h"
+
+class OpenXRActionSetEditor : public HBoxContainer {
+ GDCLASS(OpenXRActionSetEditor, HBoxContainer);
+
+private:
+ Ref<OpenXRActionMap> action_map;
+ Ref<OpenXRActionSet> action_set;
+
+ bool is_expanded = true;
+
+ PanelContainer *panel = nullptr;
+ Button *fold_btn = nullptr;
+ VBoxContainer *main_vb = nullptr;
+ HBoxContainer *action_set_hb = nullptr;
+ LineEdit *action_set_name = nullptr;
+ LineEdit *action_set_localized_name = nullptr;
+ TextEdit *action_set_priority = nullptr;
+ Button *add_action = nullptr;
+ Button *rem_action_set = nullptr;
+ VBoxContainer *actions_vb = nullptr;
+
+ void _set_fold_icon();
+ void _theme_changed();
+ OpenXRActionEditor *_add_action_editor(Ref<OpenXRAction> p_action);
+ void _update_actions();
+
+ void _on_toggle_expand();
+ void _on_action_set_name_changed(const String p_new_text);
+ void _on_action_set_localized_name_changed(const String p_new_text);
+ void _on_action_set_priority_changed(const String p_new_text);
+ void _on_add_action();
+ void _on_remove_action_set();
+
+ void _on_remove_action(Object *p_action_editor);
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ Ref<OpenXRActionSet> get_action_set() { return action_set; };
+ void set_focus_on_entry();
+
+ OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set);
+};
+
+#endif // !OPENXR_ACTION_SET_EDITOR_H
diff --git a/modules/openxr/editor/openxr_editor_plugin.cpp b/modules/openxr/editor/openxr_editor_plugin.cpp
new file mode 100644
index 0000000000..b87b538511
--- /dev/null
+++ b/modules/openxr/editor/openxr_editor_plugin.cpp
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* openxr_editor_plugin.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_editor_plugin.h"
+
+#include "../action_map/openxr_action_map.h"
+#include "editor/editor_node.h"
+
+void OpenXREditorPlugin::edit(Object *p_node) {
+ if (Object::cast_to<OpenXRActionMap>(p_node)) {
+ String path = Object::cast_to<OpenXRActionMap>(p_node)->get_path();
+ if (path.is_resource_file()) {
+ action_map_editor->open_action_map(path);
+ }
+ }
+}
+
+bool OpenXREditorPlugin::handles(Object *p_node) const {
+ return (Object::cast_to<OpenXRActionMap>(p_node) != nullptr);
+}
+
+void OpenXREditorPlugin::make_visible(bool p_visible) {
+}
+
+OpenXREditorPlugin::OpenXREditorPlugin() {
+ action_map_editor = memnew(OpenXRActionMapEditor);
+ EditorNode::get_singleton()->add_bottom_panel_item(TTR("OpenXR Action Map"), action_map_editor);
+}
+
+OpenXREditorPlugin::~OpenXREditorPlugin() {
+}
diff --git a/modules/openxr/editor/openxr_editor_plugin.h b/modules/openxr/editor/openxr_editor_plugin.h
new file mode 100644
index 0000000000..af8ee7d54c
--- /dev/null
+++ b/modules/openxr/editor/openxr_editor_plugin.h
@@ -0,0 +1,53 @@
+/*************************************************************************/
+/* openxr_editor_plugin.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_EDITOR_PLUGIN_H
+#define OPENXR_EDITOR_PLUGIN_H
+
+#include "editor/editor_plugin.h"
+#include "openxr_action_map_editor.h"
+
+class OpenXREditorPlugin : public EditorPlugin {
+ GDCLASS(OpenXREditorPlugin, EditorPlugin);
+
+ OpenXRActionMapEditor *action_map_editor = nullptr;
+
+public:
+ virtual String get_name() const override { return "OpenXRPlugin"; }
+ bool has_main_screen() const override { return false; }
+ virtual void edit(Object *p_node) override;
+ virtual bool handles(Object *p_node) const override;
+ virtual void make_visible(bool p_visible) override;
+
+ OpenXREditorPlugin();
+ ~OpenXREditorPlugin();
+};
+
+#endif // !OPENXR_EDITOR_PLUGIN_H
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
new file mode 100644
index 0000000000..669cc694f2
--- /dev/null
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
@@ -0,0 +1,272 @@
+/*************************************************************************/
+/* openxr_interaction_profile_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_interaction_profile_editor.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/label.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/panel_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/text_edit.h"
+
+///////////////////////////////////////////////////////////////////////////
+// Interaction profile editor base
+
+void OpenXRInteractionProfileEditorBase::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_add_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_add_binding);
+ ClassDB::bind_method(D_METHOD("_remove_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_remove_binding);
+ ClassDB::bind_method(D_METHOD("_update_interaction_profile"), &OpenXRInteractionProfileEditorBase::_update_interaction_profile);
+}
+
+void OpenXRInteractionProfileEditorBase::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ _update_interaction_profile();
+ } break;
+
+ case NOTIFICATION_THEME_CHANGED: {
+ _theme_changed();
+ } break;
+ }
+}
+
+void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, const String p_path) {
+ ERR_FAIL_COND(action_map.is_null());
+ ERR_FAIL_COND(interaction_profile.is_null());
+
+ Ref<OpenXRAction> action = action_map->get_action(p_action);
+ ERR_FAIL_COND(action.is_null());
+
+ Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
+ if (binding.is_null()) {
+ // create a new binding
+ binding.instantiate();
+ binding->set_action(action);
+ interaction_profile->add_binding(binding);
+ }
+
+ binding->add_path(p_path);
+
+ // Update our toplevel paths
+ action->set_toplevel_paths(action_map->get_top_level_paths(action));
+
+ call_deferred("_update_interaction_profile");
+}
+
+void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action, const String p_path) {
+ ERR_FAIL_COND(action_map.is_null());
+ ERR_FAIL_COND(interaction_profile.is_null());
+
+ Ref<OpenXRAction> action = action_map->get_action(p_action);
+ ERR_FAIL_COND(action.is_null());
+
+ Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
+ if (binding.is_valid()) {
+ binding->remove_path(p_path);
+
+ if (binding->get_path_count() == 0) {
+ interaction_profile->remove_binding(binding);
+ }
+
+ // Update our toplevel paths
+ action->set_toplevel_paths(action_map->get_top_level_paths(action));
+
+ call_deferred("_update_interaction_profile");
+ }
+}
+
+OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) {
+ action_map = p_action_map;
+ interaction_profile = p_interaction_profile;
+ String profile_path = interaction_profile->get_interaction_profile_path();
+ String profile_name = profile_path;
+
+ profile_def = OpenXRDefs::get_profile(profile_path);
+ if (profile_def != nullptr) {
+ profile_name = profile_def->display_name;
+ }
+
+ set_name(profile_name);
+ set_h_size_flags(SIZE_EXPAND_FILL);
+ set_v_size_flags(SIZE_EXPAND_FILL);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Default interaction profile editor
+
+void OpenXRInteractionProfileEditor::select_action_for(const String p_io_path) {
+ selecting_for_io_path = p_io_path;
+ select_action_dialog->open();
+}
+
+void OpenXRInteractionProfileEditor::action_selected(const String p_action) {
+ _add_binding(p_action, selecting_for_io_path);
+ selecting_for_io_path = "";
+}
+
+void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path) {
+ HBoxContainer *path_hb = memnew(HBoxContainer);
+ path_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ p_container->add_child(path_hb);
+
+ Label *path_label = memnew(Label);
+ path_label->set_text(p_io_path->display_name);
+ path_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ path_hb->add_child(path_label);
+
+ Label *type_label = memnew(Label);
+ switch (p_io_path->action_type) {
+ case OpenXRAction::OPENXR_ACTION_BOOL: {
+ type_label->set_text(TTR("Boolean"));
+ } break;
+ case OpenXRAction::OPENXR_ACTION_FLOAT: {
+ type_label->set_text(TTR("Float"));
+ } break;
+ case OpenXRAction::OPENXR_ACTION_VECTOR2: {
+ type_label->set_text(TTR("Vector2"));
+ } break;
+ case OpenXRAction::OPENXR_ACTION_POSE: {
+ type_label->set_text(TTR("Pose"));
+ } break;
+ case OpenXRAction::OPENXR_ACTION_HAPTIC: {
+ type_label->set_text(TTR("Haptic"));
+ } break;
+ default: {
+ type_label->set_text(TTR("Unknown"));
+ } break;
+ }
+ type_label->set_custom_minimum_size(Size2(50.0, 0.0));
+ path_hb->add_child(type_label);
+
+ Button *path_add = memnew(Button);
+ path_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
+ path_add->set_flat(true);
+ Vector<Variant> add_binds;
+ add_binds.push_back(String(p_io_path->openxr_path));
+ path_add->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for), add_binds);
+ path_hb->add_child(path_add);
+
+ if (interaction_profile.is_valid()) {
+ String io_path = String(p_io_path->openxr_path);
+ Array bindings = interaction_profile->get_bindings();
+ for (int i = 0; i < bindings.size(); i++) {
+ Ref<OpenXRIPBinding> binding = bindings[i];
+ if (binding->has_path(io_path)) {
+ Ref<OpenXRAction> action = binding->get_action();
+
+ HBoxContainer *action_hb = memnew(HBoxContainer);
+ action_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ p_container->add_child(action_hb);
+
+ Control *indent_node = memnew(Control);
+ indent_node->set_custom_minimum_size(Size2(10.0, 0.0));
+ action_hb->add_child(indent_node);
+
+ Label *action_label = memnew(Label);
+ action_label->set_text(action->get_name_with_set() + ": " + action->get_localized_name());
+ action_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ action_hb->add_child(action_label);
+
+ Button *action_rem = memnew(Button);
+ action_rem->set_flat(true);
+ action_rem->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")));
+ Vector<Variant> remove_binds;
+ remove_binds.push_back(action->get_name_with_set());
+ remove_binds.push_back(String(p_io_path->openxr_path));
+ action_rem->connect("pressed", callable_mp((OpenXRInteractionProfileEditorBase *)this, &OpenXRInteractionProfileEditorBase::_remove_binding), remove_binds);
+ action_hb->add_child(action_rem);
+ }
+ }
+ }
+}
+
+void OpenXRInteractionProfileEditor::_update_interaction_profile() {
+ // out with the old...
+ while (main_hb->get_child_count() > 0) {
+ memdelete(main_hb->get_child(0));
+ }
+
+ // in with the new...
+
+ // Determine toplevel paths
+ Vector<const OpenXRDefs::TopLevelPath *> top_level_paths;
+ for (int i = 0; i < profile_def->io_path_count; i++) {
+ const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[i];
+
+ if (!top_level_paths.has(io_path->top_level_path)) {
+ top_level_paths.push_back(io_path->top_level_path);
+ }
+ }
+
+ for (int i = 0; i < top_level_paths.size(); i++) {
+ PanelContainer *panel = memnew(PanelContainer);
+ panel->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ main_hb->add_child(panel);
+ panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
+
+ VBoxContainer *container = memnew(VBoxContainer);
+ panel->add_child(container);
+
+ Label *label = memnew(Label);
+ label->set_text(top_level_paths[i]->display_name);
+ container->add_child(label);
+
+ for (int j = 0; j < profile_def->io_path_count; j++) {
+ const OpenXRDefs::IOPath *io_path = &profile_def->io_paths[j];
+ if (io_path->top_level_path == top_level_paths[i]) {
+ _add_io_path(container, io_path);
+ }
+ }
+ }
+}
+
+void OpenXRInteractionProfileEditor::_theme_changed() {
+ for (int i = 0; i < main_hb->get_child_count(); i++) {
+ Control *panel = static_cast<Control *>(main_hb->get_child(i));
+ if (panel) {
+ panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
+ }
+ }
+}
+
+OpenXRInteractionProfileEditor::OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) :
+ OpenXRInteractionProfileEditorBase(p_action_map, p_interaction_profile) {
+ // TODO background of scrollbox should be darker with our VBoxContainers we're adding in _update_interaction_profile the normal color
+
+ main_hb = memnew(HBoxContainer);
+ add_child(main_hb);
+
+ select_action_dialog = memnew(OpenXRSelectActionDialog(p_action_map));
+ select_action_dialog->connect("action_selected", callable_mp(this, &OpenXRInteractionProfileEditor::action_selected));
+ add_child(select_action_dialog);
+
+ _update_interaction_profile();
+}
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.h b/modules/openxr/editor/openxr_interaction_profile_editor.h
new file mode 100644
index 0000000000..f50da1a003
--- /dev/null
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.h
@@ -0,0 +1,83 @@
+/*************************************************************************/
+/* openxr_interaction_profile_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_INTERACTION_PROFILE_EDITOR_H
+#define OPENXR_INTERACTION_PROFILE_EDITOR_H
+
+#include "../action_map/openxr_action_map.h"
+#include "../action_map/openxr_defs.h"
+#include "../action_map/openxr_interaction_profile.h"
+#include "scene/gui/scroll_container.h"
+
+#include "openxr_select_action_dialog.h"
+
+class OpenXRInteractionProfileEditorBase : public ScrollContainer {
+ GDCLASS(OpenXRInteractionProfileEditorBase, ScrollContainer);
+
+protected:
+ Ref<OpenXRInteractionProfile> interaction_profile;
+ Ref<OpenXRActionMap> action_map;
+
+ static void _bind_methods();
+ void _notification(int p_what);
+
+ const OpenXRDefs::InteractionProfile *profile_def = nullptr;
+
+public:
+ Ref<OpenXRInteractionProfile> get_interaction_profile() { return interaction_profile; }
+
+ virtual void _update_interaction_profile() {}
+ virtual void _theme_changed() {}
+ void _add_binding(const String p_action, const String p_path);
+ void _remove_binding(const String p_action, const String p_path);
+
+ OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile);
+};
+
+class OpenXRInteractionProfileEditor : public OpenXRInteractionProfileEditorBase {
+ GDCLASS(OpenXRInteractionProfileEditor, OpenXRInteractionProfileEditorBase);
+
+private:
+ String selecting_for_io_path;
+ HBoxContainer *main_hb = nullptr;
+ OpenXRSelectActionDialog *select_action_dialog = nullptr;
+
+ void _add_io_path(VBoxContainer *p_container, const OpenXRDefs::IOPath *p_io_path);
+
+public:
+ void select_action_for(const String p_io_path);
+ void action_selected(const String p_action);
+
+ virtual void _update_interaction_profile() override;
+ virtual void _theme_changed() override;
+ OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile);
+};
+
+#endif // !OPENXR_INTERACTION_PROFILE_EDITOR_H
diff --git a/modules/openxr/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp
new file mode 100644
index 0000000000..c2a2965200
--- /dev/null
+++ b/modules/openxr/editor/openxr_select_action_dialog.cpp
@@ -0,0 +1,135 @@
+/*************************************************************************/
+/* openxr_select_action_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_select_action_dialog.h"
+#include "editor/editor_node.h"
+
+void OpenXRSelectActionDialog::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("action_selected", PropertyInfo(Variant::STRING, "action")));
+}
+
+void OpenXRSelectActionDialog::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ } break;
+ }
+}
+
+void OpenXRSelectActionDialog::_on_select_action(const String p_action) {
+ if (selected_action != "") {
+ NodePath button_path = action_buttons[selected_action];
+ Button *button = static_cast<Button *>(get_node(button_path));
+ if (button != nullptr) {
+ button->set_flat(true);
+ }
+ }
+
+ selected_action = p_action;
+
+ if (selected_action != "") {
+ NodePath button_path = action_buttons[selected_action];
+ Button *button = static_cast<Button *>(get_node(button_path));
+ if (button != nullptr) {
+ button->set_flat(false);
+ }
+ }
+}
+
+void OpenXRSelectActionDialog::open() {
+ ERR_FAIL_COND(action_map.is_null());
+
+ // out with the old...
+ while (main_vb->get_child_count() > 0) {
+ memdelete(main_vb->get_child(0));
+ }
+
+ selected_action = "";
+ action_buttons.clear();
+
+ Array action_sets = action_map->get_action_sets();
+ for (int i = 0; i < action_sets.size(); i++) {
+ Ref<OpenXRActionSet> action_set = action_sets[i];
+
+ Label *action_set_label = memnew(Label);
+ action_set_label->set_text(action_set->get_localized_name());
+ main_vb->add_child(action_set_label);
+
+ Array actions = action_set->get_actions();
+ for (int j = 0; j < actions.size(); j++) {
+ Ref<OpenXRAction> action = actions[j];
+
+ HBoxContainer *action_hb = memnew(HBoxContainer);
+ main_vb->add_child(action_hb);
+
+ Control *indent_node = memnew(Control);
+ indent_node->set_custom_minimum_size(Size2(10.0, 0.0));
+ action_hb->add_child(indent_node);
+
+ Button *action_button = memnew(Button);
+ String action_name = action->get_name_with_set();
+ Vector<Variant> binds;
+ binds.push_back(action_name);
+ action_button->set_flat(true);
+ action_button->set_text(action->get_name() + ": " + action->get_localized_name());
+ action_button->connect("pressed", callable_mp(this, &OpenXRSelectActionDialog::_on_select_action), binds);
+ action_hb->add_child(action_button);
+
+ action_buttons[action_name] = action_button->get_path();
+ }
+ }
+
+ popup_centered();
+}
+
+void OpenXRSelectActionDialog::ok_pressed() {
+ if (selected_action == "") {
+ return;
+ }
+
+ emit_signal("action_selected", selected_action);
+
+ hide();
+}
+
+OpenXRSelectActionDialog::OpenXRSelectActionDialog(Ref<OpenXRActionMap> p_action_map) {
+ action_map = p_action_map;
+
+ set_title(TTR("Select an action"));
+
+ scroll = memnew(ScrollContainer);
+ scroll->set_custom_minimum_size(Size2(600.0, 400.0));
+ add_child(scroll);
+
+ main_vb = memnew(VBoxContainer);
+ main_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ scroll->add_child(main_vb);
+}
diff --git a/modules/openxr/editor/openxr_select_action_dialog.h b/modules/openxr/editor/openxr_select_action_dialog.h
new file mode 100644
index 0000000000..ea2c30373b
--- /dev/null
+++ b/modules/openxr/editor/openxr_select_action_dialog.h
@@ -0,0 +1,67 @@
+/*************************************************************************/
+/* openxr_select_action_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_SELECT_ACTION_DIALOG_H
+#define OPENXR_SELECT_ACTION_DIALOG_H
+
+#include "../action_map/openxr_action_map.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/label.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/text_edit.h"
+
+class OpenXRSelectActionDialog : public ConfirmationDialog {
+ GDCLASS(OpenXRSelectActionDialog, ConfirmationDialog);
+
+private:
+ Ref<OpenXRActionMap> action_map;
+ String selected_action;
+ Dictionary action_buttons;
+
+ VBoxContainer *main_vb = nullptr;
+ ScrollContainer *scroll = nullptr;
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ void _on_select_action(const String p_action);
+ void open();
+ virtual void ok_pressed() override;
+
+ OpenXRSelectActionDialog(Ref<OpenXRActionMap> p_action_map);
+};
+
+#endif // !OPENXR_SELECT_ACTION_DIALOG_H
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
new file mode 100644
index 0000000000..12b110f146
--- /dev/null
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
@@ -0,0 +1,125 @@
+/*************************************************************************/
+/* openxr_select_interaction_profile_dialog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "openxr_select_interaction_profile_dialog.h"
+
+void OpenXRSelectInteractionProfileDialog::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("interaction_profile_selected", PropertyInfo(Variant::STRING, "interaction_profile")));
+}
+
+void OpenXRSelectInteractionProfileDialog::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree")));
+ } break;
+ }
+}
+
+void OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile(const String p_interaction_profile) {
+ if (selected_interaction_profile != "") {
+ NodePath button_path = ip_buttons[selected_interaction_profile];
+ Button *button = static_cast<Button *>(get_node(button_path));
+ if (button != nullptr) {
+ button->set_flat(true);
+ }
+ }
+
+ selected_interaction_profile = p_interaction_profile;
+
+ if (selected_interaction_profile != "") {
+ NodePath button_path = ip_buttons[selected_interaction_profile];
+ Button *button = static_cast<Button *>(get_node(button_path));
+ if (button != nullptr) {
+ button->set_flat(false);
+ }
+ }
+}
+
+void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_include) {
+ int available_count = 0;
+
+ // out with the old...
+ while (main_vb->get_child_count() > 0) {
+ memdelete(main_vb->get_child(0));
+ }
+
+ selected_interaction_profile = "";
+ ip_buttons.clear();
+
+ // in with the new
+ PackedStringArray interaction_profiles = OpenXRDefs::get_interaction_profile_paths();
+ for (int i = 0; i < interaction_profiles.size(); i++) {
+ String path = interaction_profiles[i];
+ if (!p_do_not_include.has(path)) {
+ Button *ip_button = memnew(Button);
+ Vector<Variant> binds;
+ binds.push_back(path);
+ ip_button->set_flat(true);
+ ip_button->set_text(OpenXRDefs::get_profile(path)->display_name);
+ ip_button->connect("pressed", callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile), binds);
+ main_vb->add_child(ip_button);
+
+ ip_buttons[path] = ip_button->get_path();
+ available_count++;
+ }
+ }
+
+ if (available_count == 0) {
+ // give warning that we have all profiles selected
+
+ } else {
+ // TODO maybe if we only have one, auto select it?
+
+ popup_centered();
+ }
+}
+
+void OpenXRSelectInteractionProfileDialog::ok_pressed() {
+ if (selected_interaction_profile == "") {
+ return;
+ }
+
+ emit_signal("interaction_profile_selected", selected_interaction_profile);
+
+ hide();
+}
+
+OpenXRSelectInteractionProfileDialog::OpenXRSelectInteractionProfileDialog() {
+ set_title("Select an interaction profile");
+
+ scroll = memnew(ScrollContainer);
+ scroll->set_custom_minimum_size(Size2(600.0, 400.0));
+ add_child(scroll);
+
+ main_vb = memnew(VBoxContainer);
+ // main_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ scroll->add_child(main_vb);
+}
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
new file mode 100644
index 0000000000..d177861ff3
--- /dev/null
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* openxr_select_interaction_profile_dialog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
+#define OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
+
+#include "../action_map/openxr_defs.h"
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/label.h"
+#include "scene/gui/line_edit.h"
+#include "scene/gui/scroll_container.h"
+#include "scene/gui/separator.h"
+#include "scene/gui/text_edit.h"
+
+class OpenXRSelectInteractionProfileDialog : public ConfirmationDialog {
+ GDCLASS(OpenXRSelectInteractionProfileDialog, ConfirmationDialog);
+
+private:
+ String selected_interaction_profile;
+ Dictionary ip_buttons;
+
+ VBoxContainer *main_vb = nullptr;
+ ScrollContainer *scroll = nullptr;
+
+protected:
+ static void _bind_methods();
+ void _notification(int p_what);
+
+public:
+ void _on_select_interaction_profile(const String p_interaction_profile);
+ void open(PackedStringArray p_do_not_include);
+ virtual void ok_pressed() override;
+
+ OpenXRSelectInteractionProfileDialog();
+};
+
+#endif // !OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index 5242ee6063..00f81731c2 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -43,7 +43,7 @@ class OpenXRAPI;
class OpenXRExtensionWrapper {
protected:
- OpenXRAPI *openxr_api;
+ OpenXRAPI *openxr_api = nullptr;
// Store extension we require.
// If bool pointer is a nullptr this means this extension is mandatory and initialisation will fail if it is not available
diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp
index c7c840fdf3..8736296f7a 100644
--- a/modules/openxr/extensions/openxr_vulkan_extension.cpp
+++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp
@@ -30,9 +30,9 @@
#include "core/string/print_string.h"
-#include "modules/openxr/extensions/openxr_vulkan_extension.h"
-#include "modules/openxr/openxr_api.h"
-#include "modules/openxr/openxr_util.h"
+#include "../extensions/openxr_vulkan_extension.h"
+#include "../openxr_api.h"
+#include "../openxr_util.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering_server.h"
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 7752878d82..861038be33 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -48,14 +48,14 @@
#include "extensions/openxr_vulkan_extension.h"
#endif
-#include "modules/openxr/openxr_interface.h"
+#include "openxr_interface.h"
OpenXRAPI *OpenXRAPI::singleton = nullptr;
-bool OpenXRAPI::openxr_is_enabled() {
+bool OpenXRAPI::openxr_is_enabled(bool p_check_run_in_editor) {
// @TODO we need an overrule switch so we can force enable openxr, i.e run "godot --openxr_enabled"
- if (Engine::get_singleton()->is_editor_hint()) {
+ if (Engine::get_singleton()->is_editor_hint() && p_check_run_in_editor) {
#ifdef TOOLS_ENABLED
// Disabled for now, using XR inside of the editor we'll be working on during the coming months.
return false;
@@ -408,7 +408,7 @@ bool OpenXRAPI::load_supported_view_configuration_views(XrViewConfigurationType
for (uint32_t i = 0; i < view_count; i++) {
view_configuration_views[i].type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
- view_configuration_views[i].next = NULL;
+ view_configuration_views[i].next = nullptr;
}
result = xrEnumerateViewConfigurationViews(instance, system_id, p_configuration_type, view_count, &view_count, view_configuration_views);
@@ -680,10 +680,10 @@ bool OpenXRAPI::create_main_swapchain() {
for (uint32_t i = 0; i < view_count; i++) {
views[i].type = XR_TYPE_VIEW;
- views[i].next = NULL;
+ views[i].next = nullptr;
projection_views[i].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
- projection_views[i].next = NULL;
+ projection_views[i].next = nullptr;
projection_views[i].subImage.swapchain = swapchain;
projection_views[i].subImage.imageArrayIndex = i;
projection_views[i].subImage.imageRect.offset.x = 0;
@@ -1147,7 +1147,7 @@ bool OpenXRAPI::get_view_transform(uint32_t p_view, Transform3D &r_transform) {
}
// we don't have valid view info
- if (views == NULL || !view_pose_valid) {
+ if (views == nullptr || !view_pose_valid) {
return false;
}
@@ -1167,7 +1167,7 @@ bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z
}
// we don't have valid view info
- if (views == NULL || !view_pose_valid) {
+ if (views == nullptr || !view_pose_valid) {
return false;
}
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index 1a1508e993..d641767a9b 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -222,7 +222,7 @@ protected:
void parse_velocities(const XrSpaceVelocity &p_velocity, Vector3 &r_linear_velocity, Vector3 r_angular_velocity);
public:
- static bool openxr_is_enabled();
+ static bool openxr_is_enabled(bool p_check_run_in_editor = true);
static OpenXRAPI *get_singleton();
String get_error_string(XrResult result);
diff --git a/modules/openxr/register_types.cpp b/modules/openxr/register_types.cpp
index 47ee1316e7..0b48be5f2a 100644
--- a/modules/openxr/register_types.cpp
+++ b/modules/openxr/register_types.cpp
@@ -38,6 +38,22 @@
#include "action_map/openxr_action_set.h"
#include "action_map/openxr_interaction_profile.h"
+#ifdef TOOLS_ENABLED
+
+#include "editor/editor_node.h"
+#include "editor/openxr_editor_plugin.h"
+
+static void _editor_init() {
+ if (OpenXRAPI::openxr_is_enabled(false)) {
+ // Only add our OpenXR action map editor if OpenXR is enabled for our project
+
+ OpenXREditorPlugin *openxr_plugin = memnew(OpenXREditorPlugin());
+ EditorNode::get_singleton()->add_editor_plugin(openxr_plugin);
+ }
+}
+
+#endif
+
OpenXRAPI *openxr_api = nullptr;
Ref<OpenXRInterface> openxr_interface;
@@ -74,6 +90,10 @@ void register_openxr_types() {
openxr_interface->initialize();
}
}
+
+#ifdef TOOLS_ENABLED
+ EditorNode::add_init_callback(_editor_init);
+#endif
}
void unregister_openxr_types() {
diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h
index a22e52dd17..8453c5341d 100644
--- a/modules/raycast/raycast_occlusion_cull.h
+++ b/modules/raycast/raycast_occlusion_cull.h
@@ -115,7 +115,7 @@ private:
struct Scenario {
struct RaycastThreadData {
- CameraRayTile *rays;
+ CameraRayTile *rays = nullptr;
const uint32_t *masks;
};
@@ -124,7 +124,7 @@ private:
uint32_t vertex_count;
Transform3D xform;
const Vector3 *read;
- Vector3 *write;
+ Vector3 *write = nullptr;
};
Thread *commit_thread = nullptr;
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index a745c50a58..e7221f4070 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -71,7 +71,7 @@ public:
class RegEx : public RefCounted {
GDCLASS(RegEx, RefCounted);
- void *general_ctx;
+ void *general_ctx = nullptr;
void *code = nullptr;
String pattern;
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index e02ddbb3f4..71b09a5e69 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -1044,7 +1044,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
if (RenderingServer::get_singleton() != nullptr) {
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, Image::FORMAT_RGBA8, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, Image::FORMAT_RGBA8, tex.imgdata);
if (tex.texture.is_null()) {
tex.texture.instantiate();
tex.texture->create_from_image(img);
@@ -1129,7 +1129,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
if (RenderingServer::get_singleton() != nullptr) {
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, require_format, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, require_format, tex.imgdata);
if (tex.texture.is_null()) {
tex.texture.instantiate();
@@ -2306,7 +2306,7 @@ void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vec
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, tex.format, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
tex.texture = Ref<ImageTexture>();
tex.texture.instantiate();
@@ -2325,7 +2325,7 @@ Ref<Image> TextServerAdvanced::font_get_texture_image(const RID &p_font_rid, con
const FontTexture &tex = fd->cache[size]->textures[p_texture_index];
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, tex.format, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
return img;
}
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 6c2e5a6084..2e8ccf28b9 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -486,7 +486,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
if (RenderingServer::get_singleton() != nullptr) {
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, Image::FORMAT_RGBA8, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, Image::FORMAT_RGBA8, tex.imgdata);
if (tex.texture.is_null()) {
tex.texture.instantiate();
tex.texture->create_from_image(img);
@@ -571,7 +571,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
if (RenderingServer::get_singleton() != nullptr) {
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, require_format, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, require_format, tex.imgdata);
if (tex.texture.is_null()) {
tex.texture.instantiate();
@@ -1467,7 +1467,7 @@ void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vec
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, tex.format, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
tex.texture = Ref<ImageTexture>();
tex.texture.instantiate();
@@ -1486,7 +1486,7 @@ Ref<Image> TextServerFallback::font_get_texture_image(const RID &p_font_rid, con
const FontTexture &tex = fd->cache[size]->textures[p_texture_index];
Ref<Image> img;
img.instantiate();
- img->create_from_data(tex.texture_w, tex.texture_h, 0, tex.format, tex.imgdata);
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
return img;
}
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index 3bc96908a2..b61412e665 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -112,7 +112,7 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
RingBuffer<uint8_t> ring_buffer;
Vector<uint8_t> read_buffer;
bool thread_eof = false;
- Semaphore *thread_sem;
+ Semaphore *thread_sem = nullptr;
Thread thread;
SafeFlag thread_exit;
diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h
index 6b5112f1af..faf39a14e4 100644
--- a/modules/visual_script/editor/visual_script_property_selector.h
+++ b/modules/visual_script/editor/visual_script_property_selector.h
@@ -62,23 +62,23 @@ class VisualScriptPropertySelector : public ConfirmationDialog {
SCOPE_ALL = SCOPE_BASE | SCOPE_INHERITERS | SCOPE_UNRELATED
};
- LineEdit *search_box;
+ LineEdit *search_box = nullptr;
- Button *case_sensitive_button;
- Button *hierarchy_button;
+ Button *case_sensitive_button = nullptr;
+ Button *hierarchy_button = nullptr;
- Button *search_visual_script_nodes;
- Button *search_classes;
- Button *search_operators;
+ Button *search_visual_script_nodes = nullptr;
+ Button *search_classes = nullptr;
+ Button *search_operators = nullptr;
- Button *search_methods;
- Button *search_signals;
- Button *search_constants;
- Button *search_properties;
- Button *search_theme_items;
+ Button *search_methods = nullptr;
+ Button *search_signals = nullptr;
+ Button *search_constants = nullptr;
+ Button *search_properties = nullptr;
+ Button *search_theme_items = nullptr;
- OptionButton *scope_combo;
- Tree *results_tree;
+ OptionButton *scope_combo = nullptr;
+ Tree *results_tree = nullptr;
class SearchRunner;
Ref<SearchRunner> search_runner;
@@ -94,7 +94,7 @@ class VisualScriptPropertySelector : public ConfirmationDialog {
void _item_selected();
void _hide_requested();
- EditorHelpBit *help_bit;
+ EditorHelpBit *help_bit = nullptr;
bool properties = false;
bool visual_script_generic = false;
@@ -104,9 +104,9 @@ class VisualScriptPropertySelector : public ConfirmationDialog {
String base_type;
String base_script;
ObjectID script;
- Object *instance;
+ Object *instance = nullptr;
bool virtuals_only = false;
- VBoxContainer *vbox;
+ VBoxContainer *vbox = nullptr;
protected:
void _notification(int p_what);
@@ -159,9 +159,9 @@ class VisualScriptPropertySelector::SearchRunner : public RefCounted {
}
};
- VisualScriptPropertySelector *selector_ui;
- Control *ui_service;
- Tree *results_tree;
+ VisualScriptPropertySelector *selector_ui = nullptr;
+ Control *ui_service = nullptr;
+ Tree *results_tree = nullptr;
String term;
int search_flags;
int scope_flags;
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index d72bdf9128..6b27af15f6 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -495,7 +495,7 @@ class VisualScriptLanguage : public ScriptLanguage {
String _debug_error;
int _debug_call_stack_pos = 0;
int _debug_max_call_stack;
- CallLevel *_call_stack;
+ CallLevel *_call_stack = nullptr;
public:
StringName notification = "_notification";
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index a7a8801bdc..4ac4ac03c0 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -161,6 +161,13 @@ int DisplayServerAndroid::screen_get_dpi(int p_screen) const {
return godot_io_java->get_screen_dpi();
}
+float DisplayServerAndroid::screen_get_scale(int p_screen) const {
+ GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
+ ERR_FAIL_COND_V(!godot_io_java, 1.0f);
+
+ return godot_io_java->get_scaled_density();
+}
+
float DisplayServerAndroid::screen_get_refresh_rate(int p_screen) const {
GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
if (!godot_io_java) {
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index 23077a6529..1d268bbcfd 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -106,6 +106,7 @@ public:
virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index df3693ba61..a286f768f3 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -863,6 +863,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
bool classify_as_game = p_preset->get("package/classify_as_game");
bool retain_data_on_uninstall = p_preset->get("package/retain_data_on_uninstall");
bool exclude_from_recents = p_preset->get("package/exclude_from_recents");
+ bool is_resizeable = bool(GLOBAL_GET("display/window/size/resizable"));
Vector<String> perms;
// Write permissions into the perms variable.
@@ -980,6 +981,10 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
encode_uint32(exclude_from_recents, &p_manifest.write[iofs + 16]);
}
+ if (tname == "activity" && attrname == "resizeableActivity") {
+ encode_uint32(is_resizeable, &p_manifest.write[iofs + 16]);
+ }
+
if (tname == "supports-screens") {
if (attrname == "smallScreens") {
encode_uint32(screen_support_small ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index ab915a5f85..ff7ea8f2db 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -253,11 +253,13 @@ String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))));
String manifest_activity_text = vformat(
" <activity android:name=\"com.godot.game.GodotApp\" "
- "tools:replace=\"android:screenOrientation,android:excludeFromRecents\" "
+ "tools:replace=\"android:screenOrientation,android:excludeFromRecents,android:resizeableActivity\" "
"android:excludeFromRecents=\"%s\" "
- "android:screenOrientation=\"%s\">\n",
+ "android:screenOrientation=\"%s\" "
+ "android:resizeableActivity=\"%s\">\n",
bool_to_string(p_preset->get("package/exclude_from_recents")),
- orientation);
+ orientation,
+ bool_to_string(bool(GLOBAL_GET("display/window/size/resizable"))));
if (uses_xr) {
manifest_activity_text += " <meta-data tools:node=\"replace\" android:name=\"com.oculus.vr.focusaware\" android:value=\"true\" />\n";
} else {
diff --git a/platform/android/java/editor/src/main/AndroidManifest.xml b/platform/android/java/editor/src/main/AndroidManifest.xml
index 0708ffa32f..bae075d929 100644
--- a/platform/android/java/editor/src/main/AndroidManifest.xml
+++ b/platform/android/java/editor/src/main/AndroidManifest.xml
@@ -29,8 +29,7 @@
android:name=".GodotProjectManager"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:launchMode="singleTask"
- android:resizeableActivity="false"
- android:screenOrientation="landscape"
+ android:screenOrientation="userLandscape"
android:exported="true"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
android:process=":GodotProjectManager">
@@ -46,8 +45,7 @@
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|density|keyboard|navigation|screenLayout|uiMode"
android:process=":GodotEditor"
android:launchMode="singleTask"
- android:resizeableActivity="false"
- android:screenOrientation="landscape"
+ android:screenOrientation="userLandscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
</activity>
@@ -57,8 +55,7 @@
android:label="@string/godot_project_name_string"
android:process=":GodotGame"
android:launchMode="singleTask"
- android:resizeableActivity="false"
- android:screenOrientation="landscape"
+ android:screenOrientation="userLandscape"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
</activity>
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java
index b3a340cc64..8a6bf88267 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.java
@@ -107,4 +107,18 @@ public class GodotEditor extends FullScreenGodotApp {
Intent newInstance = new Intent(this, targetClass).putExtra(COMMAND_LINE_PARAMS, args);
startActivity(newInstance);
}
+
+ @Override
+ public void setRequestedOrientation(int requestedOrientation) {
+ if (!overrideOrientationRequest()) {
+ super.setRequestedOrientation(requestedOrientation);
+ }
+ }
+
+ /**
+ * The Godot Android Editor sets its own orientation via its AndroidManifest
+ */
+ protected boolean overrideOrientationRequest() {
+ return true;
+ }
}
diff --git a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.java b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.java
index 5a0be391cf..12766775a8 100644
--- a/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.java
+++ b/platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.java
@@ -34,4 +34,7 @@ package org.godotengine.editor;
* Drives the 'run project' window of the Godot Editor.
*/
public class GodotGame extends GodotEditor {
+ protected boolean overrideOrientationRequest() {
+ return false;
+ }
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index b151e7eec1..e8e292df5d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -222,10 +222,14 @@ public class GodotIO {
}
public int getScreenDPI() {
- DisplayMetrics metrics = activity.getApplicationContext().getResources().getDisplayMetrics();
+ DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
return (int)(metrics.density * 160f);
}
+ public float getScaledDensity() {
+ return activity.getResources().getDisplayMetrics().scaledDensity;
+ }
+
public double getScreenRefreshRate(double fallback) {
Display display = activity.getWindowManager().getDefaultDisplay();
if (display != null) {
diff --git a/platform/android/java_godot_io_wrapper.cpp b/platform/android/java_godot_io_wrapper.cpp
index d6e3ad90b1..5b21e696c3 100644
--- a/platform/android/java_godot_io_wrapper.cpp
+++ b/platform/android/java_godot_io_wrapper.cpp
@@ -54,6 +54,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
_get_locale = p_env->GetMethodID(cls, "getLocale", "()Ljava/lang/String;");
_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
+ _get_scaled_density = p_env->GetMethodID(cls, "getScaledDensity", "()F");
_get_screen_refresh_rate = p_env->GetMethodID(cls, "getScreenRefreshRate", "(D)D");
_screen_get_usable_rect = p_env->GetMethodID(cls, "screenGetUsableRect", "()[I"),
_get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;");
@@ -138,6 +139,16 @@ int GodotIOJavaWrapper::get_screen_dpi() {
}
}
+float GodotIOJavaWrapper::get_scaled_density() {
+ if (_get_scaled_density) {
+ JNIEnv *env = get_jni_env();
+ ERR_FAIL_COND_V(env == nullptr, 1.0f);
+ return env->CallFloatMethod(godot_io_instance, _get_scaled_density);
+ } else {
+ return 1.0f;
+ }
+}
+
float GodotIOJavaWrapper::get_screen_refresh_rate(float fallback) {
if (_get_screen_refresh_rate) {
JNIEnv *env = get_jni_env();
diff --git a/platform/android/java_godot_io_wrapper.h b/platform/android/java_godot_io_wrapper.h
index 38a2b710a9..08e3092afd 100644
--- a/platform/android/java_godot_io_wrapper.h
+++ b/platform/android/java_godot_io_wrapper.h
@@ -51,6 +51,7 @@ private:
jmethodID _get_locale = 0;
jmethodID _get_model = 0;
jmethodID _get_screen_DPI = 0;
+ jmethodID _get_scaled_density = 0;
jmethodID _get_screen_refresh_rate = 0;
jmethodID _screen_get_usable_rect = 0;
jmethodID _get_unique_id = 0;
@@ -72,6 +73,7 @@ public:
String get_locale();
String get_model();
int get_screen_dpi();
+ float get_scaled_density();
float get_screen_refresh_rate(float fallback);
void screen_get_usable_rect(int (&p_rect_xywh)[4]);
String get_unique_id();
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 48239b3f84..a40e17dc2c 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -52,7 +52,7 @@ private:
#endif
#if defined(VULKAN_ENABLED)
- ANativeWindow *native_window;
+ ANativeWindow *native_window = nullptr;
#endif
mutable String data_dir_cache;
@@ -60,10 +60,10 @@ private:
AudioDriverOpenSL audio_driver_android;
- MainLoop *main_loop;
+ MainLoop *main_loop = nullptr;
- GodotJavaWrapper *godot_java;
- GodotIOJavaWrapper *godot_io_java;
+ GodotJavaWrapper *godot_java = nullptr;
+ GodotIOJavaWrapper *godot_io_java = nullptr;
public:
static const char *ANDROID_EXEC_PATH;
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index 3281ff0cdb..6a61f3a910 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -52,11 +52,11 @@ private:
AudioDriverCoreAudio audio_driver;
- iOS *ios;
+ iOS *ios = nullptr;
- JoypadIPhone *joypad_iphone;
+ JoypadIPhone *joypad_iphone = nullptr;
- MainLoop *main_loop;
+ MainLoop *main_loop = nullptr;
virtual void initialize_core() override;
virtual void initialize() override;
diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py
index 03c85d09ad..f3a6004356 100644
--- a/platform/linuxbsd/detect.py
+++ b/platform/linuxbsd/detect.py
@@ -162,6 +162,7 @@ def configure(env):
if env["use_ubsan"] or env["use_asan"] or env["use_lsan"] or env["use_tsan"] or env["use_msan"]:
env.extra_suffix += ".san"
+ env.Append(CCFLAGS=["-DSANITIZERS_ENABLED"])
if env["use_ubsan"]:
env.Append(
diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h
index 0f44aa4b11..cd673d94d9 100644
--- a/platform/linuxbsd/display_server_x11.h
+++ b/platform/linuxbsd/display_server_x11.h
@@ -108,7 +108,7 @@ class DisplayServerX11 : public DisplayServer {
#endif
#if defined(DBUS_ENABLED)
- FreeDesktopScreenSaver *screensaver;
+ FreeDesktopScreenSaver *screensaver = nullptr;
bool keep_screen_on = false;
#endif
@@ -168,7 +168,7 @@ class DisplayServerX11 : public DisplayServer {
String internal_clipboard_primary;
Window xdnd_source_window;
::Display *x11_display;
- char *xmbstring;
+ char *xmbstring = nullptr;
int xmblen;
unsigned long last_timestamp;
::Time last_keyrelease_time;
@@ -249,7 +249,7 @@ class DisplayServerX11 : public DisplayServer {
typedef void (*xrr_free_monitors_t)(xrr_monitor_info *monitors);
xrr_get_monitors_t xrr_get_monitors;
xrr_free_monitors_t xrr_free_monitors;
- void *xrandr_handle;
+ void *xrandr_handle = nullptr;
Bool xrandr_ext_ok;
struct Property {
diff --git a/platform/linuxbsd/gl_manager_x11.h b/platform/linuxbsd/gl_manager_x11.h
index 0bb0a446ab..e89caf3b30 100644
--- a/platform/linuxbsd/gl_manager_x11.h
+++ b/platform/linuxbsd/gl_manager_x11.h
@@ -66,7 +66,7 @@ private:
struct GLDisplay {
GLDisplay() { context = nullptr; }
~GLDisplay();
- GLManager_X11_Private *context;
+ GLManager_X11_Private *context = nullptr;
::Display *x11_display;
XVisualInfo x_vi;
XSetWindowAttributes x_swa;
@@ -82,7 +82,7 @@ private:
LocalVector<GLWindow> _windows;
LocalVector<GLDisplay> _displays;
- GLWindow *_current_window;
+ GLWindow *_current_window = nullptr;
void _internal_set_current_window(GLWindow *p_win);
diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp
index 7c9f81bd3f..9fe00568fb 100644
--- a/platform/linuxbsd/godot_linuxbsd.cpp
+++ b/platform/linuxbsd/godot_linuxbsd.cpp
@@ -33,10 +33,20 @@
#include <stdlib.h>
#include <unistd.h>
+#if defined(SANITIZERS_ENABLED)
+#include <sys/resource.h>
+#endif
+
#include "main/main.h"
#include "os_linuxbsd.h"
int main(int argc, char *argv[]) {
+#if defined(SANITIZERS_ENABLED)
+ // Note: Set stack size to be at least 30 MB (vs 8 MB default) to avoid overflow, address sanitizer can increase stack usage up to 3 times.
+ struct rlimit stack_lim = { 0x1E00000, 0x1E00000 };
+ setrlimit(RLIMIT_STACK, &stack_lim);
+#endif
+
OS_LinuxBSD os;
setlocale(LC_CTYPE, "");
diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h
index d3857e85f8..7b912ddee3 100644
--- a/platform/linuxbsd/os_linuxbsd.h
+++ b/platform/linuxbsd/os_linuxbsd.h
@@ -63,7 +63,7 @@ class OS_LinuxBSD : public OS_Unix {
CrashHandler crash_handler;
- MainLoop *main_loop;
+ MainLoop *main_loop = nullptr;
protected:
virtual void initialize() override;
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 0ff93bedb4..8d848d2094 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -127,6 +127,7 @@ def configure(env):
if env["use_ubsan"] or env["use_asan"] or env["use_tsan"]:
env.extra_suffix += ".san"
+ env.Append(CCFLAGS=["-DSANITIZERS_ENABLED"])
if env["use_ubsan"]:
env.Append(
diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm
index f3db363151..053a7f4a1d 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/osx/godot_main_osx.mm
@@ -35,12 +35,22 @@
#include <string.h>
#include <unistd.h>
+#if defined(SANITIZERS_ENABLED)
+#include <sys/resource.h>
+#endif
+
int main(int argc, char **argv) {
#if defined(VULKAN_ENABLED)
// MoltenVK - enable full component swizzling support.
setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
#endif
+#if defined(SANITIZERS_ENABLED)
+ // Note: Set stack size to be at least 30 MB (vs 8 MB default) to avoid overflow, address sanitizer can increase stack usage up to 3 times.
+ struct rlimit stack_lim = { 0x1E00000, 0x1E00000 };
+ setrlimit(RLIMIT_STACK, &stack_lim);
+#endif
+
int first_arg = 1;
const char *dbg_arg = "-NSDocumentRevisionsDebugMode";
printf("arguments\n");
diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h
index 4ca7fb1698..b09d5ce34a 100644
--- a/platform/osx/joypad_osx.h
+++ b/platform/osx/joypad_osx.h
@@ -94,7 +94,7 @@ class JoypadOSX {
};
private:
- Input *input;
+ Input *input = nullptr;
IOHIDManagerRef hid_manager;
Vector<joypad> device_list;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 7e0cf9f9cc..afbd338832 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -313,21 +313,22 @@ String OS_OSX::get_executable_path() const {
}
Error OS_OSX::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
- if (@available(macOS 10.15, *)) {
- // Use NSWorkspace if path is an .app bundle.
- NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
- NSBundle *bundle = [NSBundle bundleWithURL:url];
- if (bundle) {
- NSMutableArray *arguments = [[NSMutableArray alloc] init];
- for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
- [arguments addObject:[NSString stringWithUTF8String:E->get().utf8().get_data()]];
- }
+ // Use NSWorkspace if path is an .app bundle.
+ NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (bundle) {
+ NSMutableArray *arguments = [[NSMutableArray alloc] init];
+ for (const String &arg : p_arguments) {
+ [arguments addObject:[NSString stringWithUTF8String:arg.utf8().get_data()]];
+ }
+ if (@available(macOS 10.15, *)) {
NSWorkspaceOpenConfiguration *configuration = [[NSWorkspaceOpenConfiguration alloc] init];
[configuration setArguments:arguments];
[configuration setCreatesNewApplicationInstance:YES];
__block dispatch_semaphore_t lock = dispatch_semaphore_create(0);
__block Error err = ERR_TIMEOUT;
__block pid_t pid = 0;
+
[[NSWorkspace sharedWorkspace] openApplicationAtURL:url
configuration:configuration
completionHandler:^(NSRunningApplication *app, NSError *error) {
@@ -350,7 +351,19 @@ Error OS_OSX::create_process(const String &p_path, const List<String> &p_argumen
return err;
} else {
- return OS_Unix::create_process(p_path, p_arguments, r_child_id, p_open_console);
+ Error err = ERR_TIMEOUT;
+ NSError *error = nullptr;
+ NSRunningApplication *app = [[NSWorkspace sharedWorkspace] launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error];
+ if (error) {
+ err = ERR_CANT_FORK;
+ NSLog(@"Failed to execute: %@", error.localizedDescription);
+ } else {
+ if (r_child_id) {
+ *r_child_id = (ProcessID)[app processIdentifier];
+ }
+ err = OK;
+ }
+ return err;
}
} else {
return OS_Unix::create_process(p_path, p_arguments, r_child_id, p_open_console);
diff --git a/platform/uwp/joypad_uwp.h b/platform/uwp/joypad_uwp.h
index 29f5109056..0869f1961d 100644
--- a/platform/uwp/joypad_uwp.h
+++ b/platform/uwp/joypad_uwp.h
@@ -68,7 +68,7 @@ private:
ControllerDevice controllers[MAX_CONTROLLERS];
- InputDefault *input;
+ InputDefault *input = nullptr;
void OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value);
void OnGamepadRemoved(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ value);
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index 573d86af7c..f955be1da9 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -74,7 +74,7 @@ private:
KEY_EVENT_BUFFER_SIZE = 512
};
- FILE *stdo;
+ FILE *stdo = nullptr;
KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE];
int key_event_pos;
@@ -87,16 +87,16 @@ private:
bool outside;
int old_x, old_y;
Point2i center;
- RenderingServer *rendering_server;
+ RenderingServer *rendering_server = nullptr;
int pressrc;
- ContextEGL_UWP *gl_context;
+ ContextEGL_UWP *gl_context = nullptr;
Windows::UI::Core::CoreWindow ^ window;
VideoMode video_mode;
int video_driver_index;
- MainLoop *main_loop;
+ MainLoop *main_loop = nullptr;
AudioDriverXAudio2 audio_driver;
@@ -111,7 +111,7 @@ private:
CursorShape cursor_shape;
- InputDefault *input;
+ InputDefault *input = nullptr;
JoypadUWP ^ joypad;
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 71fedf2bca..fcf4b5a728 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -392,7 +392,7 @@ class DisplayServerWindows : public DisplayServer {
Rect2i parent_safe_rect;
};
- JoypadWindows *joypad;
+ JoypadWindows *joypad = nullptr;
HHOOK mouse_monitor = nullptr;
List<WindowID> popup_list;
uint64_t time_since_popup = 0;
diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h
index 6423c54855..f789cba327 100644
--- a/platform/windows/gl_manager_windows.h
+++ b/platform/windows/gl_manager_windows.h
@@ -75,7 +75,7 @@ private:
LocalVector<GLWindow> _windows;
LocalVector<GLDisplay> _displays;
- GLWindow *_current_window;
+ GLWindow *_current_window = nullptr;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h
index 4f15bcf080..d239471a5c 100644
--- a/platform/windows/joypad_windows.h
+++ b/platform/windows/joypad_windows.h
@@ -105,10 +105,10 @@ private:
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex, XINPUT_STATE *pState);
typedef DWORD(WINAPI *XInputSetState_t)(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration);
- HWND *hWnd;
+ HWND *hWnd = nullptr;
HANDLE xinput_dll;
LPDIRECTINPUT8 dinput;
- Input *input;
+ Input *input = nullptr;
int id_to_change;
int slider_count;
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 5bfd24327e..adeecf37c5 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -60,14 +60,14 @@
class JoypadWindows;
class OS_Windows : public OS {
#ifdef STDOUT_FILE
- FILE *stdo;
+ FILE *stdo = nullptr;
#endif
uint64_t ticks_start;
uint64_t ticks_per_second;
HINSTANCE hInstance;
- MainLoop *main_loop;
+ MainLoop *main_loop = nullptr;
#ifdef WASAPI_ENABLED
AudioDriverWASAPI driver_wasapi;
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index c503de2d59..50863f2c4d 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -81,7 +81,7 @@ void CollisionObject2D::_notification(int p_what) {
return;
}
- Transform2D global_transform = get_global_transform_with_canvas();
+ Transform2D global_transform = get_global_transform();
if (area) {
PhysicsServer2D::get_singleton()->area_set_transform(rid, global_transform);
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 5d3ef6bf8e..91549d75f0 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -58,6 +58,9 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent2D::set_path_max_distance);
ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent2D::get_path_max_distance);
+ ClassDB::bind_method(D_METHOD("set_navigable_layers", "navigable_layers"), &NavigationAgent2D::set_navigable_layers);
+ ClassDB::bind_method(D_METHOD("get_navigable_layers"), &NavigationAgent2D::get_navigable_layers);
+
ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent2D::set_target_location);
ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent2D::get_target_location);
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent2D::get_next_location);
@@ -79,6 +82,7 @@ void NavigationAgent2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_time_horizon", "get_time_horizon");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01"), "set_max_speed", "get_max_speed");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1"), "set_path_max_distance", "get_path_max_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
@@ -127,8 +131,11 @@ NavigationAgent2D::~NavigationAgent2D() {
}
void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) {
+ bool layers_changed = navigable_layers != p_layers;
navigable_layers = p_layers;
- update_navigation();
+ if (layers_changed) {
+ _request_repath();
+ }
}
uint32_t NavigationAgent2D::get_navigable_layers() const {
@@ -174,10 +181,7 @@ real_t NavigationAgent2D::get_path_max_distance() {
void NavigationAgent2D::set_target_location(Vector2 p_location) {
target_location = p_location;
- navigation_path.clear();
- target_reached = false;
- navigation_finished = false;
- update_frame_id = 0;
+ _request_repath();
}
Vector2 NavigationAgent2D::get_target_location() const {
@@ -312,6 +316,13 @@ void NavigationAgent2D::update_navigation() {
}
}
+void NavigationAgent2D::_request_repath() {
+ navigation_path.clear();
+ target_reached = false;
+ navigation_finished = false;
+ update_frame_id = 0;
+}
+
void NavigationAgent2D::_check_distance_to_target() {
if (!target_reached) {
if (distance_to_target() < target_desired_distance) {
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index dcedc6506a..2fb6fab91c 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -139,6 +139,7 @@ public:
private:
void update_navigation();
+ void _request_repath();
void _check_distance_to_target();
};
diff --git a/scene/2d/physical_bone_2d.h b/scene/2d/physical_bone_2d.h
index 9f31c22031..22d329c320 100644
--- a/scene/2d/physical_bone_2d.h
+++ b/scene/2d/physical_bone_2d.h
@@ -49,7 +49,7 @@ private:
NodePath bone2d_nodepath;
bool follow_bone_when_simulating = false;
- Joint2D *child_joint;
+ Joint2D *child_joint = nullptr;
bool auto_configure_joint = true;
bool simulate_physics = false;
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 9a68c17269..4a4a2a1da0 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -190,7 +190,7 @@ String TouchScreenButton::get_action() const {
void TouchScreenButton::input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
- if (!get_tree()) {
+ if (!is_visible_in_tree()) {
return;
}
@@ -198,8 +198,6 @@ void TouchScreenButton::input(const Ref<InputEvent> &p_event) {
return;
}
- ERR_FAIL_COND(!is_visible_in_tree());
-
const InputEventScreenTouch *st = Object::cast_to<InputEventScreenTouch>(*p_event);
if (passby_press) {
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index d7a2472678..86c11b3789 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -62,6 +62,9 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path_max_distance", "max_speed"), &NavigationAgent3D::set_path_max_distance);
ClassDB::bind_method(D_METHOD("get_path_max_distance"), &NavigationAgent3D::get_path_max_distance);
+ ClassDB::bind_method(D_METHOD("set_navigable_layers", "navigable_layers"), &NavigationAgent3D::set_navigable_layers);
+ ClassDB::bind_method(D_METHOD("get_navigable_layers"), &NavigationAgent3D::get_navigable_layers);
+
ClassDB::bind_method(D_METHOD("set_target_location", "location"), &NavigationAgent3D::set_target_location);
ClassDB::bind_method(D_METHOD("get_target_location"), &NavigationAgent3D::get_target_location);
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent3D::get_next_location);
@@ -85,6 +88,7 @@ void NavigationAgent3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01"), "set_max_speed", "get_max_speed");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
@@ -133,6 +137,18 @@ NavigationAgent3D::~NavigationAgent3D() {
agent = RID(); // Pointless
}
+void NavigationAgent3D::set_navigable_layers(uint32_t p_layers) {
+ bool layers_changed = navigable_layers != p_layers;
+ navigable_layers = p_layers;
+ if (layers_changed) {
+ _request_repath();
+ }
+}
+
+uint32_t NavigationAgent3D::get_navigable_layers() const {
+ return navigable_layers;
+}
+
void NavigationAgent3D::set_target_desired_distance(real_t p_dd) {
target_desired_distance = p_dd;
}
@@ -181,10 +197,7 @@ real_t NavigationAgent3D::get_path_max_distance() {
void NavigationAgent3D::set_target_location(Vector3 p_location) {
target_location = p_location;
- navigation_path.clear();
- target_reached = false;
- navigation_finished = false;
- update_frame_id = 0;
+ _request_repath();
}
Vector3 NavigationAgent3D::get_target_location() const {
@@ -294,7 +307,7 @@ void NavigationAgent3D::update_navigation() {
}
if (reload_path) {
- navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true);
+ navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true, navigable_layers);
navigation_finished = false;
nav_path_index = 0;
emit_signal(SNAME("path_changed"));
@@ -320,6 +333,13 @@ void NavigationAgent3D::update_navigation() {
}
}
+void NavigationAgent3D::_request_repath() {
+ navigation_path.clear();
+ target_reached = false;
+ navigation_finished = false;
+ update_frame_id = 0;
+}
+
void NavigationAgent3D::_check_distance_to_target() {
if (!target_reached) {
if (distance_to_target() < target_desired_distance) {
diff --git a/scene/3d/navigation_agent_3d.h b/scene/3d/navigation_agent_3d.h
index aebd5be7e4..f4afebb36e 100644
--- a/scene/3d/navigation_agent_3d.h
+++ b/scene/3d/navigation_agent_3d.h
@@ -42,6 +42,8 @@ class NavigationAgent3D : public Node {
RID agent;
+ uint32_t navigable_layers = 1;
+
real_t target_desired_distance = 1.0;
real_t radius;
real_t navigation_height_offset = 0.0;
@@ -77,6 +79,9 @@ public:
return agent;
}
+ void set_navigable_layers(uint32_t p_layers);
+ uint32_t get_navigable_layers() const;
+
void set_target_desired_distance(real_t p_dd);
real_t get_target_desired_distance() const {
return target_desired_distance;
@@ -146,6 +151,7 @@ public:
private:
void update_navigation();
+ void _request_repath();
void _check_distance_to_target();
};
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 80ff2a1f79..279c3e49a2 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -44,13 +44,13 @@ class SkinReference : public RefCounted {
GDCLASS(SkinReference, RefCounted)
friend class Skeleton3D;
- Skeleton3D *skeleton_node;
+ Skeleton3D *skeleton_node = nullptr;
RID skeleton;
Ref<Skin> skin;
uint32_t bind_count = 0;
uint64_t skeleton_version = 0;
Vector<uint32_t> skin_bone_indices;
- uint32_t *skin_bone_indices_ptrs;
+ uint32_t *skin_bone_indices_ptrs = nullptr;
void _skin_changed();
protected:
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index c8eb270a0a..ccc878a6ec 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -130,6 +130,7 @@ void Tween::stop() {
started = false;
running = false;
dead = false;
+ total_time = 0;
}
void Tween::pause() {
@@ -272,12 +273,14 @@ bool Tween::step(float p_delta) {
ERR_FAIL_COND_V_MSG(tweeners.is_empty(), false, "Tween started, but has no Tweeners.");
current_step = 0;
loops_done = 0;
+ total_time = 0;
start_tweeners();
started = true;
}
float rem_delta = p_delta * speed_scale;
bool step_active = false;
+ total_time += rem_delta;
while (rem_delta > 0 && running) {
float step_delta = rem_delta;
@@ -346,6 +349,10 @@ Node *Tween::get_bound_node() const {
}
}
+float Tween::get_total_time() const {
+ return total_time;
+}
+
real_t Tween::run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t p_time, real_t p_initial, real_t p_delta, real_t p_duration) {
if (p_duration == 0) {
// Special case to avoid dividing by 0 in equations.
@@ -624,6 +631,7 @@ void Tween::_bind_methods() {
ClassDB::bind_method(D_METHOD("pause"), &Tween::pause);
ClassDB::bind_method(D_METHOD("play"), &Tween::play);
ClassDB::bind_method(D_METHOD("kill"), &Tween::kill);
+ ClassDB::bind_method(D_METHOD("get_total_elapsed_time"), &Tween::get_total_time);
ClassDB::bind_method(D_METHOD("is_running"), &Tween::is_running);
ClassDB::bind_method(D_METHOD("is_valid"), &Tween::is_valid);
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index 62c357dfb4..e28a499259 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -103,6 +103,7 @@ private:
ObjectID bound_node;
Vector<List<Ref<Tweener>>> tweeners;
+ float total_time = 0;
int current_step = -1;
int loops = 1;
int loops_done = 0;
@@ -166,6 +167,7 @@ public:
bool step(float p_delta);
bool can_process(bool p_tree_paused) const;
Node *get_bound_node() const;
+ float get_total_time() const;
Tween() {}
};
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 2f96ee675f..96d2b29fc1 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -367,7 +367,7 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
void Control::_get_property_list(List<PropertyInfo> *p_list) const {
Ref<Theme> theme = Theme::get_default();
- p_list->push_back(PropertyInfo(Variant::NIL, "Theme Overrides", PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
+ p_list->push_back(PropertyInfo(Variant::NIL, TTRC("Theme Overrides"), PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
{
List<StringName> names;
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index be57ca9084..0bb96a18a5 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -39,13 +39,13 @@
void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> key = p_event;
- if (key.is_valid() && key->is_pressed() && key->get_keycode() == Key::ESCAPE) {
+ if (close_on_escape && key.is_valid() && key->is_pressed() && key->get_keycode() == Key::ESCAPE) {
_cancel_pressed();
}
}
void AcceptDialog::_parent_focused() {
- if (!is_exclusive()) {
+ if (close_on_escape && !is_exclusive()) {
_cancel_pressed();
}
}
@@ -145,6 +145,14 @@ bool AcceptDialog::get_hide_on_ok() const {
return hide_on_ok;
}
+void AcceptDialog::set_close_on_escape(bool p_hide) {
+ close_on_escape = p_hide;
+}
+
+bool AcceptDialog::get_close_on_escape() const {
+ return close_on_escape;
+}
+
void AcceptDialog::set_autowrap(bool p_autowrap) {
label->set_autowrap_mode(p_autowrap ? Label::AUTOWRAP_WORD : Label::AUTOWRAP_OFF);
}
@@ -288,6 +296,8 @@ void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_label"), &AcceptDialog::get_label);
ClassDB::bind_method(D_METHOD("set_hide_on_ok", "enabled"), &AcceptDialog::set_hide_on_ok);
ClassDB::bind_method(D_METHOD("get_hide_on_ok"), &AcceptDialog::get_hide_on_ok);
+ ClassDB::bind_method(D_METHOD("set_close_on_escape", "enabled"), &AcceptDialog::set_close_on_escape);
+ ClassDB::bind_method(D_METHOD("get_close_on_escape"), &AcceptDialog::get_close_on_escape);
ClassDB::bind_method(D_METHOD("add_button", "text", "right", "action"), &AcceptDialog::add_button, DEFVAL(false), DEFVAL(""));
ClassDB::bind_method(D_METHOD("add_cancel_button", "name"), &AcceptDialog::add_cancel_button);
ClassDB::bind_method(D_METHOD("remove_button", "button"), &AcceptDialog::remove_button);
@@ -304,6 +314,7 @@ void AcceptDialog::_bind_methods() {
ADD_GROUP("Dialog", "dialog");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "dialog_text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_hide_on_ok"), "set_hide_on_ok", "get_hide_on_ok");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_close_on_escape"), "set_close_on_escape", "get_close_on_escape");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dialog_autowrap"), "set_autowrap", "has_autowrap");
}
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index 1365b1df24..41fd9c0a10 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -45,11 +45,12 @@ class AcceptDialog : public Window {
GDCLASS(AcceptDialog, Window);
Window *parent_visible = nullptr;
- Panel *bg;
- HBoxContainer *hbc;
- Label *label;
- Button *ok;
+ Panel *bg = nullptr;
+ HBoxContainer *hbc = nullptr;
+ Label *label = nullptr;
+ Button *ok = nullptr;
bool hide_on_ok = true;
+ bool close_on_escape = true;
void _custom_action(const String &p_action);
void _update_child_rects();
@@ -87,6 +88,9 @@ public:
void set_hide_on_ok(bool p_hide);
bool get_hide_on_ok() const;
+ void set_close_on_escape(bool p_enable);
+ bool get_close_on_escape() const;
+
void set_text(String p_text);
String get_text() const;
@@ -99,7 +103,7 @@ public:
class ConfirmationDialog : public AcceptDialog {
GDCLASS(ConfirmationDialog, AcceptDialog);
- Button *cancel;
+ Button *cancel = nullptr;
protected:
static void _bind_methods();
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 7a50efe40f..9bba93bb89 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -65,34 +65,34 @@ public:
static RegisterFunc unregister_func;
private:
- ConfirmationDialog *makedialog;
- LineEdit *makedirname;
+ ConfirmationDialog *makedialog = nullptr;
+ LineEdit *makedirname = nullptr;
- Button *makedir;
+ Button *makedir = nullptr;
Access access = ACCESS_RESOURCES;
- VBoxContainer *vbox;
+ VBoxContainer *vbox = nullptr;
FileMode mode;
- LineEdit *dir;
- HBoxContainer *drives_container;
- HBoxContainer *shortcuts_container;
- OptionButton *drives;
- Tree *tree;
- HBoxContainer *file_box;
- LineEdit *file;
- OptionButton *filter;
- AcceptDialog *mkdirerr;
- AcceptDialog *exterr;
- DirAccess *dir_access;
- ConfirmationDialog *confirm_save;
-
- Label *message;
-
- Button *dir_prev;
- Button *dir_next;
- Button *dir_up;
-
- Button *refresh;
- Button *show_hidden;
+ LineEdit *dir = nullptr;
+ HBoxContainer *drives_container = nullptr;
+ HBoxContainer *shortcuts_container = nullptr;
+ OptionButton *drives = nullptr;
+ Tree *tree = nullptr;
+ HBoxContainer *file_box = nullptr;
+ LineEdit *file = nullptr;
+ OptionButton *filter = nullptr;
+ AcceptDialog *mkdirerr = nullptr;
+ AcceptDialog *exterr = nullptr;
+ DirAccess *dir_access = nullptr;
+ ConfirmationDialog *confirm_save = nullptr;
+
+ Label *message = nullptr;
+
+ Button *dir_prev = nullptr;
+ Button *dir_next = nullptr;
+ Button *dir_up = nullptr;
+
+ Button *refresh = nullptr;
+ Button *show_hidden = nullptr;
Vector<String> filters;
diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h
index 67531d4f4a..4e3c6525f9 100644
--- a/scene/gui/gradient_edit.h
+++ b/scene/gui/gradient_edit.h
@@ -38,8 +38,8 @@
class GradientEdit : public Control {
GDCLASS(GradientEdit, Control);
- PopupPanel *popup;
- ColorPicker *picker;
+ PopupPanel *popup = nullptr;
+ ColorPicker *picker = nullptr;
bool grabbing = false;
int grabbed = -1;
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index b0d1944d6e..18b9eeebd4 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -46,7 +46,7 @@ class GraphEditFilter : public Control {
friend class GraphEdit;
friend class GraphEditMinimap;
- GraphEdit *ge;
+ GraphEdit *ge = nullptr;
virtual bool has_point(const Point2 &p_point) const override;
public:
@@ -58,7 +58,7 @@ class GraphEditMinimap : public Control {
friend class GraphEdit;
friend class GraphEditFilter;
- GraphEdit *ge;
+ GraphEdit *ge = nullptr;
protected:
public:
@@ -109,20 +109,20 @@ public:
};
private:
- Label *zoom_label;
- Button *zoom_minus;
- Button *zoom_reset;
- Button *zoom_plus;
+ Label *zoom_label = nullptr;
+ Button *zoom_minus = nullptr;
+ Button *zoom_reset = nullptr;
+ Button *zoom_plus = nullptr;
- Button *snap_button;
- SpinBox *snap_amount;
+ Button *snap_button = nullptr;
+ SpinBox *snap_amount = nullptr;
- Button *minimap_button;
+ Button *minimap_button = nullptr;
- Button *layout_button;
+ Button *layout_button = nullptr;
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
+ HScrollBar *h_scroll = nullptr;
+ VScrollBar *v_scroll = nullptr;
float port_grab_distance_horizontal = 0.0;
float port_grab_distance_vertical;
@@ -190,9 +190,9 @@ private:
void _scroll_moved(double);
virtual void gui_input(const Ref<InputEvent> &p_ev) override;
- Control *connections_layer;
- GraphEditFilter *top_layer;
- GraphEditMinimap *minimap;
+ Control *connections_layer = nullptr;
+ GraphEditFilter *top_layer = nullptr;
+ GraphEditMinimap *minimap = nullptr;
void _top_layer_input(const Ref<InputEvent> &p_ev);
bool is_in_input_hotzone(GraphNode *p_graph_node, int p_slot_index, const Vector2 &p_mouse_pos, const Vector2i &p_port_size);
@@ -236,7 +236,7 @@ private:
void _set_drag_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, bool p_drag);
void _set_position_of_comment_enclosed_nodes(GraphNode *p_node, HashMap<StringName, Vector<GraphNode *>> &p_comment_enclosed_nodes, Vector2 p_pos);
- HBoxContainer *zoom_hb;
+ HBoxContainer *zoom_hb = nullptr;
friend class GraphEditFilter;
bool _filter_input(const Point2 &p_point);
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 96735678c1..ffbe7d055a 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -98,7 +98,7 @@ private:
SelectMode select_mode = SELECT_SINGLE;
IconMode icon_mode = ICON_MODE_LEFT;
- VScrollBar *scroll_bar;
+ VScrollBar *scroll_bar = nullptr;
TextParagraph::OverrunBehavior text_overrun_behavior = TextParagraph::OVERRUN_TRIM_ELLIPSIS;
uint64_t search_time_msec = 0;
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index 9cfb780255..e3ead9c291 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -40,7 +40,7 @@ class MenuButton : public Button {
bool clicked = false;
bool switch_on_hover = false;
bool disable_shortcuts = false;
- PopupMenu *popup;
+ PopupMenu *popup = nullptr;
Vector2i mouse_pos_adjusted;
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index 732730e0f4..921b76c52a 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -37,7 +37,7 @@
class OptionButton : public Button {
GDCLASS(OptionButton, Button);
- PopupMenu *popup;
+ PopupMenu *popup = nullptr;
int current = -1;
void _focused(int p_which);
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index c45f4ddc24..6211af4d20 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -65,7 +65,7 @@ public:
class PopupPanel : public Popup {
GDCLASS(PopupPanel, Popup);
- Panel *panel;
+ Panel *panel = nullptr;
protected:
void _update_child_rects();
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 5ce55209d4..518ba14dae 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -89,7 +89,7 @@ class PopupMenu : public Popup {
bool close_allowed = false;
Timer *minimum_lifetime_timer = nullptr;
- Timer *submenu_timer;
+ Timer *submenu_timer = nullptr;
List<Rect2> autohide_areas;
Vector<Item> items;
MouseButton initial_button_mask = MouseButton::NONE;
@@ -125,9 +125,9 @@ class PopupMenu : public Popup {
uint64_t search_time_msec = 0;
String search_string = "";
- MarginContainer *margin_container;
- ScrollContainer *scroll_container;
- Control *control;
+ MarginContainer *margin_container = nullptr;
+ ScrollContainer *scroll_container = nullptr;
+ Control *control = nullptr;
void _draw_items();
void _draw_background();
diff --git a/scene/gui/range.h b/scene/gui/range.h
index 597c50ca26..46b0d39202 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -50,7 +50,7 @@ class Range : public Control {
void emit_changed(const char *p_what = "");
};
- Shared *shared;
+ Shared *shared = nullptr;
void _ref_shared(Shared *p_shared);
void _unref_shared();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 70755a2870..86f0b37482 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1650,8 +1650,7 @@ void RichTextLabel::_notification(int p_what) {
case NOTIFICATION_FOCUS_EXIT: {
if (deselect_on_focus_loss_enabled) {
- selection.active = false;
- update();
+ deselect();
}
} break;
@@ -1742,9 +1741,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
selection.to_line = 0;
selection.to_item = nullptr;
selection.to_char = 0;
- selection.active = false;
-
- update();
+ deselect();
}
}
}
@@ -1802,9 +1799,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
selection.to_line = 0;
selection.to_item = nullptr;
selection.to_char = 0;
- selection.active = false;
-
- update();
+ deselect();
}
}
@@ -1925,8 +1920,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
if (selection.from_char > selection.to_char) {
swap = true;
} else if (selection.from_char == selection.to_char) {
- selection.active = false;
- update();
+ deselect();
return;
}
}
@@ -2977,11 +2971,10 @@ void RichTextLabel::clear() {
main->lines.clear();
main->lines.resize(1);
main->first_invalid_line = 0;
- update();
selection.click_frame = nullptr;
selection.click_item = nullptr;
- selection.active = false;
+ deselect();
current_idx = 1;
current_char_ofs = 0;
@@ -3890,8 +3883,7 @@ void RichTextLabel::set_selection_enabled(bool p_enabled) {
selection.enabled = p_enabled;
if (!p_enabled) {
if (selection.active) {
- selection.active = false;
- update();
+ deselect();
}
set_focus_mode(FOCUS_NONE);
} else {
@@ -3902,8 +3894,7 @@ void RichTextLabel::set_selection_enabled(bool p_enabled) {
void RichTextLabel::set_deselect_on_focus_loss_enabled(const bool p_enabled) {
deselect_on_focus_loss_enabled = p_enabled;
if (p_enabled && selection.active && !has_focus()) {
- selection.active = false;
- update();
+ deselect();
}
}
@@ -4154,6 +4145,11 @@ String RichTextLabel::get_selected_text() const {
return text;
}
+void RichTextLabel::deselect() {
+ selection.active = false;
+ update();
+}
+
void RichTextLabel::selection_copy() {
String text = get_selected_text();
@@ -4460,6 +4456,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_selection_to"), &RichTextLabel::get_selection_to);
ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text);
+ ClassDB::bind_method(D_METHOD("deselect"), &RichTextLabel::deselect);
ClassDB::bind_method(D_METHOD("parse_bbcode", "bbcode"), &RichTextLabel::parse_bbcode);
ClassDB::bind_method(D_METHOD("append_text", "bbcode"), &RichTextLabel::append_text);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index c9cbbe9d15..ccac1d5ea6 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -587,6 +587,7 @@ public:
void selection_copy();
void set_deselect_on_focus_loss_enabled(const bool p_enabled);
bool is_deselect_on_focus_loss_enabled() const;
+ void deselect();
void parse_bbcode(const String &p_bbcode);
void append_text(const String &p_bbcode);
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index c00df87b18..b9fcf64db6 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -47,8 +47,8 @@ public:
};
private:
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
+ HScrollBar *h_scroll = nullptr;
+ VScrollBar *v_scroll = nullptr;
Size2 child_max_size;
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index a15e3fe5f5..d118b28334 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -38,11 +38,11 @@
class SpinBox : public Range {
GDCLASS(SpinBox, Range);
- LineEdit *line_edit;
+ LineEdit *line_edit = nullptr;
int last_w = 0;
bool update_on_text_changed = false;
- Timer *range_click_timer;
+ Timer *range_click_timer = nullptr;
void _range_click_timeout();
void _release_mouse();
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 05f1ee3dad..84a62c71c2 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -472,6 +472,10 @@ void TabContainer::_on_tab_selected(int p_tab) {
emit_signal(SNAME("tab_selected"), p_tab);
}
+void TabContainer::_on_tab_button_pressed(int p_tab) {
+ emit_signal(SNAME("tab_button_pressed"), p_tab);
+}
+
void TabContainer::_refresh_tab_names() {
Vector<Control *> controls = _get_tab_controls();
for (int i = 0; i < controls.size(); i++) {
@@ -733,6 +737,17 @@ bool TabContainer::is_tab_hidden(int p_tab) const {
return tab_bar->is_tab_hidden(p_tab);
}
+void TabContainer::set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon) {
+ tab_bar->set_tab_button_icon(p_tab, p_icon);
+
+ _update_margins();
+ _repaint();
+}
+
+Ref<Texture2D> TabContainer::get_tab_button_icon(int p_tab) const {
+ return tab_bar->get_tab_button_icon(p_tab);
+}
+
void TabContainer::get_translatable_strings(List<String> *p_strings) const {
Vector<Control *> controls = _get_tab_controls();
for (int i = 0; i < controls.size(); i++) {
@@ -877,6 +892,8 @@ void TabContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_tab_disabled", "tab_idx"), &TabContainer::is_tab_disabled);
ClassDB::bind_method(D_METHOD("set_tab_hidden", "tab_idx", "hidden"), &TabContainer::set_tab_hidden);
ClassDB::bind_method(D_METHOD("is_tab_hidden", "tab_idx"), &TabContainer::is_tab_hidden);
+ ClassDB::bind_method(D_METHOD("set_tab_button_icon", "tab_idx", "icon"), &TabContainer::set_tab_button_icon);
+ ClassDB::bind_method(D_METHOD("get_tab_button_icon", "tab_idx"), &TabContainer::get_tab_button_icon);
ClassDB::bind_method(D_METHOD("get_tab_idx_at_point", "point"), &TabContainer::get_tab_idx_at_point);
ClassDB::bind_method(D_METHOD("get_tab_idx_from_control", "control"), &TabContainer::get_tab_idx_from_control);
ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup);
@@ -896,6 +913,7 @@ void TabContainer::_bind_methods() {
ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("tab_selected", PropertyInfo(Variant::INT, "tab")));
+ ADD_SIGNAL(MethodInfo("tab_button_pressed", PropertyInfo(Variant::INT, "tab")));
ADD_SIGNAL(MethodInfo("pre_popup_pressed"));
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment");
@@ -915,6 +933,7 @@ TabContainer::TabContainer() {
tab_bar->set_anchors_and_offsets_preset(Control::PRESET_TOP_WIDE);
tab_bar->connect("tab_changed", callable_mp(this, &TabContainer::_on_tab_changed));
tab_bar->connect("tab_selected", callable_mp(this, &TabContainer::_on_tab_selected));
+ tab_bar->connect("tab_button_pressed", callable_mp(this, &TabContainer::_on_tab_button_pressed));
connect("mouse_exited", callable_mp(this, &TabContainer::_on_mouse_exited));
}
diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h
index c54934b37b..9adaa0d844 100644
--- a/scene/gui/tab_container.h
+++ b/scene/gui/tab_container.h
@@ -38,7 +38,7 @@
class TabContainer : public Container {
GDCLASS(TabContainer, Container);
- TabBar *tab_bar;
+ TabBar *tab_bar = nullptr;
bool tabs_visible = true;
bool all_tabs_in_front = false;
bool menu_hovered = false;
@@ -56,6 +56,7 @@ class TabContainer : public Container {
void _on_mouse_exited();
void _on_tab_changed(int p_tab);
void _on_tab_selected(int p_tab);
+ void _on_tab_button_pressed(int p_tab);
Variant _get_drag_data_fw(const Point2 &p_point, Control *p_from_control);
bool _can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from_control) const;
@@ -97,6 +98,9 @@ public:
void set_tab_hidden(int p_tab, bool p_hidden);
bool is_tab_hidden(int p_tab) const;
+ void set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon);
+ Ref<Texture2D> get_tab_button_icon(int p_tab) const;
+
int get_tab_count() const;
void set_current_tab(int p_current);
int get_current_tab() const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 3c80e3f987..1bed72c907 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -471,6 +471,11 @@ void TextEdit::_notification(int p_what) {
// To ensure minimap is responsive override the speed setting.
double vel = ((target_y / dist) * ((minimap_clicked) ? 3000 : v_scroll_speed)) * get_physics_process_delta_time();
+ // Prevent too small velocity to block scrolling
+ if (Math::abs(vel) < v_scroll->get_step()) {
+ vel = v_scroll->get_step() * SIGN(vel);
+ }
+
if (Math::abs(vel) >= dist) {
set_v_scroll(target_v_scroll);
scrolling = false;
@@ -2133,16 +2138,21 @@ void TextEdit::_move_caret_left(bool p_select, bool p_move_by_word) {
if (p_move_by_word) {
int cc = caret.column;
-
+ // If the caret is at the start of the line, and not on the first line, move it up to the end of the previous line.
if (cc == 0 && caret.line > 0) {
set_caret_line(caret.line - 1);
set_caret_column(text[caret.line].length());
} else {
PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
- for (int i = words.size() - 2; i >= 0; i = i - 2) {
- if (words[i] < cc) {
- cc = words[i];
- break;
+ if (words.is_empty() || cc <= words[0]) {
+ // This solves the scenario where there are no words but glyfs that can be ignored.
+ cc = 0;
+ } else {
+ for (int i = words.size() - 2; i >= 0; i = i - 2) {
+ if (words[i] < cc) {
+ cc = words[i];
+ break;
+ }
}
}
set_caret_column(cc);
@@ -2184,16 +2194,21 @@ void TextEdit::_move_caret_right(bool p_select, bool p_move_by_word) {
if (p_move_by_word) {
int cc = caret.column;
-
+ // If the caret is at the end of the line, and not on the last line, move it down to the beginning of the next line.
if (cc == text[caret.line].length() && caret.line < text.size() - 1) {
set_caret_line(caret.line + 1);
set_caret_column(0);
} else {
PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
- for (int i = 1; i < words.size(); i = i + 2) {
- if (words[i] > cc) {
- cc = words[i];
- break;
+ if (words.is_empty() || cc >= words[words.size() - 1]) {
+ // This solves the scenario where there are no words but glyfs that can be ignored.
+ cc = text[caret.line].length();
+ } else {
+ for (int i = 1; i < words.size(); i = i + 2) {
+ if (words[i] > cc) {
+ cc = words[i];
+ break;
+ }
}
}
set_caret_column(cc);
@@ -2364,11 +2379,11 @@ void TextEdit::_move_caret_page_down(bool p_select) {
}
void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) {
- if (!editable) {
+ if (!editable || (caret.column == 0 && caret.line == 0)) {
return;
}
- if (has_selection() || (!p_all_to_left && !p_word)) {
+ if (has_selection() || (!p_all_to_left && !p_word) || caret.column == 0) {
backspace();
return;
}
@@ -2381,20 +2396,30 @@ void TextEdit::_do_backspace(bool p_word, bool p_all_to_left) {
}
if (p_word) {
- int line = caret.line;
int column = caret.column;
-
- PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(line)->get_rid());
- for (int i = words.size() - 2; i >= 0; i = i - 2) {
- if (words[i] < column) {
- column = words[i];
- break;
+ // Check for the case "<word><space><caret>" and ignore the space.
+ // No need to check for column being 0 since it is cheked above.
+ if (is_whitespace(text[caret.line][caret.column - 1])) {
+ column -= 1;
+ }
+ // Get a list with the indices of the word bounds of the given text line.
+ const PackedInt32Array words = TS->shaped_text_get_word_breaks(text.get_line_data(caret.line)->get_rid());
+ if (words.is_empty() || column <= words[0]) {
+ // If "words" is empty, meaning no words are left, we can remove everything until the begining of the line.
+ column = 0;
+ } else {
+ // Otherwise search for the first word break that is smaller than the index from we're currentlu deleteing
+ for (int i = words.size() - 2; i >= 0; i = i - 2) {
+ if (words[i] < column) {
+ column = words[i];
+ break;
+ }
}
}
- _remove_text(line, column, caret.line, caret.column);
+ _remove_text(caret.line, column, caret.line, caret.column);
- set_caret_line(line, false);
+ set_caret_line(caret.line, false);
set_caret_column(column);
return;
}
@@ -4390,6 +4415,8 @@ int TextEdit::get_h_scroll() const {
}
void TextEdit::set_v_scroll_speed(float p_speed) {
+ // Prevent setting a vertical scroll speed value under 1.0
+ ERR_FAIL_COND(p_speed < 1.0);
v_scroll_speed = p_speed;
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 6deaf76e5e..7d36051a37 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -325,7 +325,7 @@ private:
List<TextOperation> undo_stack;
List<TextOperation>::Element *undo_stack_pos = nullptr;
- Timer *idle_detect;
+ Timer *idle_detect = nullptr;
uint32_t version = 0;
uint32_t saved_version = 0;
@@ -380,7 +380,7 @@ private:
bool draw_caret = true;
bool caret_blink_enabled = false;
- Timer *caret_blink_timer;
+ Timer *caret_blink_timer = nullptr;
bool move_caret_on_right_click = true;
@@ -426,7 +426,7 @@ private:
bool dragging_selection = false;
- Timer *click_select_held;
+ Timer *click_select_held = nullptr;
uint64_t last_dblclk = 0;
Vector2 last_dblclk_pos;
void _click_selection_held();
@@ -449,8 +449,8 @@ private:
void _update_caret_wrap_offset();
/* Viewport. */
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
+ HScrollBar *h_scroll = nullptr;
+ VScrollBar *v_scroll = nullptr;
bool scroll_past_end_of_file_enabled = false;
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 04d4b9b935..74ad4f94b8 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -134,7 +134,7 @@ private:
Vector<TreeItem *> children_cache;
bool is_root = false; // for tree root
- Tree *tree; // tree (for reference)
+ Tree *tree = nullptr; // tree (for reference)
TreeItem(Tree *p_tree);
@@ -428,18 +428,18 @@ private:
bool show_column_titles = false;
- VBoxContainer *popup_editor_vb;
+ VBoxContainer *popup_editor_vb = nullptr;
- Popup *popup_editor;
+ Popup *popup_editor = nullptr;
LineEdit *text_editor = nullptr;
- HSlider *value_editor;
+ HSlider *value_editor = nullptr;
bool updating_value_editor = false;
uint64_t focus_in_id = 0;
PopupMenu *popup_menu = nullptr;
Vector<ColumnInfo> columns;
- Timer *range_click_timer;
+ Timer *range_click_timer = nullptr;
TreeItem *range_item_last = nullptr;
bool range_up_last = false;
void _range_click_timeout();
@@ -553,8 +553,8 @@ private:
int _get_title_button_height() const;
void _scroll_moved(float p_value);
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
+ HScrollBar *h_scroll = nullptr;
+ VScrollBar *v_scroll = nullptr;
bool h_scroll_enabled = true;
bool v_scroll_enabled = true;
diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp
index 71865b4864..892d0aba29 100644
--- a/scene/gui/view_panner.cpp
+++ b/scene/gui/view_panner.cpp
@@ -37,7 +37,7 @@
bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- Vector2i scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP));
+ Vector2 scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP));
if (scroll_vec != Vector2()) {
if (control_scheme == SCROLL_PANS) {
if (mb->is_ctrl_pressed()) {
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 26d648458f..8b3441f7d7 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -144,7 +144,7 @@ public:
void set_max_redirects(int p_max);
int get_max_redirects() const;
- Timer *timer;
+ Timer *timer = nullptr;
void set_timeout(double p_timeout);
double get_timeout();
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 10839ca425..0f8cbedb41 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -115,7 +115,7 @@ private:
int node_count = 0;
#ifdef TOOLS_ENABLED
- Node *edited_scene_root;
+ Node *edited_scene_root = nullptr;
#endif
struct UGCall {
StringName group;
@@ -138,7 +138,7 @@ private:
Array _get_nodes_in_group(const StringName &p_group);
- Node *current_scene;
+ Node *current_scene = nullptr;
Color debug_collisions_color;
Color debug_collision_contact_color;
diff --git a/scene/multiplayer/scene_cache_interface.h b/scene/multiplayer/scene_cache_interface.h
index c709d26b51..d53cf387fb 100644
--- a/scene/multiplayer/scene_cache_interface.h
+++ b/scene/multiplayer/scene_cache_interface.h
@@ -37,7 +37,7 @@ class SceneCacheInterface : public MultiplayerCacheInterface {
GDCLASS(SceneCacheInterface, MultiplayerCacheInterface);
private:
- MultiplayerAPI *multiplayer;
+ MultiplayerAPI *multiplayer = nullptr;
//path sent caches
struct PathSentCache {
diff --git a/scene/multiplayer/scene_replication_interface.h b/scene/multiplayer/scene_replication_interface.h
index 855878d029..60ac95c93c 100644
--- a/scene/multiplayer/scene_replication_interface.h
+++ b/scene/multiplayer/scene_replication_interface.h
@@ -47,7 +47,7 @@ private:
void _free_remotes(int p_peer);
Ref<SceneReplicationState> rep_state;
- MultiplayerAPI *multiplayer;
+ MultiplayerAPI *multiplayer = nullptr;
PackedByteArray packet_cache;
int sync_mtu = 1350; // Highly dependent on underlying protocol.
diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp
index 47a87bdea5..552fa84bad 100644
--- a/scene/resources/navigation_mesh.cpp
+++ b/scene/resources/navigation_mesh.cpp
@@ -388,6 +388,10 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() {
debug_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
+ if (!lines.size()) {
+ return debug_mesh;
+ }
+
Array arr;
arr.resize(Mesh::ARRAY_MAX);
arr[Mesh::ARRAY_VERTEX] = varr;
diff --git a/scene/resources/skeleton_modification_2d.h b/scene/resources/skeleton_modification_2d.h
index d49f9e7f51..3b9235ffd8 100644
--- a/scene/resources/skeleton_modification_2d.h
+++ b/scene/resources/skeleton_modification_2d.h
@@ -49,7 +49,7 @@ class SkeletonModification2D : public Resource {
protected:
static void _bind_methods();
- SkeletonModificationStack2D *stack;
+ SkeletonModificationStack2D *stack = nullptr;
int execution_mode = 0; // 0 = process
bool enabled = true;
diff --git a/scene/resources/skeleton_modification_3d.h b/scene/resources/skeleton_modification_3d.h
index a81c0c38bd..ab736fcbd2 100644
--- a/scene/resources/skeleton_modification_3d.h
+++ b/scene/resources/skeleton_modification_3d.h
@@ -44,7 +44,7 @@ class SkeletonModification3D : public Resource {
protected:
static void _bind_methods();
- SkeletonModificationStack3D *stack;
+ SkeletonModificationStack3D *stack = nullptr;
int execution_mode = 0; // 0 = process
bool enabled = true;
diff --git a/scene/resources/text_line.cpp b/scene/resources/text_line.cpp
index db5f1338db..337776fd47 100644
--- a/scene/resources/text_line.cpp
+++ b/scene/resources/text_line.cpp
@@ -327,10 +327,18 @@ void TextLine::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_color) co
case HORIZONTAL_ALIGNMENT_LEFT:
break;
case HORIZONTAL_ALIGNMENT_CENTER: {
- if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.x += Math::floor((width - length) / 2.0);
- } else {
- ofs.y += Math::floor((width - length) / 2.0);
+ if (length <= width) {
+ if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += Math::floor((width - length) / 2.0);
+ } else {
+ ofs.y += Math::floor((width - length) / 2.0);
+ }
+ } else if (TS->shaped_text_get_inferred_direction(rid) == TextServer::DIRECTION_RTL) {
+ if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += width - length;
+ } else {
+ ofs.y += width - length;
+ }
}
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
@@ -366,10 +374,18 @@ void TextLine::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outline_si
case HORIZONTAL_ALIGNMENT_LEFT:
break;
case HORIZONTAL_ALIGNMENT_CENTER: {
- if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.x += Math::floor((width - length) / 2.0);
- } else {
- ofs.y += Math::floor((width - length) / 2.0);
+ if (length <= width) {
+ if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += Math::floor((width - length) / 2.0);
+ } else {
+ ofs.y += Math::floor((width - length) / 2.0);
+ }
+ } else if (TS->shaped_text_get_inferred_direction(rid) == TextServer::DIRECTION_RTL) {
+ if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += width - length;
+ } else {
+ ofs.y += width - length;
+ }
}
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp
index d74d7c88c6..61adaf43dd 100644
--- a/scene/resources/text_paragraph.cpp
+++ b/scene/resources/text_paragraph.cpp
@@ -609,10 +609,18 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo
case HORIZONTAL_ALIGNMENT_LEFT:
break;
case HORIZONTAL_ALIGNMENT_CENTER: {
- if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.x += Math::floor((l_width - line_width) / 2.0);
- } else {
- ofs.y += Math::floor((l_width - line_width) / 2.0);
+ if (line_width <= l_width) {
+ if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += Math::floor((l_width - line_width) / 2.0);
+ } else {
+ ofs.y += Math::floor((l_width - line_width) / 2.0);
+ }
+ } else if (TS->shaped_text_get_inferred_direction(lines_rid[i]) == TextServer::DIRECTION_RTL) {
+ if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += l_width - line_width;
+ } else {
+ ofs.y += l_width - line_width;
+ }
}
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
@@ -701,10 +709,18 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli
case HORIZONTAL_ALIGNMENT_LEFT:
break;
case HORIZONTAL_ALIGNMENT_CENTER: {
- if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
- ofs.x += Math::floor((l_width - length) / 2.0);
- } else {
- ofs.y += Math::floor((l_width - length) / 2.0);
+ if (length <= l_width) {
+ if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += Math::floor((l_width - length) / 2.0);
+ } else {
+ ofs.y += Math::floor((l_width - length) / 2.0);
+ }
+ } else if (TS->shaped_text_get_inferred_direction(lines_rid[i]) == TextServer::DIRECTION_RTL) {
+ if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) {
+ ofs.x += l_width - length;
+ } else {
+ ofs.y += l_width - length;
+ }
}
} break;
case HORIZONTAL_ALIGNMENT_RIGHT: {
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index a66d9d9f27..44da90de30 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -1142,7 +1142,7 @@ bool Texture3D::has_mipmaps() const {
if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) {
return ret;
}
- return 0;
+ return false;
}
Vector<Ref<Image>> Texture3D::get_data() const {
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 6324e2f5d3..68b523e086 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -40,7 +40,7 @@ class AudioDriverDummy : public AudioDriver {
Thread thread;
Mutex mutex;
- int32_t *samples_in;
+ int32_t *samples_in = nullptr;
static void thread_func(void *p_udata);
diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h
index 9e55662d0a..1ec1abd4d5 100644
--- a/servers/audio/audio_filter_sw.h
+++ b/servers/audio/audio_filter_sw.h
@@ -57,7 +57,7 @@ public:
class Processor { // simple filter processor
- AudioFilterSW *filter;
+ AudioFilterSW *filter = nullptr;
Coeffs coeffs;
float ha1, ha2, hb1, hb2; //history
Coeffs incr_coeffs;
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
index 3fbe684c3e..81ac6332e2 100644
--- a/servers/audio/audio_rb_resampler.h
+++ b/servers/audio/audio_rb_resampler.h
@@ -55,8 +55,8 @@ struct AudioRBResampler {
MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
};
- float *read_buf;
- float *rb;
+ float *read_buf = nullptr;
+ float *rb = nullptr;
template <int C>
uint32_t _resample(AudioFrame *p_dest, int p_todo, int32_t p_increment);
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h
index 8b8b7b47a0..1f93d1cf9f 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.h
+++ b/servers/audio/effects/audio_effect_stereo_enhance.h
@@ -44,7 +44,7 @@ class AudioEffectStereoEnhanceInstance : public AudioEffectInstance {
MAX_DELAY_MS = 50
};
- float *delay_ringbuff;
+ float *delay_ringbuff = nullptr;
unsigned int ringbuff_pos;
unsigned int ringbuff_mask;
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 51288262b3..2ce4b95fcf 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -65,7 +65,7 @@ class AudioStreamGeneratorPlayback : public AudioStreamPlaybackResampled {
int skips;
bool active;
float mixed;
- AudioStreamGenerator *generator;
+ AudioStreamGenerator *generator = nullptr;
protected:
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h
index ff59ab8d82..de25e8c52b 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb.h
@@ -75,7 +75,7 @@ private:
Comb comb[MAX_COMBS];
AllPass allpass[MAX_ALLPASS];
- float *input_buffer;
+ float *input_buffer = nullptr;
float *echo_buffer = nullptr;
int echo_buffer_size;
int echo_buffer_pos;
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 9d83e5cacc..777bebcf60 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -1343,6 +1343,7 @@ void AudioServer::init_channels_and_buffers() {
for (int j = 0; j < channel_count; j++) {
buses.write[i]->channels.write[j].buffer.resize(buffer_size);
}
+ _update_bus_effects(i);
}
}
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 0c150427f2..5563d60e4a 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -284,7 +284,7 @@ private:
struct CallbackItem {
AudioCallback callback;
- void *userdata;
+ void *userdata = nullptr;
};
SafeList<CallbackItem *> update_callback_list;
diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h
index 77e867a05a..ce6bed41c9 100644
--- a/servers/extensions/physics_server_3d_extension.h
+++ b/servers/extensions/physics_server_3d_extension.h
@@ -193,7 +193,7 @@ typedef PhysicsServer3D::MotionCollision PhysicsServer3DExtensionMotionCollision
typedef PhysicsServer3D::MotionResult PhysicsServer3DExtensionMotionResult;
struct PhysicsServer3DExtensionStateCallback {
- void *instance;
+ void *instance = nullptr;
void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state);
};
diff --git a/servers/physics_3d/godot_area_pair_3d.h b/servers/physics_3d/godot_area_pair_3d.h
index c416477204..64b43a3b51 100644
--- a/servers/physics_3d/godot_area_pair_3d.h
+++ b/servers/physics_3d/godot_area_pair_3d.h
@@ -37,8 +37,8 @@
#include "godot_soft_body_3d.h"
class GodotAreaPair3D : public GodotConstraint3D {
- GodotBody3D *body;
- GodotArea3D *area;
+ GodotBody3D *body = nullptr;
+ GodotArea3D *area = nullptr;
int body_shape;
int area_shape;
bool colliding = false;
@@ -55,8 +55,8 @@ public:
};
class GodotArea2Pair3D : public GodotConstraint3D {
- GodotArea3D *area_a;
- GodotArea3D *area_b;
+ GodotArea3D *area_a = nullptr;
+ GodotArea3D *area_b = nullptr;
int shape_a;
int shape_b;
bool colliding_a = false;
@@ -76,8 +76,8 @@ public:
};
class GodotAreaSoftBodyPair3D : public GodotConstraint3D {
- GodotSoftBody3D *soft_body;
- GodotArea3D *area;
+ GodotSoftBody3D *soft_body = nullptr;
+ GodotArea3D *area = nullptr;
int soft_body_shape;
int area_shape;
bool colliding = false;
diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h
index 00ed763e01..d2078a912c 100644
--- a/servers/physics_3d/godot_physics_server_3d.h
+++ b/servers/physics_3d/godot_physics_server_3d.h
@@ -74,7 +74,7 @@ public:
struct CollCbkData {
int max;
int amount;
- Vector3 *ptr;
+ Vector3 *ptr = nullptr;
};
static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
diff --git a/servers/physics_3d/godot_space_3d.h b/servers/physics_3d/godot_space_3d.h
index ac54c8bf69..6308ede9a9 100644
--- a/servers/physics_3d/godot_space_3d.h
+++ b/servers/physics_3d/godot_space_3d.h
@@ -47,7 +47,7 @@ class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D {
GDCLASS(GodotPhysicsDirectSpaceState3D, PhysicsDirectSpaceState3D);
public:
- GodotSpace3D *space;
+ GodotSpace3D *space = nullptr;
virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override;
virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override;
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
index 069b2e6695..f7bd7d0d18 100644
--- a/servers/rendering/dummy/rasterizer_dummy.h
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -40,6 +40,7 @@
#include "servers/rendering/dummy/storage/canvas_texture_storage.h"
#include "servers/rendering/dummy/storage/decal_atlas_storage.h"
#include "servers/rendering/dummy/storage/material_storage.h"
+#include "servers/rendering/dummy/storage/mesh_storage.h"
#include "servers/rendering/dummy/storage/texture_storage.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
@@ -53,6 +54,7 @@ protected:
RasterizerCanvasDummy canvas;
RendererDummy::CanvasTextureStorage canvas_texture_storage;
RendererDummy::MaterialStorage material_storage;
+ RendererDummy::MeshStorage mesh_storage;
RendererDummy::TextureStorage texture_storage;
RendererDummy::DecalAtlasStorage decal_atlas_storage;
RasterizerStorageDummy storage;
@@ -61,6 +63,7 @@ protected:
public:
RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; };
RendererMaterialStorage *get_material_storage() override { return &material_storage; };
+ RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
RendererDecalAtlasStorage *get_decal_atlas_storage() override { return &decal_atlas_storage; };
RendererStorage *get_storage() override { return &storage; }
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h
index 4ae2a51c7d..ea69d2f9a6 100644
--- a/servers/rendering/dummy/rasterizer_storage_dummy.h
+++ b/servers/rendering/dummy/rasterizer_storage_dummy.h
@@ -36,82 +36,6 @@
class RasterizerStorageDummy : public RendererStorage {
public:
- /* MESH API */
-
- RID mesh_allocate() override { return RID(); }
- void mesh_initialize(RID p_rid) override {}
- void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
- bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
- RID mesh_instance_create(RID p_base) override { return RID(); }
- void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
- void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
- void mesh_instance_check_for_update(RID p_mesh_instance) override {}
- void update_mesh_instances() override {}
- void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
- float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
-
- void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
-
- int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
- RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
-
- void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
- void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
- void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
-
- void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
- RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
-
- RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
- int mesh_get_surface_count(RID p_mesh) const override { return 0; }
-
- void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
- AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
-
- AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
- void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
- void mesh_clear(RID p_mesh) override {}
-
- /* MULTIMESH API */
-
- RID multimesh_allocate() override { return RID(); }
- void multimesh_initialize(RID p_rid) override {}
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
- int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {}
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
-
- RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
- AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
-
- Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); }
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
- Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
- int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
-
- /* SKELETON API */
-
- RID skeleton_allocate() override { return RID(); }
- void skeleton_initialize(RID p_rid) override {}
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
- int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {}
- Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); }
- void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
- Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
-
/* Light API */
RID directional_light_allocate() override { return RID(); }
@@ -171,6 +95,8 @@ public:
void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
+ void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
+ float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
@@ -181,7 +107,6 @@ public:
bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
- void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
/* VOXEL GI API */
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
new file mode 100644
index 0000000000..dfbd265bba
--- /dev/null
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -0,0 +1,129 @@
+/*************************************************************************/
+/* mesh_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MESH_STORAGE_DUMMY_H
+#define MESH_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/mesh_storage.h"
+
+namespace RendererDummy {
+
+class MeshStorage : public RendererMeshStorage {
+public:
+ /* MESH API */
+
+ virtual RID mesh_allocate() override { return RID(); }
+ virtual void mesh_initialize(RID p_rid) override {}
+ virtual void mesh_free(RID p_rid) override {}
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
+
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override {}
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override { return RS::BLEND_SHAPE_MODE_NORMALIZED; }
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override {}
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
+ virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; }
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override { return AABB(); }
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override {}
+ virtual void mesh_clear(RID p_mesh) override {}
+
+ /* MESH INSTANCE */
+
+ virtual RID mesh_instance_create(RID p_base) override { return RID(); }
+ virtual void mesh_instance_free(RID p_rid) override {}
+
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) override {}
+ virtual void update_mesh_instances() override {}
+
+ /* MULTIMESH API */
+
+ virtual RID multimesh_allocate() override { return RID(); }
+ virtual void multimesh_initialize(RID p_rid) override {}
+ virtual void multimesh_free(RID p_rid) override {}
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override {}
+ virtual int multimesh_get_instance_count(RID p_multimesh) const override { return 0; }
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override {}
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override {}
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override {}
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override {}
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override {}
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const override { return RID(); }
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const override { return AABB(); }
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override { return Transform3D(); }
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override { return Transform2D(); }
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override { return Color(); }
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override { return Color(); }
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override {}
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override { return Vector<float>(); }
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override {}
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const override { return 0; }
+
+ /* SKELETON API */
+
+ virtual RID skeleton_allocate() override { return RID(); }
+ virtual void skeleton_initialize(RID p_rid) override {}
+ virtual void skeleton_free(RID p_rid) override {}
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override {}
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override {}
+ virtual int skeleton_get_bone_count(RID p_skeleton) const override { return 0; }
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override {}
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override { return Transform3D(); }
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
+
+ virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override {}
+};
+
+} // namespace RendererDummy
+
+#endif // !MESH_STORAGE_DUMMY_H
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 22149c9e43..f38d800aa7 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -997,8 +997,8 @@ void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, con
ERR_FAIL_COND(!m);
m->mesh = p_mesh;
if (canvas_item->skeleton.is_valid()) {
- m->mesh_instance = RSG::storage->mesh_instance_create(p_mesh);
- RSG::storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton);
+ m->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_mesh);
+ RSG::mesh_storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton);
}
m->texture = p_texture;
@@ -1093,12 +1093,12 @@ void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton)
Item::CommandMesh *cm = static_cast<Item::CommandMesh *>(c);
if (canvas_item->skeleton.is_valid()) {
if (cm->mesh_instance.is_null()) {
- cm->mesh_instance = RSG::storage->mesh_instance_create(cm->mesh);
+ cm->mesh_instance = RSG::mesh_storage->mesh_instance_create(cm->mesh);
}
- RSG::storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton);
+ RSG::mesh_storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton);
} else {
if (cm->mesh_instance.is_valid()) {
- RSG::storage->free(cm->mesh_instance);
+ RSG::mesh_storage->mesh_instance_free(cm->mesh_instance);
cm->mesh_instance = RID();
}
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index fc53ce2327..94bae30ae0 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -124,7 +124,7 @@ public:
Set<RID> viewports;
struct ChildItem {
Point2 mirror;
- Item *item;
+ Item *item = nullptr;
bool operator<(const ChildItem &p_item) const {
return item->index < p_item.item->index;
}
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 1840925f78..46ca3b0da8 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -31,6 +31,7 @@
#ifndef RENDERINGSERVERCANVASRENDER_H
#define RENDERINGSERVERCANVASRENDER_H
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_storage.h"
class RendererCanvasRender {
@@ -82,10 +83,10 @@ public:
Transform2D light_shader_xform;
//Vector2 light_shader_pos;
- Light *shadows_next_ptr;
- Light *filter_next_ptr;
- Light *next_ptr;
- Light *directional_next_ptr;
+ Light *shadows_next_ptr = nullptr;
+ Light *filter_next_ptr = nullptr;
+ Light *next_ptr = nullptr;
+ Light *directional_next_ptr = nullptr;
RID light_internal;
uint64_t version;
@@ -167,7 +168,7 @@ public:
MAX_SIZE = 4096
};
uint32_t usage;
- uint8_t *memory;
+ uint8_t *memory = nullptr;
};
struct Command {
@@ -184,7 +185,7 @@ public:
TYPE_ANIMATION_SLICE,
};
- Command *next;
+ Command *next = nullptr;
Type type;
virtual ~Command() {}
};
@@ -304,8 +305,8 @@ public:
};
struct ViewportRender {
- RenderingServer *owner;
- void *udata;
+ RenderingServer *owner = nullptr;
+ void *udata = nullptr;
Rect2 rect;
};
@@ -333,22 +334,22 @@ public:
RID material;
RID skeleton;
- Item *next;
+ Item *next = nullptr;
struct CopyBackBuffer {
Rect2 rect;
Rect2 screen_rect;
bool full;
};
- CopyBackBuffer *copy_back_buffer;
+ CopyBackBuffer *copy_back_buffer = nullptr;
Color final_modulate;
Transform2D final_transform;
Rect2 final_clip_rect;
- Item *final_clip_owner;
- Item *material_owner;
- Item *canvas_group_owner;
- ViewportRender *vp_render;
+ Item *final_clip_owner = nullptr;
+ Item *material_owner = nullptr;
+ Item *canvas_group_owner = nullptr;
+ ViewportRender *vp_render = nullptr;
bool distance_field;
bool light_masked;
@@ -403,14 +404,14 @@ public:
} break;
case Item::Command::TYPE_MESH: {
const Item::CommandMesh *mesh = static_cast<const Item::CommandMesh *>(c);
- AABB aabb = RendererStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID());
+ AABB aabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(mesh->mesh, RID());
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
} break;
case Item::Command::TYPE_MULTIMESH: {
const Item::CommandMultiMesh *multimesh = static_cast<const Item::CommandMultiMesh *>(c);
- AABB aabb = RendererStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh);
+ AABB aabb = RendererRD::MeshStorage::get_singleton()->multimesh_get_aabb(multimesh->multimesh);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
@@ -452,14 +453,14 @@ public:
return rect;
}
- Command *commands;
- Command *last_command;
+ Command *commands = nullptr;
+ Command *last_command = nullptr;
Vector<CommandBlock> blocks;
uint32_t current_block;
template <class T>
T *alloc_command() {
- T *command;
+ T *command = nullptr;
if (commands == nullptr) {
// As the most common use case of canvas items is to
// use only one command, the first is done with it's
@@ -589,7 +590,7 @@ public:
bool sdf_collision;
RS::CanvasOccluderPolygonCullMode cull_cache;
- LightOccluderInstance *next;
+ LightOccluderInstance *next = nullptr;
LightOccluderInstance() {
enabled = true;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 28d4a9d75d..74eff4bb40 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -37,6 +37,7 @@
#include "servers/rendering/storage/canvas_texture_storage.h"
#include "servers/rendering/storage/decal_atlas_storage.h"
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/texture_storage.h"
#include "servers/rendering_server.h"
@@ -76,6 +77,7 @@ public:
virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0;
virtual RendererMaterialStorage *get_material_storage() = 0;
+ virtual RendererMeshStorage *get_mesh_storage() = 0;
virtual RendererTextureStorage *get_texture_storage() = 0;
virtual RendererDecalAtlasStorage *get_decal_atlas_storage() = 0;
virtual RendererStorage *get_storage() = 0;
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 0c3bf58a85..d1995eb39f 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -31,6 +31,7 @@
#include "render_forward_clustered.h"
#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
@@ -59,14 +60,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
{
Vector<RID> fb;
- fb.push_back(color);
- fb.push_back(specular);
- fb.push_back(depth);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -79,14 +72,6 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular()
{
Vector<RID> fb;
- fb.push_back(color_msaa);
- fb.push_back(specular_msaa);
- fb.push_back(depth_msaa);
-
- color_specular_fb = RD::get_singleton()->framebuffer_create(fb);
- }
- {
- Vector<RID> fb;
fb.push_back(specular_msaa);
specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
@@ -165,11 +150,10 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
color = RID();
depth = RID();
- color_specular_fb = RID();
- specular_only_fb = RID();
- color_fb = RID();
depth_fb = RID();
+ color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
+
if (normal_roughness_buffer.is_valid()) {
RD::get_singleton()->free(normal_roughness_buffer);
if (normal_roughness_buffer_msaa.is_valid()) {
@@ -203,7 +187,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(p_color_buffer);
fb.push_back(depth);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
@@ -246,7 +230,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
fb.push_back(color_msaa);
fb.push_back(depth_msaa);
- color_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
+ color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
}
{
Vector<RID> fb;
@@ -257,6 +241,31 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
}
}
+RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) {
+ if (color_framebuffers.has(p_color_pass_flags)) {
+ return color_framebuffers[p_color_pass_flags];
+ }
+
+ bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED;
+
+ Vector<RID> fb;
+ fb.push_back(use_msaa ? color_msaa : color);
+
+ if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ ensure_specular();
+ fb.push_back(use_msaa ? specular_msaa : specular);
+ } else {
+ fb.push_back(RID());
+ }
+
+ fb.push_back(use_msaa ? depth_msaa : depth);
+
+ int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
+ RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
+ color_framebuffers[p_color_pass_flags] = framebuffer;
+ return framebuffer;
+}
+
void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) {
if (rb->normal_roughness_buffer.is_valid()) {
return;
@@ -306,8 +315,9 @@ bool RenderForwardClustered::free(RID p_rid) {
/// RENDERING ///
-template <RenderForwardClustered::PassMode p_pass_mode>
+template <RenderForwardClustered::PassMode p_pass_mode, uint32_t p_color_pass_flags>
void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -340,7 +350,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i];
const RenderElementInfo &element_info = p_params->element_info[i];
- if ((p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_SPECULAR) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
+ if ((p_pass_mode == PASS_MODE_COLOR && !(p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT)) && !(surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) {
continue; // Objects with "Depth-prepass" transparency are included in both render lists, but should only be rendered in the transparent pass
}
@@ -403,10 +413,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
RID xforms_uniform_set = surf->owner->transforms_uniform_set;
SceneShaderForwardClustered::PipelineVersion pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
-
+ uint32_t pipeline_color_pass_flags = 0;
uint32_t pipeline_specialization = 0;
- if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) {
+ if (p_pass_mode == PASS_MODE_COLOR) {
if (element_info.uses_softshadow) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS;
}
@@ -422,28 +432,26 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
switch (p_pass_mode) {
case PASS_MODE_COLOR: {
if (element_info.uses_lightmap) {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS;
- } else {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS;
- }
- } break;
- case PASS_MODE_COLOR_TRANSPARENT: {
- if (element_info.uses_lightmap) {
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS;
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_LIGHTMAP;
} else {
if (element_info.uses_forward_gi) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
}
- pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_TRANSPARENT_PASS;
}
- } break;
- case PASS_MODE_COLOR_SPECULAR: {
- ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for specular pass");
- if (element_info.uses_lightmap) {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
- } else {
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR;
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_TRANSPARENT;
+ }
+
+ if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) != 0) {
+ pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_COLOR_PASS;
} break;
case PASS_MODE_SHADOW:
case PASS_MODE_DEPTH: {
@@ -473,7 +481,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
PipelineCacheRD *pipeline = nullptr;
- pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ if constexpr (p_pass_mode == PASS_MODE_COLOR) {
+ pipeline = &shader->color_pipelines[cull_variant][primitive][pipeline_color_pass_flags];
+ } else {
+ pipeline = &shader->pipelines[cull_variant][primitive][pipeline_version];
+ }
RD::VertexFormatID vertex_format = -1;
RID vertex_array_rd;
@@ -481,12 +493,12 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
//skeleton and blend shape
if (surf->owner->mesh_instance.is_valid()) {
- storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
} else {
- storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
}
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
+ index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
if (prev_vertex_array_rd != vertex_array_rd) {
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
@@ -544,14 +556,23 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
//use template for faster performance (pass mode comparisons are inlined)
switch (p_params->pass_mode) {
+#define VALID_FLAG_COMBINATION(f) \
+ case f: { \
+ _render_list_template<PASS_MODE_COLOR, f>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); \
+ } break;
+
case PASS_MODE_COLOR: {
- _render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
- } break;
- case PASS_MODE_COLOR_SPECULAR: {
- _render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
- } break;
- case PASS_MODE_COLOR_TRANSPARENT: {
- _render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
+ switch (p_params->color_pass_flags) {
+ VALID_FLAG_COMBINATION(0);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW);
+ VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW);
+ default: {
+ ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags));
+ }
+ }
+
} break;
case PASS_MODE_SHADOW: {
_render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element);
@@ -944,6 +965,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
}
void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
@@ -1080,7 +1103,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1104,7 +1127,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t indices;
- surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1116,13 +1139,13 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
} else {
surf->sort.lod_index = 0;
if (p_render_data->render_info) {
- uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
to_draw = _indices_to_primitives(surf->primitive, to_draw);
to_draw *= inst->instance_count;
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
} else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
}
}
}
@@ -1238,12 +1261,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.opaque_prepass_threshold = 0.99f;
Size2i screen_size;
- RID opaque_framebuffer;
- RID opaque_specular_framebuffer;
+ RID color_framebuffer;
+ RID color_only_framebuffer;
RID depth_framebuffer;
- RID alpha_framebuffer;
PassMode depth_pass_mode = PASS_MODE_DEPTH;
+ uint32_t color_pass_flags = 0;
Vector<Color> depth_pass_clear;
bool using_separate_specular = false;
bool using_ssr = false;
@@ -1256,15 +1279,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
screen_size.x = render_buffer->width;
screen_size.y = render_buffer->height;
- opaque_framebuffer = render_buffer->color_fb;
-
if (p_render_data->voxel_gi_instances->size() > 0) {
using_voxelgi = true;
}
- if (!p_render_data->environment.is_valid() && using_voxelgi) {
+ if (p_render_data->view_count > 1) {
+ depth_pass_mode = PASS_MODE_DEPTH;
+ } else if (!p_render_data->environment.is_valid() && using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
if (environment_is_sdfgi_enabled(p_render_data->environment)) {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi
@@ -1272,14 +1294,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
} else {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
-
if (environment_is_ssr_enabled(p_render_data->environment)) {
- render_buffer->ensure_specular();
using_separate_specular = true;
using_ssr = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
-
} else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
@@ -1304,15 +1323,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
};
}
- alpha_framebuffer = opaque_framebuffer;
+ if (p_render_data->view_count > 1) {
+ color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
+ color_only_framebuffer = render_buffer->color_only_fb;
} else if (p_render_data->reflection_probe.is_valid()) {
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
- opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_only_framebuffer = color_framebuffer;
depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- alpha_framebuffer = opaque_framebuffer;
if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
@@ -1342,11 +1366,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
- if (using_sss) {
- using_separate_specular = true;
- render_buffer->ensure_specular();
+ if (using_sss && !using_separate_specular) {
using_separate_specular = true;
- opaque_specular_framebuffer = render_buffer->color_specular_fb;
+ color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
}
RID radiance_texture;
bool draw_sky = false;
@@ -1449,7 +1472,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1495,20 +1518,21 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only || debug_voxelgis || debug_sdfgi_probes);
- //regular forward for now
Vector<Color> c;
- if (using_separate_specular) {
+ {
Color cc = clear_color.to_linear();
- cc.a = 0; //subsurf scatter must be 0
+ if (using_separate_specular) {
+ cc.a = 0; //subsurf scatter must be 0
+ }
c.push_back(cc);
- c.push_back(Color(0, 0, 0, 0));
- } else {
- c.push_back(clear_color.to_linear());
+
+ if (render_buffer) {
+ c.push_back(Color(0, 0, 0, 0));
+ }
}
- RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
- _render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ _render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
@@ -1526,10 +1550,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
- gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
+ gi.debug_voxel_gi((*p_render_data->voxel_gi_instances)[i], draw_list, color_only_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_VOXEL_GI_EMISSION, 1.0);
}
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
@@ -1543,9 +1567,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix dc;
dc.set_depth_correction(true);
CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
- _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, opaque_framebuffer, cm);
+ _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm);
RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->draw_list_end();
}
@@ -1559,9 +1583,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
CameraMatrix correction;
correction.set_depth_correction(true);
CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
} else {
- sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
}
RD::get_singleton()->draw_command_end_label();
}
@@ -1588,12 +1612,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (using_ssr) {
RENDER_TIMESTAMP("Screen-Space Reflections");
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
- _process_ssr(p_render_data->render_buffers, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
RD::get_singleton()->draw_command_end_label();
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
- storage->get_effects()->merge_specular(render_buffer->color_fb, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
+ storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
}
}
@@ -1616,7 +1640,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR_TRANSPARENT, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer;
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -1738,7 +1764,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1781,7 +1807,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
{
//regular forward for now
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set);
_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
}
RD::get_singleton()->draw_command_end_label();
@@ -1818,7 +1844,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1864,7 +1890,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RENDER_TIMESTAMP("Render 3D Material");
{
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, true);
//regular forward for now
Vector<Color> clear = {
Color(0, 0, 0, 0),
@@ -1984,7 +2010,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
}
- RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, false);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false);
_render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
}
@@ -2588,6 +2614,8 @@ void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_g
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = (p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha;
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
@@ -2638,10 +2666,10 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
material_shadow = (SceneShaderForwardClustered::MaterialData *)RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
- RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
+ RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
if (shadow_mesh.is_valid()) {
- surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface);
+ surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface);
}
} else {
@@ -2654,8 +2682,8 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->shader = p_material->shader_data;
sdcache->material_uniform_set = p_material->uniform_set;
- sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface);
- sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface);
+ sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
@@ -2751,6 +2779,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
}
void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2764,7 +2793,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
uint32_t surface_count;
RID mesh = ginstance->data->base;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
//if no materials, no surfaces.
const RID *inst_materials = ginstance->data->surface_materials.ptr();
@@ -2781,19 +2810,19 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
} break;
case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base);
if (mesh.is_valid()) {
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t j = 0; j < surface_count; j++) {
_geometry_instance_add_surface(ginstance, j, materials[j], mesh);
}
}
- ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
@@ -2818,7 +2847,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t k = 0; k < surface_count; k++) {
_geometry_instance_add_surface(ginstance, k, materials[k], mesh);
@@ -2842,17 +2871,17 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
- if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
}
- if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -2869,10 +2898,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
- if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
- ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
if (ginstance->data->dirty_dependencies) {
- storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
}
}
}
@@ -2912,7 +2941,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
- ginstance->instance_count = static_cast<RenderForwardClustered *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
default: {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index b770cc8f0e..37366d3e14 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -103,10 +103,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID depth_fb;
RID depth_normal_roughness_fb;
RID depth_normal_roughness_voxelgi_fb;
- RID color_fb;
- RID color_specular_fb;
+ RID color_only_fb;
RID specular_only_fb;
int width, height;
+ Map<uint32_t, RID> color_framebuffers;
uint32_t view_count;
RID render_sdfgi_uniform_set;
@@ -114,6 +114,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void ensure_voxelgi();
void clear();
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count);
+ RID get_color_pass_fb(uint32_t p_color_pass_flags);
~RenderBufferDataForwardClustered();
};
@@ -135,8 +136,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
enum PassMode {
PASS_MODE_COLOR,
- PASS_MODE_COLOR_SPECULAR,
- PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_SHADOW,
PASS_MODE_SHADOW_DP,
PASS_MODE_DEPTH,
@@ -146,6 +145,12 @@ class RenderForwardClustered : public RendererSceneRenderRD {
PASS_MODE_SDF,
};
+ enum ColorPassFlags {
+ COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ COLOR_PASS_FLAG_MULTIVIEW = 1 << 2
+ };
+
struct GeometryInstanceSurfaceDataCache;
struct RenderElementInfo;
@@ -155,6 +160,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
int element_count = 0;
bool reverse_cull = false;
PassMode pass_mode = PASS_MODE_COLOR;
+ uint32_t color_pass_flags = 0;
bool no_gi = false;
uint32_t view_count = 1;
RID render_pass_uniform_set;
@@ -168,12 +174,13 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t barrier = RD::BARRIER_MASK_ALL;
bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
reverse_cull = p_reverse_cull;
pass_mode = p_pass_mode;
+ color_pass_flags = p_color_pass_flags;
no_gi = p_no_gi;
view_count = p_view_count;
render_pass_uniform_set = p_render_pass_uniform_set;
@@ -325,7 +332,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 };
LocalVector<InstanceData> instance_data[RENDER_LIST_MAX];
- LightmapCaptureData *lightmap_captures;
+ LightmapCaptureData *lightmap_captures = nullptr;
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
@@ -374,7 +381,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t lod_index : 8;
};
- template <PassMode p_pass_mode>
+ template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0>
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index bba13ab9bc..c42ac98a84 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -234,10 +234,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
}
}
- RD::PipelineColorBlendState blend_state_blend;
- blend_state_blend.attachments.push_back(blend_attachment);
- RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
- RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2);
+ // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular
+ RD::PipelineColorBlendState blend_state_color_blend;
+ blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment() };
+ RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(2);
RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1);
RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2);
@@ -280,18 +280,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
-
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
+ SHADER_VERSION_COLOR_PASS,
};
shader_version = shader_version_table[k];
@@ -307,38 +297,62 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
RD::PipelineMultisampleState multisample_state;
- if (k == PIPELINE_VERSION_TRANSPARENT_PASS || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS || k == PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW) {
- if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
- multisample_state.enable_alpha_to_coverage = true;
- } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
- multisample_state.enable_alpha_to_coverage = true;
- multisample_state.enable_alpha_to_one = true;
+ if (k == PIPELINE_VERSION_COLOR_PASS) {
+ for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) {
+ if (!shader_singleton->valid_color_pass_pipelines.has(l)) {
+ continue;
+ }
+
+ int shader_flags = 0;
+ if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) {
+ if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
+ multisample_state.enable_alpha_to_coverage = true;
+ multisample_state.enable_alpha_to_one = true;
+ }
+
+ blend_state = blend_state_color_blend;
+
+ if (depth_draw == DEPTH_DRAW_OPAQUE) {
+ depth_stencil.enable_depth_write = false; //alpha does not draw depth
+ }
+ } else {
+ blend_state = blend_state_color_opaque;
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
+ }
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP;
+ }
+
+ if (l & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) {
+ shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW;
+ }
+
+ int variant = shader_version + shader_flags;
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, variant);
+ color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
-
- blend_state = blend_state_blend;
-
- if (depth_draw == DEPTH_DRAW_OPAQUE) {
- depth_stencil.enable_depth_write = false; //alpha does not draw depth
- }
- } else if (k == PIPELINE_VERSION_OPAQUE_PASS || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS || k == PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW || k == PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW) {
- blend_state = blend_state_opaque;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW || k == PIPELINE_VERSION_DEPTH_PASS_DP) {
- //none, leave empty
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
- blend_state = blend_state_depth_normal_roughness;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
- blend_state = blend_state_depth_normal_roughness_giprobe;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
- blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
- blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
} else {
- //specular write
- blend_state = blend_state_opaque_specular;
- }
+ if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) {
+ //none, leave empty
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ blend_state = blend_state_depth_normal_roughness;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
+ blend_state = blend_state_depth_normal_roughness_giprobe;
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
+ blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
+ blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
+ }
- RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
- pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
+ pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
+ }
}
}
}
@@ -509,25 +523,38 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
- shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
- shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
- shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
-
- // multiview versions of our shaders
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
- shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
+
+ Vector<String> color_pass_flags = {
+ "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
+ "\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP
+ "\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW
+ };
+
+ for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) {
+ String version = "";
+ for (int j = 0; (1 << j) < SHADER_COLOR_PASS_FLAG_COUNT; j += 1) {
+ if ((1 << j) & i) {
+ version += color_pass_flags[j];
+ }
+ }
+ shader_versions.push_back(version);
+ }
shader.initialize(shader_versions, p_defines);
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
- shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
+ // TODO Add a way to enable/disable color pass flags
}
}
+ valid_color_pass_pipelines.insert(0);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+
material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 9cc13c955d..1b7709bedb 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -42,7 +42,7 @@ private:
static SceneShaderForwardClustered *singleton;
public:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
@@ -51,18 +51,18 @@ public:
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
- SHADER_VERSION_COLOR_PASS,
- SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
-
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
- SHADER_VERSION_COLOR_PASS_MULTIVIEW,
- SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
-
+ SHADER_VERSION_COLOR_PASS,
SHADER_VERSION_MAX
};
+ enum ShaderColorPassFlags {
+ SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0,
+ SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1,
+ SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2,
+ SHADER_COLOR_PASS_FLAG_COUNT = 1 << 3
+ };
+
enum PipelineVersion {
PIPELINE_VERSION_DEPTH_PASS,
PIPELINE_VERSION_DEPTH_PASS_DP,
@@ -70,22 +70,19 @@ public:
PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL,
PIPELINE_VERSION_DEPTH_PASS_WITH_SDF,
- PIPELINE_VERSION_OPAQUE_PASS,
- PIPELINE_VERSION_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_TRANSPARENT_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_WITH_SEPARATE_SPECULAR,
- PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS,
-
PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW,
- PIPELINE_VERSION_OPAQUE_PASS_MULTIVIEW,
- PIPELINE_VERSION_TRANSPARENT_PASS_MULTIVIEW,
- PIPELINE_VERSION_LIGHTMAP_OPAQUE_PASS_MULTIVIEW,
- PIPELINE_VERSION_LIGHTMAP_TRANSPARENT_PASS_MULTIVIEW,
-
+ PIPELINE_VERSION_COLOR_PASS,
PIPELINE_VERSION_MAX
};
+ enum PipelineColorPassFlags {
+ PIPELINE_COLOR_PASS_FLAG_TRANSPARENT = 1 << 0,
+ PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
+ PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
+ PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
+ PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 4,
+ };
+
enum ShaderSpecializations {
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
@@ -137,6 +134,7 @@ public:
RID version;
uint32_t vertex_input_mask;
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
+ PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT];
String path;
@@ -201,7 +199,7 @@ public:
}
struct MaterialData : public RendererRD::MaterialData {
- ShaderData *shader_data;
+ ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
uint32_t index = 0;
@@ -240,6 +238,7 @@ public:
ShaderData *overdraw_material_shader_ptr = nullptr;
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
+ Set<uint32_t> valid_color_pass_pipelines;
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
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 1153a33a27..71b0c17165 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -31,6 +31,7 @@
#include "render_forward_mobile.h"
#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
@@ -1325,6 +1326,8 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
}
void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
if (p_render_list == RENDER_LIST_OPAQUE) {
scene_state.used_sss = false;
scene_state.used_screen_texture = false;
@@ -1414,7 +1417,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) {
+ if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
//lod
Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
@@ -1438,7 +1441,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t indices;
- surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1450,13 +1453,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
} else {
surf->lod_index = 0;
if (p_render_data->render_info) {
- uint32_t to_draw = storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ uint32_t to_draw = mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
to_draw = _indices_to_primitives(surf->primitive, to_draw);
to_draw *= inst->instance_count;
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
} else if (p_render_list == RENDER_LIST_SECONDARY) { //shadow
- p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += storage->mesh_surface_get_vertices_drawn_count(surf->surface);
+ p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME] += mesh_storage->mesh_surface_get_vertices_drawn_count(surf->surface);
}
}
}
@@ -1814,6 +1817,8 @@ void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceF
template <RenderForwardMobile::PassMode p_pass_mode>
void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
RD::DrawListID draw_list = p_draw_list;
RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;
@@ -1956,12 +1961,12 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
//skeleton and blend shape
if (surf->owner->mesh_instance.is_valid()) {
- storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
} else {
- storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format);
}
- index_array_rd = storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
+ index_array_rd = mesh_storage->mesh_surface_get_index_array(mesh_surface, element_info.lod_index);
if (prev_vertex_array_rd != vertex_array_rd) {
RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd);
@@ -2280,6 +2285,8 @@ void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geom
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture;
bool has_base_alpha = ((p_material->shader_data->uses_alpha && !p_material->shader_data->uses_alpha_clip) || has_read_screen_alpha);
bool has_blend_alpha = p_material->shader_data->uses_blend_alpha;
@@ -2330,10 +2337,10 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
material_shadow = (SceneShaderForwardMobile::MaterialData *)RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D);
- RID shadow_mesh = storage->mesh_get_shadow_mesh(p_mesh);
+ RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
if (shadow_mesh.is_valid()) {
- surface_shadow = storage->mesh_get_surface(shadow_mesh, p_surface);
+ surface_shadow = mesh_storage->mesh_get_surface(shadow_mesh, p_surface);
}
} else {
@@ -2346,8 +2353,8 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->shader = p_material->shader_data;
sdcache->material_uniform_set = p_material->uniform_set;
- sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface);
- sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface);
+ sdcache->surface = mesh_storage->mesh_get_surface(p_mesh, p_surface);
+ sdcache->primitive = mesh_storage->mesh_surface_get_primitive(sdcache->surface);
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
@@ -2441,6 +2448,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
}
void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2454,7 +2462,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
uint32_t surface_count;
RID mesh = ginstance->data->base;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
//if no materials, no surfaces.
const RID *inst_materials = ginstance->data->surface_materials.ptr();
@@ -2471,19 +2479,19 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
} break;
case RS::INSTANCE_MULTIMESH: {
- RID mesh = storage->multimesh_get_mesh(ginstance->data->base);
+ RID mesh = mesh_storage->multimesh_get_mesh(ginstance->data->base);
if (mesh.is_valid()) {
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t j = 0; j < surface_count; j++) {
_geometry_instance_add_surface(ginstance, j, materials[j], mesh);
}
}
- ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = mesh_storage->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
@@ -2508,7 +2516,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
const RID *materials = nullptr;
uint32_t surface_count;
- materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count);
+ materials = mesh_storage->mesh_get_surface_count_and_materials(mesh, surface_count);
if (materials) {
for (uint32_t k = 0; k < surface_count; k++) {
_geometry_instance_add_surface(ginstance, k, materials[k], mesh);
@@ -2531,17 +2539,17 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
- if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D;
}
- if (storage->multimesh_uses_colors(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_colors(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
}
- if (storage->multimesh_uses_custom_data(ginstance->data->base)) {
+ if (mesh_storage->multimesh_uses_custom_data(ginstance->data->base)) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA;
}
- ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
@@ -2561,10 +2569,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_MESH) {
- if (storage->skeleton_is_valid(ginstance->data->skeleton)) {
- ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ if (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
+ ginstance->transforms_uniform_set = mesh_storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
if (ginstance->data->dirty_dependencies) {
- storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
+ mesh_storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker);
}
}
}
@@ -2597,7 +2605,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage:
case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
- ginstance->instance_count = static_cast<RenderForwardMobile *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base);
+ ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
}
} break;
default: {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 6162ca55af..0ddfe89eea 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -328,7 +328,7 @@ protected:
uint32_t max_lightmaps;
RID lightmap_buffer;
- LightmapCaptureData *lightmap_captures;
+ LightmapCaptureData *lightmap_captures = nullptr;
uint32_t max_lightmap_captures;
RID lightmap_capture_buffer;
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 0f5017dba1..b89fe908d3 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -40,7 +40,7 @@ namespace RendererSceneRenderImplementation {
class SceneShaderForwardMobile {
private:
static SceneShaderForwardMobile *singleton;
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
public:
enum ShaderVersion {
@@ -163,7 +163,7 @@ public:
}
struct MaterialData : public RendererRD::MaterialData {
- ShaderData *shader_data;
+ ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
uint32_t index = 0;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 8d82480b38..1e80381d88 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -57,7 +57,7 @@ class PipelineCacheRD {
RID pipeline;
};
- Version *versions;
+ Version *versions = nullptr;
uint32_t version_count;
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations = 0);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 8c8532d367..fa0c956c64 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -109,6 +109,8 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
// This dramatically reduces the amount of pipeline objects
// that need to be created for these formats.
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+
uint32_t vertex_count = p_points.size();
uint32_t stride = 2; //vertices always repeat
if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) {
@@ -191,7 +193,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[1] = vd;
- buffers.write[1] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_COLOR);
+ buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR);
}
//uvs
@@ -219,7 +221,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[2] = vd;
- buffers.write[2] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_TEX_UV);
+ buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV);
}
//bones
@@ -252,7 +254,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[3] = vd;
- buffers.write[3] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_BONES);
+ buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES);
}
//weights
@@ -285,7 +287,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[4] = vd;
- buffers.write[4] = storage->mesh_get_default_rd_buffer(RendererStorageRD::DEFAULT_RD_BUFFER_WEIGHTS);
+ buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS);
}
//check that everything is as it should be
@@ -399,6 +401,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) {
//create an empty push constant
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RS::CanvasItemTextureFilter current_filter = default_filter;
RS::CanvasItemTextureRepeat current_repeat = default_repeat;
@@ -753,26 +756,26 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
} else if (c->type == Item::Command::TYPE_MULTIMESH) {
const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c);
RID multimesh = mm->multimesh;
- mesh = storage->multimesh_get_mesh(multimesh);
+ mesh = mesh_storage->multimesh_get_mesh(multimesh);
texture = mm->texture;
- if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
+ if (mesh_storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) {
break;
}
- instance_count = storage->multimesh_get_instances_to_draw(multimesh);
+ instance_count = mesh_storage->multimesh_get_instances_to_draw(multimesh);
if (instance_count == 0) {
break;
}
- RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
+ RID uniform_set = mesh_storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET);
push_constant.flags |= 1; //multimesh, trails disabled
- if (storage->multimesh_uses_colors(multimesh)) {
+ if (mesh_storage->multimesh_uses_colors(multimesh)) {
push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS;
}
- if (storage->multimesh_uses_custom_data(multimesh)) {
+ if (mesh_storage->multimesh_uses_custom_data(multimesh)) {
push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
}
} else if (c->type == Item::Command::TYPE_PARTICLES) {
@@ -837,7 +840,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
_bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size);
- uint32_t surf_count = storage->mesh_get_surface_count(mesh);
+ uint32_t surf_count = mesh_storage->mesh_get_surface_count(mesh);
static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP };
push_constant.modulation[0] = base_color.r * modulate.r;
@@ -852,9 +855,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
for (uint32_t j = 0; j < surf_count; j++) {
- void *surface = storage->mesh_get_surface(mesh, j);
+ void *surface = mesh_storage->mesh_get_surface(mesh, j);
- RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface);
+ RS::PrimitiveType primitive = mesh_storage->mesh_surface_get_primitive(surface);
ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX);
uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask();
@@ -863,15 +866,15 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID;
if (mesh_instance.is_valid()) {
- storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format);
} else {
- storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format);
+ mesh_storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format);
}
RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
- RID index_array = storage->mesh_surface_get_index_array(surface, 0);
+ RID index_array = mesh_storage->mesh_surface_get_index_array(surface, 0);
if (index_array.is_valid()) {
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array);
@@ -1134,6 +1137,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
r_sdf_used = false;
int item_count = 0;
@@ -1395,7 +1399,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (c->type == Item::Command::TYPE_MESH) {
const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c);
if (cm->mesh_instance.is_valid()) {
- storage->mesh_instance_check_for_update(cm->mesh_instance);
+ mesh_storage->mesh_instance_check_for_update(cm->mesh_instance);
update_skeletons = true;
}
}
@@ -1407,7 +1411,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (canvas_group_owner == nullptr) {
//Canvas group begins here, render until before this item
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
@@ -1430,7 +1434,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (ci == canvas_group_owner) {
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
@@ -1447,7 +1451,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (backbuffer_copy) {
//render anything pending, including clearing if no items
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
@@ -1463,7 +1467,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) {
if (update_skeletons) {
- storage->update_mesh_instances();
+ mesh_storage->update_mesh_instances();
update_skeletons = false;
}
@@ -2579,7 +2583,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 0;
- u.append_id(storage->get_default_rd_storage_buffer());
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index b33ee3fbfe..6448e1a664 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -41,7 +41,7 @@
#include "servers/rendering/shader_compiler.h"
class RendererCanvasRenderRD : public RendererCanvasRender {
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
enum {
BASE_UNIFORM_SET = 0,
@@ -200,7 +200,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
}
struct CanvasMaterialData : public RendererRD::MaterialData {
- CanvasShaderData *shader_data;
+ CanvasShaderData *shader_data = nullptr;
RID uniform_set;
virtual void set_render_priority(int p_priority) {}
@@ -361,7 +361,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t pad2;
};
- LightUniform *light_uniforms;
+ LightUniform *light_uniforms = nullptr;
RID lights_uniform_buffer;
RID canvas_state_buffer;
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index cfec5dac5d..5b7c63b508 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -156,6 +156,7 @@ void RendererCompositorRD::finalize() {
memdelete(canvas);
memdelete(storage);
memdelete(decal_atlas_storage);
+ memdelete(mesh_storage);
memdelete(material_storage);
memdelete(texture_storage);
memdelete(canvas_texture_storage);
@@ -291,6 +292,7 @@ RendererCompositorRD::RendererCompositorRD() {
texture_storage = memnew(RendererRD::TextureStorage);
decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage);
material_storage = memnew(RendererRD::MaterialStorage);
+ mesh_storage = memnew(RendererRD::MeshStorage);
storage = memnew(RendererStorageRD);
canvas = memnew(RendererCanvasRenderRD(storage));
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index f2d7679e23..542cff0159 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -42,19 +42,21 @@
#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
class RendererCompositorRD : public RendererCompositor {
protected:
- UniformSetCacheRD *uniform_set_cache;
- RendererCanvasRenderRD *canvas;
+ UniformSetCacheRD *uniform_set_cache = nullptr;
+ RendererCanvasRenderRD *canvas = nullptr;
RendererRD::CanvasTextureStorage *canvas_texture_storage;
RendererRD::MaterialStorage *material_storage;
+ RendererRD::MeshStorage *mesh_storage;
RendererRD::TextureStorage *texture_storage;
RendererRD::DecalAtlasStorage *decal_atlas_storage;
- RendererStorageRD *storage;
- RendererSceneRenderRD *scene;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneRenderRD *scene = nullptr;
enum BlitMode {
BLIT_MODE_NORMAL,
@@ -99,6 +101,7 @@ public:
RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }
RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; }
RendererMaterialStorage *get_material_storage() { return material_storage; };
+ RendererMeshStorage *get_mesh_storage() { return mesh_storage; };
RendererTextureStorage *get_texture_storage() { return texture_storage; };
RendererStorage *get_storage() { return storage; }
RendererCanvasRender *get_canvas() { return canvas; }
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index d51b1bf691..ed60bc4362 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -55,7 +55,7 @@ class RendererSceneRenderRD;
class RendererSceneGIRD {
private:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
/* VOXEL_GI INSTANCE */
@@ -331,8 +331,8 @@ public:
struct VoxelGIInstance {
// access to our containers
- RendererStorageRD *storage;
- RendererSceneGIRD *gi;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneGIRD *gi = nullptr;
RID probe;
RID texture;
@@ -455,8 +455,8 @@ public:
};
// access to our containers
- RendererStorageRD *storage;
- RendererSceneGIRD *gi;
+ RendererStorageRD *storage = nullptr;
+ RendererSceneGIRD *gi = nullptr;
// used for rendering (voxelization)
RID render_albedo;
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index b5a40f6c86..1c60e42466 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -5501,7 +5501,7 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
GeometryInstance *gi = geometry_instance_create(p_base);
- uint32_t sc = RSG::storage->mesh_get_surface_count(p_base);
+ uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base);
Vector<RID> materials;
materials.resize(sc);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 77c0437e83..b2c8daffb1 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -92,7 +92,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
friend RendererSceneGIRD;
protected:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
double time;
double time_step = 0;
@@ -314,10 +314,10 @@ private:
float shadows_quality_radius = 1.0;
float directional_shadow_quality_radius = 1.0;
- float *directional_penumbra_shadow_kernel;
- float *directional_soft_shadow_kernel;
- float *penumbra_shadow_kernel;
- float *soft_shadow_kernel;
+ float *directional_penumbra_shadow_kernel = nullptr;
+ float *directional_soft_shadow_kernel = nullptr;
+ float *penumbra_shadow_kernel = nullptr;
+ float *soft_shadow_kernel = nullptr;
int directional_penumbra_shadow_samples = 0;
int directional_soft_shadow_samples = 0;
int penumbra_shadow_samples = 0;
@@ -705,27 +705,27 @@ private:
template <class T>
struct InstanceSort {
float depth;
- T *instance;
+ T *instance = nullptr;
bool operator<(const InstanceSort &p_sort) const {
return depth < p_sort.depth;
}
};
- ReflectionData *reflections;
+ ReflectionData *reflections = nullptr;
InstanceSort<ReflectionProbeInstance> *reflection_sort;
uint32_t max_reflections;
RID reflection_buffer;
uint32_t max_reflection_probes_per_instance;
uint32_t reflection_count = 0;
- DecalData *decals;
+ DecalData *decals = nullptr;
InstanceSort<DecalInstance> *decal_sort;
uint32_t max_decals;
RID decal_buffer;
uint32_t decal_count;
- LightData *omni_lights;
- LightData *spot_lights;
+ LightData *omni_lights = nullptr;
+ LightData *spot_lights = nullptr;
InstanceSort<LightInstance> *omni_light_sort;
InstanceSort<LightInstance> *spot_light_sort;
@@ -735,7 +735,7 @@ private:
uint32_t omni_light_count = 0;
uint32_t spot_light_count = 0;
- DirectionalLightData *directional_lights;
+ DirectionalLightData *directional_lights = nullptr;
uint32_t max_directional_lights;
RID directional_light_buffer;
@@ -938,7 +938,7 @@ private:
};
struct FogMaterialData : public RendererRD::MaterialData {
- FogShaderData *shader_data;
+ FogShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
index 7a3e545add..010e2178a9 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
@@ -63,7 +63,7 @@ public:
};
private:
- RendererStorageRD *storage;
+ RendererStorageRD *storage = nullptr;
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
@@ -162,8 +162,8 @@ public:
UBO ubo;
- SkyDirectionalLightData *directional_lights;
- SkyDirectionalLightData *last_frame_directional_lights;
+ SkyDirectionalLightData *directional_lights = nullptr;
+ SkyDirectionalLightData *last_frame_directional_lights = nullptr;
uint32_t max_directional_lights;
uint32_t last_frame_directional_light_count;
RID directional_light_buffer;
@@ -228,7 +228,7 @@ public:
} sky_shader;
struct SkyMaterialData : public RendererRD::MaterialData {
- SkyShaderData *shader_data;
+ SkyShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
@@ -262,7 +262,7 @@ public:
Sky *dirty_list = nullptr;
//State to track when radiance cubemap needs updating
- SkyMaterialData *prev_material;
+ SkyMaterialData *prev_material = nullptr;
Vector3 prev_position;
float prev_time;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index c5df3a9f4e..499cb545c7 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -35,6 +35,10 @@
#include "core/io/resource_loader.h"
#include "core/math/math_defs.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
@@ -134,1489 +138,6 @@ void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
}
}
-/* MESH API */
-
-RID RendererStorageRD::mesh_allocate() {
- return mesh_owner.allocate_rid();
-}
-void RendererStorageRD::mesh_initialize(RID p_rid) {
- mesh_owner.initialize_rid(p_rid, Mesh());
-}
-
-void RendererStorageRD::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
- ERR_FAIL_COND(p_blend_shape_count < 0);
-
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
-
- mesh->blend_shape_count = p_blend_shape_count;
-}
-
-/// Returns stride
-void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
-
-#ifdef DEBUG_ENABLED
- //do a validation, to catch errors first
- {
- uint32_t stride = 0;
- uint32_t attrib_stride = 0;
- uint32_t skin_stride = 0;
-
- for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
- if ((p_surface.format & (1 << i))) {
- switch (i) {
- case RS::ARRAY_VERTEX: {
- if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
- stride += sizeof(float) * 2;
- } else {
- stride += sizeof(float) * 3;
- }
-
- } break;
- case RS::ARRAY_NORMAL: {
- stride += sizeof(int32_t);
-
- } break;
- case RS::ARRAY_TANGENT: {
- stride += sizeof(int32_t);
-
- } break;
- case RS::ARRAY_COLOR: {
- attrib_stride += sizeof(uint32_t);
- } break;
- case RS::ARRAY_TEX_UV: {
- attrib_stride += sizeof(float) * 2;
-
- } break;
- case RS::ARRAY_TEX_UV2: {
- attrib_stride += sizeof(float) * 2;
-
- } break;
- case RS::ARRAY_CUSTOM0:
- case RS::ARRAY_CUSTOM1:
- case RS::ARRAY_CUSTOM2:
- case RS::ARRAY_CUSTOM3: {
- int idx = i - RS::ARRAY_CUSTOM0;
- uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
- uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
- uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
- attrib_stride += fmtsize[fmt];
-
- } break;
- case RS::ARRAY_WEIGHTS:
- case RS::ARRAY_BONES: {
- //uses a separate array
- bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
- skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8);
- } break;
- }
- }
- }
-
- int expected_size = stride * p_surface.vertex_count;
- ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
-
- int bs_expected_size = expected_size * mesh->blend_shape_count;
-
- ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")");
-
- int expected_attrib_size = attrib_stride * p_surface.vertex_count;
- ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")");
-
- if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) {
- expected_size = skin_stride * p_surface.vertex_count;
- ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
- }
- }
-
-#endif
-
- Mesh::Surface *s = memnew(Mesh::Surface);
-
- s->format = p_surface.format;
- s->primitive = p_surface.primitive;
-
- bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
-
- s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
- s->vertex_buffer_size = p_surface.vertex_data.size();
-
- if (p_surface.attribute_data.size()) {
- s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
- }
- if (p_surface.skin_data.size()) {
- s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage);
- s->skin_buffer_size = p_surface.skin_data.size();
- }
-
- s->vertex_count = p_surface.vertex_count;
-
- if (p_surface.format & RS::ARRAY_FORMAT_BONES) {
- mesh->has_bone_weights = true;
- }
-
- if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536;
-
- s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
- s->index_count = p_surface.index_count;
- s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count);
- if (p_surface.lods.size()) {
- s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
- s->lod_count = p_surface.lods.size();
-
- for (int i = 0; i < p_surface.lods.size(); i++) {
- uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
- s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
- s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
- s->lods[i].edge_length = p_surface.lods[i].edge_length;
- s->lods[i].index_count = indices;
- }
- }
- }
-
- s->aabb = p_surface.aabb;
- s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
-
- if (mesh->blend_shape_count > 0) {
- s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
- }
-
- if (use_as_storage) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s->vertex_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- if (s->skin_buffer.is_valid()) {
- u.append_id(s->skin_buffer);
- } else {
- u.append_id(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- if (s->blend_shape_buffer.is_valid()) {
- u.append_id(s->blend_shape_buffer);
- } else {
- u.append_id(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
-
- s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE);
- }
-
- if (mesh->surface_count == 0) {
- mesh->bone_aabbs = p_surface.bone_aabbs;
- mesh->aabb = p_surface.aabb;
- } else {
- if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) {
- // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone
- // Each surface may affect different numbers of bones.
- mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
- }
- for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
- mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
- }
- mesh->aabb.merge_with(p_surface.aabb);
- }
-
- s->material = p_surface.material;
-
- mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
- mesh->surfaces[mesh->surface_count] = s;
- mesh->surface_count++;
-
- for (MeshInstance *mi : mesh->instances) {
- _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
- }
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
-
- mesh->material_cache.clear();
-}
-
-int RendererStorageRD::mesh_get_blend_shape_count(RID p_mesh) const {
- const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, -1);
- return mesh->blend_shape_count;
-}
-
-void RendererStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX((int)p_mode, 2);
-
- mesh->blend_shape_mode = p_mode;
-}
-
-RS::BlendShapeMode RendererStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
- return mesh->blend_shape_mode;
-}
-
-void RendererStorageRD::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- ERR_FAIL_COND(p_data.size() == 0);
- ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
- uint64_t data_size = p_data.size();
- const uint8_t *r = p_data.ptr();
-
- RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
-}
-
-void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
- mesh->surfaces[p_surface]->material = p_material;
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);
- mesh->material_cache.clear();
-}
-
-RID RendererStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RID());
- ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
-
- return mesh->surfaces[p_surface]->material;
-}
-
-RS::SurfaceData RendererStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
- ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
-
- Mesh::Surface &s = *mesh->surfaces[p_surface];
-
- RS::SurfaceData sd;
- sd.format = s.format;
- sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
- if (s.attribute_buffer.is_valid()) {
- sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
- }
- if (s.skin_buffer.is_valid()) {
- sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer);
- }
- sd.vertex_count = s.vertex_count;
- sd.index_count = s.index_count;
- sd.primitive = s.primitive;
-
- if (sd.index_count) {
- sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
- }
- sd.aabb = s.aabb;
- for (uint32_t i = 0; i < s.lod_count; i++) {
- RS::SurfaceData::LOD lod;
- lod.edge_length = s.lods[i].edge_length;
- lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
- sd.lods.push_back(lod);
- }
-
- sd.bone_aabbs = s.bone_aabbs;
-
- if (s.blend_shape_buffer.is_valid()) {
- sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
- }
-
- return sd;
-}
-
-int RendererStorageRD::mesh_get_surface_count(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, 0);
- return mesh->surface_count;
-}
-
-void RendererStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- mesh->custom_aabb = p_aabb;
-}
-
-AABB RendererStorageRD::mesh_get_custom_aabb(RID p_mesh) const {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
- return mesh->custom_aabb;
-}
-
-AABB RendererStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, AABB());
-
- if (mesh->custom_aabb != AABB()) {
- return mesh->custom_aabb;
- }
-
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- if (!skeleton || skeleton->size == 0) {
- return mesh->aabb;
- }
-
- AABB aabb;
-
- for (uint32_t i = 0; i < mesh->surface_count; i++) {
- AABB laabb;
- if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
- int bs = mesh->surfaces[i]->bone_aabbs.size();
- const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
-
- int sbs = skeleton->size;
- ERR_CONTINUE(bs > sbs);
- const float *baseptr = skeleton->data.ptr();
-
- bool first = true;
-
- if (skeleton->use_2d) {
- for (int j = 0; j < bs; j++) {
- if (skbones[0].size == Vector3()) {
- continue; //bone is unused
- }
-
- const float *dataptr = baseptr + j * 8;
-
- Transform3D mtx;
-
- mtx.basis.elements[0].x = dataptr[0];
- mtx.basis.elements[1].x = dataptr[1];
- mtx.origin.x = dataptr[3];
-
- mtx.basis.elements[0].y = dataptr[4];
- mtx.basis.elements[1].y = dataptr[5];
- mtx.origin.y = dataptr[7];
-
- AABB baabb = mtx.xform(skbones[j]);
-
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- } else {
- for (int j = 0; j < bs; j++) {
- if (skbones[0].size == Vector3()) {
- continue; //bone is unused
- }
-
- const float *dataptr = baseptr + j * 12;
-
- Transform3D mtx;
-
- mtx.basis.elements[0][0] = dataptr[0];
- mtx.basis.elements[0][1] = dataptr[1];
- mtx.basis.elements[0][2] = dataptr[2];
- mtx.origin.x = dataptr[3];
- mtx.basis.elements[1][0] = dataptr[4];
- mtx.basis.elements[1][1] = dataptr[5];
- mtx.basis.elements[1][2] = dataptr[6];
- mtx.origin.y = dataptr[7];
- mtx.basis.elements[2][0] = dataptr[8];
- mtx.basis.elements[2][1] = dataptr[9];
- mtx.basis.elements[2][2] = dataptr[10];
- mtx.origin.z = dataptr[11];
-
- AABB baabb = mtx.xform(skbones[j]);
- if (first) {
- laabb = baabb;
- first = false;
- } else {
- laabb.merge_with(baabb);
- }
- }
- }
-
- if (laabb.size == Vector3()) {
- laabb = mesh->surfaces[i]->aabb;
- }
- } else {
- laabb = mesh->surfaces[i]->aabb;
- }
-
- if (i == 0) {
- aabb = laabb;
- } else {
- aabb.merge_with(laabb);
- }
- }
-
- return aabb;
-}
-
-void RendererStorageRD::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
-
- Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
- if (shadow_mesh) {
- shadow_mesh->shadow_owners.erase(mesh);
- }
- mesh->shadow_mesh = p_shadow_mesh;
-
- shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
-
- if (shadow_mesh) {
- shadow_mesh->shadow_owners.insert(mesh);
- }
-
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-}
-
-void RendererStorageRD::mesh_clear(RID p_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND(!mesh);
- for (uint32_t i = 0; i < mesh->surface_count; i++) {
- Mesh::Surface &s = *mesh->surfaces[i];
- RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
- if (s.attribute_buffer.is_valid()) {
- RD::get_singleton()->free(s.attribute_buffer);
- }
- if (s.skin_buffer.is_valid()) {
- RD::get_singleton()->free(s.skin_buffer);
- }
- if (s.versions) {
- memfree(s.versions); //reallocs, so free with memfree.
- }
-
- if (s.index_buffer.is_valid()) {
- RD::get_singleton()->free(s.index_buffer);
- }
-
- if (s.lod_count) {
- for (uint32_t j = 0; j < s.lod_count; j++) {
- RD::get_singleton()->free(s.lods[j].index_buffer);
- }
- memdelete_arr(s.lods);
- }
-
- if (s.blend_shape_buffer.is_valid()) {
- RD::get_singleton()->free(s.blend_shape_buffer);
- }
-
- memdelete(mesh->surfaces[i]);
- }
- if (mesh->surfaces) {
- memfree(mesh->surfaces);
- }
-
- mesh->surfaces = nullptr;
- mesh->surface_count = 0;
- mesh->material_cache.clear();
- //clear instance data
- for (MeshInstance *mi : mesh->instances) {
- _mesh_instance_clear(mi);
- }
- mesh->has_bone_weights = false;
- mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
-}
-
-bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, false);
-
- return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
-}
-
-/* MESH INSTANCE */
-
-RID RendererStorageRD::mesh_instance_create(RID p_base) {
- Mesh *mesh = mesh_owner.get_or_null(p_base);
- ERR_FAIL_COND_V(!mesh, RID());
-
- RID rid = mesh_instance_owner.make_rid();
- MeshInstance *mi = mesh_instance_owner.get_or_null(rid);
-
- mi->mesh = mesh;
-
- for (uint32_t i = 0; i < mesh->surface_count; i++) {
- _mesh_instance_add_surface(mi, mesh, i);
- }
-
- mi->I = mesh->instances.push_back(mi);
-
- mi->dirty = true;
-
- return rid;
-}
-void RendererStorageRD::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
- if (mi->skeleton == p_skeleton) {
- return;
- }
- mi->skeleton = p_skeleton;
- mi->skeleton_version = 0;
- mi->dirty = true;
-}
-
-void RendererStorageRD::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
- ERR_FAIL_COND(!mi);
- ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size());
- mi->blend_weights[p_shape] = p_weight;
- mi->weights_dirty = true;
- //will be eventually updated
-}
-
-void RendererStorageRD::_mesh_instance_clear(MeshInstance *mi) {
- for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].versions) {
- for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
- RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array);
- }
- memfree(mi->surfaces[i].versions);
- }
- if (mi->surfaces[i].vertex_buffer.is_valid()) {
- RD::get_singleton()->free(mi->surfaces[i].vertex_buffer);
- }
- }
- mi->surfaces.clear();
-
- if (mi->blend_weights_buffer.is_valid()) {
- RD::get_singleton()->free(mi->blend_weights_buffer);
- }
- mi->blend_weights.clear();
- mi->weights_dirty = false;
- mi->skeleton_version = 0;
-}
-
-void RendererStorageRD::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
- if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) {
- mi->blend_weights.resize(mesh->blend_shape_count);
- for (uint32_t i = 0; i < mi->blend_weights.size(); i++) {
- mi->blend_weights[i] = 0;
- }
- mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array());
- mi->weights_dirty = true;
- }
-
- MeshInstance::Surface s;
- if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
- //surface warrants transform
- s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s.vertex_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- if (mi->blend_weights_buffer.is_valid()) {
- u.append_id(mi->blend_weights_buffer);
- } else {
- u.append_id(default_rd_storage_buffer);
- }
- uniforms.push_back(u);
- }
- s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE);
- }
-
- mi->surfaces.push_back(s);
- mi->dirty = true;
-}
-
-void RendererStorageRD::mesh_instance_check_for_update(RID p_mesh_instance) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
-
- bool needs_update = mi->dirty;
-
- if (mi->weights_dirty && !mi->weight_update_list.in_list()) {
- dirty_mesh_instance_weights.add(&mi->weight_update_list);
- needs_update = true;
- }
-
- if (mi->array_update_list.in_list()) {
- return;
- }
-
- if (!needs_update && mi->skeleton.is_valid()) {
- Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
- if (sk && sk->version != mi->skeleton_version) {
- needs_update = true;
- }
- }
-
- if (needs_update) {
- dirty_mesh_instance_arrays.add(&mi->array_update_list);
- }
-}
-
-void RendererStorageRD::update_mesh_instances() {
- while (dirty_mesh_instance_weights.first()) {
- MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
-
- if (mi->blend_weights_buffer.is_valid()) {
- RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr());
- }
- dirty_mesh_instance_weights.remove(&mi->weight_update_list);
- mi->weights_dirty = false;
- }
- if (dirty_mesh_instance_arrays.first() == nullptr) {
- return; //nothing to do
- }
-
- //process skeletons and blend shapes
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- while (dirty_mesh_instance_arrays.first()) {
- MeshInstance *mi = dirty_mesh_instance_arrays.first()->self();
-
- Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
-
- for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) {
- continue;
- }
-
- bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE);
- if (sk && sk->uniform_set_mi.is_valid()) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON);
- }
-
- SkeletonShader::PushConstant push_constant;
-
- push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL;
- push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT;
- push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES);
- push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0;
-
- push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count;
- push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
- push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
- push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2;
-
- push_constant.blend_shape_count = mi->mesh->blend_shape_count;
- push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED;
- push_constant.pad0 = 0;
- push_constant.pad1 = 0;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant));
-
- //dispatch without barrier, so all is done at the same time
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1);
- }
-
- mi->dirty = false;
- if (sk) {
- mi->skeleton_version = sk->version;
- }
- dirty_mesh_instance_arrays.remove(&mi->array_update_list);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RendererStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) {
- Vector<RD::VertexAttribute> attributes;
- Vector<RID> buffers;
-
- uint32_t stride = 0;
- uint32_t attribute_stride = 0;
- uint32_t skin_stride = 0;
-
- for (int i = 0; i < RS::ARRAY_INDEX; i++) {
- RD::VertexAttribute vd;
- RID buffer;
- vd.location = i;
-
- if (!(s->format & (1 << i))) {
- // Not supplied by surface, use default value
- buffer = mesh_default_rd_buffers[i];
- vd.stride = 0;
- switch (i) {
- case RS::ARRAY_VERTEX: {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
-
- } break;
- case RS::ARRAY_NORMAL: {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
- } break;
- case RS::ARRAY_TANGENT: {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- } break;
- case RS::ARRAY_COLOR: {
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
-
- } break;
- case RS::ARRAY_TEX_UV: {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
-
- } break;
- case RS::ARRAY_TEX_UV2: {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- } break;
- case RS::ARRAY_CUSTOM0:
- case RS::ARRAY_CUSTOM1:
- case RS::ARRAY_CUSTOM2:
- case RS::ARRAY_CUSTOM3: {
- //assumed weights too
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- } break;
- case RS::ARRAY_BONES: {
- //assumed weights too
- vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
- } break;
- case RS::ARRAY_WEIGHTS: {
- //assumed weights too
- vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
- } break;
- }
- } else {
- //Supplied, use it
-
- vd.stride = 1; //mark that it needs a stride set (default uses 0)
-
- switch (i) {
- case RS::ARRAY_VERTEX: {
- vd.offset = stride;
-
- if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- stride += sizeof(float) * 2;
- } else {
- vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
- stride += sizeof(float) * 3;
- }
-
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
-
- } break;
- case RS::ARRAY_NORMAL: {
- vd.offset = stride;
-
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
-
- stride += sizeof(uint32_t);
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
- } break;
- case RS::ARRAY_TANGENT: {
- vd.offset = stride;
-
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
- stride += sizeof(uint32_t);
- if (mis) {
- buffer = mis->vertex_buffer;
- } else {
- buffer = s->vertex_buffer;
- }
- } break;
- case RS::ARRAY_COLOR: {
- vd.offset = attribute_stride;
-
- vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- attribute_stride += sizeof(int8_t) * 4;
- buffer = s->attribute_buffer;
- } break;
- case RS::ARRAY_TEX_UV: {
- vd.offset = attribute_stride;
-
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- attribute_stride += sizeof(float) * 2;
- buffer = s->attribute_buffer;
-
- } break;
- case RS::ARRAY_TEX_UV2: {
- vd.offset = attribute_stride;
-
- vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
- attribute_stride += sizeof(float) * 2;
- buffer = s->attribute_buffer;
- } break;
- case RS::ARRAY_CUSTOM0:
- case RS::ARRAY_CUSTOM1:
- case RS::ARRAY_CUSTOM2:
- case RS::ARRAY_CUSTOM3: {
- vd.offset = attribute_stride;
-
- int idx = i - RS::ARRAY_CUSTOM0;
- uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
- uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
- uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
- RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT };
- vd.format = fmtrd[fmt];
- attribute_stride += fmtsize[fmt];
- buffer = s->attribute_buffer;
- } break;
- case RS::ARRAY_BONES: {
- vd.offset = skin_stride;
-
- vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
- skin_stride += sizeof(int16_t) * 4;
- buffer = s->skin_buffer;
- } break;
- case RS::ARRAY_WEIGHTS: {
- vd.offset = skin_stride;
-
- vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
- skin_stride += sizeof(int16_t) * 4;
- buffer = s->skin_buffer;
- } break;
- }
- }
-
- if (!(p_input_mask & (1 << i))) {
- continue; // Shader does not need this, skip it (but computing stride was important anyway)
- }
-
- attributes.push_back(vd);
- buffers.push_back(buffer);
- }
-
- //update final stride
- for (int i = 0; i < attributes.size(); i++) {
- if (attributes[i].stride == 0) {
- continue; //default location
- }
- int loc = attributes[i].location;
-
- if (loc < RS::ARRAY_COLOR) {
- attributes.write[i].stride = stride;
- } else if (loc < RS::ARRAY_BONES) {
- attributes.write[i].stride = attribute_stride;
- } else {
- attributes.write[i].stride = skin_stride;
- }
- }
-
- v.input_mask = p_input_mask;
- v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
- v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
-}
-
-////////////////// MULTIMESH
-
-RID RendererStorageRD::multimesh_allocate() {
- return multimesh_owner.allocate_rid();
-}
-void RendererStorageRD::multimesh_initialize(RID p_rid) {
- multimesh_owner.initialize_rid(p_rid, MultiMesh());
-}
-
-void RendererStorageRD::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
- return;
- }
-
- if (multimesh->buffer.is_valid()) {
- RD::get_singleton()->free(multimesh->buffer);
- multimesh->buffer = RID();
- multimesh->uniform_set_2d = RID(); //cleared by dependency
- multimesh->uniform_set_3d = RID(); //cleared by dependency
- }
-
- if (multimesh->data_cache_dirty_regions) {
- memdelete_arr(multimesh->data_cache_dirty_regions);
- multimesh->data_cache_dirty_regions = nullptr;
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- multimesh->instances = p_instances;
- multimesh->xform_format = p_transform_format;
- multimesh->uses_colors = p_use_colors;
- multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
- multimesh->uses_custom_data = p_use_custom_data;
- multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
- multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
- multimesh->buffer_set = false;
-
- //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
- multimesh->data_cache = Vector<float>();
- multimesh->aabb = AABB();
- multimesh->aabb_dirty = false;
- multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
-
- if (multimesh->instances) {
- multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
- }
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH);
-}
-
-int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, 0);
- return multimesh->instances;
-}
-
-void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- if (multimesh->mesh == p_mesh) {
- return;
- }
- multimesh->mesh = p_mesh;
-
- if (multimesh->instances == 0) {
- return;
- }
-
- if (multimesh->data_cache.size()) {
- //we have a data cache, just mark it dirt
- _multimesh_mark_all_dirty(multimesh, false, true);
- } else if (multimesh->instances) {
- //need to re-create AABB unfortunately, calling this has a penalty
- if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- const uint8_t *r = buffer.ptr();
- const float *data = (const float *)r;
- _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- }
- }
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
-}
-
-#define MULTIMESH_DIRTY_REGION_SIZE 512
-
-void RendererStorageRD::_multimesh_make_local(MultiMesh *multimesh) const {
- if (multimesh->data_cache.size() > 0) {
- return; //already local
- }
- ERR_FAIL_COND(multimesh->data_cache.size() > 0);
- // this means that the user wants to load/save individual elements,
- // for this, the data must reside on CPU, so just copy it there.
- multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
- {
- float *w = multimesh->data_cache.ptrw();
-
- if (multimesh->buffer_set) {
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- {
- const uint8_t *r = buffer.ptr();
- memcpy(w, r, buffer.size());
- }
- } else {
- memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
- }
- }
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
- multimesh->data_cache_used_dirty_regions = 0;
-}
-
-void RendererStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
- uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
-#ifdef DEBUG_ENABLED
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
-#endif
- if (!multimesh->data_cache_dirty_regions[region_index]) {
- multimesh->data_cache_dirty_regions[region_index] = true;
- multimesh->data_cache_used_dirty_regions++;
- }
-
- if (p_aabb) {
- multimesh->aabb_dirty = true;
- }
-
- if (!multimesh->dirty) {
- multimesh->dirty_list = multimesh_dirty_list;
- multimesh_dirty_list = multimesh;
- multimesh->dirty = true;
- }
-}
-
-void RendererStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) {
- if (p_data) {
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
-
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- if (!multimesh->data_cache_dirty_regions[i]) {
- multimesh->data_cache_dirty_regions[i] = true;
- multimesh->data_cache_used_dirty_regions++;
- }
- }
- }
-
- if (p_aabb) {
- multimesh->aabb_dirty = true;
- }
-
- if (!multimesh->dirty) {
- multimesh->dirty_list = multimesh_dirty_list;
- multimesh_dirty_list = multimesh;
- multimesh->dirty = true;
- }
-}
-
-void RendererStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) {
- ERR_FAIL_COND(multimesh->mesh.is_null());
- AABB aabb;
- AABB mesh_aabb = mesh_get_aabb(multimesh->mesh);
- for (int i = 0; i < p_instances; i++) {
- const float *data = p_data + multimesh->stride_cache * i;
- Transform3D t;
-
- if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
- t.basis.elements[0][0] = data[0];
- t.basis.elements[0][1] = data[1];
- t.basis.elements[0][2] = data[2];
- t.origin.x = data[3];
- t.basis.elements[1][0] = data[4];
- t.basis.elements[1][1] = data[5];
- t.basis.elements[1][2] = data[6];
- t.origin.y = data[7];
- t.basis.elements[2][0] = data[8];
- t.basis.elements[2][1] = data[9];
- t.basis.elements[2][2] = data[10];
- t.origin.z = data[11];
-
- } else {
- t.basis.elements[0].x = data[0];
- t.basis.elements[1].x = data[1];
- t.origin.x = data[3];
-
- t.basis.elements[0].y = data[4];
- t.basis.elements[1].y = data[5];
- t.origin.y = data[7];
- }
-
- if (i == 0) {
- aabb = t.xform(mesh_aabb);
- } else {
- aabb.merge_with(t.xform(mesh_aabb));
- }
- }
-
- multimesh->aabb = aabb;
-}
-
-void RendererStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache;
-
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
- dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
- dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
- dataptr[11] = p_transform.origin.z;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, true);
-}
-
-void RendererStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache;
-
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
- dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
- dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
- }
-
- _multimesh_mark_dirty(multimesh, p_index, true);
-}
-
-void RendererStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(!multimesh->uses_colors);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, false);
-}
-
-void RendererStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index, multimesh->instances);
- ERR_FAIL_COND(!multimesh->uses_custom_data);
-
- _multimesh_make_local(multimesh);
-
- {
- float *w = multimesh->data_cache.ptrw();
-
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- dataptr[0] = p_color.r;
- dataptr[1] = p_color.g;
- dataptr[2] = p_color.b;
- dataptr[3] = p_color.a;
- }
-
- _multimesh_mark_dirty(multimesh, p_index, false);
-}
-
-RID RendererStorageRD::multimesh_get_mesh(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, RID());
-
- return multimesh->mesh;
-}
-
-Transform3D RendererStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform3D());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
- ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
-
- _multimesh_make_local(multimesh);
-
- Transform3D t;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache;
-
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
- t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
- t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
- t.origin.z = dataptr[11];
- }
-
- return t;
-}
-
-Transform2D RendererStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Transform2D());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
- ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D());
-
- _multimesh_make_local(multimesh);
-
- Transform2D t;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache;
-
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
- }
-
- return t;
-}
-
-Color RendererStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
- ERR_FAIL_COND_V(!multimesh->uses_colors, Color());
-
- _multimesh_make_local(multimesh);
-
- Color c;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
- }
-
- return c;
-}
-
-Color RendererStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Color());
- ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
- ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color());
-
- _multimesh_make_local(multimesh);
-
- Color c;
- {
- const float *r = multimesh->data_cache.ptr();
-
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
-
- c.r = dataptr[0];
- c.g = dataptr[1];
- c.b = dataptr[2];
- c.a = dataptr[3];
- }
-
- return c;
-}
-
-void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
-
- {
- const float *r = p_buffer.ptr();
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r);
- multimesh->buffer_set = true;
- }
-
- if (multimesh->data_cache.size()) {
- //if we have a data cache, just update it
- multimesh->data_cache = p_buffer;
- {
- //clear dirty since nothing will be dirty anymore
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- _multimesh_mark_all_dirty(multimesh, false, true); //update AABB
- } else if (multimesh->mesh.is_valid()) {
- //if we have a mesh set, we need to re-generate the AABB from the new data
- const float *data = p_buffer.ptr();
-
- _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
-}
-
-Vector<float> RendererStorageRD::multimesh_get_buffer(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, Vector<float>());
- if (multimesh->buffer.is_null()) {
- return Vector<float>();
- } else if (multimesh->data_cache.size()) {
- return multimesh->data_cache;
- } else {
- //get from memory
-
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- Vector<float> ret;
- ret.resize(multimesh->instances * multimesh->stride_cache);
- {
- float *w = ret.ptrw();
- const uint8_t *r = buffer.ptr();
- memcpy(w, r, buffer.size());
- }
-
- return ret;
- }
-}
-
-void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
- if (multimesh->visible_instances == p_visible) {
- return;
- }
-
- if (multimesh->data_cache.size()) {
- //there is a data cache..
- _multimesh_mark_all_dirty(multimesh, false, true);
- }
-
- multimesh->visible_instances = p_visible;
-
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
-}
-
-int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, 0);
- return multimesh->visible_instances;
-}
-
-AABB RendererStorageRD::multimesh_get_aabb(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- ERR_FAIL_COND_V(!multimesh, AABB());
- if (multimesh->aabb_dirty) {
- const_cast<RendererStorageRD *>(this)->_update_dirty_multimeshes();
- }
- return multimesh->aabb;
-}
-
-void RendererStorageRD::_update_dirty_multimeshes() {
- while (multimesh_dirty_list) {
- MultiMesh *multimesh = multimesh_dirty_list;
-
- if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
- const float *data = multimesh->data_cache.ptr();
-
- uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
-
- if (multimesh->data_cache_used_dirty_regions) {
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
-
- uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
-
- if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
- //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
- } else {
- //not that many regions? update them all
- for (uint32_t i = 0; i < visible_region_count; i++) {
- if (multimesh->data_cache_dirty_regions[i]) {
- uint32_t offset = i * region_size;
- uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
- uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
- RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
- }
- }
- }
-
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
-
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- if (multimesh->aabb_dirty) {
- //aabb is dirty..
- _multimesh_re_create_aabb(multimesh, data, visible_instances);
- multimesh->aabb_dirty = false;
- multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
- }
-
- multimesh_dirty_list = multimesh->dirty_list;
-
- multimesh->dirty_list = nullptr;
- multimesh->dirty = false;
- }
-
- multimesh_dirty_list = nullptr;
-}
-
/* PARTICLES */
RID RendererStorageRD::particles_allocate() {
@@ -2024,7 +545,7 @@ AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
float longest_axis_size = 0;
for (int i = 0; i < particles->draw_passes.size(); i++) {
if (particles->draw_passes[i].is_valid()) {
- AABB maabb = mesh_get_aabb(particles->draw_passes[i], RID());
+ AABB maabb = RendererRD::MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID());
longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
}
}
@@ -2113,7 +634,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
if (p_particles->emission_storage_buffer.is_valid()) {
u.append_id(p_particles->emission_storage_buffer);
} else {
- u.append_id(default_rd_storage_buffer);
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
}
uniforms.push_back(u);
}
@@ -2128,7 +649,7 @@ void RendererStorageRD::_particles_process(Particles *p_particles, double p_delt
}
u.append_id(sub_emitter->emission_storage_buffer);
} else {
- u.append_id(default_rd_storage_buffer);
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
}
uniforms.push_back(u);
}
@@ -2771,7 +1292,7 @@ void RendererStorageRD::update_particles() {
if (particles->trail_bind_pose_buffer.is_valid()) {
u.append_id(particles->trail_bind_pose_buffer);
} else {
- u.append_id(default_rd_storage_buffer);
+ u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
}
uniforms.push_back(u);
}
@@ -3407,195 +1928,6 @@ void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, b
}
}
-/* SKELETON API */
-
-RID RendererStorageRD::skeleton_allocate() {
- return skeleton_owner.allocate_rid();
-}
-void RendererStorageRD::skeleton_initialize(RID p_rid) {
- skeleton_owner.initialize_rid(p_rid, Skeleton());
-}
-
-void RendererStorageRD::_skeleton_make_dirty(Skeleton *skeleton) {
- if (!skeleton->dirty) {
- skeleton->dirty = true;
- skeleton->dirty_list = skeleton_dirty_list;
- skeleton_dirty_list = skeleton;
- }
-}
-
-void RendererStorageRD::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_COND(p_bones < 0);
-
- if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
- return;
- }
-
- skeleton->size = p_bones;
- skeleton->use_2d = p_2d_skeleton;
- skeleton->uniform_set_3d = RID();
-
- if (skeleton->buffer.is_valid()) {
- RD::get_singleton()->free(skeleton->buffer);
- skeleton->buffer = RID();
- skeleton->data.clear();
- skeleton->uniform_set_mi = RID();
- }
-
- if (skeleton->size) {
- skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
- skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
- memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
-
- _skeleton_make_dirty(skeleton);
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(skeleton->buffer);
- uniforms.push_back(u);
- }
- skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
- }
- }
-
- skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA);
-}
-
-int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, 0);
-
- return skeleton->size;
-}
-
-void RendererStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(skeleton->use_2d);
-
- float *dataptr = skeleton->data.ptrw() + p_bone * 12;
-
- dataptr[0] = p_transform.basis.elements[0][0];
- dataptr[1] = p_transform.basis.elements[0][1];
- dataptr[2] = p_transform.basis.elements[0][2];
- dataptr[3] = p_transform.origin.x;
- dataptr[4] = p_transform.basis.elements[1][0];
- dataptr[5] = p_transform.basis.elements[1][1];
- dataptr[6] = p_transform.basis.elements[1][2];
- dataptr[7] = p_transform.origin.y;
- dataptr[8] = p_transform.basis.elements[2][0];
- dataptr[9] = p_transform.basis.elements[2][1];
- dataptr[10] = p_transform.basis.elements[2][2];
- dataptr[11] = p_transform.origin.z;
-
- _skeleton_make_dirty(skeleton);
-}
-
-Transform3D RendererStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform3D());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
- ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
-
- const float *dataptr = skeleton->data.ptr() + p_bone * 12;
-
- Transform3D t;
-
- t.basis.elements[0][0] = dataptr[0];
- t.basis.elements[0][1] = dataptr[1];
- t.basis.elements[0][2] = dataptr[2];
- t.origin.x = dataptr[3];
- t.basis.elements[1][0] = dataptr[4];
- t.basis.elements[1][1] = dataptr[5];
- t.basis.elements[1][2] = dataptr[6];
- t.origin.y = dataptr[7];
- t.basis.elements[2][0] = dataptr[8];
- t.basis.elements[2][1] = dataptr[9];
- t.basis.elements[2][2] = dataptr[10];
- t.origin.z = dataptr[11];
-
- return t;
-}
-
-void RendererStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX(p_bone, skeleton->size);
- ERR_FAIL_COND(!skeleton->use_2d);
-
- float *dataptr = skeleton->data.ptrw() + p_bone * 8;
-
- dataptr[0] = p_transform.elements[0][0];
- dataptr[1] = p_transform.elements[1][0];
- dataptr[2] = 0;
- dataptr[3] = p_transform.elements[2][0];
- dataptr[4] = p_transform.elements[0][1];
- dataptr[5] = p_transform.elements[1][1];
- dataptr[6] = 0;
- dataptr[7] = p_transform.elements[2][1];
-
- _skeleton_make_dirty(skeleton);
-}
-
-Transform2D RendererStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND_V(!skeleton, Transform2D());
- ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
- ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
-
- const float *dataptr = skeleton->data.ptr() + p_bone * 8;
-
- Transform2D t;
- t.elements[0][0] = dataptr[0];
- t.elements[1][0] = dataptr[1];
- t.elements[2][0] = dataptr[3];
- t.elements[0][1] = dataptr[4];
- t.elements[1][1] = dataptr[5];
- t.elements[2][1] = dataptr[7];
-
- return t;
-}
-
-void RendererStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
-
- ERR_FAIL_COND(!skeleton->use_2d);
-
- skeleton->base_transform_2d = p_base_transform;
-}
-
-void RendererStorageRD::_update_dirty_skeletons() {
- while (skeleton_dirty_list) {
- Skeleton *skeleton = skeleton_dirty_list;
-
- if (skeleton->size) {
- RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr());
- }
-
- skeleton_dirty_list = skeleton->dirty_list;
-
- skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES);
-
- skeleton->version++;
-
- skeleton->dirty = false;
- skeleton->dirty_list = nullptr;
- }
-
- skeleton_dirty_list = nullptr;
-}
-
/* LIGHT */
void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) {
@@ -5311,11 +3643,11 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta
}
void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
- if (mesh_owner.owns(p_base)) {
- Mesh *mesh = mesh_owner.get_or_null(p_base);
+ if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) {
+ RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base);
p_instance->update_dependency(&mesh->dependency);
- } else if (multimesh_owner.owns(p_base)) {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_base);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) {
+ RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base);
p_instance->update_dependency(&multimesh->dependency);
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
@@ -5350,18 +3682,11 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
}
}
-void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND(!skeleton);
-
- p_instance->update_dependency(&skeleton->dependency);
-}
-
RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
- if (mesh_owner.owns(p_rid)) {
+ if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
return RS::INSTANCE_MESH;
}
- if (multimesh_owner.owns(p_rid)) {
+ if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
return RS::INSTANCE_MULTIMESH;
}
if (reflection_probe_owner.owns(p_rid)) {
@@ -5398,8 +3723,8 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
void RendererStorageRD::update_dirty_resources() {
RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
RendererRD::MaterialStorage::get_singleton()->_update_queued_materials();
- _update_dirty_multimeshes();
- _update_dirty_skeletons();
+ RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes();
+ RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons();
RendererRD::DecalAtlasStorage::get_singleton()->update_decal_atlas();
}
@@ -5432,42 +3757,14 @@ bool RendererStorageRD::free(RID p_rid) {
RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid);
} else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) {
RendererRD::MaterialStorage::get_singleton()->material_free(p_rid);
- } else if (mesh_owner.owns(p_rid)) {
- mesh_clear(p_rid);
- mesh_set_shadow_mesh(p_rid, RID());
- Mesh *mesh = mesh_owner.get_or_null(p_rid);
- mesh->dependency.deleted_notify(p_rid);
- if (mesh->instances.size()) {
- ERR_PRINT("deleting mesh with active instances");
- }
- if (mesh->shadow_owners.size()) {
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
- Mesh *shadow_owner = E->get();
- shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);
- }
- }
- mesh_owner.free(p_rid);
- } else if (mesh_instance_owner.owns(p_rid)) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid);
- _mesh_instance_clear(mi);
- mi->mesh->instances.erase(mi->I);
- mi->I = nullptr;
-
- mesh_instance_owner.free(p_rid);
-
- } else if (multimesh_owner.owns(p_rid)) {
- _update_dirty_multimeshes();
- multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
- multimesh->dependency.deleted_notify(p_rid);
- multimesh_owner.free(p_rid);
- } else if (skeleton_owner.owns(p_rid)) {
- _update_dirty_skeletons();
- skeleton_allocate_data(p_rid, 0);
- Skeleton *skeleton = skeleton_owner.get_or_null(p_rid);
- skeleton->dependency.deleted_notify(p_rid);
- skeleton_owner.free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid);
+ } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) {
+ RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid);
} else if (reflection_probe_owner.owns(p_rid)) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
reflection_probe->dependency.deleted_notify(p_rid);
@@ -5696,120 +3993,6 @@ RendererStorageRD::RendererStorageRD() {
//custom sampler
sampler_rd_configure_custom(0.0f);
- //default rd buffers
- {
- Vector<uint8_t> buffer;
- {
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //normal
- buffer.resize(sizeof(float) * 3);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //tangent
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //color
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 1.0;
- fptr[1] = 1.0;
- fptr[2] = 1.0;
- fptr[3] = 1.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //tex uv 1
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
- { //tex uv 2
- buffer.resize(sizeof(float) * 2);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //bones
- buffer.resize(sizeof(uint32_t) * 4);
- {
- uint8_t *w = buffer.ptrw();
- uint32_t *fptr = (uint32_t *)w;
- fptr[0] = 0;
- fptr[1] = 0;
- fptr[2] = 0;
- fptr[3] = 0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
-
- { //weights
- buffer.resize(sizeof(float) * 4);
- {
- uint8_t *w = buffer.ptrw();
- float *fptr = (float *)w;
- fptr[0] = 0.0;
- fptr[1] = 0.0;
- fptr[2] = 0.0;
- fptr[3] = 0.0;
- }
- mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
- }
- }
-
using_lightmap_array = true; // high end
if (using_lightmap_array) {
uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
@@ -5952,8 +4135,6 @@ void process() {
particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0);
}
- default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
-
{
Vector<String> copy_modes;
for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
@@ -5996,30 +4177,6 @@ void process() {
rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
}
}
- {
- Vector<String> skeleton_modes;
- skeleton_modes.push_back("\n#define MODE_2D\n");
- skeleton_modes.push_back("");
-
- skeleton_shader.shader.initialize(skeleton_modes);
- skeleton_shader.version = skeleton_shader.shader.version_create();
- for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) {
- skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i);
- skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]);
- }
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(default_rd_storage_buffer);
- uniforms.push_back(u);
- }
- skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
- }
- }
}
RendererStorageRD::~RendererStorageRD() {
@@ -6041,21 +4198,12 @@ RendererStorageRD::~RendererStorageRD() {
}
}
- //def buffers
- for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
- RD::get_singleton()->free(mesh_default_rd_buffers[i]);
- }
-
particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
rt_sdf.shader.version_free(rt_sdf.shader_version);
- skeleton_shader.shader.version_free(skeleton_shader.version);
-
material_storage->material_free(particles_shader.default_material);
material_storage->shader_free(particles_shader.default_shader);
- RD::get_singleton()->free(default_rd_storage_buffer);
-
if (effects) {
memdelete(effects);
effects = nullptr;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
index 42d4141f9c..4c45dd4295 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -39,12 +39,8 @@
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
@@ -129,232 +125,11 @@ public:
}
}
- enum DefaultRDBuffer {
- DEFAULT_RD_BUFFER_VERTEX,
- DEFAULT_RD_BUFFER_NORMAL,
- DEFAULT_RD_BUFFER_TANGENT,
- DEFAULT_RD_BUFFER_COLOR,
- DEFAULT_RD_BUFFER_TEX_UV,
- DEFAULT_RD_BUFFER_TEX_UV2,
- DEFAULT_RD_BUFFER_CUSTOM0,
- DEFAULT_RD_BUFFER_CUSTOM1,
- DEFAULT_RD_BUFFER_CUSTOM2,
- DEFAULT_RD_BUFFER_CUSTOM3,
- DEFAULT_RD_BUFFER_BONES,
- DEFAULT_RD_BUFFER_WEIGHTS,
- DEFAULT_RD_BUFFER_MAX,
- };
-
private:
/* TEXTURE API */
RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
- RID default_rd_storage_buffer;
-
- /* Mesh */
-
- struct MeshInstance;
-
- struct Mesh {
- struct Surface {
- RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
- uint32_t format = 0;
-
- RID vertex_buffer;
- RID attribute_buffer;
- RID skin_buffer;
- uint32_t vertex_count = 0;
- uint32_t vertex_buffer_size = 0;
- uint32_t skin_buffer_size = 0;
-
- // A different pipeline needs to be allocated
- // depending on the inputs available in the
- // material.
- // There are never that many geometry/material
- // combinations, so a simple array is the most
- // cache-efficient structure.
-
- struct Version {
- uint32_t input_mask = 0;
- RD::VertexFormatID vertex_format = 0;
- RID vertex_array;
- };
-
- SpinLock version_lock; //needed to access versions
- Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
-
- RID index_buffer;
- RID index_array;
- uint32_t index_count = 0;
-
- struct LOD {
- float edge_length = 0.0;
- uint32_t index_count = 0;
- RID index_buffer;
- RID index_array;
- };
-
- LOD *lods = nullptr;
- uint32_t lod_count = 0;
-
- AABB aabb;
-
- Vector<AABB> bone_aabbs;
-
- RID blend_shape_buffer;
-
- RID material;
-
- uint32_t render_index = 0;
- uint64_t render_pass = 0;
-
- uint32_t multimesh_render_index = 0;
- uint64_t multimesh_render_pass = 0;
-
- uint32_t particles_render_index = 0;
- uint64_t particles_render_pass = 0;
-
- RID uniform_set;
- };
-
- uint32_t blend_shape_count = 0;
- RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
-
- Surface **surfaces = nullptr;
- uint32_t surface_count = 0;
-
- Vector<AABB> bone_aabbs;
-
- bool has_bone_weights = false;
-
- AABB aabb;
- AABB custom_aabb;
-
- Vector<RID> material_cache;
-
- List<MeshInstance *> instances;
-
- RID shadow_mesh;
- Set<Mesh *> shadow_owners;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Mesh, true> mesh_owner;
-
- struct MeshInstance {
- Mesh *mesh;
- RID skeleton;
- struct Surface {
- RID vertex_buffer;
- RID uniform_set;
-
- Mesh::Surface::Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
- };
- LocalVector<Surface> surfaces;
- LocalVector<float> blend_weights;
-
- RID blend_weights_buffer;
- List<MeshInstance *>::Element *I = nullptr; //used to erase itself
- uint64_t skeleton_version = 0;
- bool dirty = false;
- bool weights_dirty = false;
- SelfList<MeshInstance> weight_update_list;
- SelfList<MeshInstance> array_update_list;
- MeshInstance() :
- weight_update_list(this), array_update_list(this) {}
- };
-
- void _mesh_instance_clear(MeshInstance *mi);
- void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
-
- mutable RID_Owner<MeshInstance> mesh_instance_owner;
-
- SelfList<MeshInstance>::List dirty_mesh_instance_weights;
- SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
-
- struct SkeletonShader {
- struct PushConstant {
- uint32_t has_normal;
- uint32_t has_tangent;
- uint32_t has_skeleton;
- uint32_t has_blend_shape;
-
- uint32_t vertex_count;
- uint32_t vertex_stride;
- uint32_t skin_stride;
- uint32_t skin_weight_offset;
-
- uint32_t blend_shape_count;
- uint32_t normalized_blend_shapes;
- uint32_t pad0;
- uint32_t pad1;
- };
-
- enum {
- UNIFORM_SET_INSTANCE = 0,
- UNIFORM_SET_SURFACE = 1,
- UNIFORM_SET_SKELETON = 2,
- };
- enum {
- SHADER_MODE_2D,
- SHADER_MODE_3D,
- SHADER_MODE_MAX
- };
-
- SkeletonShaderRD shader;
- RID version;
- RID version_shader[SHADER_MODE_MAX];
- RID pipeline[SHADER_MODE_MAX];
-
- RID default_skeleton_uniform_set;
- } skeleton_shader;
-
- void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
-
- RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
-
- /* MultiMesh */
- struct MultiMesh {
- RID mesh;
- int instances = 0;
- RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
- bool uses_colors = false;
- bool uses_custom_data = false;
- int visible_instances = -1;
- AABB aabb;
- bool aabb_dirty = false;
- bool buffer_set = false;
- uint32_t stride_cache = 0;
- uint32_t color_offset_cache = 0;
- uint32_t custom_data_offset_cache = 0;
-
- Vector<float> data_cache; //used if individual setting is used
- bool *data_cache_dirty_regions = nullptr;
- uint32_t data_cache_used_dirty_regions = 0;
-
- RID buffer; //storage buffer
- RID uniform_set_3d;
- RID uniform_set_2d;
-
- bool dirty = false;
- MultiMesh *dirty_list = nullptr;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<MultiMesh, true> multimesh_owner;
-
- MultiMesh *multimesh_dirty_list = nullptr;
-
- _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
- _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
- _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
- void _update_dirty_multimeshes();
/* PARTICLES */
@@ -732,34 +507,6 @@ private:
mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
- /* Skeleton */
-
- struct Skeleton {
- bool use_2d = false;
- int size = 0;
- Vector<float> data;
- RID buffer;
-
- bool dirty = false;
- Skeleton *dirty_list = nullptr;
- Transform2D base_transform_2d;
-
- RID uniform_set_3d;
- RID uniform_set_mi;
-
- uint64_t version = 1;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Skeleton, true> skeleton_owner;
-
- _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
-
- Skeleton *skeleton_dirty_list = nullptr;
-
- void _update_dirty_skeletons();
-
/* LIGHT */
struct Light {
@@ -975,360 +722,6 @@ public:
void sampler_rd_set_default(float p_mipmap_bias);
- /* MESH API */
-
- RID mesh_allocate();
- void mesh_initialize(RID p_mesh);
-
- virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count);
-
- /// Return stride
- virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface);
-
- virtual int mesh_get_blend_shape_count(RID p_mesh) const;
-
- virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode);
- virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const;
-
- virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
- virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
- virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data);
-
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material);
- virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
-
- virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const;
-
- virtual int mesh_get_surface_count(RID p_mesh) const;
-
- virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb);
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
-
- virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID());
- virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh);
-
- virtual void mesh_clear(RID p_mesh);
-
- virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton);
-
- /* MESH INSTANCE */
-
- virtual RID mesh_instance_create(RID p_base);
- virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton);
- virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight);
- virtual void mesh_instance_check_for_update(RID p_mesh_instance);
- virtual void update_mesh_instances();
-
- _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, nullptr);
- r_surface_count = mesh->surface_count;
- if (r_surface_count == 0) {
- return nullptr;
- }
- if (mesh->material_cache.is_empty()) {
- mesh->material_cache.resize(mesh->surface_count);
- for (uint32_t i = 0; i < r_surface_count; i++) {
- mesh->material_cache.write[i] = mesh->surfaces[i]->material;
- }
- }
-
- return mesh->material_cache.ptr();
- }
-
- _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, nullptr);
- ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
-
- return mesh->surfaces[p_surface_index];
- }
-
- _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- ERR_FAIL_COND_V(!mesh, RID());
-
- return mesh->shadow_mesh;
- }
-
- _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
- Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
- return surface->primitive;
- }
-
- _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
- return s->lod_count > 0;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
- return s->index_count ? s->index_count : s->vertex_count;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- int32_t current_lod = -1;
- if (r_index_count) {
- *r_index_count = s->index_count;
- }
- for (uint32_t i = 0; i < s->lod_count; i++) {
- float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
- if (screen_size > p_mesh_lod_threshold) {
- break;
- }
- current_lod = i;
- }
- if (current_lod == -1) {
- return 0;
- } else {
- if (r_index_count) {
- *r_index_count = s->lods[current_lod].index_count;
- }
- return current_lod + 1;
- }
- }
-
- _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- if (p_lod == 0) {
- return s->index_array;
- } else {
- return s->lods[p_lod - 1].index_array;
- }
- }
-
- _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
- Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
-
- s->version_lock.lock();
-
- //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
-
- for (uint32_t i = 0; i < s->version_count; i++) {
- if (s->versions[i].input_mask != p_input_mask) {
- continue;
- }
- //we have this version, hooray
- r_vertex_format = s->versions[i].vertex_format;
- r_vertex_array_rd = s->versions[i].vertex_array;
- s->version_lock.unlock();
- return;
- }
-
- uint32_t version = s->version_count;
- s->version_count++;
- s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count);
-
- _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask);
-
- r_vertex_format = s->versions[version].vertex_format;
- r_vertex_array_rd = s->versions[version].vertex_array;
-
- s->version_lock.unlock();
- }
-
- _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
- MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
- ERR_FAIL_COND(!mi);
- Mesh *mesh = mi->mesh;
- ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count);
-
- MeshInstance::Surface *mis = &mi->surfaces[p_surface_index];
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- s->version_lock.lock();
-
- //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
-
- for (uint32_t i = 0; i < mis->version_count; i++) {
- if (mis->versions[i].input_mask != p_input_mask) {
- continue;
- }
- //we have this version, hooray
- r_vertex_format = mis->versions[i].vertex_format;
- r_vertex_array_rd = mis->versions[i].vertex_array;
- s->version_lock.unlock();
- return;
- }
-
- uint32_t version = mis->version_count;
- mis->version_count++;
- mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count);
-
- _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis);
-
- r_vertex_format = mis->versions[version].vertex_format;
- r_vertex_array_rd = mis->versions[version].vertex_array;
-
- s->version_lock.unlock();
- }
-
- _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) {
- ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID());
- return mesh_default_rd_buffers[p_buffer];
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->render_pass != p_render_pass) {
- (*r_index)++;
- s->render_pass = p_render_pass;
- s->render_index = *r_index;
- }
-
- return s->render_index;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->multimesh_render_pass != p_render_pass) {
- (*r_index)++;
- s->multimesh_render_pass = p_render_pass;
- s->multimesh_render_index = *r_index;
- }
-
- return s->multimesh_render_index;
- }
-
- _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
- Mesh *mesh = mesh_owner.get_or_null(p_mesh);
- Mesh::Surface *s = mesh->surfaces[p_surface_index];
-
- if (s->particles_render_pass != p_render_pass) {
- (*r_index)++;
- s->particles_render_pass = p_render_pass;
- s->particles_render_index = *r_index;
- }
-
- return s->particles_render_index;
- }
-
- /* MULTIMESH API */
-
- RID multimesh_allocate();
- void multimesh_initialize(RID p_multimesh);
-
- void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false);
- int multimesh_get_instance_count(RID p_multimesh) const;
-
- void multimesh_set_mesh(RID p_multimesh, RID p_mesh);
- void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform);
- void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform);
- void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color);
- void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color);
-
- RID multimesh_get_mesh(RID p_multimesh) const;
-
- Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const;
- Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const;
- Color multimesh_instance_get_color(RID p_multimesh, int p_index) const;
- Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const;
-
- void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer);
- Vector<float> multimesh_get_buffer(RID p_multimesh) const;
-
- void multimesh_set_visible_instances(RID p_multimesh, int p_visible);
- int multimesh_get_visible_instances(RID p_multimesh) const;
-
- AABB multimesh_get_aabb(RID p_multimesh) const;
-
- _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->xform_format;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_colors;
- }
-
- _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- return multimesh->uses_custom_data;
- }
-
- _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (multimesh->visible_instances >= 0) {
- return multimesh->visible_instances;
- }
- return multimesh->instances;
- }
-
- _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (!multimesh->uniform_set_3d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(multimesh->buffer);
- uniforms.push_back(u);
- multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return multimesh->uniform_set_3d;
- }
-
- _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
- MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
- if (!multimesh->uniform_set_2d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(multimesh->buffer);
- uniforms.push_back(u);
- multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return multimesh->uniform_set_2d;
- }
-
- /* SKELETON API */
-
- RID skeleton_allocate();
- void skeleton_initialize(RID p_skeleton);
-
- void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false);
- void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform);
- void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
- int skeleton_get_bone_count(RID p_skeleton) const;
- void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform);
- Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const;
- void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);
- Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const;
-
- _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
- return skeleton_owner.get_or_null(p_skeleton) != nullptr;
- }
-
- _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
- Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
- ERR_FAIL_COND_V(!skeleton, RID());
- ERR_FAIL_COND_V(skeleton->size == 0, RID());
- if (skeleton->use_2d) {
- return RID();
- }
- if (!skeleton->uniform_set_3d.is_valid()) {
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(skeleton->buffer);
- uniforms.push_back(u);
- skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return skeleton->uniform_set_3d;
- }
/* Light API */
void _light_initialize(RID p_rid, RS::LightType p_type);
@@ -1498,7 +891,6 @@ public:
float reflection_probe_get_ambient_color_energy(RID p_probe) const;
void base_update_dependency(RID p_base, DependencyTracker *p_instance);
- void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);
/* VOXEL GI API */
@@ -1829,8 +1221,6 @@ public:
virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
virtual String get_captured_timestamp_name(uint32_t p_index) const;
- RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
-
static RendererStorageRD *base_singleton;
void init_effects(bool p_prefer_raster_effects);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 4e6e50bc44..abe1a09b06 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -499,14 +499,14 @@ layout(location = 1) out uvec2 voxel_gi_buffer;
#endif //MODE_RENDER_NORMAL
#else // RENDER DEPTH
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness
layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter)
#else
layout(location = 0) out vec4 frag_color;
-#endif // MODE_MULTIPLE_RENDER_TARGETS
+#endif // MODE_SEPARATE_SPECULAR
#endif // RENDER DEPTH
@@ -1966,7 +1966,7 @@ void main() {
//restore fog
fog = vec4(unpackHalf2x16(fog_rg), unpackHalf2x16(fog_ba));
-#ifdef MODE_MULTIPLE_RENDER_TARGETS
+#ifdef MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
diffuse_buffer = vec4(albedo.rgb, 0.0);
@@ -1984,7 +1984,7 @@ void main() {
diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);
specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);
-#else //MODE_MULTIPLE_RENDER_TARGETS
+#else //MODE_SEPARATE_SPECULAR
#ifdef MODE_UNSHADED
frag_color = vec4(albedo, alpha);
@@ -1996,7 +1996,7 @@ void main() {
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
-#endif //MODE_MULTIPLE_RENDER_TARGETS
+#endif //MODE_SEPARATE_SPECULAR
#endif //MODE_RENDER_DEPTH
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index 69b7b702b0..270d9f0982 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -73,7 +73,7 @@ typedef ShaderData *(*ShaderDataRequestFunction)();
struct Material;
struct Shader {
- ShaderData *data;
+ ShaderData *data = nullptr;
String code;
ShaderType type;
Map<StringName, Map<int, RID>> default_texture_parameter;
@@ -177,9 +177,9 @@ struct GlobalVariables {
List<RID> materials_using_texture;
RID buffer;
- Value *buffer_values;
- ValueUsage *buffer_usage;
- bool *buffer_dirty_regions;
+ Value *buffer_values = nullptr;
+ ValueUsage *buffer_usage = nullptr;
+ bool *buffer_dirty_regions = nullptr;
uint32_t buffer_dirty_region_count = 0;
uint32_t buffer_size;
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
new file mode 100644
index 0000000000..8c60264ce3
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -0,0 +1,1921 @@
+/*************************************************************************/
+/* mesh_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "mesh_storage.h"
+
+using namespace RendererRD;
+
+MeshStorage *MeshStorage::singleton = nullptr;
+
+MeshStorage *MeshStorage::get_singleton() {
+ return singleton;
+}
+
+MeshStorage::MeshStorage() {
+ singleton = this;
+
+ default_rd_storage_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4);
+
+ //default rd buffers
+ {
+ Vector<uint8_t> buffer;
+ {
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //normal
+ buffer.resize(sizeof(float) * 3);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tangent
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //color
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 1.0;
+ fptr[1] = 1.0;
+ fptr[2] = 1.0;
+ fptr[3] = 1.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //tex uv 1
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ { //tex uv 2
+ buffer.resize(sizeof(float) * 2);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_CUSTOM0 + i] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //bones
+ buffer.resize(sizeof(uint32_t) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ uint32_t *fptr = (uint32_t *)w;
+ fptr[0] = 0;
+ fptr[1] = 0;
+ fptr[2] = 0;
+ fptr[3] = 0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+
+ { //weights
+ buffer.resize(sizeof(float) * 4);
+ {
+ uint8_t *w = buffer.ptrw();
+ float *fptr = (float *)w;
+ fptr[0] = 0.0;
+ fptr[1] = 0.0;
+ fptr[2] = 0.0;
+ fptr[3] = 0.0;
+ }
+ mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer);
+ }
+ }
+
+ {
+ Vector<String> skeleton_modes;
+ skeleton_modes.push_back("\n#define MODE_2D\n");
+ skeleton_modes.push_back("");
+
+ skeleton_shader.shader.initialize(skeleton_modes);
+ skeleton_shader.version = skeleton_shader.shader.version_create();
+ for (int i = 0; i < SkeletonShader::SHADER_MODE_MAX; i++) {
+ skeleton_shader.version_shader[i] = skeleton_shader.shader.version_get_shader(skeleton_shader.version, i);
+ skeleton_shader.pipeline[i] = RD::get_singleton()->compute_pipeline_create(skeleton_shader.version_shader[i]);
+ }
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(default_rd_storage_buffer);
+ uniforms.push_back(u);
+ }
+ skeleton_shader.default_skeleton_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
+ }
+ }
+}
+
+MeshStorage::~MeshStorage() {
+ //def buffers
+ for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) {
+ RD::get_singleton()->free(mesh_default_rd_buffers[i]);
+ }
+
+ skeleton_shader.shader.version_free(skeleton_shader.version);
+
+ RD::get_singleton()->free(default_rd_storage_buffer);
+
+ singleton = nullptr;
+}
+
+/* MESH API */
+
+RID MeshStorage::mesh_allocate() {
+ return mesh_owner.allocate_rid();
+}
+
+void MeshStorage::mesh_initialize(RID p_rid) {
+ mesh_owner.initialize_rid(p_rid, Mesh());
+}
+
+void MeshStorage::mesh_free(RID p_rid) {
+ mesh_clear(p_rid);
+ mesh_set_shadow_mesh(p_rid, RID());
+ Mesh *mesh = mesh_owner.get_or_null(p_rid);
+ mesh->dependency.deleted_notify(p_rid);
+ if (mesh->instances.size()) {
+ ERR_PRINT("deleting mesh with active instances");
+ }
+ if (mesh->shadow_owners.size()) {
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+ }
+ mesh_owner.free(p_rid);
+}
+
+void MeshStorage::mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) {
+ ERR_FAIL_COND(p_blend_shape_count < 0);
+
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ ERR_FAIL_COND(mesh->surface_count > 0); //surfaces already exist
+
+ mesh->blend_shape_count = p_blend_shape_count;
+}
+
+/// Returns stride
+void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
+
+#ifdef DEBUG_ENABLED
+ //do a validation, to catch errors first
+ {
+ uint32_t stride = 0;
+ uint32_t attrib_stride = 0;
+ uint32_t skin_stride = 0;
+
+ for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) {
+ if ((p_surface.format & (1 << i))) {
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ stride += sizeof(float) * 2;
+ } else {
+ stride += sizeof(float) * 3;
+ }
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ stride += sizeof(int32_t);
+
+ } break;
+ case RS::ARRAY_TANGENT: {
+ stride += sizeof(int32_t);
+
+ } break;
+ case RS::ARRAY_COLOR: {
+ attrib_stride += sizeof(uint32_t);
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ attrib_stride += sizeof(float) * 2;
+
+ } break;
+ case RS::ARRAY_TEX_UV2: {
+ attrib_stride += sizeof(float) * 2;
+
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ int idx = i - RS::ARRAY_CUSTOM0;
+ uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
+ uint32_t fmt = (p_surface.format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
+ attrib_stride += fmtsize[fmt];
+
+ } break;
+ case RS::ARRAY_WEIGHTS:
+ case RS::ARRAY_BONES: {
+ //uses a separate array
+ bool use_8 = p_surface.format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
+ skin_stride += sizeof(int16_t) * (use_8 ? 16 : 8);
+ } break;
+ }
+ }
+ }
+
+ int expected_size = stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of vertex data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
+
+ int bs_expected_size = expected_size * mesh->blend_shape_count;
+
+ ERR_FAIL_COND_MSG(bs_expected_size != p_surface.blend_shape_data.size(), "Size of blend shape data provided (" + itos(p_surface.blend_shape_data.size()) + ") does not match expected (" + itos(bs_expected_size) + ")");
+
+ int expected_attrib_size = attrib_stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_attrib_size != p_surface.attribute_data.size(), "Size of attribute data provided (" + itos(p_surface.attribute_data.size()) + ") does not match expected (" + itos(expected_attrib_size) + ")");
+
+ if ((p_surface.format & RS::ARRAY_FORMAT_WEIGHTS) && (p_surface.format & RS::ARRAY_FORMAT_BONES)) {
+ expected_size = skin_stride * p_surface.vertex_count;
+ ERR_FAIL_COND_MSG(expected_size != p_surface.skin_data.size(), "Size of skin data provided (" + itos(p_surface.skin_data.size()) + ") does not match expected (" + itos(expected_size) + ")");
+ }
+ }
+
+#endif
+
+ Mesh::Surface *s = memnew(Mesh::Surface);
+
+ s->format = p_surface.format;
+ s->primitive = p_surface.primitive;
+
+ bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
+
+ s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
+ s->vertex_buffer_size = p_surface.vertex_data.size();
+
+ if (p_surface.attribute_data.size()) {
+ s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
+ }
+ if (p_surface.skin_data.size()) {
+ s->skin_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.skin_data.size(), p_surface.skin_data, use_as_storage);
+ s->skin_buffer_size = p_surface.skin_data.size();
+ }
+
+ s->vertex_count = p_surface.vertex_count;
+
+ if (p_surface.format & RS::ARRAY_FORMAT_BONES) {
+ mesh->has_bone_weights = true;
+ }
+
+ if (p_surface.index_count) {
+ bool is_index_16 = p_surface.vertex_count <= 65536;
+
+ s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
+ s->index_count = p_surface.index_count;
+ s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count);
+ if (p_surface.lods.size()) {
+ s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
+ s->lod_count = p_surface.lods.size();
+
+ for (int i = 0; i < p_surface.lods.size(); i++) {
+ uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4);
+ s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data);
+ s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices);
+ s->lods[i].edge_length = p_surface.lods[i].edge_length;
+ s->lods[i].index_count = indices;
+ }
+ }
+ }
+
+ s->aabb = p_surface.aabb;
+ s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
+
+ if (mesh->blend_shape_count > 0) {
+ s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
+ }
+
+ if (use_as_storage) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(s->vertex_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ if (s->skin_buffer.is_valid()) {
+ u.append_id(s->skin_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ if (s->blend_shape_buffer.is_valid()) {
+ u.append_id(s->blend_shape_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
+ uniforms.push_back(u);
+ }
+
+ s->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SURFACE);
+ }
+
+ if (mesh->surface_count == 0) {
+ mesh->bone_aabbs = p_surface.bone_aabbs;
+ mesh->aabb = p_surface.aabb;
+ } else {
+ if (mesh->bone_aabbs.size() < p_surface.bone_aabbs.size()) {
+ // ArrayMesh::_surface_set_data only allocates bone_aabbs up to max_bone
+ // Each surface may affect different numbers of bones.
+ mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
+ }
+ for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
+ mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
+ }
+ mesh->aabb.merge_with(p_surface.aabb);
+ }
+
+ s->material = p_surface.material;
+
+ mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1));
+ mesh->surfaces[mesh->surface_count] = s;
+ mesh->surface_count++;
+
+ for (MeshInstance *mi : mesh->instances) {
+ _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
+ }
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+
+ mesh->material_cache.clear();
+}
+
+int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const {
+ const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, -1);
+ return mesh->blend_shape_count;
+}
+
+void MeshStorage::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_INDEX((int)p_mode, 2);
+
+ mesh->blend_shape_mode = p_mode;
+}
+
+RS::BlendShapeMode MeshStorage::mesh_get_blend_shape_mode(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED);
+ return mesh->blend_shape_mode;
+}
+
+void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->attribute_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->attribute_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->skin_buffer.is_null());
+ uint64_t data_size = p_data.size();
+ const uint8_t *r = p_data.ptr();
+
+ RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->skin_buffer, p_offset, data_size, r);
+}
+
+void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
+ mesh->surfaces[p_surface]->material = p_material;
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ mesh->material_cache.clear();
+}
+
+RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID());
+
+ return mesh->surfaces[p_surface]->material;
+}
+
+RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
+
+ Mesh::Surface &s = *mesh->surfaces[p_surface];
+
+ RS::SurfaceData sd;
+ sd.format = s.format;
+ sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ if (s.attribute_buffer.is_valid()) {
+ sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
+ }
+ if (s.skin_buffer.is_valid()) {
+ sd.skin_data = RD::get_singleton()->buffer_get_data(s.skin_buffer);
+ }
+ sd.vertex_count = s.vertex_count;
+ sd.index_count = s.index_count;
+ sd.primitive = s.primitive;
+
+ if (sd.index_count) {
+ sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer);
+ }
+ sd.aabb = s.aabb;
+ for (uint32_t i = 0; i < s.lod_count; i++) {
+ RS::SurfaceData::LOD lod;
+ lod.edge_length = s.lods[i].edge_length;
+ lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ sd.lods.push_back(lod);
+ }
+
+ sd.bone_aabbs = s.bone_aabbs;
+
+ if (s.blend_shape_buffer.is_valid()) {
+ sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
+ }
+
+ return sd;
+}
+
+int MeshStorage::mesh_get_surface_count(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, 0);
+ return mesh->surface_count;
+}
+
+void MeshStorage::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ mesh->custom_aabb = p_aabb;
+}
+
+AABB MeshStorage::mesh_get_custom_aabb(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+ return mesh->custom_aabb;
+}
+
+AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, AABB());
+
+ if (mesh->custom_aabb != AABB()) {
+ return mesh->custom_aabb;
+ }
+
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ if (!skeleton || skeleton->size == 0) {
+ return mesh->aabb;
+ }
+
+ AABB aabb;
+
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ AABB laabb;
+ if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
+ int bs = mesh->surfaces[i]->bone_aabbs.size();
+ const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
+
+ int sbs = skeleton->size;
+ ERR_CONTINUE(bs > sbs);
+ const float *baseptr = skeleton->data.ptr();
+
+ bool first = true;
+
+ if (skeleton->use_2d) {
+ for (int j = 0; j < bs; j++) {
+ if (skbones[0].size == Vector3()) {
+ continue; //bone is unused
+ }
+
+ const float *dataptr = baseptr + j * 8;
+
+ Transform3D mtx;
+
+ mtx.basis.elements[0].x = dataptr[0];
+ mtx.basis.elements[1].x = dataptr[1];
+ mtx.origin.x = dataptr[3];
+
+ mtx.basis.elements[0].y = dataptr[4];
+ mtx.basis.elements[1].y = dataptr[5];
+ mtx.origin.y = dataptr[7];
+
+ AABB baabb = mtx.xform(skbones[j]);
+
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ } else {
+ for (int j = 0; j < bs; j++) {
+ if (skbones[0].size == Vector3()) {
+ continue; //bone is unused
+ }
+
+ const float *dataptr = baseptr + j * 12;
+
+ Transform3D mtx;
+
+ mtx.basis.elements[0][0] = dataptr[0];
+ mtx.basis.elements[0][1] = dataptr[1];
+ mtx.basis.elements[0][2] = dataptr[2];
+ mtx.origin.x = dataptr[3];
+ mtx.basis.elements[1][0] = dataptr[4];
+ mtx.basis.elements[1][1] = dataptr[5];
+ mtx.basis.elements[1][2] = dataptr[6];
+ mtx.origin.y = dataptr[7];
+ mtx.basis.elements[2][0] = dataptr[8];
+ mtx.basis.elements[2][1] = dataptr[9];
+ mtx.basis.elements[2][2] = dataptr[10];
+ mtx.origin.z = dataptr[11];
+
+ AABB baabb = mtx.xform(skbones[j]);
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ }
+
+ if (laabb.size == Vector3()) {
+ laabb = mesh->surfaces[i]->aabb;
+ }
+ } else {
+ laabb = mesh->surfaces[i]->aabb;
+ }
+
+ if (i == 0) {
+ aabb = laabb;
+ } else {
+ aabb.merge_with(laabb);
+ }
+ }
+
+ return aabb;
+}
+
+void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+
+ Mesh *shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.erase(mesh);
+ }
+ mesh->shadow_mesh = p_shadow_mesh;
+
+ shadow_mesh = mesh_owner.get_or_null(mesh->shadow_mesh);
+
+ if (shadow_mesh) {
+ shadow_mesh->shadow_owners.insert(mesh);
+ }
+
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+}
+
+void MeshStorage::mesh_clear(RID p_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!mesh);
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ Mesh::Surface &s = *mesh->surfaces[i];
+ RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ if (s.attribute_buffer.is_valid()) {
+ RD::get_singleton()->free(s.attribute_buffer);
+ }
+ if (s.skin_buffer.is_valid()) {
+ RD::get_singleton()->free(s.skin_buffer);
+ }
+ if (s.versions) {
+ memfree(s.versions); //reallocs, so free with memfree.
+ }
+
+ if (s.index_buffer.is_valid()) {
+ RD::get_singleton()->free(s.index_buffer);
+ }
+
+ if (s.lod_count) {
+ for (uint32_t j = 0; j < s.lod_count; j++) {
+ RD::get_singleton()->free(s.lods[j].index_buffer);
+ }
+ memdelete_arr(s.lods);
+ }
+
+ if (s.blend_shape_buffer.is_valid()) {
+ RD::get_singleton()->free(s.blend_shape_buffer);
+ }
+
+ memdelete(mesh->surfaces[i]);
+ }
+ if (mesh->surfaces) {
+ memfree(mesh->surfaces);
+ }
+
+ mesh->surfaces = nullptr;
+ mesh->surface_count = 0;
+ mesh->material_cache.clear();
+ //clear instance data
+ for (MeshInstance *mi : mesh->instances) {
+ _mesh_instance_clear(mi);
+ }
+ mesh->has_bone_weights = false;
+ mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+
+ for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ Mesh *shadow_owner = E->get();
+ shadow_owner->shadow_mesh = RID();
+ shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ }
+}
+
+bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, false);
+
+ return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
+}
+
+/* MESH INSTANCE */
+
+RID MeshStorage::mesh_instance_create(RID p_base) {
+ Mesh *mesh = mesh_owner.get_or_null(p_base);
+ ERR_FAIL_COND_V(!mesh, RID());
+
+ RID rid = mesh_instance_owner.make_rid();
+ MeshInstance *mi = mesh_instance_owner.get_or_null(rid);
+
+ mi->mesh = mesh;
+
+ for (uint32_t i = 0; i < mesh->surface_count; i++) {
+ _mesh_instance_add_surface(mi, mesh, i);
+ }
+
+ mi->I = mesh->instances.push_back(mi);
+
+ mi->dirty = true;
+
+ return rid;
+}
+
+void MeshStorage::mesh_instance_free(RID p_rid) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_rid);
+ _mesh_instance_clear(mi);
+ mi->mesh->instances.erase(mi->I);
+ mi->I = nullptr;
+
+ mesh_instance_owner.free(p_rid);
+}
+
+void MeshStorage::mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ if (mi->skeleton == p_skeleton) {
+ return;
+ }
+ mi->skeleton = p_skeleton;
+ mi->skeleton_version = 0;
+ mi->dirty = true;
+}
+
+void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ ERR_FAIL_COND(!mi);
+ ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size());
+ mi->blend_weights[p_shape] = p_weight;
+ mi->weights_dirty = true;
+ //will be eventually updated
+}
+
+void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
+ for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
+ if (mi->surfaces[i].versions) {
+ for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
+ RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array);
+ }
+ memfree(mi->surfaces[i].versions);
+ }
+ if (mi->surfaces[i].vertex_buffer.is_valid()) {
+ RD::get_singleton()->free(mi->surfaces[i].vertex_buffer);
+ }
+ }
+ mi->surfaces.clear();
+
+ if (mi->blend_weights_buffer.is_valid()) {
+ RD::get_singleton()->free(mi->blend_weights_buffer);
+ }
+ mi->blend_weights.clear();
+ mi->weights_dirty = false;
+ mi->skeleton_version = 0;
+}
+
+void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
+ if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) {
+ mi->blend_weights.resize(mesh->blend_shape_count);
+ for (uint32_t i = 0; i < mi->blend_weights.size(); i++) {
+ mi->blend_weights[i] = 0;
+ }
+ mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array());
+ mi->weights_dirty = true;
+ }
+
+ MeshInstance::Surface s;
+ if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
+ //surface warrants transform
+ s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(s.vertex_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ if (mi->blend_weights_buffer.is_valid()) {
+ u.append_id(mi->blend_weights_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
+ uniforms.push_back(u);
+ }
+ s.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_INSTANCE);
+ }
+
+ mi->surfaces.push_back(s);
+ mi->dirty = true;
+}
+
+void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+
+ bool needs_update = mi->dirty;
+
+ if (mi->weights_dirty && !mi->weight_update_list.in_list()) {
+ dirty_mesh_instance_weights.add(&mi->weight_update_list);
+ needs_update = true;
+ }
+
+ if (mi->array_update_list.in_list()) {
+ return;
+ }
+
+ if (!needs_update && mi->skeleton.is_valid()) {
+ Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
+ if (sk && sk->version != mi->skeleton_version) {
+ needs_update = true;
+ }
+ }
+
+ if (needs_update) {
+ dirty_mesh_instance_arrays.add(&mi->array_update_list);
+ }
+}
+
+void MeshStorage::update_mesh_instances() {
+ while (dirty_mesh_instance_weights.first()) {
+ MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
+
+ if (mi->blend_weights_buffer.is_valid()) {
+ RD::get_singleton()->buffer_update(mi->blend_weights_buffer, 0, mi->blend_weights.size() * sizeof(float), mi->blend_weights.ptr());
+ }
+ dirty_mesh_instance_weights.remove(&mi->weight_update_list);
+ mi->weights_dirty = false;
+ }
+ if (dirty_mesh_instance_arrays.first() == nullptr) {
+ return; //nothing to do
+ }
+
+ //process skeletons and blend shapes
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ while (dirty_mesh_instance_arrays.first()) {
+ MeshInstance *mi = dirty_mesh_instance_arrays.first()->self();
+
+ Skeleton *sk = skeleton_owner.get_or_null(mi->skeleton);
+
+ for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
+ if (mi->surfaces[i].uniform_set == RID() || mi->mesh->surfaces[i]->uniform_set == RID()) {
+ continue;
+ }
+
+ bool array_is_2d = mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_2D_VERTICES;
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, skeleton_shader.pipeline[array_is_2d ? SkeletonShader::SHADER_MODE_2D : SkeletonShader::SHADER_MODE_3D]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->surfaces[i].uniform_set, SkeletonShader::UNIFORM_SET_INSTANCE);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, mi->mesh->surfaces[i]->uniform_set, SkeletonShader::UNIFORM_SET_SURFACE);
+ if (sk && sk->uniform_set_mi.is_valid()) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sk->uniform_set_mi, SkeletonShader::UNIFORM_SET_SKELETON);
+ } else {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, skeleton_shader.default_skeleton_uniform_set, SkeletonShader::UNIFORM_SET_SKELETON);
+ }
+
+ SkeletonShader::PushConstant push_constant;
+
+ push_constant.has_normal = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_NORMAL;
+ push_constant.has_tangent = mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_TANGENT;
+ push_constant.has_skeleton = sk != nullptr && sk->use_2d == array_is_2d && (mi->mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES);
+ push_constant.has_blend_shape = mi->mesh->blend_shape_count > 0;
+
+ push_constant.vertex_count = mi->mesh->surfaces[i]->vertex_count;
+ push_constant.vertex_stride = (mi->mesh->surfaces[i]->vertex_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
+ push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
+ push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2;
+
+ push_constant.blend_shape_count = mi->mesh->blend_shape_count;
+ push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED;
+ push_constant.pad0 = 0;
+ push_constant.pad1 = 0;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SkeletonShader::PushConstant));
+
+ //dispatch without barrier, so all is done at the same time
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.vertex_count, 1, 1);
+ }
+
+ mi->dirty = false;
+ if (sk) {
+ mi->skeleton_version = sk->version;
+ }
+ dirty_mesh_instance_arrays.remove(&mi->array_update_list);
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis) {
+ Vector<RD::VertexAttribute> attributes;
+ Vector<RID> buffers;
+
+ uint32_t stride = 0;
+ uint32_t attribute_stride = 0;
+ uint32_t skin_stride = 0;
+
+ for (int i = 0; i < RS::ARRAY_INDEX; i++) {
+ RD::VertexAttribute vd;
+ RID buffer;
+ vd.location = i;
+
+ if (!(s->format & (1 << i))) {
+ // Not supplied by surface, use default value
+ buffer = mesh_default_rd_buffers[i];
+ vd.stride = 0;
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ } break;
+ case RS::ARRAY_TANGENT: {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ case RS::ARRAY_COLOR: {
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+
+ } break;
+ case RS::ARRAY_TEX_UV2: {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ case RS::ARRAY_BONES: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
+ } break;
+ case RS::ARRAY_WEIGHTS: {
+ //assumed weights too
+ vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ } break;
+ }
+ } else {
+ //Supplied, use it
+
+ vd.stride = 1; //mark that it needs a stride set (default uses 0)
+
+ switch (i) {
+ case RS::ARRAY_VERTEX: {
+ vd.offset = stride;
+
+ if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) {
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ stride += sizeof(float) * 2;
+ } else {
+ vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT;
+ stride += sizeof(float) * 3;
+ }
+
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+
+ } break;
+ case RS::ARRAY_NORMAL: {
+ vd.offset = stride;
+
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+
+ stride += sizeof(uint32_t);
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+ } break;
+ case RS::ARRAY_TANGENT: {
+ vd.offset = stride;
+
+ vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
+ stride += sizeof(uint32_t);
+ if (mis) {
+ buffer = mis->vertex_buffer;
+ } else {
+ buffer = s->vertex_buffer;
+ }
+ } break;
+ case RS::ARRAY_COLOR: {
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ attribute_stride += sizeof(int8_t) * 4;
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_TEX_UV: {
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ attribute_stride += sizeof(float) * 2;
+ buffer = s->attribute_buffer;
+
+ } break;
+ case RS::ARRAY_TEX_UV2: {
+ vd.offset = attribute_stride;
+
+ vd.format = RD::DATA_FORMAT_R32G32_SFLOAT;
+ attribute_stride += sizeof(float) * 2;
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_CUSTOM0:
+ case RS::ARRAY_CUSTOM1:
+ case RS::ARRAY_CUSTOM2:
+ case RS::ARRAY_CUSTOM3: {
+ vd.offset = attribute_stride;
+
+ int idx = i - RS::ARRAY_CUSTOM0;
+ uint32_t fmt_shift[RS::ARRAY_CUSTOM_COUNT] = { RS::ARRAY_FORMAT_CUSTOM0_SHIFT, RS::ARRAY_FORMAT_CUSTOM1_SHIFT, RS::ARRAY_FORMAT_CUSTOM2_SHIFT, RS::ARRAY_FORMAT_CUSTOM3_SHIFT };
+ uint32_t fmt = (s->format >> fmt_shift[idx]) & RS::ARRAY_FORMAT_CUSTOM_MASK;
+ uint32_t fmtsize[RS::ARRAY_CUSTOM_MAX] = { 4, 4, 4, 8, 4, 8, 12, 16 };
+ RD::DataFormat fmtrd[RS::ARRAY_CUSTOM_MAX] = { RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::DATA_FORMAT_R8G8B8A8_SNORM, RD::DATA_FORMAT_R16G16_SFLOAT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::DATA_FORMAT_R32_SFLOAT, RD::DATA_FORMAT_R32G32_SFLOAT, RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::DATA_FORMAT_R32G32B32A32_SFLOAT };
+ vd.format = fmtrd[fmt];
+ attribute_stride += fmtsize[fmt];
+ buffer = s->attribute_buffer;
+ } break;
+ case RS::ARRAY_BONES: {
+ vd.offset = skin_stride;
+
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UINT;
+ skin_stride += sizeof(int16_t) * 4;
+ buffer = s->skin_buffer;
+ } break;
+ case RS::ARRAY_WEIGHTS: {
+ vd.offset = skin_stride;
+
+ vd.format = RD::DATA_FORMAT_R16G16B16A16_UNORM;
+ skin_stride += sizeof(int16_t) * 4;
+ buffer = s->skin_buffer;
+ } break;
+ }
+ }
+
+ if (!(p_input_mask & (1 << i))) {
+ continue; // Shader does not need this, skip it (but computing stride was important anyway)
+ }
+
+ attributes.push_back(vd);
+ buffers.push_back(buffer);
+ }
+
+ //update final stride
+ for (int i = 0; i < attributes.size(); i++) {
+ if (attributes[i].stride == 0) {
+ continue; //default location
+ }
+ int loc = attributes[i].location;
+
+ if (loc < RS::ARRAY_COLOR) {
+ attributes.write[i].stride = stride;
+ } else if (loc < RS::ARRAY_BONES) {
+ attributes.write[i].stride = attribute_stride;
+ } else {
+ attributes.write[i].stride = skin_stride;
+ }
+ }
+
+ v.input_mask = p_input_mask;
+ v.vertex_format = RD::get_singleton()->vertex_format_create(attributes);
+ v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers);
+}
+
+////////////////// MULTIMESH
+
+RID MeshStorage::multimesh_allocate() {
+ return multimesh_owner.allocate_rid();
+}
+void MeshStorage::multimesh_initialize(RID p_rid) {
+ multimesh_owner.initialize_rid(p_rid, MultiMesh());
+}
+
+void MeshStorage::multimesh_free(RID p_rid) {
+ _update_dirty_multimeshes();
+ multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
+ multimesh->dependency.deleted_notify(p_rid);
+ multimesh_owner.free(p_rid);
+}
+
+void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+
+ if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) {
+ return;
+ }
+
+ if (multimesh->buffer.is_valid()) {
+ RD::get_singleton()->free(multimesh->buffer);
+ multimesh->buffer = RID();
+ multimesh->uniform_set_2d = RID(); //cleared by dependency
+ multimesh->uniform_set_3d = RID(); //cleared by dependency
+ }
+
+ if (multimesh->data_cache_dirty_regions) {
+ memdelete_arr(multimesh->data_cache_dirty_regions);
+ multimesh->data_cache_dirty_regions = nullptr;
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ multimesh->instances = p_instances;
+ multimesh->xform_format = p_transform_format;
+ multimesh->uses_colors = p_use_colors;
+ multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12;
+ multimesh->uses_custom_data = p_use_custom_data;
+ multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0);
+ multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0);
+ multimesh->buffer_set = false;
+
+ //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances));
+ multimesh->data_cache = Vector<float>();
+ multimesh->aabb = AABB();
+ multimesh->aabb_dirty = false;
+ multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
+
+ if (multimesh->instances) {
+ multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
+ }
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH);
+}
+
+int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, 0);
+ return multimesh->instances;
+}
+
+void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ if (multimesh->mesh == p_mesh) {
+ return;
+ }
+ multimesh->mesh = p_mesh;
+
+ if (multimesh->instances == 0) {
+ return;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //we have a data cache, just mark it dirt
+ _multimesh_mark_all_dirty(multimesh, false, true);
+ } else if (multimesh->instances) {
+ //need to re-create AABB unfortunately, calling this has a penalty
+ if (multimesh->buffer_set) {
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ const uint8_t *r = buffer.ptr();
+ const float *data = (const float *)r;
+ _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ }
+ }
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+}
+
+#define MULTIMESH_DIRTY_REGION_SIZE 512
+
+void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
+ if (multimesh->data_cache.size() > 0) {
+ return; //already local
+ }
+ ERR_FAIL_COND(multimesh->data_cache.size() > 0);
+ // this means that the user wants to load/save individual elements,
+ // for this, the data must reside on CPU, so just copy it there.
+ multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ if (multimesh->buffer_set) {
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ {
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+ } else {
+ memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
+ }
+ }
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+ multimesh->data_cache_used_dirty_regions = 0;
+}
+
+void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
+ uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE;
+#ifdef DEBUG_ENABLED
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug
+#endif
+ if (!multimesh->data_cache_dirty_regions[region_index]) {
+ multimesh->data_cache_dirty_regions[region_index] = true;
+ multimesh->data_cache_used_dirty_regions++;
+ }
+
+ if (p_aabb) {
+ multimesh->aabb_dirty = true;
+ }
+
+ if (!multimesh->dirty) {
+ multimesh->dirty_list = multimesh_dirty_list;
+ multimesh_dirty_list = multimesh;
+ multimesh->dirty = true;
+ }
+}
+
+void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) {
+ if (p_data) {
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ if (!multimesh->data_cache_dirty_regions[i]) {
+ multimesh->data_cache_dirty_regions[i] = true;
+ multimesh->data_cache_used_dirty_regions++;
+ }
+ }
+ }
+
+ if (p_aabb) {
+ multimesh->aabb_dirty = true;
+ }
+
+ if (!multimesh->dirty) {
+ multimesh->dirty_list = multimesh_dirty_list;
+ multimesh_dirty_list = multimesh;
+ multimesh->dirty = true;
+ }
+}
+
+void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) {
+ ERR_FAIL_COND(multimesh->mesh.is_null());
+ AABB aabb;
+ AABB mesh_aabb = mesh_get_aabb(multimesh->mesh);
+ for (int i = 0; i < p_instances; i++) {
+ const float *data = p_data + multimesh->stride_cache * i;
+ Transform3D t;
+
+ if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) {
+ t.basis.elements[0][0] = data[0];
+ t.basis.elements[0][1] = data[1];
+ t.basis.elements[0][2] = data[2];
+ t.origin.x = data[3];
+ t.basis.elements[1][0] = data[4];
+ t.basis.elements[1][1] = data[5];
+ t.basis.elements[1][2] = data[6];
+ t.origin.y = data[7];
+ t.basis.elements[2][0] = data[8];
+ t.basis.elements[2][1] = data[9];
+ t.basis.elements[2][2] = data[10];
+ t.origin.z = data[11];
+
+ } else {
+ t.basis.elements[0].x = data[0];
+ t.basis.elements[1].x = data[1];
+ t.origin.x = data[3];
+
+ t.basis.elements[0].y = data[4];
+ t.basis.elements[1].y = data[5];
+ t.origin.y = data[7];
+ }
+
+ if (i == 0) {
+ aabb = t.xform(mesh_aabb);
+ } else {
+ aabb.merge_with(t.xform(mesh_aabb));
+ }
+ }
+
+ multimesh->aabb = aabb;
+}
+
+void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache;
+
+ dataptr[0] = p_transform.basis.elements[0][0];
+ dataptr[1] = p_transform.basis.elements[0][1];
+ dataptr[2] = p_transform.basis.elements[0][2];
+ dataptr[3] = p_transform.origin.x;
+ dataptr[4] = p_transform.basis.elements[1][0];
+ dataptr[5] = p_transform.basis.elements[1][1];
+ dataptr[6] = p_transform.basis.elements[1][2];
+ dataptr[7] = p_transform.origin.y;
+ dataptr[8] = p_transform.basis.elements[2][0];
+ dataptr[9] = p_transform.basis.elements[2][1];
+ dataptr[10] = p_transform.basis.elements[2][2];
+ dataptr[11] = p_transform.origin.z;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, true);
+}
+
+void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache;
+
+ dataptr[0] = p_transform.elements[0][0];
+ dataptr[1] = p_transform.elements[1][0];
+ dataptr[2] = 0;
+ dataptr[3] = p_transform.elements[2][0];
+ dataptr[4] = p_transform.elements[0][1];
+ dataptr[5] = p_transform.elements[1][1];
+ dataptr[6] = 0;
+ dataptr[7] = p_transform.elements[2][1];
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, true);
+}
+
+void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(!multimesh->uses_colors);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+
+ dataptr[0] = p_color.r;
+ dataptr[1] = p_color.g;
+ dataptr[2] = p_color.b;
+ dataptr[3] = p_color.a;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, false);
+}
+
+void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_INDEX(p_index, multimesh->instances);
+ ERR_FAIL_COND(!multimesh->uses_custom_data);
+
+ _multimesh_make_local(multimesh);
+
+ {
+ float *w = multimesh->data_cache.ptrw();
+
+ float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+
+ dataptr[0] = p_color.r;
+ dataptr[1] = p_color.g;
+ dataptr[2] = p_color.b;
+ dataptr[3] = p_color.a;
+ }
+
+ _multimesh_mark_dirty(multimesh, p_index, false);
+}
+
+RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, RID());
+
+ return multimesh->mesh;
+}
+
+Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Transform3D());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
+ ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform3D());
+
+ _multimesh_make_local(multimesh);
+
+ Transform3D t;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache;
+
+ t.basis.elements[0][0] = dataptr[0];
+ t.basis.elements[0][1] = dataptr[1];
+ t.basis.elements[0][2] = dataptr[2];
+ t.origin.x = dataptr[3];
+ t.basis.elements[1][0] = dataptr[4];
+ t.basis.elements[1][1] = dataptr[5];
+ t.basis.elements[1][2] = dataptr[6];
+ t.origin.y = dataptr[7];
+ t.basis.elements[2][0] = dataptr[8];
+ t.basis.elements[2][1] = dataptr[9];
+ t.basis.elements[2][2] = dataptr[10];
+ t.origin.z = dataptr[11];
+ }
+
+ return t;
+}
+
+Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Transform2D());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
+ ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D());
+
+ _multimesh_make_local(multimesh);
+
+ Transform2D t;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache;
+
+ t.elements[0][0] = dataptr[0];
+ t.elements[1][0] = dataptr[1];
+ t.elements[2][0] = dataptr[3];
+ t.elements[0][1] = dataptr[4];
+ t.elements[1][1] = dataptr[5];
+ t.elements[2][1] = dataptr[7];
+ }
+
+ return t;
+}
+
+Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Color());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
+ ERR_FAIL_COND_V(!multimesh->uses_colors, Color());
+
+ _multimesh_make_local(multimesh);
+
+ Color c;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+
+ c.r = dataptr[0];
+ c.g = dataptr[1];
+ c.b = dataptr[2];
+ c.a = dataptr[3];
+ }
+
+ return c;
+}
+
+Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Color());
+ ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
+ ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color());
+
+ _multimesh_make_local(multimesh);
+
+ Color c;
+ {
+ const float *r = multimesh->data_cache.ptr();
+
+ const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+
+ c.r = dataptr[0];
+ c.g = dataptr[1];
+ c.b = dataptr[2];
+ c.a = dataptr[3];
+ }
+
+ return c;
+}
+
+void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
+
+ {
+ const float *r = p_buffer.ptr();
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r);
+ multimesh->buffer_set = true;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //if we have a data cache, just update it
+ multimesh->data_cache = p_buffer;
+ {
+ //clear dirty since nothing will be dirty anymore
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ _multimesh_mark_all_dirty(multimesh, false, true); //update AABB
+ } else if (multimesh->mesh.is_valid()) {
+ //if we have a mesh set, we need to re-generate the AABB from the new data
+ const float *data = p_buffer.ptr();
+
+ _multimesh_re_create_aabb(multimesh, data, multimesh->instances);
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+}
+
+Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, Vector<float>());
+ if (multimesh->buffer.is_null()) {
+ return Vector<float>();
+ } else if (multimesh->data_cache.size()) {
+ return multimesh->data_cache;
+ } else {
+ //get from memory
+
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ Vector<float> ret;
+ ret.resize(multimesh->instances * multimesh->stride_cache);
+ {
+ float *w = ret.ptrw();
+ const uint8_t *r = buffer.ptr();
+ memcpy(w, r, buffer.size());
+ }
+
+ return ret;
+ }
+}
+
+void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
+ if (multimesh->visible_instances == p_visible) {
+ return;
+ }
+
+ if (multimesh->data_cache.size()) {
+ //there is a data cache..
+ _multimesh_mark_all_dirty(multimesh, false, true);
+ }
+
+ multimesh->visible_instances = p_visible;
+
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
+}
+
+int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, 0);
+ return multimesh->visible_instances;
+}
+
+AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, AABB());
+ if (multimesh->aabb_dirty) {
+ const_cast<MeshStorage *>(this)->_update_dirty_multimeshes();
+ }
+ return multimesh->aabb;
+}
+
+void MeshStorage::_update_dirty_multimeshes() {
+ while (multimesh_dirty_list) {
+ MultiMesh *multimesh = multimesh_dirty_list;
+
+ if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
+ const float *data = multimesh->data_cache.ptr();
+
+ uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
+
+ if (multimesh->data_cache_used_dirty_regions) {
+ uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+
+ uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
+
+ if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
+ //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
+ } else {
+ //not that many regions? update them all
+ for (uint32_t i = 0; i < visible_region_count; i++) {
+ if (multimesh->data_cache_dirty_regions[i]) {
+ uint32_t offset = i * region_size;
+ uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
+ uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
+ RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
+ }
+ }
+ }
+
+ for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
+ multimesh->data_cache_dirty_regions[i] = false;
+ }
+
+ multimesh->data_cache_used_dirty_regions = 0;
+ }
+
+ if (multimesh->aabb_dirty) {
+ //aabb is dirty..
+ _multimesh_re_create_aabb(multimesh, data, visible_instances);
+ multimesh->aabb_dirty = false;
+ multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+ }
+
+ multimesh_dirty_list = multimesh->dirty_list;
+
+ multimesh->dirty_list = nullptr;
+ multimesh->dirty = false;
+ }
+
+ multimesh_dirty_list = nullptr;
+}
+
+/* SKELETON API */
+
+RID MeshStorage::skeleton_allocate() {
+ return skeleton_owner.allocate_rid();
+}
+void MeshStorage::skeleton_initialize(RID p_rid) {
+ skeleton_owner.initialize_rid(p_rid, Skeleton());
+}
+
+void MeshStorage::skeleton_free(RID p_rid) {
+ _update_dirty_skeletons();
+ skeleton_allocate_data(p_rid, 0);
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_rid);
+ skeleton->dependency.deleted_notify(p_rid);
+ skeleton_owner.free(p_rid);
+}
+
+void MeshStorage::_skeleton_make_dirty(Skeleton *skeleton) {
+ if (!skeleton->dirty) {
+ skeleton->dirty = true;
+ skeleton->dirty_list = skeleton_dirty_list;
+ skeleton_dirty_list = skeleton;
+ }
+}
+
+void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_COND(p_bones < 0);
+
+ if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) {
+ return;
+ }
+
+ skeleton->size = p_bones;
+ skeleton->use_2d = p_2d_skeleton;
+ skeleton->uniform_set_3d = RID();
+
+ if (skeleton->buffer.is_valid()) {
+ RD::get_singleton()->free(skeleton->buffer);
+ skeleton->buffer = RID();
+ skeleton->data.clear();
+ skeleton->uniform_set_mi = RID();
+ }
+
+ if (skeleton->size) {
+ skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12));
+ skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float));
+ memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
+
+ _skeleton_make_dirty(skeleton);
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.append_id(skeleton->buffer);
+ uniforms.push_back(u);
+ }
+ skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);
+ }
+ }
+
+ skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA);
+}
+
+int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND_V(!skeleton, 0);
+
+ return skeleton->size;
+}
+
+void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 12;
+
+ dataptr[0] = p_transform.basis.elements[0][0];
+ dataptr[1] = p_transform.basis.elements[0][1];
+ dataptr[2] = p_transform.basis.elements[0][2];
+ dataptr[3] = p_transform.origin.x;
+ dataptr[4] = p_transform.basis.elements[1][0];
+ dataptr[5] = p_transform.basis.elements[1][1];
+ dataptr[6] = p_transform.basis.elements[1][2];
+ dataptr[7] = p_transform.origin.y;
+ dataptr[8] = p_transform.basis.elements[2][0];
+ dataptr[9] = p_transform.basis.elements[2][1];
+ dataptr[10] = p_transform.basis.elements[2][2];
+ dataptr[11] = p_transform.origin.z;
+
+ _skeleton_make_dirty(skeleton);
+}
+
+Transform3D MeshStorage::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform3D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform3D());
+ ERR_FAIL_COND_V(skeleton->use_2d, Transform3D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 12;
+
+ Transform3D t;
+
+ t.basis.elements[0][0] = dataptr[0];
+ t.basis.elements[0][1] = dataptr[1];
+ t.basis.elements[0][2] = dataptr[2];
+ t.origin.x = dataptr[3];
+ t.basis.elements[1][0] = dataptr[4];
+ t.basis.elements[1][1] = dataptr[5];
+ t.basis.elements[1][2] = dataptr[6];
+ t.origin.y = dataptr[7];
+ t.basis.elements[2][0] = dataptr[8];
+ t.basis.elements[2][1] = dataptr[9];
+ t.basis.elements[2][2] = dataptr[10];
+ t.origin.z = dataptr[11];
+
+ return t;
+}
+
+void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton);
+ ERR_FAIL_INDEX(p_bone, skeleton->size);
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ float *dataptr = skeleton->data.ptrw() + p_bone * 8;
+
+ dataptr[0] = p_transform.elements[0][0];
+ dataptr[1] = p_transform.elements[1][0];
+ dataptr[2] = 0;
+ dataptr[3] = p_transform.elements[2][0];
+ dataptr[4] = p_transform.elements[0][1];
+ dataptr[5] = p_transform.elements[1][1];
+ dataptr[6] = 0;
+ dataptr[7] = p_transform.elements[2][1];
+
+ _skeleton_make_dirty(skeleton);
+}
+
+Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND_V(!skeleton, Transform2D());
+ ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
+ ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
+
+ const float *dataptr = skeleton->data.ptr() + p_bone * 8;
+
+ Transform2D t;
+ t.elements[0][0] = dataptr[0];
+ t.elements[1][0] = dataptr[1];
+ t.elements[2][0] = dataptr[3];
+ t.elements[0][1] = dataptr[4];
+ t.elements[1][1] = dataptr[5];
+ t.elements[2][1] = dataptr[7];
+
+ return t;
+}
+
+void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+
+ ERR_FAIL_COND(!skeleton->use_2d);
+
+ skeleton->base_transform_2d = p_base_transform;
+}
+
+void MeshStorage::_update_dirty_skeletons() {
+ while (skeleton_dirty_list) {
+ Skeleton *skeleton = skeleton_dirty_list;
+
+ if (skeleton->size) {
+ RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr());
+ }
+
+ skeleton_dirty_list = skeleton->dirty_list;
+
+ skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES);
+
+ skeleton->version++;
+
+ skeleton->dirty = false;
+ skeleton->dirty_list = nullptr;
+ }
+
+ skeleton_dirty_list = nullptr;
+}
+
+void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND(!skeleton);
+
+ p_instance->update_dependency(&skeleton->dependency);
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
new file mode 100644
index 0000000000..e8da8ad563
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -0,0 +1,694 @@
+/*************************************************************************/
+/* mesh_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MESH_STORAGE_RD_H
+#define MESH_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
+
+namespace RendererRD {
+
+/* Mesh */
+
+enum DefaultRDBuffer {
+ DEFAULT_RD_BUFFER_VERTEX,
+ DEFAULT_RD_BUFFER_NORMAL,
+ DEFAULT_RD_BUFFER_TANGENT,
+ DEFAULT_RD_BUFFER_COLOR,
+ DEFAULT_RD_BUFFER_TEX_UV,
+ DEFAULT_RD_BUFFER_TEX_UV2,
+ DEFAULT_RD_BUFFER_CUSTOM0,
+ DEFAULT_RD_BUFFER_CUSTOM1,
+ DEFAULT_RD_BUFFER_CUSTOM2,
+ DEFAULT_RD_BUFFER_CUSTOM3,
+ DEFAULT_RD_BUFFER_BONES,
+ DEFAULT_RD_BUFFER_WEIGHTS,
+ DEFAULT_RD_BUFFER_MAX,
+};
+
+struct MeshInstance;
+
+struct Mesh {
+ struct Surface {
+ RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
+ uint32_t format = 0;
+
+ RID vertex_buffer;
+ RID attribute_buffer;
+ RID skin_buffer;
+ uint32_t vertex_count = 0;
+ uint32_t vertex_buffer_size = 0;
+ uint32_t skin_buffer_size = 0;
+
+ // A different pipeline needs to be allocated
+ // depending on the inputs available in the
+ // material.
+ // There are never that many geometry/material
+ // combinations, so a simple array is the most
+ // cache-efficient structure.
+
+ struct Version {
+ uint32_t input_mask = 0;
+ RD::VertexFormatID vertex_format = 0;
+ RID vertex_array;
+ };
+
+ SpinLock version_lock; //needed to access versions
+ Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+
+ RID index_buffer;
+ RID index_array;
+ uint32_t index_count = 0;
+
+ struct LOD {
+ float edge_length = 0.0;
+ uint32_t index_count = 0;
+ RID index_buffer;
+ RID index_array;
+ };
+
+ LOD *lods = nullptr;
+ uint32_t lod_count = 0;
+
+ AABB aabb;
+
+ Vector<AABB> bone_aabbs;
+
+ RID blend_shape_buffer;
+
+ RID material;
+
+ uint32_t render_index = 0;
+ uint64_t render_pass = 0;
+
+ uint32_t multimesh_render_index = 0;
+ uint64_t multimesh_render_pass = 0;
+
+ uint32_t particles_render_index = 0;
+ uint64_t particles_render_pass = 0;
+
+ RID uniform_set;
+ };
+
+ uint32_t blend_shape_count = 0;
+ RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
+
+ Surface **surfaces = nullptr;
+ uint32_t surface_count = 0;
+
+ Vector<AABB> bone_aabbs;
+
+ bool has_bone_weights = false;
+
+ AABB aabb;
+ AABB custom_aabb;
+
+ Vector<RID> material_cache;
+
+ List<MeshInstance *> instances;
+
+ RID shadow_mesh;
+ Set<Mesh *> shadow_owners;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* Mesh Instance */
+
+struct MeshInstance {
+ Mesh *mesh = nullptr;
+ RID skeleton;
+ struct Surface {
+ RID vertex_buffer;
+ RID uniform_set;
+
+ Mesh::Surface::Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+ };
+ LocalVector<Surface> surfaces;
+ LocalVector<float> blend_weights;
+
+ RID blend_weights_buffer;
+ List<MeshInstance *>::Element *I = nullptr; //used to erase itself
+ uint64_t skeleton_version = 0;
+ bool dirty = false;
+ bool weights_dirty = false;
+ SelfList<MeshInstance> weight_update_list;
+ SelfList<MeshInstance> array_update_list;
+ MeshInstance() :
+ weight_update_list(this), array_update_list(this) {}
+};
+
+/* MultiMesh */
+
+struct MultiMesh {
+ RID mesh;
+ int instances = 0;
+ RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
+ bool uses_colors = false;
+ bool uses_custom_data = false;
+ int visible_instances = -1;
+ AABB aabb;
+ bool aabb_dirty = false;
+ bool buffer_set = false;
+ uint32_t stride_cache = 0;
+ uint32_t color_offset_cache = 0;
+ uint32_t custom_data_offset_cache = 0;
+
+ Vector<float> data_cache; //used if individual setting is used
+ bool *data_cache_dirty_regions = nullptr;
+ uint32_t data_cache_used_dirty_regions = 0;
+
+ RID buffer; //storage buffer
+ RID uniform_set_3d;
+ RID uniform_set_2d;
+
+ bool dirty = false;
+ MultiMesh *dirty_list = nullptr;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* Skeleton */
+
+struct SkeletonShader {
+ struct PushConstant {
+ uint32_t has_normal;
+ uint32_t has_tangent;
+ uint32_t has_skeleton;
+ uint32_t has_blend_shape;
+
+ uint32_t vertex_count;
+ uint32_t vertex_stride;
+ uint32_t skin_stride;
+ uint32_t skin_weight_offset;
+
+ uint32_t blend_shape_count;
+ uint32_t normalized_blend_shapes;
+ uint32_t pad0;
+ uint32_t pad1;
+ };
+
+ enum {
+ UNIFORM_SET_INSTANCE = 0,
+ UNIFORM_SET_SURFACE = 1,
+ UNIFORM_SET_SKELETON = 2,
+ };
+ enum {
+ SHADER_MODE_2D,
+ SHADER_MODE_3D,
+ SHADER_MODE_MAX
+ };
+
+ SkeletonShaderRD shader;
+ RID version;
+ RID version_shader[SHADER_MODE_MAX];
+ RID pipeline[SHADER_MODE_MAX];
+
+ RID default_skeleton_uniform_set;
+};
+
+struct Skeleton {
+ bool use_2d = false;
+ int size = 0;
+ Vector<float> data;
+ RID buffer;
+
+ bool dirty = false;
+ Skeleton *dirty_list = nullptr;
+ Transform2D base_transform_2d;
+
+ RID uniform_set_3d;
+ RID uniform_set_mi;
+
+ uint64_t version = 1;
+
+ RendererStorage::Dependency dependency;
+};
+
+class MeshStorage : public RendererMeshStorage {
+private:
+ static MeshStorage *singleton;
+
+ RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
+ RID default_rd_storage_buffer;
+
+ /* Mesh */
+
+ mutable RID_Owner<Mesh, true> mesh_owner;
+
+ void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
+
+ /* Mesh Instance API */
+
+ void _mesh_instance_clear(MeshInstance *mi);
+ void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
+
+ mutable RID_Owner<MeshInstance> mesh_instance_owner;
+
+ SelfList<MeshInstance>::List dirty_mesh_instance_weights;
+ SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
+
+ /* MultiMesh */
+
+ mutable RID_Owner<MultiMesh, true> multimesh_owner;
+
+ MultiMesh *multimesh_dirty_list = nullptr;
+
+ _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
+ _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
+ _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
+
+ /* Skeleton */
+
+ SkeletonShader skeleton_shader;
+
+ mutable RID_Owner<Skeleton, true> skeleton_owner;
+
+ _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton);
+
+ Skeleton *skeleton_dirty_list = nullptr;
+
+public:
+ static MeshStorage *get_singleton();
+
+ MeshStorage();
+ virtual ~MeshStorage();
+
+ RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
+
+ /* MESH API */
+
+ Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); };
+ bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
+
+ virtual RID mesh_allocate() override;
+ virtual void mesh_initialize(RID p_mesh) override;
+ virtual void mesh_free(RID p_rid) override;
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override;
+
+ /// Return stride
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override;
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const override;
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) override;
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const override;
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) override;
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override;
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override;
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override;
+
+ virtual int mesh_get_surface_count(RID p_mesh) const override;
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const override;
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) override;
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
+
+ virtual void mesh_clear(RID p_mesh) override;
+
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override;
+
+ _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+ r_surface_count = mesh->surface_count;
+ if (r_surface_count == 0) {
+ return nullptr;
+ }
+ if (mesh->material_cache.is_empty()) {
+ mesh->material_cache.resize(mesh->surface_count);
+ for (uint32_t i = 0; i < r_surface_count; i++) {
+ mesh->material_cache.write[i] = mesh->surfaces[i]->material;
+ }
+ }
+
+ return mesh->material_cache.ptr();
+ }
+
+ _FORCE_INLINE_ void *mesh_get_surface(RID p_mesh, uint32_t p_surface_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, nullptr);
+
+ return mesh->surfaces[p_surface_index];
+ }
+
+ _FORCE_INLINE_ RID mesh_get_shadow_mesh(RID p_mesh) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RID());
+
+ return mesh->shadow_mesh;
+ }
+
+ _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(void *p_surface) {
+ Mesh::Surface *surface = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return surface->primitive;
+ }
+
+ _FORCE_INLINE_ bool mesh_surface_has_lod(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return s->lod_count > 0;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_vertices_drawn_count(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+ return s->index_count ? s->index_count : s->vertex_count;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ int32_t current_lod = -1;
+ if (r_index_count) {
+ *r_index_count = s->index_count;
+ }
+ for (uint32_t i = 0; i < s->lod_count; i++) {
+ float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
+ if (screen_size > p_mesh_lod_threshold) {
+ break;
+ }
+ current_lod = i;
+ }
+ if (current_lod == -1) {
+ return 0;
+ } else {
+ if (r_index_count) {
+ *r_index_count = s->lods[current_lod].index_count;
+ }
+ return current_lod + 1;
+ }
+ }
+
+ _FORCE_INLINE_ RID mesh_surface_get_index_array(void *p_surface, uint32_t p_lod) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ if (p_lod == 0) {
+ return s->index_array;
+ } else {
+ return s->lods[p_lod - 1].index_array;
+ }
+ }
+
+ _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ s->version_lock.lock();
+
+ //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
+
+ for (uint32_t i = 0; i < s->version_count; i++) {
+ if (s->versions[i].input_mask != p_input_mask) {
+ continue;
+ }
+ //we have this version, hooray
+ r_vertex_format = s->versions[i].vertex_format;
+ r_vertex_array_rd = s->versions[i].vertex_array;
+ s->version_lock.unlock();
+ return;
+ }
+
+ uint32_t version = s->version_count;
+ s->version_count++;
+ s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count);
+
+ _mesh_surface_generate_version_for_input_mask(s->versions[version], s, p_input_mask);
+
+ r_vertex_format = s->versions[version].vertex_format;
+ r_vertex_array_rd = s->versions[version].vertex_array;
+
+ s->version_lock.unlock();
+ }
+
+ _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ ERR_FAIL_COND(!mi);
+ Mesh *mesh = mi->mesh;
+ ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count);
+
+ MeshInstance::Surface *mis = &mi->surfaces[p_surface_index];
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ s->version_lock.lock();
+
+ //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way
+
+ for (uint32_t i = 0; i < mis->version_count; i++) {
+ if (mis->versions[i].input_mask != p_input_mask) {
+ continue;
+ }
+ //we have this version, hooray
+ r_vertex_format = mis->versions[i].vertex_format;
+ r_vertex_array_rd = mis->versions[i].vertex_array;
+ s->version_lock.unlock();
+ return;
+ }
+
+ uint32_t version = mis->version_count;
+ mis->version_count++;
+ mis->versions = (Mesh::Surface::Version *)memrealloc(mis->versions, sizeof(Mesh::Surface::Version) * mis->version_count);
+
+ _mesh_surface_generate_version_for_input_mask(mis->versions[version], s, p_input_mask, mis);
+
+ r_vertex_format = mis->versions[version].vertex_format;
+ r_vertex_array_rd = mis->versions[version].vertex_array;
+
+ s->version_lock.unlock();
+ }
+
+ _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) {
+ ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID());
+ return mesh_default_rd_buffers[p_buffer];
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->render_pass != p_render_pass) {
+ (*r_index)++;
+ s->render_pass = p_render_pass;
+ s->render_index = *r_index;
+ }
+
+ return s->render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->multimesh_render_pass != p_render_pass) {
+ (*r_index)++;
+ s->multimesh_render_pass = p_render_pass;
+ s->multimesh_render_index = *r_index;
+ }
+
+ return s->multimesh_render_index;
+ }
+
+ _FORCE_INLINE_ uint32_t mesh_surface_get_particles_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ Mesh::Surface *s = mesh->surfaces[p_surface_index];
+
+ if (s->particles_render_pass != p_render_pass) {
+ (*r_index)++;
+ s->particles_render_pass = p_render_pass;
+ s->particles_render_index = *r_index;
+ }
+
+ return s->particles_render_index;
+ }
+
+ /* MESH INSTANCE API */
+
+ MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
+ bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
+
+ virtual RID mesh_instance_create(RID p_base) override;
+ virtual void mesh_instance_free(RID p_rid) override;
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
+ virtual void update_mesh_instances() override;
+
+ /* MULTIMESH API */
+
+ MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
+ bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
+
+ virtual RID multimesh_allocate() override;
+ virtual void multimesh_initialize(RID p_multimesh) override;
+ virtual void multimesh_free(RID p_rid) override;
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
+ virtual int multimesh_get_instance_count(RID p_multimesh) const override;
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const override;
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
+
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override;
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const override;
+
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
+
+ void _update_dirty_multimeshes();
+
+ _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->xform_format;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_colors;
+ }
+
+ _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ return multimesh->uses_custom_data;
+ }
+
+ _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (multimesh->visible_instances >= 0) {
+ return multimesh->visible_instances;
+ }
+ return multimesh->instances;
+ }
+
+ _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (!multimesh->uniform_set_3d.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(multimesh->buffer);
+ uniforms.push_back(u);
+ multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return multimesh->uniform_set_3d;
+ }
+
+ _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ if (!multimesh->uniform_set_2d.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(multimesh->buffer);
+ uniforms.push_back(u);
+ multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return multimesh->uniform_set_2d;
+ }
+
+ /* SKELETON API */
+
+ Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
+ bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
+
+ virtual RID skeleton_allocate() override;
+ virtual void skeleton_initialize(RID p_skeleton) override;
+ virtual void skeleton_free(RID p_rid) override;
+
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) override;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) override;
+ void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform3D &p_world_transform);
+ virtual int skeleton_get_bone_count(RID p_skeleton) const override;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) override;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const override;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
+
+ virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override;
+
+ void _update_dirty_skeletons();
+
+ _FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) {
+ return skeleton_owner.get_or_null(p_skeleton) != nullptr;
+ }
+
+ _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {
+ Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_COND_V(!skeleton, RID());
+ ERR_FAIL_COND_V(skeleton->size == 0, RID());
+ if (skeleton->use_2d) {
+ return RID();
+ }
+ if (!skeleton->uniform_set_3d.is_valid()) {
+ Vector<RD::Uniform> uniforms;
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(skeleton->buffer);
+ uniforms.push_back(u);
+ skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return skeleton->uniform_set_3d;
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !MESH_STORAGE_RD_H
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index d70e4ffa0c..1304c811f7 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -464,10 +464,10 @@ void RendererSceneCull::instance_initialize(RID p_rid) {
}
void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
- bool needs_instance = RSG::storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid());
+ bool needs_instance = RSG::mesh_storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid());
if (needs_instance != p_instance->mesh_instance.is_valid()) {
if (needs_instance) {
- p_instance->mesh_instance = RSG::storage->mesh_instance_create(p_instance->base);
+ p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base);
} else {
RSG::storage->free(p_instance->mesh_instance);
@@ -488,7 +488,7 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
}
if (p_instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);
+ RSG::mesh_storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);
}
}
@@ -890,7 +890,7 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
+ RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
}
}
@@ -900,7 +900,7 @@ void RendererSceneCull::instance_set_surface_override_material(RID p_instance, i
if (instance->base_type == RS::INSTANCE_MESH) {
//may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case
- instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base)));
+ instance->materials.resize(MAX(p_surface + 1, RSG::mesh_storage->mesh_get_surface_count(instance->base)));
}
ERR_FAIL_INDEX(p_surface, instance->materials.size());
@@ -997,7 +997,7 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
if (p_skeleton.is_valid()) {
//update the dependency now, so if cleared, we remove it
- RSG::storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);
+ RSG::mesh_storage->skeleton_update_dependency(p_skeleton, &instance->dependency_tracker);
}
_instance_queue_update(instance, true, true);
@@ -1847,7 +1847,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
} else {
- new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
+ new_aabb = RSG::mesh_storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
}
} break;
@@ -1856,7 +1856,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
} else {
- new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base);
+ new_aabb = RSG::mesh_storage->multimesh_get_aabb(p_instance->base);
}
} break;
@@ -2271,14 +2271,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
shadow_data.light = light->instance;
@@ -2348,14 +2348,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
animated_material_found = true;
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
shadow_data.light = light->instance;
@@ -2412,13 +2412,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
shadow_data.instances.push_back(static_cast<InstanceGeometryData *>(instance->base_data)->geometry_instance);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
shadow_data.light = light->instance;
@@ -3037,9 +3037,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
if (scene_cull_result.mesh_instances.size()) {
for (uint64_t i = 0; i < scene_cull_result.mesh_instances.size(); i++) {
- RSG::storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
+ RSG::mesh_storage->mesh_instance_check_for_update(scene_cull_result.mesh_instances[i]);
}
- RSG::storage->update_mesh_instances();
+ RSG::mesh_storage->update_mesh_instances();
}
}
@@ -3677,7 +3677,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (p_instance->base_type == RS::INSTANCE_MESH) {
//remove materials no longer used and un-own them
- int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base);
+ int new_mat_count = RSG::mesh_storage->mesh_get_surface_count(p_instance->base);
p_instance->materials.resize(new_mat_count);
_instance_update_mesh_instance(p_instance);
@@ -3717,7 +3717,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
bool cast_shadows = false;
for (int i = 0; i < p_instance->materials.size(); i++) {
- RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i);
+ RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::mesh_storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
@@ -3742,13 +3742,13 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
} else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) {
- RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base);
+ RID mesh = RSG::mesh_storage->multimesh_get_mesh(p_instance->base);
if (mesh.is_valid()) {
bool cast_shadows = false;
- int sc = RSG::storage->mesh_get_surface_count(mesh);
+ int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);
for (int i = 0; i < sc; i++) {
- RID mat = RSG::storage->mesh_surface_get_material(mesh, i);
+ RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, i);
if (!mat.is_valid()) {
cast_shadows = true;
@@ -3784,9 +3784,9 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
continue;
}
- int sc = RSG::storage->mesh_get_surface_count(mesh);
+ int sc = RSG::mesh_storage->mesh_get_surface_count(mesh);
for (int j = 0; j < sc; j++) {
- RID mat = RSG::storage->mesh_surface_get_material(mesh, j);
+ RID mat = RSG::mesh_storage->mesh_surface_get_material(mesh, j);
if (!mat.is_valid()) {
cast_shadows = true;
@@ -3851,7 +3851,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->skeleton.is_valid()) {
- RSG::storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
+ RSG::mesh_storage->skeleton_update_dependency(p_instance->skeleton, &p_instance->dependency_tracker);
}
p_instance->dependency_tracker.update_end();
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index 2112118673..5f71250ced 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -47,7 +47,7 @@
class RendererSceneCull : public RendererScene {
public:
- RendererSceneRender *scene_render;
+ RendererSceneRender *scene_render = nullptr;
enum {
SDFGI_MAX_CASCADES = 8,
@@ -115,7 +115,7 @@ public:
/* VISIBILITY NOTIFIER API */
- RendererSceneOcclusionCull *dummy_occlusion_culling;
+ RendererSceneOcclusionCull *dummy_occlusion_culling = nullptr;
/* SCENARIO API */
@@ -273,7 +273,7 @@ public:
union {
uint64_t instance_data_rid;
RendererSceneRender::GeometryInstance *instance_geometry;
- InstanceVisibilityNotifierData *visibility_notifier;
+ InstanceVisibilityNotifierData *visibility_notifier = nullptr;
};
Instance *instance = nullptr;
int32_t parent_array_index = -1;
@@ -365,8 +365,8 @@ public:
/* INSTANCING API */
struct InstancePair {
- Instance *a;
- Instance *b;
+ Instance *a = nullptr;
+ Instance *b = nullptr;
SelfList<InstancePair> list_a;
SelfList<InstancePair> list_b;
InstancePair() :
@@ -409,7 +409,7 @@ public:
bool dynamic_gi : 2; //same above for dynamic objects
bool redraw_if_visible : 4;
- Instance *lightmap;
+ Instance *lightmap = nullptr;
Rect2 lightmap_uv_scale;
int lightmap_slice_index;
uint32_t lightmap_cull_index;
@@ -455,7 +455,7 @@ public:
SelfList<Instance> update_item;
- AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
+ AABB *custom_aabb = nullptr; // <Zylann> would using aabb directly with a bool be better?
float extra_margin;
ObjectID object_id;
@@ -465,7 +465,7 @@ public:
uint64_t version; // changes to this, and changes to base increase version
- InstanceBaseData *base_data;
+ InstanceBaseData *base_data = nullptr;
SelfList<InstancePair>::List pairs;
uint64_t pair_check;
@@ -597,7 +597,7 @@ public:
};
struct InstanceReflectionProbeData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
Set<Instance *> geometries;
@@ -613,7 +613,7 @@ public:
};
struct InstanceDecalData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
RID instance;
Set<Instance *> geometries;
@@ -656,7 +656,7 @@ public:
Set<Instance *> geometries;
- Instance *baked_light;
+ Instance *baked_light = nullptr;
RS::LightBakeMode bake_mode;
uint32_t max_sdfgi_cascade = 2;
@@ -671,7 +671,7 @@ public:
};
struct InstanceVoxelGIData : public InstanceBaseData {
- Instance *owner;
+ Instance *owner = nullptr;
Set<Instance *> geometries;
Set<Instance *> dynamic_geometries;
@@ -1023,7 +1023,7 @@ public:
struct VisibilityCullData {
uint64_t viewport_mask;
- Scenario *scenario;
+ Scenario *scenario = nullptr;
Vector3 camera_position;
uint32_t cull_offset;
uint32_t cull_count;
@@ -1035,12 +1035,12 @@ public:
_FORCE_INLINE_ int _visibility_range_check(InstanceVisibilityData &r_vis_data, const Vector3 &p_camera_pos, uint64_t p_viewport_mask);
struct CullData {
- Cull *cull;
- Scenario *scenario;
+ Cull *cull = nullptr;
+ Scenario *scenario = nullptr;
RID shadow_atlas;
Transform3D cam_transform;
uint32_t visible_layers;
- Instance *render_reflection_probe;
+ Instance *render_reflection_probe = nullptr;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
const CameraMatrix *camera_matrix;
uint64_t visibility_viewport_mask;
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 5f9c4bb816..0b8734e68c 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -223,7 +223,7 @@ public:
struct RenderSDFGIUpdateData {
bool update_static = false;
uint32_t static_cascade_count;
- uint32_t *static_cascade_indices;
+ uint32_t *static_cascade_indices = nullptr;
PagedArray<RID> *static_positional_lights;
const Vector<RID> *directional_lights;
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index b9cd1f55ba..7bbd414465 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -119,94 +119,6 @@ public:
Set<Dependency *> dependencies;
};
- /* MESH API */
-
- virtual RID mesh_allocate() = 0;
- virtual void mesh_initialize(RID p_rid) = 0;
-
- virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0;
-
- /// Returns stride
- virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0;
-
- virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
-
- virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0;
- virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
-
- virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
- virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
- virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
-
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
- virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
-
- virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0;
-
- virtual int mesh_get_surface_count(RID p_mesh) const = 0;
-
- virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
-
- virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0;
-
- virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0;
-
- virtual void mesh_clear(RID p_mesh) = 0;
-
- virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0;
-
- /* MESH INSTANCE */
-
- virtual RID mesh_instance_create(RID p_base) = 0;
- virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0;
- virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0;
- virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0;
- virtual void update_mesh_instances() = 0;
-
- /* MULTIMESH API */
-
- virtual RID multimesh_allocate() = 0;
- virtual void multimesh_initialize(RID p_rid) = 0;
-
- virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
-
- virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
-
- virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
- virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0;
- virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
- virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
- virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
-
- virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
-
- virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
- virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
- virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
- virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
-
- virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0;
- virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0;
-
- virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
- virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
-
- virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
-
- /* SKELETON API */
-
- virtual RID skeleton_allocate() = 0;
- virtual void skeleton_initialize(RID p_rid) = 0;
-
- virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
- virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
- virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0;
- virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
- virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
- virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
- virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
-
/* Light API */
virtual RID directional_light_allocate() = 0;
@@ -282,7 +194,6 @@ public:
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
- virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
/* VOXEL GI API */
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 2245d9a216..b6e44e8436 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -129,7 +129,7 @@ public:
};
struct CanvasData {
- CanvasBase *canvas;
+ CanvasBase *canvas = nullptr;
Transform2D transform;
int layer;
int sublayer;
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index ecbb11efca..1902b5f74a 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -528,6 +528,7 @@ public:
/*********************/
struct AttachmentFormat {
+ enum { UNUSED_ATTACHMENT = 0xFFFFFFFF };
DataFormat format;
TextureSamples samples;
uint32_t usage_flags;
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 3969682e15..2dab7cb84c 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -401,6 +401,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage();
RSG::decal_atlas_storage = RSG::rasterizer->get_decal_atlas_storage();
RSG::material_storage = RSG::rasterizer->get_material_storage();
+ RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
RSG::texture_storage = RSG::rasterizer->get_texture_storage();
RSG::storage = RSG::rasterizer->get_storage();
RSG::canvas_render = RSG::rasterizer->get_canvas();
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 52e0c2c0ac..cc1edc728a 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -252,11 +252,11 @@ public:
#undef ServerName
#undef server_name
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererMeshStorage
+#define server_name RSG::mesh_storage
virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces, int p_blend_shape_count = 0) override {
- RID mesh = RSG::storage->mesh_allocate();
+ RID mesh = RSG::mesh_storage->mesh_allocate();
// TODO once we have RSG::mesh_storage, add can_create_resources_async and call here instead of texture_storage!!
@@ -264,16 +264,16 @@ public:
if (Thread::get_caller_id() == server_thread) {
command_queue.flush_if_pending();
}
- RSG::storage->mesh_initialize(mesh);
- RSG::storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
+ RSG::mesh_storage->mesh_initialize(mesh);
+ RSG::mesh_storage->mesh_set_blend_shape_count(mesh, p_blend_shape_count);
for (int i = 0; i < p_surfaces.size(); i++) {
- RSG::storage->mesh_add_surface(mesh, p_surfaces[i]);
+ RSG::mesh_storage->mesh_add_surface(mesh, p_surfaces[i]);
}
} else {
- command_queue.push(RSG::storage, &RendererStorage::mesh_initialize, mesh);
- command_queue.push(RSG::storage, &RendererStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_initialize, mesh);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_set_blend_shape_count, mesh, p_blend_shape_count);
for (int i = 0; i < p_surfaces.size(); i++) {
- command_queue.push(RSG::storage, &RendererStorage::mesh_add_surface, mesh, p_surfaces[i]);
+ command_queue.push(RSG::mesh_storage, &RendererMeshStorage::mesh_add_surface, mesh, p_surfaces[i]);
}
}
@@ -348,6 +348,11 @@ public:
FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
/* Light API */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
FUNCRIDSPLIT(directional_light)
FUNCRIDSPLIT(omni_light)
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index 6a2ba5ee6b..2be87c27b1 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -35,6 +35,7 @@ bool RenderingServerGlobals::threaded = false;
RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr;
RendererDecalAtlasStorage *RenderingServerGlobals::decal_atlas_storage = nullptr;
RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;
+RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr;
RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
RendererStorage *RenderingServerGlobals::storage = nullptr;
RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index 2f9eddff09..40fd638425 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -37,6 +37,7 @@
#include "servers/rendering/storage/canvas_texture_storage.h"
#include "servers/rendering/storage/decal_atlas_storage.h"
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/texture_storage.h"
class RendererCanvasCull;
@@ -49,6 +50,7 @@ public:
static RendererCanvasTextureStorage *canvas_texture_storage;
static RendererMaterialStorage *material_storage;
+ static RendererMeshStorage *mesh_storage;
static RendererTextureStorage *texture_storage;
static RendererDecalAtlasStorage *decal_atlas_storage;
static RendererStorage *storage;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index a6f3a48398..fa3e09f746 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -5134,9 +5134,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
@@ -5287,9 +5291,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!expr->is_indexed() && expr->get_array_size() > 0) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
@@ -5587,9 +5595,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
mn->assign_expression = assign_expression;
} else if (tk.type == TK_PERIOD) {
completion_class = TAG_ARRAY;
- p_block->block_tag = SubClassTag::TAG_ARRAY;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_ARRAY;
+ }
Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
- p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ if (p_block != nullptr) {
+ p_block->block_tag = SubClassTag::TAG_GLOBAL;
+ }
if (!call_expression) {
return nullptr;
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index e5ac14a7db..25ec8760af 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -386,7 +386,7 @@ public:
return node;
}
- Node *nodes;
+ Node *nodes = nullptr;
struct OperatorNode : public Node {
DataType return_cache = TYPE_VOID;
@@ -615,20 +615,20 @@ public:
DataType type;
StringName type_str;
DataPrecision precision;
- ConstantNode *initializer;
+ ConstantNode *initializer = nullptr;
int array_size;
};
struct Function {
StringName name;
- FunctionNode *function;
+ FunctionNode *function = nullptr;
Set<StringName> uses_function;
bool callable;
};
struct Struct {
StringName name;
- StructNode *shader_struct;
+ StructNode *shader_struct = nullptr;
};
struct Varying {
@@ -715,7 +715,7 @@ public:
bool is_op;
union {
Operator op;
- Node *node;
+ Node *node = nullptr;
};
};
@@ -973,7 +973,7 @@ private:
Token _make_token(TokenType p_type, const StringName &p_text = StringName());
Token _get_token();
- ShaderNode *shader;
+ ShaderNode *shader = nullptr;
enum IdentifierType {
IDENTIFIER_FUNCTION,
@@ -1021,7 +1021,7 @@ private:
CompletionType completion_type;
int completion_line;
- BlockNode *completion_block;
+ BlockNode *completion_block = nullptr;
DataType completion_base;
bool completion_base_array;
SubClassTag completion_class;
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
new file mode 100644
index 0000000000..1dac51319c
--- /dev/null
+++ b/servers/rendering/storage/mesh_storage.h
@@ -0,0 +1,136 @@
+/*************************************************************************/
+/* mesh_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef MESH_STORAGE_H
+#define MESH_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererMeshStorage {
+public:
+ virtual ~RendererMeshStorage() {}
+
+ /* MESH API */
+
+ virtual RID mesh_allocate() = 0;
+ virtual void mesh_initialize(RID p_rid) = 0;
+ virtual void mesh_free(RID p_rid) = 0;
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) = 0;
+
+ /// Returns stride
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0;
+
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0;
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0;
+ virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0;
+
+ virtual void mesh_surface_update_vertex_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_attribute_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+ virtual void mesh_surface_update_skin_region(RID p_mesh, int p_surface, int p_offset, const Vector<uint8_t> &p_data) = 0;
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0;
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0;
+
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0;
+
+ virtual int mesh_get_surface_count(RID p_mesh) const = 0;
+
+ virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0;
+ virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0;
+
+ virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0;
+
+ virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) = 0;
+
+ virtual void mesh_clear(RID p_mesh) = 0;
+
+ virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) = 0;
+
+ /* MESH INSTANCE */
+
+ virtual RID mesh_instance_create(RID p_base) = 0;
+ virtual void mesh_instance_free(RID p_rid) = 0;
+ virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0;
+ virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0;
+ virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0;
+ virtual void update_mesh_instances() = 0;
+
+ /* MULTIMESH API */
+
+ virtual RID multimesh_allocate() = 0;
+ virtual void multimesh_initialize(RID p_rid) = 0;
+ virtual void multimesh_free(RID p_rid) = 0;
+
+ virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0;
+
+ virtual int multimesh_get_instance_count(RID p_multimesh) const = 0;
+
+ virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0;
+ virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) = 0;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0;
+ virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0;
+ virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0;
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const = 0;
+
+ virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0;
+ virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0;
+ virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0;
+
+ virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) = 0;
+ virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const = 0;
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0;
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0;
+
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0;
+
+ /* SKELETON API */
+
+ virtual RID skeleton_allocate() = 0;
+ virtual void skeleton_initialize(RID p_rid) = 0;
+ virtual void skeleton_free(RID p_rid) = 0;
+
+ virtual void skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0;
+ virtual int skeleton_get_bone_count(RID p_skeleton) const = 0;
+ virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform3D &p_transform) = 0;
+ virtual Transform3D skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
+ virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
+
+ virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) = 0;
+};
+
+#endif // !MESH_STORAGE_H
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index ec31885cae..2f32e81f06 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -758,7 +758,7 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, in
int word_start = range.x;
- int l_size = shaped_text_get_glyph_count(p_shaped);
+ const int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
diff --git a/tests/core/math/test_geometry_3d.h b/tests/core/math/test_geometry_3d.h
index 1b8d2eee34..99a4ef2d46 100644
--- a/tests/core/math/test_geometry_3d.h
+++ b/tests/core/math/test_geometry_3d.h
@@ -288,7 +288,7 @@ TEST_CASE("[Geometry3D] Is Point in Projected Triangle") {
TEST_CASE("[Geometry3D] Does Ray Intersect Triangle") {
struct Case {
Vector3 from, direction, v_1, v_2, v_3;
- Vector3 *result;
+ Vector3 *result = nullptr;
bool want;
Case(){};
Case(Vector3 p_from, Vector3 p_direction, Vector3 p_v_1, Vector3 p_v_2, Vector3 p_v_3, bool p_want) :
@@ -390,7 +390,7 @@ TEST_CASE("[Geometry3D] Triangle and Box Overlap") {
struct Case {
Vector3 box_centre;
Vector3 box_half_size;
- Vector3 *tri_verts;
+ Vector3 *tri_verts = nullptr;
bool want;
Case(){};
Case(Vector3 p_centre, Vector3 p_half_size, Vector3 *p_verts, bool p_want) :
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 02d73fbe18..41cd0230cc 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -7,9 +7,9 @@ readability.
## amd-fsr
-Upstream: https://github.com/GPUOpen-Effects/FidelityFX-FSR
-Version: 1.0.2 (a21ffb8f6c13233ba336352bdff293894c706575, 2021)
-License: MIT
+- Upstream: https://github.com/GPUOpen-Effects/FidelityFX-FSR
+- Version: 1.0.2 (a21ffb8f6c13233ba336352bdff293894c706575, 2021)
+- License: MIT
Files extracted from upstream source: