summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format22
-rw-r--r--.github/workflows/linux_builds.yml8
-rw-r--r--core/config/project_settings.cpp56
-rw-r--r--core/core_bind.cpp140
-rw-r--r--core/core_bind.h6
-rw-r--r--core/extension/extension_api_dump.cpp3
-rw-r--r--core/extension/gdnative_interface.cpp8
-rw-r--r--core/extension/gdnative_interface.h1
-rw-r--r--core/extension/native_extension_manager.cpp4
-rw-r--r--core/input/input.cpp2
-rw-r--r--core/io/config_file.cpp45
-rw-r--r--core/io/config_file.h4
-rw-r--r--core/io/dir_access.cpp88
-rw-r--r--core/io/dir_access.h41
-rw-r--r--core/io/file_access.cpp58
-rw-r--r--core/io/file_access.h37
-rw-r--r--core/io/file_access_compressed.cpp58
-rw-r--r--core/io/file_access_compressed.h7
-rw-r--r--core/io/file_access_encrypted.cpp42
-rw-r--r--core/io/file_access_encrypted.h10
-rw-r--r--core/io/file_access_memory.cpp6
-rw-r--r--core/io/file_access_memory.h3
-rw-r--r--core/io/file_access_network.cpp9
-rw-r--r--core/io/file_access_network.h2
-rw-r--r--core/io/file_access_pack.cpp85
-rw-r--r--core/io/file_access_pack.h29
-rw-r--r--core/io/file_access_zip.cpp52
-rw-r--r--core/io/file_access_zip.h5
-rw-r--r--core/io/image.cpp119
-rw-r--r--core/io/image.h2
-rw-r--r--core/io/image_loader.cpp27
-rw-r--r--core/io/image_loader.h4
-rw-r--r--core/io/logger.cpp28
-rw-r--r--core/io/logger.h5
-rw-r--r--core/io/pck_packer.cpp56
-rw-r--r--core/io/pck_packer.h3
-rw-r--r--core/io/resource.cpp12
-rw-r--r--core/io/resource_format_binary.cpp221
-rw-r--r--core/io/resource_format_binary.h16
-rw-r--r--core/io/resource_importer.cpp15
-rw-r--r--core/io/resource_loader.cpp9
-rw-r--r--core/io/resource_uid.cpp20
-rw-r--r--core/io/translation_loader_po.cpp67
-rw-r--r--core/io/translation_loader_po.h2
-rw-r--r--core/io/xml_parser.cpp4
-rw-r--r--core/io/zip_io.cpp50
-rw-r--r--core/io/zip_io.h10
-rw-r--r--core/math/color.h4
-rw-r--r--core/math/triangle_mesh.cpp20
-rw-r--r--core/object/object.cpp13
-rw-r--r--core/object/object.h1
-rw-r--r--core/os/os.cpp33
-rw-r--r--core/os/time.cpp121
-rw-r--r--core/string/print_string.h10
-rw-r--r--core/string/translation_po.cpp3
-rw-r--r--core/templates/cowdata.h25
-rw-r--r--core/templates/safe_list.h30
-rw-r--r--core/variant/variant.h1
-rw-r--r--core/variant/variant_call.cpp4
-rw-r--r--core/variant/variant_parser.h2
-rw-r--r--core/variant/variant_setget.cpp104
-rw-r--r--doc/classes/@GlobalScope.xml4
-rw-r--r--doc/classes/AnimationLibrary.xml70
-rw-r--r--doc/classes/AnimationPlayer.xml34
-rw-r--r--doc/classes/Camera3D.xml2
-rw-r--r--doc/classes/CanvasItem.xml10
-rw-r--r--doc/classes/CharacterBody2D.xml2
-rw-r--r--doc/classes/CharacterBody3D.xml2
-rw-r--r--doc/classes/CheckBox.xml10
-rw-r--r--doc/classes/CollisionObject2D.xml1
-rw-r--r--doc/classes/Color.xml26
-rw-r--r--doc/classes/EditorInspector.xml10
-rw-r--r--doc/classes/EditorSceneFormatImporter.xml14
-rw-r--r--doc/classes/EditorScenePostImportPlugin.xml6
-rw-r--r--doc/classes/Image.xml8
-rw-r--r--doc/classes/NavigationServer2D.xml6
-rw-r--r--doc/classes/NavigationServer3D.xml6
-rw-r--r--doc/classes/OptionButton.xml20
-rw-r--r--doc/classes/PopupMenu.xml14
-rw-r--r--doc/classes/RenderingServer.xml5
-rw-r--r--doc/classes/RichTextLabel.xml26
-rw-r--r--doc/classes/Signal.xml2
-rw-r--r--doc/classes/TextServer.xml4
-rw-r--r--doc/classes/Time.xml3
-rw-r--r--doc/classes/Tree.xml3
-rw-r--r--doc/classes/Viewport.xml4
-rw-r--r--doc/classes/Window.xml9
-rwxr-xr-xdoc/tools/make_rst.py78
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp50
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.h5
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp84
-rw-r--r--drivers/gles3/rasterizer_gles3.h41
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp1298
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h252
-rw-r--r--drivers/gles3/shader_gles3.cpp14
-rw-r--r--drivers/gles3/storage/canvas_texture_storage.cpp96
-rw-r--r--drivers/gles3/storage/config.cpp11
-rw-r--r--drivers/gles3/storage/config.h1
-rw-r--r--drivers/gles3/storage/decal_atlas_storage.cpp75
-rw-r--r--drivers/gles3/storage/decal_atlas_storage.h67
-rw-r--r--drivers/gles3/storage/light_storage.cpp316
-rw-r--r--drivers/gles3/storage/light_storage.h154
-rw-r--r--drivers/gles3/storage/particles_storage.cpp254
-rw-r--r--drivers/gles3/storage/particles_storage.h140
-rw-r--r--drivers/gles3/storage/render_target_storage.h132
-rw-r--r--drivers/gles3/storage/texture_storage.cpp932
-rw-r--r--drivers/gles3/storage/texture_storage.h228
-rw-r--r--drivers/png/image_loader_png.cpp4
-rw-r--r--drivers/png/image_loader_png.h2
-rw-r--r--drivers/png/resource_saver_png.cpp6
-rw-r--r--drivers/unix/dir_access_unix.cpp4
-rw-r--r--drivers/unix/dir_access_unix.h4
-rw-r--r--drivers/unix/file_access_unix.cpp11
-rw-r--r--drivers/unix/file_access_unix.h4
-rw-r--r--drivers/vulkan/rendering_device_vulkan.cpp3
-rw-r--r--drivers/windows/dir_access_windows.cpp2
-rw-r--r--drivers/windows/dir_access_windows.h2
-rw-r--r--drivers/windows/file_access_windows.cpp9
-rw-r--r--drivers/windows/file_access_windows.h3
-rw-r--r--editor/action_map_editor.cpp115
-rw-r--r--editor/action_map_editor.h11
-rw-r--r--editor/animation_track_editor.cpp82
-rw-r--r--editor/animation_track_editor.h2
-rw-r--r--editor/create_dialog.cpp61
-rw-r--r--editor/debugger/script_editor_debugger.cpp4
-rw-r--r--editor/dependency_editor.cpp2
-rw-r--r--editor/doc_tools.cpp14
-rw-r--r--editor/editor_asset_installer.cpp13
-rw-r--r--editor/editor_dir_dialog.cpp4
-rw-r--r--editor/editor_export.cpp62
-rw-r--r--editor/editor_export.h4
-rw-r--r--editor/editor_feature_profile.cpp13
-rw-r--r--editor/editor_file_dialog.cpp2
-rw-r--r--editor/editor_file_dialog.h2
-rw-r--r--editor/editor_file_system.cpp431
-rw-r--r--editor/editor_file_system.h4
-rw-r--r--editor/editor_folding.cpp2
-rw-r--r--editor/editor_fonts.cpp2
-rw-r--r--editor/editor_inspector.cpp2
-rw-r--r--editor/editor_log.cpp2
-rw-r--r--editor/editor_node.cpp23
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_paths.cpp11
-rw-r--r--editor/editor_plugin.cpp8
-rw-r--r--editor/editor_plugin_settings.cpp2
-rw-r--r--editor/editor_resource_preview.cpp30
-rw-r--r--editor/editor_settings.cpp34
-rw-r--r--editor/editor_themes.cpp4
-rw-r--r--editor/editor_translation.cpp6
-rw-r--r--editor/editor_vcs_interface.cpp8
-rw-r--r--editor/export_template_manager.cpp54
-rw-r--r--editor/fileserver/editor_file_server.cpp6
-rw-r--r--editor/fileserver/editor_file_server.h2
-rw-r--r--editor/filesystem_dock.cpp52
-rw-r--r--editor/find_in_files.cpp18
-rw-r--r--editor/icons/AnimationLibrary.svg1
-rw-r--r--editor/icons/ArrayOccluder3D.svg1
-rw-r--r--editor/icons/BoxOccluder3D.svg1
-rw-r--r--editor/icons/GuiVsplitBg.svg1
-rw-r--r--editor/icons/Occluder3D.svg2
-rw-r--r--editor/icons/PolygonOccluder3D.svg1
-rw-r--r--editor/icons/QuadOccluder3D.svg1
-rw-r--r--editor/icons/SphereOccluder3D.svg1
-rw-r--r--editor/import/editor_import_collada.cpp30
-rw-r--r--editor/import/editor_import_collada.h1
-rw-r--r--editor/import/resource_importer_csv_translation.cpp5
-rw-r--r--editor/import/resource_importer_image.cpp11
-rw-r--r--editor/import/resource_importer_layered_texture.cpp4
-rw-r--r--editor/import/resource_importer_obj.cpp12
-rw-r--r--editor/import/resource_importer_obj.h1
-rw-r--r--editor/import/resource_importer_scene.cpp144
-rw-r--r--editor/import/resource_importer_scene.h39
-rw-r--r--editor/import/resource_importer_shader_file.cpp4
-rw-r--r--editor/import/resource_importer_texture.cpp8
-rw-r--r--editor/import/resource_importer_texture.h2
-rw-r--r--editor/import/resource_importer_wav.cpp19
-rw-r--r--editor/import/scene_import_settings.cpp128
-rw-r--r--editor/import/scene_import_settings.h7
-rw-r--r--editor/plugin_config_dialog.cpp6
-rw-r--r--editor/plugins/animation_library_editor.cpp689
-rw-r--r--editor/plugins/animation_library_editor.h (renamed from drivers/gles3/storage/canvas_texture_storage.h)140
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp453
-rw-r--r--editor/plugins/animation_player_editor_plugin.h22
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp25
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/input_event_editor_plugin.cpp38
-rw-r--r--editor/plugins/input_event_editor_plugin.h6
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/ot_features_plugin.cpp6
-rw-r--r--editor/plugins/script_editor_plugin.cpp27
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp267
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.h21
-rw-r--r--editor/plugins/texture_editor_plugin.cpp2
-rw-r--r--editor/pot_generator.cpp6
-rw-r--r--editor/pot_generator.h2
-rw-r--r--editor/project_manager.cpp40
-rw-r--r--editor/project_manager.h4
-rw-r--r--editor/scene_tree_dock.cpp7
-rw-r--r--editor/script_create_dialog.cpp14
-rw-r--r--editor/shader_create_dialog.cpp6
-rw-r--r--main/main.cpp14
-rw-r--r--modules/bmp/image_loader_bmp.cpp13
-rw-r--r--modules/bmp/image_loader_bmp.h3
-rw-r--r--modules/dds/texture_loader_dds.cpp6
-rw-r--r--modules/gdscript/gdscript.cpp31
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp2
-rw-r--r--modules/gdscript/gdscript_cache.cpp3
-rw-r--r--modules/gdscript/gdscript_compiler.cpp4
-rw-r--r--modules/gdscript/gdscript_disassembler.cpp2
-rw-r--r--modules/gdscript/gdscript_editor.cpp27
-rw-r--r--modules/gdscript/gdscript_function.h2
-rw-r--r--modules/gdscript/gdscript_vm.cpp4
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp2
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp4
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.h3
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp2
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp9
-rw-r--r--modules/gdscript/tests/test_gdscript.cpp4
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.cpp19
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.h4
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.cpp18
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.h4
-rw-r--r--modules/gltf/editor/editor_scene_importer_gltf.cpp5
-rw-r--r--modules/gltf/editor/editor_scene_importer_gltf.h2
-rw-r--r--modules/gltf/gltf_document.cpp70
-rw-r--r--modules/gltf/gltf_document.h4
-rw-r--r--modules/gltf/register_types.cpp8
-rw-r--r--modules/hdr/image_loader_hdr.cpp4
-rw-r--r--modules/hdr/image_loader_hdr.h2
-rw-r--r--modules/jpg/image_loader_jpegd.cpp4
-rw-r--r--modules/jpg/image_loader_jpegd.h2
-rw-r--r--modules/mbedtls/crypto_mbedtls.cpp22
-rw-r--r--modules/minimp3/resource_importer_mp3.cpp7
-rw-r--r--modules/mono/class_db_api_json.cpp5
-rw-r--r--modules/mono/csharp_script.cpp18
-rw-r--r--modules/mono/editor/bindings_generator.cpp18
-rw-r--r--modules/mono/editor/code_completion.cpp2
-rw-r--r--modules/mono/godotsharp_dirs.cpp2
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp28
-rw-r--r--modules/mono/mono_gd/gd_mono_log.h2
-rw-r--r--modules/mono/utils/string_utils.cpp4
-rw-r--r--modules/navigation/nav_map.cpp5
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp104
-rw-r--r--modules/navigation/navigation_mesh_generator.h1
-rw-r--r--modules/noise/fastnoise_lite.cpp8
-rw-r--r--modules/openxr/action_map/openxr_action_map.cpp131
-rw-r--r--modules/openxr/action_map/openxr_defs.cpp168
-rw-r--r--modules/openxr/action_map/openxr_defs.h4
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.cpp2
-rw-r--r--modules/openxr/extensions/openxr_extension_wrapper.h1
-rw-r--r--modules/openxr/extensions/openxr_vulkan_extension.cpp3
-rw-r--r--modules/openxr/openxr_api.cpp17
-rw-r--r--modules/openxr/openxr_api.h6
-rw-r--r--modules/svg/image_loader_svg.cpp2
-rw-r--r--modules/svg/image_loader_svg.h2
-rw-r--r--modules/text_server_adv/text_server_adv.cpp4
-rw-r--r--modules/tga/image_loader_tga.cpp11
-rw-r--r--modules/tga/image_loader_tga.h2
-rw-r--r--modules/theora/video_stream_theora.cpp28
-rw-r--r--modules/theora/video_stream_theora.h2
-rw-r--r--modules/tinyexr/image_loader_tinyexr.cpp8
-rw-r--r--modules/tinyexr/image_loader_tinyexr.h2
-rw-r--r--modules/tinyexr/image_saver_tinyexr.cpp4
-rw-r--r--modules/visual_script/editor/visual_script_editor.cpp2
-rw-r--r--modules/vorbis/resource_importer_ogg_vorbis.cpp7
-rw-r--r--modules/webp/image_loader_webp.cpp4
-rw-r--r--modules/webp/image_loader_webp.h2
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml7
-rw-r--r--modules/websocket/emws_server.cpp3
-rw-r--r--modules/websocket/emws_server.h1
-rw-r--r--modules/websocket/websocket_server.cpp1
-rw-r--r--modules/websocket/websocket_server.h1
-rw-r--r--modules/websocket/wsl_server.cpp11
-rw-r--r--modules/websocket/wsl_server.h4
-rw-r--r--platform/android/dir_access_jandroid.cpp8
-rw-r--r--platform/android/dir_access_jandroid.h4
-rw-r--r--platform/android/export/export_plugin.cpp37
-rw-r--r--platform/android/export/gradle_export_util.cpp18
-rw-r--r--platform/android/file_access_android.cpp8
-rw-r--r--platform/android/file_access_android.h5
-rw-r--r--platform/iphone/export/export_plugin.cpp93
-rw-r--r--platform/iphone/export/export_plugin.h6
-rw-r--r--platform/iphone/os_iphone.mm2
-rw-r--r--platform/javascript/api/javascript_tools_editor_plugin.cpp27
-rw-r--r--platform/javascript/export/export_plugin.cpp40
-rw-r--r--platform/javascript/export/export_server.h7
-rw-r--r--platform/linuxbsd/display_server_x11.cpp2
-rw-r--r--platform/linuxbsd/export/export_plugin.cpp12
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp24
-rw-r--r--platform/osx/display_server_osx.mm7
-rw-r--r--platform/osx/export/codesign.cpp67
-rw-r--r--platform/osx/export/codesign.h14
-rw-r--r--platform/osx/export/export_plugin.cpp89
-rw-r--r--platform/osx/export/export_plugin.h4
-rw-r--r--platform/osx/export/lipo.cpp31
-rw-r--r--platform/osx/export/lipo.h2
-rw-r--r--platform/osx/export/macho.cpp48
-rw-r--r--platform/osx/export/macho.h8
-rw-r--r--platform/osx/export/plist.cpp4
-rw-r--r--platform/osx/os_osx.mm2
-rw-r--r--platform/uwp/export/app_packager.cpp49
-rw-r--r--platform/uwp/export/app_packager.h4
-rw-r--r--platform/uwp/export/export_plugin.cpp5
-rw-r--r--platform/uwp/export/export_plugin.h24
-rw-r--r--platform/windows/display_server_windows.cpp7
-rw-r--r--platform/windows/export/export_plugin.cpp13
-rw-r--r--scene/3d/camera_3d.cpp4
-rw-r--r--scene/3d/lightmap_gi.cpp7
-rw-r--r--scene/3d/node_3d.cpp10
-rw-r--r--scene/animation/animation_player.cpp366
-rw-r--r--scene/animation/animation_player.h36
-rw-r--r--scene/animation/animation_tree.cpp133
-rw-r--r--scene/animation/animation_tree.h6
-rw-r--r--scene/gui/aspect_ratio_container.cpp2
-rw-r--r--scene/gui/file_dialog.cpp2
-rw-r--r--scene/gui/file_dialog.h2
-rw-r--r--scene/gui/graph_edit.cpp20
-rw-r--r--scene/gui/graph_node.cpp1
-rw-r--r--scene/gui/grid_container.cpp3
-rw-r--r--scene/gui/option_button.cpp47
-rw-r--r--scene/gui/option_button.h6
-rw-r--r--scene/gui/popup_menu.cpp46
-rw-r--r--scene/gui/popup_menu.h3
-rw-r--r--scene/gui/rich_text_label.cpp167
-rw-r--r--scene/gui/rich_text_label.h26
-rw-r--r--scene/gui/text_edit.cpp75
-rw-r--r--scene/gui/tree.cpp157
-rw-r--r--scene/gui/tree.h5
-rw-r--r--scene/main/canvas_item.cpp10
-rw-r--r--scene/main/canvas_item.h5
-rw-r--r--scene/main/http_request.cpp15
-rw-r--r--scene/main/http_request.h3
-rw-r--r--scene/main/scene_tree.cpp2
-rw-r--r--scene/main/viewport.cpp6
-rw-r--r--scene/main/window.cpp11
-rw-r--r--scene/register_scene_types.cpp2
-rw-r--r--scene/resources/animation.cpp2
-rw-r--r--scene/resources/animation_library.cpp134
-rw-r--r--scene/resources/animation_library.h (renamed from servers/rendering/storage/canvas_texture_storage.h)41
-rw-r--r--scene/resources/audio_stream_sample.cpp6
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/default_theme/default_theme.cpp8
-rw-r--r--scene/resources/default_theme/popup_menu_arrow_left.svg1
-rw-r--r--scene/resources/default_theme/popup_menu_arrow_right.svg1
-rw-r--r--scene/resources/environment.cpp6
-rw-r--r--scene/resources/font.cpp4
-rw-r--r--scene/resources/primitive_meshes.cpp16
-rw-r--r--scene/resources/primitive_meshes.h8
-rw-r--r--scene/resources/resource_format_text.cpp288
-rw-r--r--scene/resources/resource_format_text.h16
-rw-r--r--scene/resources/shader.cpp5
-rw-r--r--scene/resources/text_file.cpp5
-rw-r--r--scene/resources/texture.cpp18
-rw-r--r--scene/resources/texture.h2
-rw-r--r--servers/navigation_server_2d.cpp2
-rw-r--r--servers/navigation_server_3d.cpp2
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h12
-rw-r--r--servers/rendering/dummy/rasterizer_storage_dummy.h186
-rw-r--r--servers/rendering/dummy/storage/canvas_texture_storage.h53
-rw-r--r--servers/rendering/dummy/storage/decal_atlas_storage.h62
-rw-r--r--servers/rendering/dummy/storage/light_storage.h135
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h126
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h56
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp416
-rw-r--r--servers/rendering/renderer_canvas_cull.h2
-rw-r--r--servers/rendering/renderer_canvas_render.h3
-rw-r--r--servers/rendering/renderer_compositor.h8
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp105
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp26
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp100
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp125
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h12
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp111
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_gi_rd.h1
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp320
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp39
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp3552
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h928
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp14
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl22
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl22
-rw-r--r--servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp235
-rw-r--r--servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h90
-rw-r--r--servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp437
-rw-r--r--servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h211
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp788
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h370
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp206
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h18
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp1897
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h565
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp1338
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h338
-rw-r--r--servers/rendering/renderer_scene_cull.cpp198
-rw-r--r--servers/rendering/renderer_storage.h203
-rw-r--r--servers/rendering/renderer_viewport.cpp69
-rw-r--r--servers/rendering/rendering_server_default.cpp6
-rw-r--r--servers/rendering/rendering_server_default.h48
-rw-r--r--servers/rendering/rendering_server_globals.cpp4
-rw-r--r--servers/rendering/rendering_server_globals.h8
-rw-r--r--servers/rendering/shader_language.cpp7
-rw-r--r--servers/rendering/shader_language.h8
-rw-r--r--servers/rendering/storage/decal_atlas_storage.h60
-rw-r--r--servers/rendering/storage/light_storage.h139
-rw-r--r--servers/rendering/storage/particles_storage.h129
-rw-r--r--servers/rendering/storage/texture_storage.h62
-rw-r--r--servers/rendering_server.cpp2
-rw-r--r--servers/rendering_server.h2
-rw-r--r--servers/text_server.cpp43
-rw-r--r--servers/xr/xr_interface_extension.cpp7
-rw-r--r--tests/SCsub5
-rw-r--r--tests/core/io/test_config_file.h2
-rw-r--r--tests/core/io/test_file_access.h4
-rw-r--r--tests/core/io/test_image.h10
-rw-r--r--tests/core/io/test_pck_packer.h4
-rw-r--r--tests/core/math/test_color.h8
-rw-r--r--tests/core/math/test_math.cpp690
-rw-r--r--tests/core/math/test_math.h41
-rw-r--r--tests/core/templates/test_oa_hash_map.cpp301
-rw-r--r--tests/core/templates/test_oa_hash_map.h41
-rw-r--r--tests/scene/test_gui.cpp259
-rw-r--r--tests/scene/test_gui.h41
-rw-r--r--tests/servers/test_physics_2d.cpp374
-rw-r--r--tests/servers/test_physics_2d.h41
-rw-r--r--tests/servers/test_physics_3d.cpp410
-rw-r--r--tests/servers/test_physics_3d.h41
-rw-r--r--tests/servers/test_render.cpp232
-rw-r--r--tests/servers/test_render.h41
-rw-r--r--tests/servers/test_shader_lang.cpp364
-rw-r--r--tests/servers/test_shader_lang.h41
-rw-r--r--tests/test_main.cpp7
434 files changed, 14832 insertions, 15191 deletions
diff --git a/.clang-format b/.clang-format
index e011f060b7..f7527b8927 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,6 +1,6 @@
# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
-# chosen value in case the base style changes (last sync: Clang 13.0).
+# chosen value in case the base style changes (last sync: Clang 14.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
@@ -15,7 +15,6 @@ AlignAfterOpenBracket: DontAlign
AlignOperands: DontAlign
AlignTrailingComments: false
# AllowAllArgumentsOnNextLine: true
-# AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
# AllowShortEnumsOnASingleLine: true
# AllowShortBlocksOnASingleLine: Never
@@ -62,8 +61,8 @@ BreakConstructorInitializers: AfterColon
# BreakStringLiterals: true
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
+# QualifierAlignment: Leave
# CompactNamespaces: false
-ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
@@ -73,6 +72,9 @@ Cpp11BracedListStyle: false
# EmptyLineAfterAccessModifier: Never
# EmptyLineBeforeAccessModifier: LogicalBlock
# ExperimentalAutoDetectBinPacking: false
+# PackConstructorInitializers: BinPack
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+# AllowAllConstructorInitializersOnNextLine: true
# FixNamespaceComments: true
# ForEachMacros:
# - foreach
@@ -112,6 +114,7 @@ KeepEmptyLinesAtTheStartOfBlocks: false
# PenaltyBreakBeforeFirstCallParameter: 19
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
+# PenaltyBreakOpenParenthesis: 0
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
@@ -121,6 +124,8 @@ KeepEmptyLinesAtTheStartOfBlocks: false
# PPIndentWidth: -1
# ReferenceAlignment: Pointer
# ReflowComments: true
+# RemoveBracesLLVM: false
+# SeparateDefinitionBlocks: Leave
# ShortNamespaceLines: 1
# SortIncludes: CaseSensitive
# SortJavaStaticImport: Before
@@ -134,15 +139,20 @@ KeepEmptyLinesAtTheStartOfBlocks: false
# SpaceBeforeCtorInitializerColon: true
# SpaceBeforeInheritanceColon: true
# SpaceBeforeParens: ControlStatements
+# SpaceBeforeParensOptions:
+# AfterControlStatements: true
+# AfterForeachMacros: true
+# AfterFunctionDefinitionName: false
+# AfterFunctionDeclarationName: false
+# AfterIfMacros: true
+# AfterOverloadedOperator: false
+# BeforeNonEmptyParentheses: false
# SpaceAroundPointerQualifiers: Default
# SpaceBeforeRangeBasedForLoopColon: true
-# SpaceInEmptyParentheses: false
-# SpacesBeforeTrailingComments: 1
# SpaceInEmptyBlock: false
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpacesInAngles: Never
-# SpacesInContainerLiterals: true
# SpacesInConditionalStatement: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml
index 1594f5b2d9..7ac364c45f 100644
--- a/.github/workflows/linux_builds.yml
+++ b/.github/workflows/linux_builds.yml
@@ -193,14 +193,6 @@ jobs:
cp -f extension_api.json godot-cpp/godot-headers/
cp -f core/extension/gdnative_interface.h godot-cpp/godot-headers/godot/
- # Build godot-cpp library
- - name: Build godot-cpp library
- if: ${{ matrix.godot-cpp-test }}
- run: |
- cd godot-cpp
- scons target=${{ matrix.target }} generate_bindings=yes -j2
- cd ..
-
# Build godot-cpp test extension
- name: Build godot-cpp test extension
if: ${{ matrix.godot-cpp-test }}
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp
index 93c1abe7b5..06bfc0c562 100644
--- a/core/config/project_settings.cpp
+++ b/core/config/project_settings.cpp
@@ -145,7 +145,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
return p_path.simplify_path();
}
- DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String path = p_path.replace("\\", "/").simplify_path();
@@ -537,8 +537,8 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// Nothing was found, try to find a project file in provided path (`p_path`)
// or, if requested (`p_upwards`) in parent directories.
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V_MSG(!d, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V_MSG(d.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_path + "'.");
d->change_dir(p_path);
String current_dir = d->get_current_dir();
@@ -613,17 +613,14 @@ bool ProjectSettings::has_setting(String p_var) const {
Error ProjectSettings::_load_settings_binary(const String &p_path) {
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err != OK) {
return err;
}
uint8_t hdr[4];
f->get_buffer(hdr, 4);
- if (hdr[0] != 'E' || hdr[1] != 'C' || hdr[2] != 'F' || hdr[3] != 'G') {
- memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Corrupted header in binary project.binary (not ECFG).");
- }
+ ERR_FAIL_COND_V_MSG((hdr[0] != 'E' || hdr[1] != 'C' || hdr[2] != 'F' || hdr[3] != 'G'), ERR_FILE_CORRUPT, "Corrupted header in binary project.binary (not ECFG).");
uint32_t count = f->get_32();
@@ -646,16 +643,14 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
set(key, value);
}
- f->close();
- memdelete(f);
return OK;
}
Error ProjectSettings::_load_settings_text(const String &p_path) {
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
+ if (f.is_null()) {
// FIXME: Above 'err' error code is ERR_FILE_CANT_OPEN if the file is missing
// This needs to be streamlined if we want decent error reporting
return ERR_FILE_NOT_FOUND;
@@ -680,25 +675,18 @@ Error ProjectSettings::_load_settings_text(const String &p_path) {
err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
if (err == ERR_FILE_EOF) {
- memdelete(f);
// If we're loading a project.godot from source code, we can operate some
// ProjectSettings conversions if need be.
_convert_to_last_version(config_version);
last_save_time = FileAccess::get_modified_time(get_resource_path().plus_file("project.godot"));
return OK;
- } else if (err != OK) {
- ERR_PRINT("Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted.");
- memdelete(f);
- return err;
}
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Error parsing " + p_path + " at line " + itos(lines) + ": " + error_text + " File might be corrupted.");
if (!assign.is_empty()) {
if (section.is_empty() && assign == "config_version") {
config_version = value;
- if (config_version > CONFIG_VERSION) {
- memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CANT_OPEN, vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION));
- }
+ ERR_FAIL_COND_V_MSG(config_version > CONFIG_VERSION, ERR_FILE_CANT_OPEN, vformat("Can't open project at '%s', its `config_version` (%d) is from a more recent and incompatible version of the engine. Expected config version: %d.", p_path, config_version, CONFIG_VERSION));
} else {
if (section.is_empty()) {
set(assign, value);
@@ -778,7 +766,7 @@ Error ProjectSettings::save() {
Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) {
Error err;
- FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.binary at " + p_file + ".");
uint8_t hdr[4] = { 'E', 'C', 'F', 'G' };
@@ -798,19 +786,13 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
int len;
err = encode_variant(p_custom_features, nullptr, len, false);
- if (err != OK) {
- memdelete(file);
- ERR_FAIL_V(err);
- }
+ ERR_FAIL_COND_V(err != OK, err);
Vector<uint8_t> buff;
buff.resize(len);
err = encode_variant(p_custom_features, buff.ptrw(), len, false);
- if (err != OK) {
- memdelete(file);
- ERR_FAIL_V(err);
- }
+ ERR_FAIL_COND_V(err != OK, err);
file->store_32(len);
file->store_buffer(buff.ptr(), buff.size());
@@ -834,33 +816,24 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
int len;
err = encode_variant(value, nullptr, len, true);
- if (err != OK) {
- memdelete(file);
- }
ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant.");
Vector<uint8_t> buff;
buff.resize(len);
err = encode_variant(value, buff.ptrw(), len, true);
- if (err != OK) {
- memdelete(file);
- }
ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Error when trying to encode Variant.");
file->store_32(len);
file->store_buffer(buff.ptr(), buff.size());
}
}
- file->close();
- memdelete(file);
-
return OK;
}
Error ProjectSettings::_save_settings_text(const String &p_file, const Map<String, List<String>> &props, const CustomMap &p_custom, const String &p_custom_features) {
Error err;
- FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Couldn't save project.godot - " + p_file + ".");
@@ -905,9 +878,6 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin
}
}
- file->close();
- memdelete(file);
-
return OK;
}
diff --git a/core/core_bind.cpp b/core/core_bind.cpp
index 706395afa9..892b74c26a 100644
--- a/core/core_bind.cpp
+++ b/core/core_bind.cpp
@@ -1027,10 +1027,10 @@ Error File::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const V
return err;
}
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
err = fae->open_and_parse(f, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ);
if (err) {
- memdelete(fae);
close();
return err;
}
@@ -1044,10 +1044,10 @@ Error File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, co
return err;
}
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
err = fae->open_and_parse_password(f, p_pass, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ);
if (err) {
- memdelete(fae);
close();
return err;
}
@@ -1057,14 +1057,13 @@ Error File::open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, co
}
Error File::open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode) {
- FileAccessCompressed *fac = memnew(FileAccessCompressed);
-
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
fac->configure("GCPF", (Compression::Mode)p_compress_mode);
Error err = fac->_open(p_path, p_mode_flags);
if (err) {
- memdelete(fac);
return err;
}
@@ -1073,25 +1072,22 @@ Error File::open_compressed(const String &p_path, ModeFlags p_mode_flags, Compre
}
Error File::open(const String &p_path, ModeFlags p_mode_flags) {
- close();
Error err;
f = FileAccess::open(p_path, p_mode_flags, &err);
- if (f) {
+ if (f.is_valid()) {
f->set_big_endian(big_endian);
}
return err;
}
void File::flush() {
- ERR_FAIL_COND_MSG(!f, "File must be opened before flushing.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before flushing.");
f->flush();
}
void File::close() {
- if (f) {
- memdelete(f);
- }
- f = nullptr;
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened.");
+ f.unref();
}
bool File::is_open() const {
@@ -1099,79 +1095,79 @@ bool File::is_open() const {
}
String File::get_path() const {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), "", "File must be opened before use, or is lacking read-write permission.");
return f->get_path();
}
String File::get_path_absolute() const {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), "", "File must be opened before use, or is lacking read-write permission.");
return f->get_path_absolute();
}
void File::seek(int64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
ERR_FAIL_COND_MSG(p_position < 0, "Seek position must be a positive integer.");
f->seek(p_position);
}
void File::seek_end(int64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->seek_end(p_position);
}
uint64_t File::get_position() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_position();
}
uint64_t File::get_length() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_length();
}
bool File::eof_reached() const {
- ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), false, "File must be opened before use, or is lacking read-write permission.");
return f->eof_reached();
}
uint8_t File::get_8() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_8();
}
uint16_t File::get_16() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_16();
}
uint32_t File::get_32() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_32();
}
uint64_t File::get_64() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_64();
}
float File::get_float() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_float();
}
double File::get_double() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_double();
}
real_t File::get_real() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use, or is lacking read-write permission.");
return f->get_real();
}
Vector<uint8_t> File::get_buffer(int64_t p_length) const {
Vector<uint8_t> data;
- ERR_FAIL_COND_V_MSG(!f, data, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), data, "File must be opened before use, or is lacking read-write permission.");
ERR_FAIL_COND_V_MSG(p_length < 0, data, "Length of buffer cannot be smaller than 0.");
if (p_length == 0) {
@@ -1192,11 +1188,11 @@ Vector<uint8_t> File::get_buffer(int64_t p_length) const {
}
String File::get_as_text() const {
- ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission.");
String text;
uint64_t original_pos = f->get_position();
- f->seek(0);
+ const_cast<FileAccess *>(*f)->seek(0);
String l = get_line();
while (!eof_reached()) {
@@ -1205,7 +1201,7 @@ String File::get_as_text() const {
}
text += l;
- f->seek(original_pos);
+ const_cast<FileAccess *>(*f)->seek(original_pos);
return text;
}
@@ -1219,12 +1215,12 @@ String File::get_sha256(const String &p_path) const {
}
String File::get_line() const {
- ERR_FAIL_COND_V_MSG(!f, String(), "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), String(), "File must be opened before use, or is lacking read-write permission.");
return f->get_line();
}
Vector<String> File::get_csv_line(const String &p_delim) const {
- ERR_FAIL_COND_V_MSG(!f, Vector<String>(), "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), Vector<String>(), "File must be opened before use, or is lacking read-write permission.");
return f->get_csv_line(p_delim);
}
@@ -1235,7 +1231,7 @@ Vector<String> File::get_csv_line(const String &p_delim) const {
void File::set_big_endian(bool p_big_endian) {
big_endian = p_big_endian;
- if (f) {
+ if (f.is_valid()) {
f->set_big_endian(p_big_endian);
}
}
@@ -1245,84 +1241,84 @@ bool File::is_big_endian() {
}
Error File::get_error() const {
- if (!f) {
+ if (f.is_null()) {
return ERR_UNCONFIGURED;
}
return f->get_error();
}
void File::store_8(uint8_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_8(p_dest);
}
void File::store_16(uint16_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_16(p_dest);
}
void File::store_32(uint32_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_32(p_dest);
}
void File::store_64(uint64_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_64(p_dest);
}
void File::store_float(float p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_float(p_dest);
}
void File::store_double(double p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_double(p_dest);
}
void File::store_real(real_t p_real) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_real(p_real);
}
void File::store_string(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_string(p_string);
}
void File::store_pascal_string(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_pascal_string(p_string);
}
String File::get_pascal_string() {
- ERR_FAIL_COND_V_MSG(!f, "", "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), "", "File must be opened before use, or is lacking read-write permission.");
return f->get_pascal_string();
}
void File::store_line(const String &p_string) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_line(p_string);
}
void File::store_csv_line(const Vector<String> &p_values, const String &p_delim) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
f->store_csv_line(p_values, p_delim);
}
void File::store_buffer(const Vector<uint8_t> &p_buffer) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
uint64_t len = p_buffer.size();
if (len == 0) {
@@ -1339,7 +1335,7 @@ bool File::file_exists(const String &p_name) {
}
void File::store_var(const Variant &p_var, bool p_full_objects) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use, or is lacking read-write permission.");
int len;
Error err = encode_variant(p_var, nullptr, len, p_full_objects);
ERR_FAIL_COND_MSG(err != OK, "Error when trying to encode Variant.");
@@ -1356,7 +1352,7 @@ void File::store_var(const Variant &p_var, bool p_full_objects) {
}
Variant File::get_var(bool p_allow_objects) const {
- ERR_FAIL_COND_V_MSG(!f, Variant(), "File must be opened before use, or is lacking read-write permission.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), Variant(), "File must be opened before use, or is lacking read-write permission.");
uint32_t len = get_32();
Vector<uint8_t> buff = get_buffer(len);
ERR_FAIL_COND_V((uint32_t)buff.size() != len, Variant());
@@ -1440,24 +1436,14 @@ void File::_bind_methods() {
BIND_ENUM_CONSTANT(COMPRESSION_GZIP);
}
-File::~File() {
- if (f) {
- memdelete(f);
- }
-}
-
////// Directory //////
Error Directory::open(const String &p_path) {
Error err;
- DirAccess *alt = DirAccess::open(p_path, &err);
-
- if (!alt) {
+ Ref<DirAccess> alt = DirAccess::open(p_path, &err);
+ if (alt.is_null()) {
return err;
}
- if (d) {
- memdelete(d);
- }
d = alt;
dir_open = true;
@@ -1465,7 +1451,7 @@ Error Directory::open(const String &p_path) {
}
bool Directory::is_open() const {
- return d && dir_open;
+ return d.is_valid() && dir_open;
}
Error Directory::list_dir_begin() {
@@ -1550,7 +1536,7 @@ int Directory::get_current_drive() {
}
Error Directory::change_dir(String p_dir) {
- ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
+ ERR_FAIL_COND_V_MSG(d.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
Error err = d->change_dir(p_dir);
if (err != OK) {
@@ -1567,25 +1553,25 @@ String Directory::get_current_dir() {
}
Error Directory::make_dir(String p_dir) {
- ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
+ ERR_FAIL_COND_V_MSG(d.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccessRef da = DirAccess::create_for_path(p_dir);
+ Ref<DirAccess> da = DirAccess::create_for_path(p_dir);
return da->make_dir(p_dir);
}
return d->make_dir(p_dir);
}
Error Directory::make_dir_recursive(String p_dir) {
- ERR_FAIL_COND_V_MSG(!d, ERR_UNCONFIGURED, "Directory is not configured properly.");
+ ERR_FAIL_COND_V_MSG(d.is_null(), ERR_UNCONFIGURED, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
- DirAccessRef da = DirAccess::create_for_path(p_dir);
+ Ref<DirAccess> da = DirAccess::create_for_path(p_dir);
return da->make_dir_recursive(p_dir);
}
return d->make_dir_recursive(p_dir);
}
bool Directory::file_exists(String p_file) {
- ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
+ ERR_FAIL_COND_V_MSG(d.is_null(), false, "Directory is not configured properly.");
if (!p_file.is_relative_path()) {
return FileAccess::exists(p_file);
}
@@ -1593,7 +1579,7 @@ bool Directory::file_exists(String p_file) {
}
bool Directory::dir_exists(String p_dir) {
- ERR_FAIL_COND_V_MSG(!d, false, "Directory is not configured properly.");
+ ERR_FAIL_COND_V_MSG(d.is_null(), false, "Directory is not configured properly.");
if (!p_dir.is_relative_path()) {
return DirAccess::exists(p_dir);
}
@@ -1601,7 +1587,7 @@ bool Directory::dir_exists(String p_dir) {
}
uint64_t Directory::get_space_left() {
- ERR_FAIL_COND_V_MSG(!d, 0, "Directory must be opened before use.");
+ ERR_FAIL_COND_V_MSG(d.is_null(), 0, "Directory must be opened before use.");
return d->get_space_left() / 1024 * 1024; // Truncate to closest MiB.
}
@@ -1615,7 +1601,7 @@ Error Directory::rename(String p_from, String p_to) {
ERR_FAIL_COND_V_MSG(p_from.is_empty() || p_from == "." || p_from == "..", ERR_INVALID_PARAMETER, "Invalid path to rename.");
if (!p_from.is_relative_path()) {
- DirAccessRef da = DirAccess::create_for_path(p_from);
+ Ref<DirAccess> da = DirAccess::create_for_path(p_from);
ERR_FAIL_COND_V_MSG(!da->file_exists(p_from) && !da->dir_exists(p_from), ERR_DOES_NOT_EXIST, "File or directory does not exist.");
return da->rename(p_from, p_to);
}
@@ -1627,7 +1613,7 @@ Error Directory::rename(String p_from, String p_to) {
Error Directory::remove(String p_name) {
ERR_FAIL_COND_V_MSG(!is_open(), ERR_UNCONFIGURED, "Directory must be opened before use.");
if (!p_name.is_relative_path()) {
- DirAccessRef da = DirAccess::create_for_path(p_name);
+ Ref<DirAccess> da = DirAccess::create_for_path(p_name);
return da->remove(p_name);
}
@@ -1669,12 +1655,6 @@ Directory::Directory() {
d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
}
-Directory::~Directory() {
- if (d) {
- memdelete(d);
- }
-}
-
////// Marshalls //////
Marshalls *Marshalls::singleton = nullptr;
diff --git a/core/core_bind.h b/core/core_bind.h
index 4d26698f99..591cacdabb 100644
--- a/core/core_bind.h
+++ b/core/core_bind.h
@@ -349,7 +349,7 @@ public:
class File : public RefCounted {
GDCLASS(File, RefCounted);
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
bool big_endian = false;
protected:
@@ -442,12 +442,11 @@ public:
uint64_t get_modified_time(const String &p_file) const;
File() {}
- virtual ~File();
};
class Directory : public RefCounted {
GDCLASS(Directory, RefCounted);
- DirAccess *d = nullptr;
+ Ref<DirAccess> d;
bool dir_open = false;
bool include_navigational = false;
@@ -495,7 +494,6 @@ public:
Error remove(String p_name);
Directory();
- virtual ~Directory();
};
class Marshalls : public Object {
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp
index 9acc28f51e..f64c30dca5 100644
--- a/core/extension/extension_api_dump.cpp
+++ b/core/extension/extension_api_dump.cpp
@@ -869,9 +869,8 @@ void NativeExtensionAPIDump::generate_extension_json_file(const String &p_path)
json.instantiate();
String text = json->stringify(api, "\t", false);
- FileAccessRef fa = FileAccess::open(p_path, FileAccess::WRITE);
+ Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
CharString cs = text.ascii();
fa->store_buffer((const uint8_t *)cs.ptr(), cs.length());
- fa->close();
}
#endif
diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp
index b5b340731d..a312ce4ebd 100644
--- a/core/extension/gdnative_interface.cpp
+++ b/core/extension/gdnative_interface.cpp
@@ -241,6 +241,13 @@ static GDNativeBool gdnative_variant_booleanize(const GDNativeVariantPtr p_self)
return self->booleanize();
}
+static void gdnative_variant_sub(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst) {
+ const Variant *a = (const Variant *)p_a;
+ const Variant *b = (const Variant *)p_b;
+ memnew_placement(r_dst, Variant);
+ Variant::sub(*a, *b, *(Variant *)r_dst);
+}
+
static void gdnative_variant_blend(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst) {
const Variant *a = (const Variant *)p_a;
const Variant *b = (const Variant *)p_b;
@@ -939,6 +946,7 @@ void gdnative_setup_interface(GDNativeInterface *p_interface) {
gdni.variant_iter_get = gdnative_variant_iter_get;
gdni.variant_hash_compare = gdnative_variant_hash_compare;
gdni.variant_booleanize = gdnative_variant_booleanize;
+ gdni.variant_sub = gdnative_variant_sub;
gdni.variant_blend = gdnative_variant_blend;
gdni.variant_interpolate = gdnative_variant_interpolate;
gdni.variant_duplicate = gdnative_variant_duplicate;
diff --git a/core/extension/gdnative_interface.h b/core/extension/gdnative_interface.h
index 732a1b5af0..2bac52dc4a 100644
--- a/core/extension/gdnative_interface.h
+++ b/core/extension/gdnative_interface.h
@@ -416,6 +416,7 @@ typedef struct {
void (*variant_iter_get)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_iter, GDNativeVariantPtr r_ret, GDNativeBool *r_valid);
GDNativeBool (*variant_hash_compare)(const GDNativeVariantPtr p_self, const GDNativeVariantPtr p_other);
GDNativeBool (*variant_booleanize)(const GDNativeVariantPtr p_self);
+ void (*variant_sub)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, GDNativeVariantPtr r_dst);
void (*variant_blend)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
void (*variant_interpolate)(const GDNativeVariantPtr p_a, const GDNativeVariantPtr p_b, float p_c, GDNativeVariantPtr r_dst);
void (*variant_duplicate)(const GDNativeVariantPtr p_self, GDNativeVariantPtr r_ret, GDNativeBool p_deep);
diff --git a/core/extension/native_extension_manager.cpp b/core/extension/native_extension_manager.cpp
index 509405494b..5436f7d51e 100644
--- a/core/extension/native_extension_manager.cpp
+++ b/core/extension/native_extension_manager.cpp
@@ -112,8 +112,8 @@ void NativeExtensionManager::deinitialize_extensions(NativeExtension::Initializa
}
void NativeExtensionManager::load_extensions() {
- FileAccessRef f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ);
- while (f && !f->eof_reached()) {
+ Ref<FileAccess> f = FileAccess::open(NativeExtension::get_extension_list_config_file(), FileAccess::READ);
+ while (f.is_valid() && !f->eof_reached()) {
String s = f->get_line().strip_edges();
if (!s.is_empty()) {
LoadStatus err = load_extension(s);
diff --git a/core/input/input.cpp b/core/input/input.cpp
index 343076b4e1..0db20a7c82 100644
--- a/core/input/input.cpp
+++ b/core/input/input.cpp
@@ -855,6 +855,8 @@ void Input::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, co
return;
}
+ ERR_FAIL_INDEX(p_shape, CursorShape::CURSOR_MAX);
+
set_custom_mouse_cursor_func(p_cursor, p_shape, p_hotspot);
}
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp
index c942b417e4..bc24cac955 100644
--- a/core/io/config_file.cpp
+++ b/core/io/config_file.cpp
@@ -129,12 +129,9 @@ void ConfigFile::erase_section_key(const String &p_section, const String &p_key)
Error ConfigFile::save(const String &p_path) {
Error err;
- FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
if (err) {
- if (file) {
- memdelete(file);
- }
return err;
}
@@ -143,17 +140,16 @@ Error ConfigFile::save(const String &p_path) {
Error ConfigFile::save_encrypted(const String &p_path, const Vector<uint8_t> &p_key) {
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
if (err) {
return err;
}
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_WRITE_AES256);
if (err) {
- memdelete(fae);
- memdelete(f);
return err;
}
return _internal_save(fae);
@@ -161,24 +157,23 @@ Error ConfigFile::save_encrypted(const String &p_path, const Vector<uint8_t> &p_
Error ConfigFile::save_encrypted_pass(const String &p_path, const String &p_pass) {
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
if (err) {
return err;
}
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_WRITE_AES256);
if (err) {
- memdelete(fae);
- memdelete(f);
return err;
}
return _internal_save(fae);
}
-Error ConfigFile::_internal_save(FileAccess *file) {
+Error ConfigFile::_internal_save(Ref<FileAccess> file) {
for (OrderedHashMap<String, OrderedHashMap<String, Variant>>::Element E = values.front(); E; E = E.next()) {
if (E != values.front()) {
file->store_string("\n");
@@ -194,16 +189,14 @@ Error ConfigFile::_internal_save(FileAccess *file) {
}
}
- memdelete(file);
-
return OK;
}
Error ConfigFile::load(const String &p_path) {
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
+ if (f.is_null()) {
return err;
}
@@ -212,17 +205,16 @@ Error ConfigFile::load(const String &p_path) {
Error ConfigFile::load_encrypted(const String &p_path, const Vector<uint8_t> &p_key) {
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
return err;
}
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
err = fae->open_and_parse(f, p_key, FileAccessEncrypted::MODE_READ);
if (err) {
- memdelete(fae);
- memdelete(f);
return err;
}
return _internal_load(p_path, fae);
@@ -230,31 +222,28 @@ Error ConfigFile::load_encrypted(const String &p_path, const Vector<uint8_t> &p_
Error ConfigFile::load_encrypted_pass(const String &p_path, const String &p_pass) {
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
return err;
}
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
err = fae->open_and_parse_password(f, p_pass, FileAccessEncrypted::MODE_READ);
if (err) {
- memdelete(fae);
- memdelete(f);
return err;
}
return _internal_load(p_path, fae);
}
-Error ConfigFile::_internal_load(const String &p_path, FileAccess *f) {
+Error ConfigFile::_internal_load(const String &p_path, Ref<FileAccess> f) {
VariantParser::StreamFile stream;
stream.f = f;
Error err = _parse(p_path, &stream);
- memdelete(f);
-
return err;
}
diff --git a/core/io/config_file.h b/core/io/config_file.h
index 71e9080fb7..7a52b0e16a 100644
--- a/core/io/config_file.h
+++ b/core/io/config_file.h
@@ -43,8 +43,8 @@ class ConfigFile : public RefCounted {
PackedStringArray _get_sections() const;
PackedStringArray _get_section_keys(const String &p_section) const;
- Error _internal_load(const String &p_path, FileAccess *f);
- Error _internal_save(FileAccess *file);
+ Error _internal_load(const String &p_path, Ref<FileAccess> f);
+ Error _internal_save(Ref<FileAccess> file);
Error _parse(const String &p_path, VariantParser::Stream *p_stream);
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index 73efdeb38e..433a7efb21 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -217,8 +217,8 @@ String DirAccess::fix_path(String p_path) const {
DirAccess::CreateFunc DirAccess::create_func[ACCESS_MAX] = { nullptr, nullptr, nullptr };
-DirAccess *DirAccess::create_for_path(const String &p_path) {
- DirAccess *da = nullptr;
+Ref<DirAccess> DirAccess::create_for_path(const String &p_path) {
+ Ref<DirAccess> da;
if (p_path.begins_with("res://")) {
da = create(ACCESS_RESOURCES);
} else if (p_path.begins_with("user://")) {
@@ -230,25 +230,23 @@ DirAccess *DirAccess::create_for_path(const String &p_path) {
return da;
}
-DirAccess *DirAccess::open(const String &p_path, Error *r_error) {
- DirAccess *da = create_for_path(p_path);
-
- ERR_FAIL_COND_V_MSG(!da, nullptr, "Cannot create DirAccess for path '" + p_path + "'.");
+Ref<DirAccess> DirAccess::open(const String &p_path, Error *r_error) {
+ Ref<DirAccess> da = create_for_path(p_path);
+ ERR_FAIL_COND_V_MSG(da.is_null(), nullptr, "Cannot create DirAccess for path '" + p_path + "'.");
Error err = da->change_dir(p_path);
if (r_error) {
*r_error = err;
}
if (err != OK) {
- memdelete(da);
return nullptr;
}
return da;
}
-DirAccess *DirAccess::create(AccessType p_access) {
- DirAccess *da = create_func[p_access] ? create_func[p_access]() : nullptr;
- if (da) {
+Ref<DirAccess> DirAccess::create(AccessType p_access) {
+ Ref<DirAccess> da = create_func[p_access] ? create_func[p_access]() : nullptr;
+ if (da.is_valid()) {
da->_access_type = p_access;
// for ACCESS_RESOURCES and ACCESS_FILESYSTEM, current_dir already defaults to where game was started
@@ -264,54 +262,45 @@ DirAccess *DirAccess::create(AccessType p_access) {
}
String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
- DirAccess *d = DirAccess::create(p_access);
- if (!d) {
+ Ref<DirAccess> d = DirAccess::create(p_access);
+ if (d.is_null()) {
return p_path;
}
d->change_dir(p_path);
String full = d->get_current_dir();
- memdelete(d);
return full;
}
Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
//printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
Error err;
- FileAccess *fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
-
- if (err) {
- ERR_PRINT("Failed to open " + p_from);
- return err;
- }
-
- FileAccess *fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
- if (err) {
- fsrc->close();
- memdelete(fsrc);
- ERR_PRINT("Failed to open " + p_to);
- return err;
- }
+ {
+ Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from);
+
+ Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to);
+
+ fsrc->seek_end(0);
+ int size = fsrc->get_position();
+ fsrc->seek(0);
+ err = OK;
+ while (size--) {
+ if (fsrc->get_error() != OK) {
+ err = fsrc->get_error();
+ break;
+ }
+ if (fdst->get_error() != OK) {
+ err = fdst->get_error();
+ break;
+ }
- fsrc->seek_end(0);
- int size = fsrc->get_position();
- fsrc->seek(0);
- err = OK;
- while (size--) {
- if (fsrc->get_error() != OK) {
- err = fsrc->get_error();
- break;
- }
- if (fdst->get_error() != OK) {
- err = fdst->get_error();
- break;
+ fdst->store_8(fsrc->get_8());
}
-
- fdst->store_8(fsrc->get_8());
}
if (err == OK && p_chmod_flags != -1) {
- fdst->close();
err = FileAccess::set_unix_permissions(p_to, p_chmod_flags);
// If running on a platform with no chmod support (i.e., Windows), don't fail
if (err == ERR_UNAVAILABLE) {
@@ -319,9 +308,6 @@ Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) {
}
}
- memdelete(fsrc);
- memdelete(fdst);
-
return err;
}
@@ -343,7 +329,7 @@ public:
}
};
-Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links) {
+Error DirAccess::_copy_dir(Ref<DirAccess> &p_target_da, String p_to, int p_chmod_flags, bool p_copy_links) {
List<String> dirs;
String curdir = get_current_dir();
@@ -399,14 +385,11 @@ Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flag
Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_copy_links) {
ERR_FAIL_COND_V_MSG(!dir_exists(p_from), ERR_FILE_NOT_FOUND, "Source directory doesn't exist.");
- DirAccess *target_da = DirAccess::create_for_path(p_to);
- ERR_FAIL_COND_V_MSG(!target_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
+ Ref<DirAccess> target_da = DirAccess::create_for_path(p_to);
+ ERR_FAIL_COND_V_MSG(target_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_to + "'.");
if (!target_da->dir_exists(p_to)) {
Error err = target_da->make_dir_recursive(p_to);
- if (err) {
- memdelete(target_da);
- }
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot create directory '" + p_to + "'.");
}
@@ -416,12 +399,11 @@ Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags, bool p_
DirChanger dir_changer(this, p_from);
Error err = _copy_dir(target_da, p_to, p_chmod_flags, p_copy_links);
- memdelete(target_da);
return err;
}
bool DirAccess::exists(String p_dir) {
- DirAccessRef da = DirAccess::create_for_path(p_dir);
+ Ref<DirAccess> da = DirAccess::create_for_path(p_dir);
return da->change_dir(p_dir) == OK;
}
diff --git a/core/io/dir_access.h b/core/io/dir_access.h
index b97d097842..0125f011b5 100644
--- a/core/io/dir_access.h
+++ b/core/io/dir_access.h
@@ -31,11 +31,12 @@
#ifndef DIR_ACCESS_H
#define DIR_ACCESS_H
+#include "core/object/ref_counted.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
//@ TODO, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies
-class DirAccess {
+class DirAccess : public RefCounted {
public:
enum AccessType {
ACCESS_RESOURCES,
@@ -44,13 +45,13 @@ public:
ACCESS_MAX
};
- typedef DirAccess *(*CreateFunc)();
+ typedef Ref<DirAccess> (*CreateFunc)();
private:
AccessType _access_type = ACCESS_FILESYSTEM;
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
- Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
+ Error _copy_dir(Ref<DirAccess> &p_target_da, String p_to, int p_chmod_flags, bool p_copy_links);
protected:
String _get_root_path() const;
@@ -59,7 +60,7 @@ protected:
String fix_path(String p_path) const;
template <class T>
- static DirAccess *_create_builtin() {
+ static Ref<DirAccess> _create_builtin() {
return memnew(T);
}
@@ -77,7 +78,7 @@ public:
virtual bool drives_are_shortcuts();
virtual Error change_dir(String p_dir) = 0; ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true) = 0; ///< return current dir location
+ virtual String get_current_dir(bool p_include_drive = true) const = 0; ///< return current dir location
virtual Error make_dir(String p_dir) = 0;
virtual Error make_dir_recursive(String p_dir);
virtual Error erase_contents_recursive(); //super dangerous, use with care!
@@ -101,51 +102,29 @@ public:
// Meant for editor code when we want to quickly remove a file without custom
// handling (e.g. removing a cache file).
static void remove_file_or_error(String p_path) {
- DirAccess *da = create(ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = create(ACCESS_FILESYSTEM);
if (da->file_exists(p_path)) {
if (da->remove(p_path) != OK) {
ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
}
}
- memdelete(da);
}
virtual String get_filesystem_type() const = 0;
static String get_full_path(const String &p_path, AccessType p_access);
- static DirAccess *create_for_path(const String &p_path);
+ static Ref<DirAccess> create_for_path(const String &p_path);
- static DirAccess *create(AccessType p_access);
+ static Ref<DirAccess> create(AccessType p_access);
template <class T>
static void make_default(AccessType p_access) {
create_func[p_access] = _create_builtin<T>;
}
- static DirAccess *open(const String &p_path, Error *r_error = nullptr);
+ static Ref<DirAccess> open(const String &p_path, Error *r_error = nullptr);
DirAccess() {}
virtual ~DirAccess() {}
};
-struct DirAccessRef {
- _FORCE_INLINE_ DirAccess *operator->() {
- return f;
- }
-
- operator bool() const { return f != nullptr; }
-
- DirAccess *f = nullptr;
-
- DirAccessRef(DirAccess *fa) { f = fa; }
- DirAccessRef(DirAccessRef &&other) {
- f = other.f;
- other.f = nullptr;
- }
- ~DirAccessRef() {
- if (f) {
- memdelete(f);
- }
- }
-};
-
#endif // DIR_ACCESS_H
diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp
index 86836454c5..7d8da1b11c 100644
--- a/core/io/file_access.cpp
+++ b/core/io/file_access.cpp
@@ -42,10 +42,10 @@ FileAccess::FileCloseFailNotify FileAccess::close_fail_notify = nullptr;
bool FileAccess::backup_save = false;
-FileAccess *FileAccess::create(AccessType p_access) {
+Ref<FileAccess> FileAccess::create(AccessType p_access) {
ERR_FAIL_INDEX_V(p_access, ACCESS_MAX, nullptr);
- FileAccess *ret = create_func[p_access]();
+ Ref<FileAccess> ret = create_func[p_access]();
ret->_set_access_type(p_access);
return ret;
}
@@ -55,11 +55,10 @@ bool FileAccess::exists(const String &p_name) {
return true;
}
- FileAccess *f = open(p_name, READ);
- if (!f) {
+ Ref<FileAccess> f = open(p_name, READ);
+ if (f.is_null()) {
return false;
}
- memdelete(f);
return true;
}
@@ -67,8 +66,8 @@ void FileAccess::_set_access_type(AccessType p_access) {
_access_type = p_access;
}
-FileAccess *FileAccess::create_for_path(const String &p_path) {
- FileAccess *ret = nullptr;
+Ref<FileAccess> FileAccess::create_for_path(const String &p_path) {
+ Ref<FileAccess> ret;
if (p_path.begins_with("res://")) {
ret = create(ACCESS_RESOURCES);
} else if (p_path.begins_with("user://")) {
@@ -85,13 +84,13 @@ Error FileAccess::reopen(const String &p_path, int p_mode_flags) {
return _open(p_path, p_mode_flags);
}
-FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
+Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error *r_error) {
//try packed data first
- FileAccess *ret = nullptr;
+ Ref<FileAccess> ret;
if (!(p_mode_flags & WRITE) && PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled()) {
ret = PackedData::get_singleton()->try_open_path(p_path);
- if (ret) {
+ if (ret.is_valid()) {
if (r_error) {
*r_error = OK;
}
@@ -106,8 +105,7 @@ FileAccess *FileAccess::open(const String &p_path, int p_mode_flags, Error *r_er
*r_error = err;
}
if (err != OK) {
- memdelete(ret);
- ret = nullptr;
+ ret.unref();
}
return ret;
@@ -463,11 +461,10 @@ uint64_t FileAccess::get_modified_time(const String &p_file) {
return 0;
}
- FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
+ Ref<FileAccess> fa = create_for_path(p_file);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
uint64_t mt = fa->_get_modified_time(p_file);
- memdelete(fa);
return mt;
}
@@ -476,11 +473,10 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) {
return 0;
}
- FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V_MSG(!fa, 0, "Cannot create FileAccess for path '" + p_file + "'.");
+ Ref<FileAccess> fa = create_for_path(p_file);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "Cannot create FileAccess for path '" + p_file + "'.");
uint32_t mt = fa->_get_unix_permissions(p_file);
- memdelete(fa);
return mt;
}
@@ -489,11 +485,10 @@ Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissi
return ERR_UNAVAILABLE;
}
- FileAccess *fa = create_for_path(p_file);
- ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
+ Ref<FileAccess> fa = create_for_path(p_file);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'.");
Error err = fa->_set_unix_permissions(p_file, p_permissions);
- memdelete(fa);
return err;
}
@@ -559,8 +554,8 @@ void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
}
Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_error) {
- FileAccess *f = FileAccess::open(p_path, READ, r_error);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, READ, r_error);
+ if (f.is_null()) {
if (r_error) { // if error requested, do not throw error
return Vector<uint8_t>();
}
@@ -569,7 +564,6 @@ Vector<uint8_t> FileAccess::get_file_as_array(const String &p_path, Error *r_err
Vector<uint8_t> data;
data.resize(f->get_length());
f->get_buffer(data.ptrw(), data.size());
- memdelete(f);
return data;
}
@@ -592,8 +586,8 @@ String FileAccess::get_file_as_string(const String &p_path, Error *r_error) {
}
String FileAccess::get_md5(const String &p_file) {
- FileAccess *f = FileAccess::open(p_file, READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_file, READ);
+ if (f.is_null()) {
return String();
}
@@ -615,8 +609,6 @@ String FileAccess::get_md5(const String &p_file) {
unsigned char hash[16];
ctx.finish(hash);
- memdelete(f);
-
return String::md5(hash);
}
@@ -625,8 +617,8 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
ctx.start();
for (int i = 0; i < p_file.size(); i++) {
- FileAccess *f = FileAccess::open(p_file[i], READ);
- ERR_CONTINUE(!f);
+ Ref<FileAccess> f = FileAccess::open(p_file[i], READ);
+ ERR_CONTINUE(f.is_null());
unsigned char step[32768];
@@ -639,7 +631,6 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
break;
}
}
- memdelete(f);
}
unsigned char hash[16];
@@ -649,8 +640,8 @@ String FileAccess::get_multiple_md5(const Vector<String> &p_file) {
}
String FileAccess::get_sha256(const String &p_file) {
- FileAccess *f = FileAccess::open(p_file, READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_file, READ);
+ if (f.is_null()) {
return String();
}
@@ -672,6 +663,5 @@ String FileAccess::get_sha256(const String &p_file) {
unsigned char hash[32];
ctx.finish(hash);
- memdelete(f);
return String::hex_encode_buffer(hash, 32);
}
diff --git a/core/io/file_access.h b/core/io/file_access.h
index a5150010da..e2c11142d7 100644
--- a/core/io/file_access.h
+++ b/core/io/file_access.h
@@ -32,6 +32,7 @@
#define FILE_ACCESS_H
#include "core/math/math_defs.h"
+#include "core/object/ref_counted.h"
#include "core/os/memory.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
@@ -40,7 +41,7 @@
* Multi-Platform abstraction for accessing to files.
*/
-class FileAccess {
+class FileAccess : public RefCounted {
public:
enum AccessType {
ACCESS_RESOURCES,
@@ -51,7 +52,7 @@ public:
typedef void (*FileCloseFailNotify)(const String &);
- typedef FileAccess *(*CreateFunc)();
+ typedef Ref<FileAccess> (*CreateFunc)();
bool big_endian = false;
bool real_is_double = false;
@@ -71,7 +72,7 @@ private:
AccessType _access_type = ACCESS_FILESYSTEM;
static CreateFunc create_func[ACCESS_MAX]; /** default file access creation function for a platform */
template <class T>
- static FileAccess *_create_builtin() {
+ static Ref<FileAccess> _create_builtin() {
return memnew(T);
}
@@ -87,7 +88,6 @@ public:
WRITE_READ = 7,
};
- virtual void close() = 0; ///< close a file
virtual bool is_open() const = 0; ///< true when file is open
virtual String get_path() const { return ""; } /// returns the path for the current open file
@@ -148,9 +148,9 @@ public:
virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
- static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
- static FileAccess *create_for_path(const String &p_path);
- static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+ static Ref<FileAccess> create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
+ static Ref<FileAccess> create_for_path(const String &p_path);
+ static Ref<FileAccess> open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static CreateFunc get_create_func(AccessType p_access);
static bool exists(const String &p_name); ///< return true if a file exists
static uint64_t get_modified_time(const String &p_file);
@@ -176,27 +176,4 @@ public:
virtual ~FileAccess() {}
};
-struct FileAccessRef {
- _FORCE_INLINE_ FileAccess *operator->() {
- return f;
- }
-
- operator bool() const { return f != nullptr; }
-
- FileAccess *f = nullptr;
-
- operator FileAccess *() { return f; }
-
- FileAccessRef(FileAccess *fa) { f = fa; }
- FileAccessRef(FileAccessRef &&other) {
- f = other.f;
- other.f = nullptr;
- }
- ~FileAccessRef() {
- if (f) {
- memdelete(f);
- }
- }
-};
-
#endif // FILE_ACCESS_H
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 85faf04315..1d0a718166 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -58,12 +58,12 @@ void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_
} \
}
-Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
+Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) {
f = p_base;
cmode = (Compression::Mode)f->get_32();
block_size = f->get_32();
if (block_size == 0) {
- f = nullptr; // Let the caller to handle the FileAccess object if failed to open as compressed file.
+ f.unref();
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted.");
}
read_total = f->get_32();
@@ -97,17 +97,13 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags == READ_WRITE, ERR_UNAVAILABLE);
-
- if (f) {
- close();
- }
+ _close();
Error err;
f = FileAccess::open(p_path, p_mode_flags, &err);
if (err != OK) {
//not openable
-
- f = nullptr;
+ f.unref();
return err;
}
@@ -127,8 +123,7 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
rmagic[4] = 0;
err = ERR_FILE_UNRECOGNIZED;
if (magic != rmagic || (err = open_after_magic(f)) != OK) {
- memdelete(f);
- f = nullptr;
+ f.unref();
return err;
}
}
@@ -136,8 +131,8 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) {
return OK;
}
-void FileAccessCompressed::close() {
- if (!f) {
+void FileAccessCompressed::_close() {
+ if (f.is_null()) {
return;
}
@@ -182,17 +177,15 @@ void FileAccessCompressed::close() {
buffer.clear();
read_blocks.clear();
}
-
- memdelete(f);
- f = nullptr;
+ f.unref();
}
bool FileAccessCompressed::is_open() const {
- return f != nullptr;
+ return f.is_valid();
}
void FileAccessCompressed::seek(uint64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
if (writing) {
ERR_FAIL_COND(p_position > write_max);
@@ -222,7 +215,7 @@ void FileAccessCompressed::seek(uint64_t p_position) {
}
void FileAccessCompressed::seek_end(int64_t p_position) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
if (writing) {
seek(write_max + p_position);
} else {
@@ -231,7 +224,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) {
}
uint64_t FileAccessCompressed::get_position() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
if (writing) {
return write_pos;
} else {
@@ -240,7 +233,7 @@ uint64_t FileAccessCompressed::get_position() const {
}
uint64_t FileAccessCompressed::get_length() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
if (writing) {
return write_max;
} else {
@@ -249,7 +242,7 @@ uint64_t FileAccessCompressed::get_length() const {
}
bool FileAccessCompressed::eof_reached() const {
- ERR_FAIL_COND_V_MSG(!f, false, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), false, "File must be opened before use.");
if (writing) {
return false;
} else {
@@ -258,7 +251,7 @@ bool FileAccessCompressed::eof_reached() const {
}
uint8_t FileAccessCompressed::get_8() const {
- ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
if (at_end) {
@@ -291,7 +284,7 @@ uint8_t FileAccessCompressed::get_8() const {
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
- ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
if (at_end) {
@@ -332,14 +325,14 @@ Error FileAccessCompressed::get_error() const {
}
void FileAccessCompressed::flush() {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
// compressed files keep data in memory till close()
}
void FileAccessCompressed::store_8(uint8_t p_dest) {
- ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
WRITE_FIT(1);
@@ -347,16 +340,15 @@ void FileAccessCompressed::store_8(uint8_t p_dest) {
}
bool FileAccessCompressed::file_exists(const String &p_name) {
- FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
- if (!fa) {
+ Ref<FileAccess> fa = FileAccess::open(p_name, FileAccess::READ);
+ if (fa.is_null()) {
return false;
}
- memdelete(fa);
return true;
}
uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
- if (f) {
+ if (f.is_valid()) {
return f->get_modified_time(p_file);
} else {
return 0;
@@ -364,21 +356,19 @@ uint64_t FileAccessCompressed::_get_modified_time(const String &p_file) {
}
uint32_t FileAccessCompressed::_get_unix_permissions(const String &p_file) {
- if (f) {
+ if (f.is_valid()) {
return f->_get_unix_permissions(p_file);
}
return 0;
}
Error FileAccessCompressed::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
- if (f) {
+ if (f.is_valid()) {
return f->_set_unix_permissions(p_file, p_permissions);
}
return FAILED;
}
FileAccessCompressed::~FileAccessCompressed() {
- if (f) {
- close();
- }
+ _close();
}
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index 97ef3fbdeb..b8382e61d9 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -61,15 +61,16 @@ class FileAccessCompressed : public FileAccess {
String magic = "GCMP";
mutable Vector<uint8_t> buffer;
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
+
+ void _close();
public:
void configure(const String &p_magic, Compression::Mode p_mode = Compression::MODE_ZSTD, uint32_t p_block_size = 4096);
- Error open_after_magic(FileAccess *p_base);
+ Error open_after_magic(Ref<FileAccess> p_base);
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(uint64_t p_position); ///< seek to a given position
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 8ee19d3d06..d1b014a0be 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -36,7 +36,7 @@
#include <stdio.h>
-Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
+Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
ERR_FAIL_COND_V_MSG(file != nullptr, ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
@@ -99,7 +99,7 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
return OK;
}
-Error FileAccessEncrypted::open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode) {
+Error FileAccessEncrypted::open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode) {
String cs = p_key.md5_text();
ERR_FAIL_COND_V(cs.length() != 32, ERR_INVALID_PARAMETER);
Vector<uint8_t> key;
@@ -115,30 +115,11 @@ Error FileAccessEncrypted::_open(const String &p_path, int p_mode_flags) {
return OK;
}
-void FileAccessEncrypted::close() {
- if (!file) {
+void FileAccessEncrypted::_close() {
+ if (file.is_null()) {
return;
}
- _release();
-
- file->close();
- memdelete(file);
-
- file = nullptr;
-}
-
-void FileAccessEncrypted::release() {
- if (!file) {
- return;
- }
-
- _release();
-
- file = nullptr;
-}
-
-void FileAccessEncrypted::_release() {
if (writing) {
Vector<uint8_t> compressed;
uint64_t len = data.size();
@@ -176,6 +157,8 @@ void FileAccessEncrypted::_release() {
file->store_buffer(compressed.ptr(), compressed.size());
data.clear();
}
+
+ file.unref();
}
bool FileAccessEncrypted::is_open() const {
@@ -183,7 +166,7 @@ bool FileAccessEncrypted::is_open() const {
}
String FileAccessEncrypted::get_path() const {
- if (file) {
+ if (file.is_valid()) {
return file->get_path();
} else {
return "";
@@ -191,7 +174,7 @@ String FileAccessEncrypted::get_path() const {
}
String FileAccessEncrypted::get_path_absolute() const {
- if (file) {
+ if (file.is_valid()) {
return file->get_path_absolute();
} else {
return "";
@@ -291,11 +274,10 @@ void FileAccessEncrypted::store_8(uint8_t p_dest) {
}
bool FileAccessEncrypted::file_exists(const String &p_name) {
- FileAccess *fa = FileAccess::open(p_name, FileAccess::READ);
- if (!fa) {
+ Ref<FileAccess> fa = FileAccess::open(p_name, FileAccess::READ);
+ if (fa.is_null()) {
return false;
}
- memdelete(fa);
return true;
}
@@ -313,7 +295,5 @@ Error FileAccessEncrypted::_set_unix_permissions(const String &p_file, uint32_t
}
FileAccessEncrypted::~FileAccessEncrypted() {
- if (file) {
- close();
- }
+ _close();
}
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index be5904c894..0d1ee6a4d8 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -46,7 +46,7 @@ public:
private:
Vector<uint8_t> key;
bool writing = false;
- FileAccess *file = nullptr;
+ Ref<FileAccess> file;
uint64_t base = 0;
uint64_t length = 0;
Vector<uint8_t> data;
@@ -54,15 +54,13 @@ private:
mutable bool eofed = false;
bool use_magic = true;
- void _release();
+ void _close();
public:
- Error open_and_parse(FileAccess *p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true);
- Error open_and_parse_password(FileAccess *p_base, const String &p_key, Mode p_mode);
+ Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true);
+ Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode);
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
- virtual void release(); ///< finish and keep base file open
virtual bool is_open() const; ///< true when file is open
virtual String get_path() const; /// returns the path for the current open file
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 4aca26b007..943dc72307 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -60,7 +60,7 @@ void FileAccessMemory::cleanup() {
memdelete(files);
}
-FileAccess *FileAccessMemory::create() {
+Ref<FileAccess> FileAccessMemory::create() {
return memnew(FileAccessMemory);
}
@@ -94,10 +94,6 @@ Error FileAccessMemory::_open(const String &p_path, int p_mode_flags) {
return OK;
}
-void FileAccessMemory::close() {
- data = nullptr;
-}
-
bool FileAccessMemory::is_open() const {
return data != nullptr;
}
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 50b23e1f32..868b8ed481 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -38,7 +38,7 @@ class FileAccessMemory : public FileAccess {
uint64_t length = 0;
mutable uint64_t pos = 0;
- static FileAccess *create();
+ static Ref<FileAccess> create();
public:
static void register_file(String p_name, Vector<uint8_t> p_data);
@@ -46,7 +46,6 @@ public:
virtual Error open_custom(const uint8_t *p_data, uint64_t p_len); ///< open a file
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(uint64_t p_position); ///< seek to a given position
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 612181f8d5..1365b4b593 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -254,9 +254,8 @@ void FileAccessNetwork::_respond(uint64_t p_len, Error p_status) {
Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) {
ERR_FAIL_COND_V(p_mode_flags != READ, ERR_UNAVAILABLE);
- if (opened) {
- close();
- }
+ _close();
+
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
DEBUG_PRINT("open: " + p_path);
@@ -287,7 +286,7 @@ Error FileAccessNetwork::_open(const String &p_path, int p_mode_flags) {
return response;
}
-void FileAccessNetwork::close() {
+void FileAccessNetwork::_close() {
if (!opened) {
return;
}
@@ -483,7 +482,7 @@ FileAccessNetwork::FileAccessNetwork() {
}
FileAccessNetwork::~FileAccessNetwork() {
- close();
+ _close();
FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton;
nc->lock_mutex();
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index 6cae49b540..6afbf6adf5 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -113,6 +113,7 @@ class FileAccessNetwork : public FileAccess {
void _queue_page(int32_t p_page) const;
void _respond(uint64_t p_len, Error p_status);
void _set_block(uint64_t p_offset, const Vector<uint8_t> &p_block);
+ void _close();
public:
enum Command {
@@ -131,7 +132,6 @@ public:
};
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(uint64_t p_position); ///< seek to a given position
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 7dbea96c3d..c6e14ffee7 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -126,8 +126,8 @@ PackedData::~PackedData() {
//////////////////////////////////////////////////////////////////
bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
return false;
}
@@ -137,19 +137,13 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
if (magic != PACK_HEADER_MAGIC) {
// loading with offset feature not supported for self contained exe files
- if (p_offset != 0) {
- f->close();
- memdelete(f);
- ERR_FAIL_V_MSG(false, "Loading self-contained executable with offset not supported.");
- }
+ ERR_FAIL_COND_V_MSG(p_offset != 0, false, "Loading self-contained executable with offset not supported.");
//maybe at the end.... self contained exe
f->seek_end();
f->seek(f->get_position() - 4);
magic = f->get_32();
if (magic != PACK_HEADER_MAGIC) {
- f->close();
- memdelete(f);
return false;
}
f->seek(f->get_position() - 12);
@@ -159,8 +153,6 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
magic = f->get_32();
if (magic != PACK_HEADER_MAGIC) {
- f->close();
- memdelete(f);
return false;
}
}
@@ -170,16 +162,8 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
uint32_t ver_minor = f->get_32();
f->get_32(); // patch number, not used for validation.
- if (version != PACK_FORMAT_VERSION) {
- f->close();
- memdelete(f);
- ERR_FAIL_V_MSG(false, "Pack version unsupported: " + itos(version) + ".");
- }
- if (ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR)) {
- f->close();
- memdelete(f);
- ERR_FAIL_V_MSG(false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
- }
+ ERR_FAIL_COND_V_MSG(version != PACK_FORMAT_VERSION, false, "Pack version unsupported: " + itos(version) + ".");
+ ERR_FAIL_COND_V_MSG(ver_major > VERSION_MAJOR || (ver_major == VERSION_MAJOR && ver_minor > VERSION_MINOR), false, "Pack created with a newer version of the engine: " + itos(ver_major) + "." + itos(ver_minor) + ".");
uint32_t pack_flags = f->get_32();
uint64_t file_base = f->get_64();
@@ -194,12 +178,9 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
int file_count = f->get_32();
if (enc_directory) {
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
- if (!fae) {
- f->close();
- memdelete(f);
- ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory.");
- }
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
+ ERR_FAIL_COND_V_MSG(fae.is_null(), false, "Can't open encrypted pack directory.");
Vector<uint8_t> key;
key.resize(32);
@@ -208,12 +189,7 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
}
Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
- if (err) {
- f->close();
- memdelete(f);
- memdelete(fae);
- ERR_FAIL_V_MSG(false, "Can't open encrypted pack directory.");
- }
+ ERR_FAIL_COND_V_MSG(err, false, "Can't open encrypted pack directory.");
f = fae;
}
@@ -236,12 +212,10 @@ bool PackedSourcePCK::try_open_pack(const String &p_path, bool p_replace_files,
PackedData::get_singleton()->add_path(p_path, path, ofs + p_offset, size, md5, this, p_replace_files, (flags & PACK_FILE_ENCRYPTED));
}
- f->close();
- memdelete(f);
return true;
}
-FileAccess *PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
+Ref<FileAccess> PackedSourcePCK::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessPack(p_path, *p_file));
}
@@ -252,15 +226,17 @@ Error FileAccessPack::_open(const String &p_path, int p_mode_flags) {
return ERR_UNAVAILABLE;
}
-void FileAccessPack::close() {
- f->close();
-}
-
bool FileAccessPack::is_open() const {
- return f->is_open();
+ if (f.is_valid()) {
+ return f->is_open();
+ } else {
+ return false;
+ }
}
void FileAccessPack::seek(uint64_t p_position) {
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
+
if (p_position > pf.size) {
eof = true;
} else {
@@ -288,6 +264,7 @@ bool FileAccessPack::eof_reached() const {
}
uint8_t FileAccessPack::get_8() const {
+ ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
if (pos >= pf.size) {
eof = true;
return 0;
@@ -298,6 +275,7 @@ uint8_t FileAccessPack::get_8() const {
}
uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
+ ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
if (eof) {
@@ -321,6 +299,8 @@ uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
}
void FileAccessPack::set_big_endian(bool p_big_endian) {
+ ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
+
FileAccess::set_big_endian(p_big_endian);
f->set_big_endian(p_big_endian);
}
@@ -351,16 +331,15 @@ bool FileAccessPack::file_exists(const String &p_name) {
FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file) :
pf(p_file),
f(FileAccess::open(pf.pack, FileAccess::READ)) {
- ERR_FAIL_COND_MSG(!f, "Can't open pack-referenced file '" + String(pf.pack) + "'.");
+ ERR_FAIL_COND_MSG(f.is_null(), "Can't open pack-referenced file '" + String(pf.pack) + "'.");
f->seek(pf.offset);
off = pf.offset;
if (pf.encrypted) {
- FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
- if (!fae) {
- ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
- }
+ Ref<FileAccessEncrypted> fae;
+ fae.instantiate();
+ ERR_FAIL_COND_MSG(fae.is_null(), "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
Vector<uint8_t> key;
key.resize(32);
@@ -369,10 +348,7 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
}
Error err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_READ, false);
- if (err) {
- memdelete(fae);
- ERR_FAIL_MSG("Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
- }
+ ERR_FAIL_COND_MSG(err, "Can't open encrypted pack-referenced file '" + String(pf.pack) + "'.");
f = fae;
off = 0;
}
@@ -380,13 +356,6 @@ FileAccessPack::FileAccessPack(const String &p_path, const PackedData::PackedFil
eof = false;
}
-FileAccessPack::~FileAccessPack() {
- if (f) {
- f->close();
- memdelete(f);
- }
-}
-
//////////////////////////////////////////////////////////////////////////////////
// DIR ACCESS
//////////////////////////////////////////////////////////////////////////////////
@@ -507,7 +476,7 @@ Error DirAccessPack::change_dir(String p_dir) {
}
}
-String DirAccessPack::get_current_dir(bool p_include_drive) {
+String DirAccessPack::get_current_dir(bool p_include_drive) const {
PackedData::PackedDir *pd = current;
String p = current->name;
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index d4b32df2c7..44df2029bd 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -120,10 +120,10 @@ public:
static PackedData *get_singleton() { return singleton; }
Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
- _FORCE_INLINE_ FileAccess *try_open_path(const String &p_path);
+ _FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path);
_FORCE_INLINE_ bool has_path(const String &p_path);
- _FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path);
+ _FORCE_INLINE_ Ref<DirAccess> try_open_directory(const String &p_path);
_FORCE_INLINE_ bool has_directory(const String &p_path);
PackedData();
@@ -133,14 +133,14 @@ public:
class PackSource {
public:
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) = 0;
- virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
+ virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) = 0;
virtual ~PackSource() {}
};
class PackedSourcePCK : public PackSource {
public:
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
- virtual FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) override;
+ virtual Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) override;
};
class FileAccessPack : public FileAccess {
@@ -150,14 +150,13 @@ class FileAccessPack : public FileAccess {
mutable bool eof;
uint64_t off;
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
virtual Error _open(const String &p_path, int p_mode_flags);
virtual uint64_t _get_modified_time(const String &p_file) { return 0; }
virtual uint32_t _get_unix_permissions(const String &p_file) { return 0; }
virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { return FAILED; }
public:
- virtual void close();
virtual bool is_open() const;
virtual void seek(uint64_t p_position);
@@ -183,10 +182,9 @@ public:
virtual bool file_exists(const String &p_name);
FileAccessPack(const String &p_path, const PackedData::PackedFile &p_file);
- ~FileAccessPack();
};
-FileAccess *PackedData::try_open_path(const String &p_path) {
+Ref<FileAccess> PackedData::try_open_path(const String &p_path) {
PathMD5 pmd5(p_path.md5_buffer());
Map<PathMD5, PackedFile>::Element *E = files.find(pmd5);
if (!E) {
@@ -204,9 +202,8 @@ bool PackedData::has_path(const String &p_path) {
}
bool PackedData::has_directory(const String &p_path) {
- DirAccess *da = try_open_directory(p_path);
- if (da) {
- memdelete(da);
+ Ref<DirAccess> da = try_open_directory(p_path);
+ if (da.is_valid()) {
return true;
} else {
return false;
@@ -233,7 +230,7 @@ public:
virtual String get_drive(int p_drive);
virtual Error change_dir(String p_dir);
- virtual String get_current_dir(bool p_include_drive = true);
+ virtual String get_current_dir(bool p_include_drive = true) const;
virtual bool file_exists(String p_file);
virtual bool dir_exists(String p_dir);
@@ -252,14 +249,12 @@ public:
virtual String get_filesystem_type() const;
DirAccessPack();
- ~DirAccessPack() {}
};
-DirAccess *PackedData::try_open_directory(const String &p_path) {
- DirAccess *da = memnew(DirAccessPack());
+Ref<DirAccess> PackedData::try_open_directory(const String &p_path) {
+ Ref<DirAccess> da = memnew(DirAccessPack());
if (da->change_dir(p_path) != OK) {
- memdelete(da);
- da = nullptr;
+ da = Ref<DirAccess>();
}
return da;
}
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 6347862775..17f2335a8e 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -38,20 +38,26 @@ ZipArchive *ZipArchive::instance = nullptr;
extern "C" {
-static void *godot_open(void *data, const char *p_fname, int mode) {
+struct ZipData {
+ Ref<FileAccess> f;
+};
+
+static void *godot_open(voidpf opaque, const char *p_fname, int mode) {
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
return nullptr;
}
- FileAccess *f = FileAccess::open(p_fname, FileAccess::READ);
- ERR_FAIL_COND_V(!f, nullptr);
+ Ref<FileAccess> f = FileAccess::open(p_fname, FileAccess::READ);
+ ERR_FAIL_COND_V(f.is_null(), nullptr);
- return f;
+ ZipData *zd = memnew(ZipData);
+ zd->f = f;
+ return zd;
}
-static uLong godot_read(void *data, void *fdata, void *buf, uLong size) {
- FileAccess *f = (FileAccess *)fdata;
- f->get_buffer((uint8_t *)buf, size);
+static uLong godot_read(voidpf opaque, voidpf stream, void *buf, uLong size) {
+ ZipData *zd = (ZipData *)stream;
+ zd->f->get_buffer((uint8_t *)buf, size);
return size;
}
@@ -60,42 +66,38 @@ static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong si
}
static long godot_tell(voidpf opaque, voidpf stream) {
- FileAccess *f = (FileAccess *)stream;
- return f->get_position();
+ ZipData *zd = (ZipData *)stream;
+ return zd->f->get_position();
}
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
- FileAccess *f = (FileAccess *)stream;
+ ZipData *zd = (ZipData *)stream;
uint64_t pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
- pos = f->get_position() + offset;
+ pos = zd->f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
- pos = f->get_length() + offset;
+ pos = zd->f->get_length() + offset;
break;
default:
break;
}
- f->seek(pos);
+ zd->f->seek(pos);
return 0;
}
static int godot_close(voidpf opaque, voidpf stream) {
- FileAccess *f = (FileAccess *)stream;
- if (f) {
- f->close();
- memdelete(f);
- f = nullptr;
- }
+ ZipData *zd = (ZipData *)stream;
+ memdelete(zd);
return 0;
}
static int godot_testerror(voidpf opaque, voidpf stream) {
- FileAccess *f = (FileAccess *)stream;
- return f->get_error() != OK ? 1 : 0;
+ ZipData *zd = (ZipData *)stream;
+ return zd->f->get_error() != OK ? 1 : 0;
}
static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) {
@@ -208,7 +210,7 @@ bool ZipArchive::file_exists(String p_name) const {
return files.has(p_name);
}
-FileAccess *ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
+Ref<FileAccess> ZipArchive::get_file(const String &p_path, PackedData::PackedFile *p_file) {
return memnew(FileAccessZip(p_path, *p_file));
}
@@ -233,7 +235,7 @@ ZipArchive::~ZipArchive() {
}
Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
- close();
+ _close();
ERR_FAIL_COND_V(p_mode_flags & FileAccess::WRITE, FAILED);
ZipArchive *arch = ZipArchive::get_singleton();
@@ -247,7 +249,7 @@ Error FileAccessZip::_open(const String &p_path, int p_mode_flags) {
return OK;
}
-void FileAccessZip::close() {
+void FileAccessZip::_close() {
if (!zfile) {
return;
}
@@ -339,7 +341,7 @@ FileAccessZip::FileAccessZip(const String &p_path, const PackedData::PackedFile
}
FileAccessZip::~FileAccessZip() {
- close();
+ _close();
}
#endif // MINIZIP_ENABLED
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index a238c66437..2504aeedc4 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -68,7 +68,7 @@ public:
bool file_exists(String p_name) const;
virtual bool try_open_pack(const String &p_path, bool p_replace_files, uint64_t p_offset) override;
- FileAccess *get_file(const String &p_path, PackedData::PackedFile *p_file) override;
+ Ref<FileAccess> get_file(const String &p_path, PackedData::PackedFile *p_file) override;
static ZipArchive *get_singleton();
@@ -82,9 +82,10 @@ class FileAccessZip : public FileAccess {
mutable bool at_eof;
+ void _close();
+
public:
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(uint64_t p_position); ///< seek to a given position
diff --git a/core/io/image.cpp b/core/io/image.cpp
index fad9942017..661a9f7177 100644
--- a/core/io/image.cpp
+++ b/core/io/image.cpp
@@ -2442,6 +2442,39 @@ Ref<Image> Image::get_rect(const Rect2 &p_area) const {
return img;
}
+void Image::_get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const {
+ r_clipped_dest_rect.position = p_dest;
+ r_clipped_src_rect = p_src_rect;
+
+ if (r_clipped_src_rect.position.x < 0) {
+ r_clipped_dest_rect.position.x -= r_clipped_src_rect.position.x;
+ r_clipped_src_rect.size.x += r_clipped_src_rect.position.x;
+ r_clipped_src_rect.position.x = 0;
+ }
+ if (r_clipped_src_rect.position.y < 0) {
+ r_clipped_dest_rect.position.y -= r_clipped_src_rect.position.y;
+ r_clipped_src_rect.size.y += r_clipped_src_rect.position.y;
+ r_clipped_src_rect.position.y = 0;
+ }
+
+ if (r_clipped_dest_rect.position.x < 0) {
+ r_clipped_src_rect.position.x -= r_clipped_dest_rect.position.x;
+ r_clipped_src_rect.size.x += r_clipped_dest_rect.position.x;
+ r_clipped_dest_rect.position.x = 0;
+ }
+ if (r_clipped_dest_rect.position.y < 0) {
+ r_clipped_src_rect.position.y -= r_clipped_dest_rect.position.y;
+ r_clipped_src_rect.size.y += r_clipped_dest_rect.position.y;
+ r_clipped_dest_rect.position.y = 0;
+ }
+
+ r_clipped_src_rect.size.x = MAX(0, MIN(r_clipped_src_rect.size.x, MIN(p_src->width - r_clipped_src_rect.position.x, width - r_clipped_dest_rect.position.x)));
+ r_clipped_src_rect.size.y = MAX(0, MIN(r_clipped_src_rect.size.y, MIN(p_src->height - r_clipped_src_rect.position.y, height - r_clipped_dest_rect.position.y)));
+
+ r_clipped_dest_rect.size.x = r_clipped_src_rect.size.x;
+ r_clipped_dest_rect.size.y = r_clipped_src_rect.size.y;
+}
+
void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
int dsize = data.size();
@@ -2451,22 +2484,13 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
ERR_FAIL_COND(format != p_src->format);
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot blit_rect in compressed or custom image formats.");
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
-
- if (p_dest.x < 0) {
- clipped_src_rect.position.x = ABS(p_dest.x);
- }
- if (p_dest.y < 0) {
- clipped_src_rect.position.y = ABS(p_dest.y);
- }
-
- if (clipped_src_rect.has_no_area()) {
+ Rect2i src_rect;
+ Rect2i dest_rect;
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
return;
}
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
-
uint8_t *wp = data.ptrw();
uint8_t *dst_data_ptr = wp;
@@ -2477,8 +2501,8 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
for (int i = 0; i < dest_rect.size.y; i++) {
for (int j = 0; j < dest_rect.size.x; j++) {
- int src_x = clipped_src_rect.position.x + j;
- int src_y = clipped_src_rect.position.y + i;
+ int src_x = src_rect.position.x + j;
+ int src_y = src_rect.position.y + i;
int dst_x = dest_rect.position.x + j;
int dst_y = dest_rect.position.y + i;
@@ -2506,22 +2530,13 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
ERR_FAIL_COND(format != p_src->format);
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
-
- if (p_dest.x < 0) {
- clipped_src_rect.position.x = ABS(p_dest.x);
- }
- if (p_dest.y < 0) {
- clipped_src_rect.position.y = ABS(p_dest.y);
- }
-
- if (clipped_src_rect.has_no_area()) {
+ Rect2i src_rect;
+ Rect2i dest_rect;
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
return;
}
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
-
uint8_t *wp = data.ptrw();
uint8_t *dst_data_ptr = wp;
@@ -2534,8 +2549,8 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
for (int i = 0; i < dest_rect.size.y; i++) {
for (int j = 0; j < dest_rect.size.x; j++) {
- int src_x = clipped_src_rect.position.x + j;
- int src_y = clipped_src_rect.position.y + i;
+ int src_x = src_rect.position.x + j;
+ int src_y = src_rect.position.y + i;
if (msk->get_pixel(src_x, src_y).a != 0) {
int dst_x = dest_rect.position.x + j;
@@ -2560,28 +2575,19 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
ERR_FAIL_COND(srcdsize == 0);
ERR_FAIL_COND(format != p_src->format);
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
-
- if (p_dest.x < 0) {
- clipped_src_rect.position.x = ABS(p_dest.x);
- }
- if (p_dest.y < 0) {
- clipped_src_rect.position.y = ABS(p_dest.y);
- }
-
- if (clipped_src_rect.has_no_area()) {
+ Rect2i src_rect;
+ Rect2i dest_rect;
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
return;
}
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
-
Ref<Image> img = p_src;
for (int i = 0; i < dest_rect.size.y; i++) {
for (int j = 0; j < dest_rect.size.x; j++) {
- int src_x = clipped_src_rect.position.x + j;
- int src_y = clipped_src_rect.position.y + i;
+ int src_x = src_rect.position.x + j;
+ int src_y = src_rect.position.y + i;
int dst_x = dest_rect.position.x + j;
int dst_y = dest_rect.position.y + i;
@@ -2609,29 +2615,20 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
ERR_FAIL_COND(format != p_src->format);
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
-
- if (p_dest.x < 0) {
- clipped_src_rect.position.x = ABS(p_dest.x);
- }
- if (p_dest.y < 0) {
- clipped_src_rect.position.y = ABS(p_dest.y);
- }
-
- if (clipped_src_rect.has_no_area()) {
+ Rect2i src_rect;
+ Rect2i dest_rect;
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
return;
}
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
-
Ref<Image> img = p_src;
Ref<Image> msk = p_mask;
for (int i = 0; i < dest_rect.size.y; i++) {
for (int j = 0; j < dest_rect.size.x; j++) {
- int src_x = clipped_src_rect.position.x + j;
- int src_y = clipped_src_rect.position.y + i;
+ int src_x = src_rect.position.x + j;
+ int src_y = src_rect.position.y + i;
// If the mask's pixel is transparent then we skip it
//Color c = msk->get_pixel(src_x, src_y);
@@ -3276,7 +3273,7 @@ Ref<Image> Image::rgbe_to_srgb() {
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
- new_image->set_pixel(col, row, get_pixel(col, row).to_srgb());
+ new_image->set_pixel(col, row, get_pixel(col, row).linear_to_srgb());
}
}
diff --git a/core/io/image.h b/core/io/image.h
index 7e1e853244..1025554d51 100644
--- a/core/io/image.h
+++ b/core/io/image.h
@@ -175,6 +175,8 @@ private:
static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = nullptr, int *r_mm_height = nullptr);
bool _can_modify(Format p_format) const;
+ _FORCE_INLINE_ void _get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const;
+
_FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel);
_FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel);
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 5518ec8ceb..2ccc95f0de 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -44,17 +44,14 @@ bool ImageFormatLoader::recognize(const String &p_extension) const {
return false;
}
-Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom, bool p_force_linear, float p_scale) {
+Error ImageLoader::load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom, bool p_force_linear, float p_scale) {
ERR_FAIL_COND_V_MSG(p_image.is_null(), ERR_INVALID_PARAMETER, "It's not a reference to a valid Image object.");
- FileAccess *f = p_custom;
- if (!f) {
+ Ref<FileAccess> f = p_custom;
+ if (f.is_null()) {
Error err;
f = FileAccess::open(p_file, FileAccess::READ, &err);
- if (!f) {
- ERR_PRINT("Error opening file '" + p_file + "'.");
- return err;
- }
+ ERR_FAIL_COND_V_MSG(f.is_null(), err, "Error opening file '" + p_file + "'.");
}
String extension = p_file.get_extension();
@@ -69,18 +66,10 @@ Error ImageLoader::load_image(String p_file, Ref<Image> p_image, FileAccess *p_c
}
if (err != ERR_FILE_UNRECOGNIZED) {
- if (!p_custom) {
- memdelete(f);
- }
-
return err;
}
}
- if (!p_custom) {
- memdelete(f);
- }
-
return ERR_FILE_UNRECOGNIZED;
}
@@ -123,8 +112,8 @@ void ImageLoader::cleanup() {
/////////////////
RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
@@ -136,7 +125,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
bool unrecognized = header[0] != 'G' || header[1] != 'D' || header[2] != 'I' || header[3] != 'M';
if (unrecognized) {
- memdelete(f);
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
@@ -155,7 +143,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
}
if (idx == -1) {
- memdelete(f);
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
@@ -167,8 +154,6 @@ RES ResourceFormatLoaderImage::load(const String &p_path, const String &p_origin
Error err = ImageLoader::loader[idx]->load_image(image, f, false, 1.0);
- memdelete(f);
-
if (err != OK) {
if (r_error) {
*r_error = err;
diff --git a/core/io/image_loader.h b/core/io/image_loader.h
index 37d7620f96..9409617268 100644
--- a/core/io/image_loader.h
+++ b/core/io/image_loader.h
@@ -44,7 +44,7 @@ class ImageFormatLoader {
friend class ResourceFormatLoaderImage;
protected:
- virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) = 0;
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, bool p_force_linear, float p_scale) = 0;
virtual void get_recognized_extensions(List<String> *p_extensions) const = 0;
bool recognize(const String &p_extension) const;
@@ -58,7 +58,7 @@ class ImageLoader {
protected:
public:
- static Error load_image(String p_file, Ref<Image> p_image, FileAccess *p_custom = nullptr, bool p_force_linear = false, float p_scale = 1.0);
+ static Error load_image(String p_file, Ref<Image> p_image, Ref<FileAccess> p_custom = Ref<FileAccess>(), bool p_force_linear = false, float p_scale = 1.0);
static void get_recognized_extensions(List<String> *p_extensions);
static ImageFormatLoader *recognize(const String &p_extension);
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
index 2b6f230434..c19fc2820b 100644
--- a/core/io/logger.cpp
+++ b/core/io/logger.cpp
@@ -115,21 +115,14 @@ void Logger::logf_error(const char *p_format, ...) {
va_end(argp);
}
-void RotatedFileLogger::close_file() {
- if (file) {
- memdelete(file);
- file = nullptr;
- }
-}
-
void RotatedFileLogger::clear_old_backups() {
int max_backups = max_files - 1; // -1 for the current file
String basename = base_path.get_file().get_basename();
String extension = base_path.get_extension();
- DirAccessRef da = DirAccess::open(base_path.get_base_dir());
- if (!da) {
+ Ref<DirAccess> da = DirAccess::open(base_path.get_base_dir());
+ if (da.is_null()) {
return;
}
@@ -155,7 +148,7 @@ void RotatedFileLogger::clear_old_backups() {
}
void RotatedFileLogger::rotate_file() {
- close_file();
+ file.unref();
if (FileAccess::exists(base_path)) {
if (max_files > 1) {
@@ -165,20 +158,21 @@ void RotatedFileLogger::rotate_file() {
backup_name += "." + base_path.get_extension();
}
- DirAccessRef da = DirAccess::open(base_path.get_base_dir());
- if (da) {
+ Ref<DirAccess> da = DirAccess::open(base_path.get_base_dir());
+ if (da.is_valid()) {
da->copy(base_path, backup_name);
}
clear_old_backups();
}
} else {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_USERDATA);
- if (da) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_USERDATA);
+ if (da.is_valid()) {
da->make_dir_recursive(base_path.get_base_dir());
}
}
file = FileAccess::open(base_path, FileAccess::WRITE);
+ file->detach_from_objectdb(); // Note: This FileAccess instance will exist longer than ObjectDB, therefor can't be registered in ObjectDB.
}
RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) :
@@ -192,7 +186,7 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
return;
}
- if (file) {
+ if (file.is_valid()) {
const int static_buf_size = 512;
char static_buf[static_buf_size];
char *buf = static_buf;
@@ -218,10 +212,6 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
}
}
-RotatedFileLogger::~RotatedFileLogger() {
- close_file();
-}
-
void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
if (!should_log(p_err)) {
return;
diff --git a/core/io/logger.h b/core/io/logger.h
index 047ee3d0f1..e3ac00f11c 100644
--- a/core/io/logger.h
+++ b/core/io/logger.h
@@ -81,9 +81,8 @@ class RotatedFileLogger : public Logger {
String base_path;
int max_files;
- FileAccess *file = nullptr;
+ Ref<FileAccess> file;
- void close_file();
void clear_old_backups();
void rotate_file();
@@ -91,8 +90,6 @@ public:
RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0;
-
- virtual ~RotatedFileLogger();
};
class CompositeLogger : public Logger {
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index b3bf0cff2d..aa1b323db2 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -83,13 +83,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
}
enc_dir = p_encrypt_directory;
- if (file != nullptr) {
- memdelete(file);
- }
-
file = FileAccess::open(p_file, FileAccess::WRITE);
-
- ERR_FAIL_COND_V_MSG(!file, ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
+ ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
alignment = p_alignment;
@@ -112,8 +107,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
}
Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) {
- FileAccess *f = FileAccess::open(p_src, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
+ if (f.is_null()) {
return ERR_FILE_CANT_OPEN;
}
@@ -149,14 +144,11 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
files.push_back(pf);
- f->close();
- memdelete(f);
-
return OK;
}
Error PCKPacker::flush(bool p_verbose) {
- ERR_FAIL_COND_V_MSG(!file, ERR_INVALID_PARAMETER, "File must be opened before use.");
+ ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
int64_t file_base_ofs = file->get_position();
file->store_64(0); // files base
@@ -168,12 +160,12 @@ Error PCKPacker::flush(bool p_verbose) {
// write the index
file->store_32(files.size());
- FileAccessEncrypted *fae = nullptr;
- FileAccess *fhead = file;
+ Ref<FileAccessEncrypted> fae;
+ Ref<FileAccess> fhead = file;
if (enc_dir) {
- fae = memnew(FileAccessEncrypted);
- ERR_FAIL_COND_V(!fae, ERR_CANT_CREATE);
+ fae.instantiate();
+ ERR_FAIL_COND_V(fae.is_null(), ERR_CANT_CREATE);
Error err = fae->open_and_parse(file, key, FileAccessEncrypted::MODE_WRITE_AES256, false);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
@@ -202,9 +194,9 @@ Error PCKPacker::flush(bool p_verbose) {
fhead->store_32(flags);
}
- if (fae) {
- fae->release();
- memdelete(fae);
+ if (fae.is_valid()) {
+ fhead.unref();
+ fae.unref();
}
int header_padding = _get_pad(alignment, file->get_position());
@@ -222,14 +214,13 @@ Error PCKPacker::flush(bool p_verbose) {
int count = 0;
for (int i = 0; i < files.size(); i++) {
- FileAccess *src = FileAccess::open(files[i].src_path, FileAccess::READ);
+ Ref<FileAccess> src = FileAccess::open(files[i].src_path, FileAccess::READ);
uint64_t to_write = files[i].size;
- fae = nullptr;
- FileAccess *ftmp = file;
+ Ref<FileAccess> ftmp = file;
if (files[i].encrypted) {
- fae = memnew(FileAccessEncrypted);
- ERR_FAIL_COND_V(!fae, ERR_CANT_CREATE);
+ fae.instantiate();
+ ERR_FAIL_COND_V(fae.is_null(), ERR_CANT_CREATE);
Error err = fae->open_and_parse(file, key, FileAccessEncrypted::MODE_WRITE_AES256, false);
ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
@@ -242,9 +233,9 @@ Error PCKPacker::flush(bool p_verbose) {
to_write -= read;
}
- if (fae) {
- fae->release();
- memdelete(fae);
+ if (fae.is_valid()) {
+ ftmp.unref();
+ fae.unref();
}
int pad = _get_pad(alignment, file->get_position());
@@ -252,8 +243,6 @@ Error PCKPacker::flush(bool p_verbose) {
file->store_8(Math::rand() % 256);
}
- src->close();
- memdelete(src);
count += 1;
const int file_num = files.size();
if (p_verbose && (file_num > 0)) {
@@ -265,15 +254,8 @@ Error PCKPacker::flush(bool p_verbose) {
printf("\n");
}
- file->close();
+ file.unref();
memdelete_arr(buf);
return OK;
}
-
-PCKPacker::~PCKPacker() {
- if (file != nullptr) {
- memdelete(file);
- }
- file = nullptr;
-}
diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h
index 583171a70b..77ec293fb2 100644
--- a/core/io/pck_packer.h
+++ b/core/io/pck_packer.h
@@ -38,7 +38,7 @@ class FileAccess;
class PCKPacker : public RefCounted {
GDCLASS(PCKPacker, RefCounted);
- FileAccess *file = nullptr;
+ Ref<FileAccess> file;
int alignment = 0;
uint64_t ofs = 0;
@@ -63,7 +63,6 @@ public:
Error flush(bool p_verbose = false);
PCKPacker() {}
- ~PCKPacker();
};
#endif // PCK_PACKER_H
diff --git a/core/io/resource.cpp b/core/io/resource.cpp
index f90a6e9304..bf91438810 100644
--- a/core/io/resource.cpp
+++ b/core/io/resource.cpp
@@ -538,10 +538,10 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
Map<String, int> type_count;
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
if (p_file) {
f = FileAccess::open(String::utf8(p_file), FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!f, "Cannot create file at path '" + String::utf8(p_file) + "'.");
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file at path '" + String::utf8(p_file) + "'.");
}
const String *K = nullptr;
@@ -555,21 +555,17 @@ void ResourceCache::dump(const char *p_file, bool p_short) {
type_count[r->get_class()]++;
if (!p_short) {
- if (f) {
+ if (f.is_valid()) {
f->store_line(r->get_class() + ": " + r->get_path());
}
}
}
for (const KeyValue<String, int> &E : type_count) {
- if (f) {
+ if (f.is_valid()) {
f->store_line(E.key + " count: " + itos(E.value));
}
}
- if (f) {
- f->close();
- memdelete(f);
- }
lock.read_unlock();
#else
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index b65993e3dd..8d4dbc3f73 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -101,6 +101,50 @@ void ResourceLoaderBinary::_advance_padding(uint32_t p_len) {
}
}
+static Error read_reals(real_t *dst, Ref<FileAccess> &f, size_t count) {
+ if (f->real_is_double) {
+ if (sizeof(real_t) == 8) {
+ // Ideal case with double-precision
+ f->get_buffer((uint8_t *)dst, count * sizeof(double));
+#ifdef BIG_ENDIAN_ENABLED
+ {
+ uint64_t *dst = (uint64_t *)dst;
+ for (size_t i = 0; i < count; i++) {
+ dst[i] = BSWAP64(dst[i]);
+ }
+ }
+#endif
+ } else if (sizeof(real_t) == 4) {
+ // May be slower, but this is for compatibility. Eventually the data should be converted.
+ for (size_t i = 0; i < count; ++i) {
+ dst[i] = f->get_double();
+ }
+ } else {
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!");
+ }
+ } else {
+ if (sizeof(real_t) == 4) {
+ // Ideal case with float-precision
+ f->get_buffer((uint8_t *)dst, count * sizeof(float));
+#ifdef BIG_ENDIAN_ENABLED
+ {
+ uint32_t *dst = (uint32_t *)dst;
+ for (size_t i = 0; i < count; i++) {
+ dst[i] = BSWAP32(dst[i]);
+ }
+ }
+#endif
+ } else if (sizeof(real_t) == 8) {
+ for (size_t i = 0; i < count; ++i) {
+ dst[i] = f->get_float();
+ }
+ } else {
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!");
+ }
+ }
+ return OK;
+}
+
StringName ResourceLoaderBinary::_get_string() {
uint32_t id = f->get_32();
if (id & 0x80000000) {
@@ -528,21 +572,9 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
Vector<Vector2> array;
array.resize(len);
Vector2 *w = array.ptrw();
- if (sizeof(Vector2) == 8) {
- f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 2);
-#ifdef BIG_ENDIAN_ENABLED
- {
- uint32_t *ptr = (uint32_t *)w.ptr();
- for (int i = 0; i < len * 2; i++) {
- ptr[i] = BSWAP32(ptr[i]);
- }
- }
-
-#endif
-
- } else {
- ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector2 size is NOT 8!");
- }
+ static_assert(sizeof(Vector2) == 2 * sizeof(real_t));
+ const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 2);
+ ERR_FAIL_COND_V(err != OK, err);
r_v = array;
@@ -553,21 +585,9 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
Vector<Vector3> array;
array.resize(len);
Vector3 *w = array.ptrw();
- if (sizeof(Vector3) == 12) {
- f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 3);
-#ifdef BIG_ENDIAN_ENABLED
- {
- uint32_t *ptr = (uint32_t *)w.ptr();
- for (int i = 0; i < len * 3; i++) {
- ptr[i] = BSWAP32(ptr[i]);
- }
- }
-
-#endif
-
- } else {
- ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Vector3 size is NOT 12!");
- }
+ static_assert(sizeof(Vector3) == 3 * sizeof(real_t));
+ const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 3);
+ ERR_FAIL_COND_V(err != OK, err);
r_v = array;
@@ -578,22 +598,19 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
Vector<Color> array;
array.resize(len);
Color *w = array.ptrw();
- if (sizeof(Color) == 16) {
- f->get_buffer((uint8_t *)w, len * sizeof(real_t) * 4);
+ // Colors always use `float` even with double-precision support enabled
+ static_assert(sizeof(Color) == 4 * sizeof(float));
+ f->get_buffer((uint8_t *)w, len * sizeof(float) * 4);
#ifdef BIG_ENDIAN_ENABLED
- {
- uint32_t *ptr = (uint32_t *)w.ptr();
- for (int i = 0; i < len * 4; i++) {
- ptr[i] = BSWAP32(ptr[i]);
- }
+ {
+ uint32_t *ptr = (uint32_t *)w.ptr();
+ for (int i = 0; i < len * 4; i++) {
+ ptr[i] = BSWAP32(ptr[i]);
}
+ }
#endif
- } else {
- ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Color size is NOT 16!");
- }
-
r_v = array;
} break;
default: {
@@ -772,7 +789,7 @@ Error ResourceLoaderBinary::load() {
resource_cache.push_back(res);
if (main) {
- f->close();
+ f.unref();
resource = res;
resource->set_as_translation_remapped(translation_remapped);
error = OK;
@@ -787,13 +804,13 @@ void ResourceLoaderBinary::set_translation_remapped(bool p_remapped) {
translation_remapped = p_remapped;
}
-static void save_ustring(FileAccess *f, const String &p_string) {
+static void save_ustring(Ref<FileAccess> f, const String &p_string) {
CharString utf8 = p_string.utf8();
f->store_32(utf8.length() + 1);
f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
}
-static String get_ustring(FileAccess *f) {
+static String get_ustring(Ref<FileAccess> f) {
int len = f->get_32();
Vector<char> str_buf;
str_buf.resize(len);
@@ -817,7 +834,7 @@ String ResourceLoaderBinary::get_unicode_string() {
return s;
}
-void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) {
+void ResourceLoaderBinary::get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types) {
open(p_f, false, true);
if (error) {
return;
@@ -839,7 +856,7 @@ void ResourceLoaderBinary::get_dependencies(FileAccess *p_f, List<String> *p_dep
}
}
-void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_keep_uuid_paths) {
+void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p_keep_uuid_paths) {
error = OK;
f = p_f;
@@ -847,11 +864,11 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
f->get_buffer(header, 4);
if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
// Compressed.
- FileAccessCompressed *fac = memnew(FileAccessCompressed);
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
error = fac->open_after_magic(f);
if (error != OK) {
- memdelete(fac);
- f->close();
+ f.unref();
ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + ".");
}
f = fac;
@@ -859,7 +876,7 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
// Not normal.
error = ERR_FILE_UNRECOGNIZED;
- f->close();
+ f.unref();
ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + ".");
}
@@ -884,7 +901,7 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
print_bl("format: " + itos(ver_format));
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
- f->close();
+ f.unref();
ERR_FAIL_MSG(vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
}
@@ -961,12 +978,12 @@ void ResourceLoaderBinary::open(FileAccess *p_f, bool p_no_resources, bool p_kee
if (f->eof_reached()) {
error = ERR_FILE_CORRUPT;
- f->close();
+ f.unref();
ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + ".");
}
}
-String ResourceLoaderBinary::recognize(FileAccess *p_f) {
+String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) {
error = OK;
f = p_f;
@@ -974,11 +991,11 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
f->get_buffer(header, 4);
if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
// Compressed.
- FileAccessCompressed *fac = memnew(FileAccessCompressed);
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
error = fac->open_after_magic(f);
if (error != OK) {
- memdelete(fac);
- f->close();
+ f.unref();
return "";
}
f = fac;
@@ -986,7 +1003,7 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
// Not normal.
error = ERR_FILE_UNRECOGNIZED;
- f->close();
+ f.unref();
return "";
}
@@ -1000,7 +1017,7 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
uint32_t ver_format = f->get_32();
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
- f->close();
+ f.unref();
return "";
}
@@ -1009,19 +1026,13 @@ String ResourceLoaderBinary::recognize(FileAccess *p_f) {
return type;
}
-ResourceLoaderBinary::~ResourceLoaderBinary() {
- if (f) {
- memdelete(f);
- }
-}
-
RES ResourceFormatLoaderBinary::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
if (r_error) {
*r_error = ERR_FILE_CANT_OPEN;
}
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'.");
@@ -1079,8 +1090,8 @@ bool ResourceFormatLoaderBinary::handles_type(const String &p_type) const {
}
void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_path + "'.");
ResourceLoaderBinary loader;
loader.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -1089,10 +1100,10 @@ void ResourceFormatLoaderBinary::get_dependencies(const String &p_path, List<Str
}
Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_path + "'.");
- FileAccess *fw = nullptr;
+ Ref<FileAccess> fw;
String local_path = p_path.get_base_dir();
@@ -1100,36 +1111,26 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
f->get_buffer(header, 4);
if (header[0] == 'R' && header[1] == 'S' && header[2] == 'C' && header[3] == 'C') {
// Compressed.
- FileAccessCompressed *fac = memnew(FileAccessCompressed);
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
Error err = fac->open_after_magic(f);
- if (err != OK) {
- memdelete(fac);
- memdelete(f);
- ERR_FAIL_V_MSG(err, "Cannot open file '" + p_path + "'.");
- }
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
f = fac;
- FileAccessCompressed *facw = memnew(FileAccessCompressed);
+ Ref<FileAccessCompressed> facw;
+ facw.instantiate();
facw->configure("RSCC");
err = facw->_open(p_path + ".depren", FileAccess::WRITE);
- if (err) {
- memdelete(fac);
- memdelete(facw);
- ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'.");
- }
+ ERR_FAIL_COND_V_MSG(err, ERR_FILE_CORRUPT, "Cannot create file '" + p_path + ".depren'.");
fw = facw;
} else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') {
// Not normal.
- memdelete(f);
ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Unrecognized binary resource file '" + local_path + "'.");
} else {
fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
- if (!fw) {
- memdelete(f);
- }
- ERR_FAIL_COND_V_MSG(!fw, ERR_CANT_CREATE, "Cannot create file '" + p_path + ".depren'.");
+ ERR_FAIL_COND_V_MSG(fw.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + ".depren'.");
uint8_t magic[4] = { 'R', 'S', 'R', 'C' };
fw->store_buffer(magic, 4);
@@ -1152,10 +1153,8 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
uint32_t ver_format = f->get_32();
if (ver_format < FORMAT_VERSION_CAN_RENAME_DEPS) {
- memdelete(f);
- memdelete(fw);
{
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->remove(p_path + ".depren");
}
@@ -1184,8 +1183,6 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
}
if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) {
- memdelete(f);
- memdelete(fw);
ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED,
vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).",
local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH));
@@ -1294,22 +1291,19 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
fw->seek(md_ofs);
fw->store_64(importmd_ofs + size_diff);
- memdelete(f);
- memdelete(fw);
-
if (!all_ok) {
return ERR_CANT_CREATE;
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(p_path);
da->rename(p_path + ".depren", p_path);
return OK;
}
String ResourceFormatLoaderBinary::get_resource_type(const String &p_path) const {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
return ""; //could not read
}
@@ -1326,8 +1320,8 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat
return ResourceUID::INVALID_ID;
}
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
return ResourceUID::INVALID_ID; //could not read
}
@@ -1345,7 +1339,7 @@ ResourceUID::ID ResourceFormatLoaderBinary::get_resource_uid(const String &p_pat
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
-void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes) {
+void ResourceFormatSaverBinaryInstance::_pad_buffer(Ref<FileAccess> f, int p_bytes) {
int extra = 4 - (p_bytes % 4);
if (extra < 4) {
for (int i = 0; i < extra; i++) {
@@ -1354,7 +1348,7 @@ void ResourceFormatSaverBinaryInstance::_pad_buffer(FileAccess *f, int p_bytes)
}
}
-void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
+void ResourceFormatSaverBinaryInstance::write_variant(Ref<FileAccess> f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint) {
switch (p_property.get_type()) {
case Variant::NIL: {
f->store_32(VARIANT_NIL);
@@ -1813,14 +1807,14 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
}
}
-void ResourceFormatSaverBinaryInstance::save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len) {
+void ResourceFormatSaverBinaryInstance::save_unicode_string(Ref<FileAccess> p_f, const String &p_string, bool p_bit_on_len) {
CharString utf8 = p_string.utf8();
if (p_bit_on_len) {
- f->store_32((utf8.length() + 1) | 0x80000000);
+ p_f->store_32((utf8.length() + 1) | 0x80000000);
} else {
- f->store_32(utf8.length() + 1);
+ p_f->store_32(utf8.length() + 1);
}
- f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
+ p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
}
int ResourceFormatSaverBinaryInstance::get_string_index(const String &p_string) {
@@ -1836,15 +1830,13 @@ int ResourceFormatSaverBinaryInstance::get_string_index(const String &p_string)
Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
Error err;
+ Ref<FileAccess> f;
if (p_flags & ResourceSaver::FLAG_COMPRESS) {
- FileAccessCompressed *fac = memnew(FileAccessCompressed);
+ Ref<FileAccessCompressed> fac;
+ fac.instantiate();
fac->configure("RSCC");
f = fac;
err = fac->_open(p_path, FileAccess::WRITE);
- if (err) {
- memdelete(f);
- }
-
} else {
f = FileAccess::open(p_path, FileAccess::WRITE, &err);
}
@@ -1885,8 +1877,6 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
f->store_32(FORMAT_VERSION);
if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
- f->close();
- memdelete(f);
return ERR_CANT_CREATE;
}
@@ -2044,14 +2034,9 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
f->store_buffer((const uint8_t *)"RSRC", 4); //magic at end
if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
- f->close();
- memdelete(f);
return ERR_CANT_CREATE;
}
- f->close();
- memdelete(f);
-
return OK;
}
diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h
index 5403168a53..72a3c6751d 100644
--- a/core/io/resource_format_binary.h
+++ b/core/io/resource_format_binary.h
@@ -43,7 +43,7 @@ class ResourceLoaderBinary {
Ref<Resource> resource;
uint32_t ver_format = 0;
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
uint64_t importmd_ofs = 0;
@@ -98,12 +98,11 @@ public:
void set_translation_remapped(bool p_remapped);
void set_remaps(const Map<String, String> &p_remaps) { remaps = p_remaps; }
- void open(FileAccess *p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
- String recognize(FileAccess *p_f);
- void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
+ void open(Ref<FileAccess> p_f, bool p_no_resources = false, bool p_keep_uuid_paths = false);
+ String recognize(Ref<FileAccess> p_f);
+ void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
ResourceLoaderBinary() {}
- ~ResourceLoaderBinary();
};
class ResourceFormatLoaderBinary : public ResourceFormatLoader {
@@ -127,7 +126,6 @@ class ResourceFormatSaverBinaryInstance {
bool skip_editor;
bool big_endian;
bool takeover_paths;
- FileAccess *f = nullptr;
String magic;
Set<RES> resource_set;
@@ -155,9 +153,9 @@ class ResourceFormatSaverBinaryInstance {
List<Property> properties;
};
- static void _pad_buffer(FileAccess *f, int p_bytes);
+ static void _pad_buffer(Ref<FileAccess> f, int p_bytes);
void _find_resources(const Variant &p_variant, bool p_main = false);
- static void save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false);
+ static void save_unicode_string(Ref<FileAccess> f, const String &p_string, bool p_bit_on_len = false);
int get_string_index(const String &p_string);
public:
@@ -170,7 +168,7 @@ public:
RESERVED_FIELDS = 11
};
Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
- static void write_variant(FileAccess *f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
+ static void write_variant(Ref<FileAccess> f, const Variant &p_property, Map<RES, int> &resource_map, Map<RES, int> &external_resources, Map<StringName, int> &string_map, const PropertyInfo &p_hint = PropertyInfo());
};
class ResourceFormatSaverBinary : public ResourceFormatSaver {
diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp
index 9b6440e2a2..b4f73b3b25 100644
--- a/core/io/resource_importer.cpp
+++ b/core/io/resource_importer.cpp
@@ -40,9 +40,9 @@ bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceIm
Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid) const {
Error err;
- FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
- if (!f) {
+ if (f.is_null()) {
if (r_valid) {
*r_valid = false;
}
@@ -70,11 +70,9 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
if (err == ERR_FILE_EOF) {
- memdelete(f);
return OK;
} else if (err != OK) {
ERR_PRINT("ResourceFormatImporter::load - " + p_path + ".import:" + itos(lines) + " error: " + error_text);
- memdelete(f);
return err;
}
@@ -110,8 +108,6 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
}
}
- memdelete(f);
-
if (r_path_and_type.path.is_empty() || r_path_and_type.type.is_empty()) {
return ERR_FILE_CORRUPT;
}
@@ -270,9 +266,9 @@ String ResourceFormatImporter::get_internal_resource_path(const String &p_path)
void ResourceFormatImporter::get_internal_resource_path_list(const String &p_path, List<String> *r_paths) {
Error err;
- FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
- if (!f) {
+ if (f.is_null()) {
return;
}
@@ -292,11 +288,9 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
err = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, nullptr, true);
if (err == ERR_FILE_EOF) {
- memdelete(f);
return;
} else if (err != OK) {
ERR_PRINT("ResourceFormatImporter::get_internal_resource_path_list - " + p_path + ".import:" + itos(lines) + " error: " + error_text);
- memdelete(f);
return;
}
@@ -310,7 +304,6 @@ void ResourceFormatImporter::get_internal_resource_path_list(const String &p_pat
break;
}
}
- memdelete(f);
}
String ResourceFormatImporter::get_import_group_file(const String &p_path) const {
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 2419c76dd3..fe9693aa20 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -206,7 +206,7 @@ RES ResourceLoader::_load(const String &p_path, const String &p_original_path, c
vformat("Failed loading resource: %s. Make sure resources have been imported by opening the project in the editor at least once.", p_path));
#ifdef TOOLS_ENABLED
- FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+ Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
ERR_FAIL_COND_V_MSG(!file_check->file_exists(p_path), RES(), "Resource file not found: " + p_path + ".");
#endif
@@ -817,9 +817,8 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
if (new_path == p_path) { // Did not remap.
// Try file remap.
Error err;
- FileAccess *f = FileAccess::open(p_path + ".remap", FileAccess::READ, &err);
-
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(p_path + ".remap", FileAccess::READ, &err);
+ if (f.is_valid()) {
VariantParser::StreamFile stream;
stream.f = f;
@@ -849,8 +848,6 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem
break;
}
}
-
- memdelete(f);
}
}
diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp
index d0335bed3a..515b7c710e 100644
--- a/core/io/resource_uid.cpp
+++ b/core/io/resource_uid.cpp
@@ -135,12 +135,12 @@ void ResourceUID::remove_id(ID p_id) {
Error ResourceUID::save_to_cache() {
String cache_file = get_cache_file();
if (!FileAccess::exists(cache_file)) {
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
d->make_dir_recursive(String(cache_file).get_base_dir()); //ensure base dir exists
}
- FileAccessRef f = FileAccess::open(cache_file, FileAccess::WRITE);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(cache_file, FileAccess::WRITE);
+ if (f.is_null()) {
return ERR_CANT_OPEN;
}
@@ -163,8 +163,8 @@ Error ResourceUID::save_to_cache() {
}
Error ResourceUID::load_from_cache() {
- FileAccessRef f = FileAccess::open(get_cache_file(), FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(get_cache_file(), FileAccess::READ);
+ if (f.is_null()) {
return ERR_CANT_OPEN;
}
@@ -201,12 +201,12 @@ Error ResourceUID::update_cache() {
}
MutexLock l(mutex);
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
for (OrderedHashMap<ID, Cache>::Element E = unique_ids.front(); E; E = E.next()) {
if (!E.get().saved_to_cache) {
- if (f == nullptr) {
+ if (f.is_null()) {
f = FileAccess::open(get_cache_file(), FileAccess::READ_WRITE); //append
- if (!f) {
+ if (f.is_null()) {
return ERR_CANT_OPEN;
}
f->seek_end();
@@ -220,11 +220,9 @@ Error ResourceUID::update_cache() {
}
}
- if (f != nullptr) {
+ if (f.is_valid()) {
f->seek(0);
f->store_32(cache_entries); //update amount of entries
- f->close();
- memdelete(f);
}
changed = false;
diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp
index 30df46a6b4..ae1ad304d7 100644
--- a/core/io/translation_loader_po.cpp
+++ b/core/io/translation_loader_po.cpp
@@ -34,7 +34,7 @@
#include "core/string/translation.h"
#include "core/string/translation_po.h"
-RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
+RES TranslationLoaderPO::load_translation(Ref<FileAccess> f, Error *r_error) {
if (r_error) {
*r_error = ERR_FILE_CORRUPT;
}
@@ -49,9 +49,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
uint16_t version_maj = f->get_16();
uint16_t version_min = f->get_16();
- if (version_maj > 1) {
- ERR_FAIL_V_MSG(RES(), vformat("Unsupported MO file %s, version %d.%d.", path, version_maj, version_min));
- }
+ ERR_FAIL_COND_V_MSG(version_maj > 1, RES(), vformat("Unsupported MO file %s, version %d.%d.", path, version_maj, version_min));
uint32_t num_strings = f->get_32();
uint32_t id_table_offset = f->get_32();
@@ -134,7 +132,6 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
}
}
- memdelete(f);
} else {
// Try to load as text PO file.
f->seek(0);
@@ -173,7 +170,6 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
// If we reached last line and it's not a content line, break, otherwise let processing that last loop
if (is_eof && l.is_empty()) {
if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) {
- memdelete(f);
ERR_FAIL_V_MSG(RES(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line));
} else {
break;
@@ -181,10 +177,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
}
if (l.begins_with("msgctxt")) {
- if (status != STATUS_READING_STRING && status != STATUS_READING_PLURAL) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(status != STATUS_READING_STRING && status != STATUS_READING_PLURAL, RES(), "Unexpected 'msgctxt', was expecting 'msgid_plural' or 'msgstr' before 'msgctxt' while parsing: " + path + ":" + itos(line));
// In PO file, "msgctxt" appears before "msgid". If we encounter a "msgctxt", we add what we have read
// and set "entered_context" to true to prevent adding twice.
@@ -192,10 +185,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
if (status == STATUS_READING_STRING) {
translation->add_message(msg_id, msg_str, msg_context);
} else if (status == STATUS_READING_PLURAL) {
- if (plural_index != plural_forms - 1) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
@@ -207,10 +197,8 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
if (l.begins_with("msgid_plural")) {
if (plural_forms == 0) {
- memdelete(f);
ERR_FAIL_V_MSG(RES(), "PO file uses 'msgid_plural' but 'Plural-Forms' is invalid or missing in header: " + path + ":" + itos(line));
} else if (status != STATUS_READING_ID) {
- memdelete(f);
ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid_plural', was expecting 'msgid' before 'msgid_plural' while parsing: " + path + ":" + itos(line));
}
// We don't record the message in "msgid_plural" itself as tr_n(), TTRN(), RTRN() interfaces provide the plural string already.
@@ -221,20 +209,14 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
msgs_plural.resize(plural_forms);
status = STATUS_READING_PLURAL;
} else if (l.begins_with("msgid")) {
- if (status == STATUS_READING_ID) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(status == STATUS_READING_ID, RES(), "Unexpected 'msgid', was expecting 'msgstr' while parsing: " + path + ":" + itos(line));
if (!msg_id.is_empty()) {
if (!skip_this && !entered_context) {
if (status == STATUS_READING_STRING) {
translation->add_message(msg_id, msg_str, msg_context);
} else if (status == STATUS_READING_PLURAL) {
- if (plural_index != plural_forms - 1) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
@@ -263,18 +245,11 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
}
if (l.begins_with("msgstr[")) {
- if (status != STATUS_READING_PLURAL) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(status != STATUS_READING_PLURAL, RES(), "Unexpected 'msgstr[]', was expecting 'msgid_plural' before 'msgstr[]' while parsing: " + path + ":" + itos(line));
plural_index++; // Increment to add to the next slot in vector msgs_plural.
l = l.substr(9, l.length()).strip_edges();
} else if (l.begins_with("msgstr")) {
- if (status != STATUS_READING_ID) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
- }
-
+ ERR_FAIL_COND_V_MSG(status != STATUS_READING_ID, RES(), "Unexpected 'msgstr', was expecting 'msgid' before 'msgstr' while parsing: " + path + ":" + itos(line));
l = l.substr(6, l.length()).strip_edges();
status = STATUS_READING_STRING;
}
@@ -287,10 +262,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
continue; // Nothing to read or comment.
}
- if (!l.begins_with("\"") || status == STATUS_NONE) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, RES(), "Invalid line '" + l + "' while parsing: " + path + ":" + itos(line));
l = l.substr(1, l.length());
// Find final quote, ignoring escaped ones (\").
@@ -312,10 +284,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
escape_next = false;
}
- if (end_pos == -1) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(end_pos == -1, RES(), "Expected '\"' at end of message while parsing: " + path + ":" + itos(line));
l = l.substr(0, end_pos);
l = l.c_unescape();
@@ -327,18 +296,13 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
} else if (status == STATUS_READING_CONTEXT) {
msg_context += l;
} else if (status == STATUS_READING_PLURAL && plural_index >= 0) {
- if (plural_index >= plural_forms) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(plural_index >= plural_forms, RES(), "Unexpected plural form while parsing: " + path + ":" + itos(line));
msgs_plural.write[plural_index] = msgs_plural[plural_index] + l;
}
line++;
}
- memdelete(f);
-
// Add the last set of data from last iteration.
if (status == STATUS_READING_STRING) {
if (!msg_id.is_empty()) {
@@ -350,10 +314,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) {
}
} else if (status == STATUS_READING_PLURAL) {
if (!skip_this && !msg_id.is_empty()) {
- if (plural_index != plural_forms - 1) {
- memdelete(f);
- ERR_FAIL_V_MSG(RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
- }
+ ERR_FAIL_COND_V_MSG(plural_index != plural_forms - 1, RES(), "Number of 'msgstr[]' doesn't match with number of plural forms: " + path + ":" + itos(line));
translation->add_plural_message(msg_id, msgs_plural, msg_context);
}
}
@@ -388,8 +349,8 @@ RES TranslationLoaderPO::load(const String &p_path, const String &p_original_pat
*r_error = ERR_CANT_OPEN;
}
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, RES(), "Cannot open file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), RES(), "Cannot open file '" + p_path + "'.");
return load_translation(f, r_error);
}
diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h
index 1c58896a00..7da361cf24 100644
--- a/core/io/translation_loader_po.h
+++ b/core/io/translation_loader_po.h
@@ -37,7 +37,7 @@
class TranslationLoaderPO : public ResourceFormatLoader {
public:
- static RES load_translation(FileAccess *f, Error *r_error = nullptr);
+ static RES load_translation(Ref<FileAccess> f, Error *r_error = nullptr);
virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 360da46f96..7b43193f47 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -472,7 +472,7 @@ Error XMLParser::open_buffer(const Vector<uint8_t> &p_buffer) {
Error XMLParser::open(const String &p_path) {
Error err;
- FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
@@ -488,8 +488,6 @@ Error XMLParser::open(const String &p_path) {
data[length] = 0;
P = data;
- memdelete(file);
-
return OK;
}
diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp
index 2c4f8346ab..2cc844b628 100644
--- a/core/io/zip_io.cpp
+++ b/core/io/zip_io.cpp
@@ -30,73 +30,69 @@
#include "zip_io.h"
-void *zipio_open(void *data, const char *p_fname, int mode) {
- FileAccess *&f = *(FileAccess **)data;
+void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
+ ZipIOData *zd = (ZipIOData *)opaque;
String fname;
fname.parse_utf8(p_fname);
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
- f = FileAccess::open(fname, FileAccess::WRITE);
+ zd->f = FileAccess::open(fname, FileAccess::WRITE);
} else {
- f = FileAccess::open(fname, FileAccess::READ);
+ zd->f = FileAccess::open(fname, FileAccess::READ);
}
- if (!f) {
+ if (zd->f.is_null()) {
return nullptr;
}
- return data;
+ return opaque;
}
-uLong zipio_read(void *data, void *fdata, void *buf, uLong size) {
- FileAccess *f = *(FileAccess **)data;
- return f->get_buffer((uint8_t *)buf, size);
+uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size) {
+ ZipIOData *zd = (ZipIOData *)opaque;
+ return zd->f->get_buffer((uint8_t *)buf, size);
}
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size) {
- FileAccess *f = *(FileAccess **)opaque;
- f->store_buffer((uint8_t *)buf, size);
+ ZipIOData *zd = (ZipIOData *)opaque;
+ zd->f->store_buffer((uint8_t *)buf, size);
return size;
}
long zipio_tell(voidpf opaque, voidpf stream) {
- FileAccess *f = *(FileAccess **)opaque;
- return f->get_position();
+ ZipIOData *zd = (ZipIOData *)opaque;
+ return zd->f->get_position();
}
long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
- FileAccess *f = *(FileAccess **)opaque;
+ ZipIOData *zd = (ZipIOData *)opaque;
uint64_t pos = offset;
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
- pos = f->get_position() + offset;
+ pos = zd->f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
- pos = f->get_length() + offset;
+ pos = zd->f->get_length() + offset;
break;
default:
break;
}
- f->seek(pos);
+ zd->f->seek(pos);
return 0;
}
int zipio_close(voidpf opaque, voidpf stream) {
- FileAccess *&f = *(FileAccess **)opaque;
- if (f) {
- f->close();
- memdelete(f);
- f = nullptr;
- }
+ ZipIOData *zd = (ZipIOData *)opaque;
+ memdelete(zd);
return 0;
}
int zipio_testerror(voidpf opaque, voidpf stream) {
- FileAccess *f = *(FileAccess **)opaque;
- return (f && f->get_error() != OK) ? 1 : 0;
+ ZipIOData *zd = (ZipIOData *)opaque;
+ return (zd->f.is_valid() && zd->f->get_error() != OK) ? 1 : 0;
}
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size) {
@@ -109,9 +105,9 @@ void zipio_free(voidpf opaque, voidpf address) {
memfree(address);
}
-zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file) {
+zlib_filefunc_def zipio_create_io() {
zlib_filefunc_def io;
- io.opaque = p_file;
+ io.opaque = (void *)memnew(ZipIOData);
io.zopen_file = zipio_open;
io.zread_file = zipio_read;
io.zwrite_file = zipio_write;
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index 6a29703449..3bcd1f830d 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -39,8 +39,12 @@
#include "thirdparty/minizip/unzip.h"
#include "thirdparty/minizip/zip.h"
-void *zipio_open(void *data, const char *p_fname, int mode);
-uLong zipio_read(void *data, void *fdata, void *buf, uLong size);
+struct ZipIOData {
+ Ref<FileAccess> f;
+};
+
+void *zipio_open(voidpf opaque, const char *p_fname, int mode);
+uLong zipio_read(voidpf opaque, voidpf stream, void *buf, uLong size);
uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong size);
long zipio_tell(voidpf opaque, voidpf stream);
@@ -53,6 +57,6 @@ int zipio_testerror(voidpf opaque, voidpf stream);
voidpf zipio_alloc(voidpf opaque, uInt items, uInt size);
void zipio_free(voidpf opaque, voidpf address);
-zlib_filefunc_def zipio_create_io_from_file(FileAccess **p_file);
+zlib_filefunc_def zipio_create_io();
#endif // ZIP_IO_H
diff --git a/core/math/color.h b/core/math/color.h
index b90a0f33a2..91e0bf5532 100644
--- a/core/math/color.h
+++ b/core/math/color.h
@@ -169,14 +169,14 @@ struct _NO_DISCARD_ Color {
return res;
}
- _FORCE_INLINE_ Color to_linear() const {
+ _FORCE_INLINE_ Color srgb_to_linear() const {
return Color(
r < 0.04045f ? r * (1.0 / 12.92) : Math::pow((r + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f),
g < 0.04045f ? g * (1.0 / 12.92) : Math::pow((g + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f),
b < 0.04045f ? b * (1.0 / 12.92) : Math::pow((b + 0.055f) * (float)(1.0 / (1 + 0.055)), 2.4f),
a);
}
- _FORCE_INLINE_ Color to_srgb() const {
+ _FORCE_INLINE_ Color linear_to_srgb() const {
return Color(
r < 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * Math::pow(r, 1.0f / 2.4f) - 0.055f,
g < 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * Math::pow(g, 1.0f / 2.4f) - 0.055f,
diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp
index debc5cd00d..e146c4a4e3 100644
--- a/core/math/triangle_mesh.cpp
+++ b/core/math/triangle_mesh.cpp
@@ -231,14 +231,14 @@ Vector3 TriangleMesh::get_area_normal(const AABB &p_aabb) const {
}
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
level++;
+ stack[level] = b.left | TEST_AABB_BIT;
continue;
}
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
level++;
+ stack[level] = b.right | TEST_AABB_BIT;
continue;
}
case VISIT_DONE_BIT: {
@@ -331,14 +331,14 @@ bool TriangleMesh::intersect_segment(const Vector3 &p_begin, const Vector3 &p_en
}
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
level++;
+ stack[level] = b.left | TEST_AABB_BIT;
continue;
}
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
level++;
+ stack[level] = b.right | TEST_AABB_BIT;
continue;
}
case VISIT_DONE_BIT: {
@@ -431,14 +431,14 @@ bool TriangleMesh::intersect_ray(const Vector3 &p_begin, const Vector3 &p_dir, V
}
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
level++;
+ stack[level] = b.left | TEST_AABB_BIT;
continue;
}
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
level++;
+ stack[level] = b.right | TEST_AABB_BIT;
continue;
}
case VISIT_DONE_BIT: {
@@ -551,14 +551,14 @@ bool TriangleMesh::intersect_convex_shape(const Plane *p_planes, int p_plane_cou
}
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
level++;
+ stack[level] = b.left | TEST_AABB_BIT;
continue;
}
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
level++;
+ stack[level] = b.right | TEST_AABB_BIT;
continue;
}
case VISIT_DONE_BIT: {
@@ -644,14 +644,14 @@ bool TriangleMesh::inside_convex_shape(const Plane *p_planes, int p_plane_count,
}
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.left | TEST_AABB_BIT;
level++;
+ stack[level] = b.left | TEST_AABB_BIT;
continue;
}
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = b.right | TEST_AABB_BIT;
level++;
+ stack[level] = b.right | TEST_AABB_BIT;
continue;
}
case VISIT_DONE_BIT: {
diff --git a/core/object/object.cpp b/core/object/object.cpp
index c2cd42ff91..897b5d18de 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1848,6 +1848,13 @@ Object::Object() {
_construct_object(false);
}
+void Object::detach_from_objectdb() {
+ if (_instance_id != ObjectID()) {
+ ObjectDB::remove_instance(this);
+ _instance_id = ObjectID();
+ }
+}
+
Object::~Object() {
if (script_instance) {
memdelete(script_instance);
@@ -1887,8 +1894,10 @@ Object::~Object() {
c.signal.get_object()->_disconnect(c.signal.get_name(), c.callable, true);
}
- ObjectDB::remove_instance(this);
- _instance_id = ObjectID();
+ if (_instance_id != ObjectID()) {
+ ObjectDB::remove_instance(this);
+ _instance_id = ObjectID();
+ }
_predelete_ok = 2;
if (_instance_bindings != nullptr) {
diff --git a/core/object/object.h b/core/object/object.h
index eeef03dcb9..c3e3c68b59 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -633,6 +633,7 @@ public:
bool _is_gpl_reversed() const { return false; }
+ void detach_from_objectdb();
_FORCE_INLINE_ ObjectID get_instance_id() const { return _instance_id; }
template <class T>
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 2e5db145a4..846aeb16c5 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -80,7 +80,9 @@ void OS::print_error(const char *p_function, const char *p_file, int p_line, con
return;
}
- _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
+ if (_logger) {
+ _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type);
+ }
}
void OS::print(const char *p_format, ...) {
@@ -91,7 +93,9 @@ void OS::print(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
- _logger->logv(p_format, argp, false);
+ if (_logger) {
+ _logger->logv(p_format, argp, false);
+ }
va_end(argp);
}
@@ -104,7 +108,9 @@ void OS::printerr(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
- _logger->logv(p_format, argp, true);
+ if (_logger) {
+ _logger->logv(p_format, argp, true);
+ }
va_end(argp);
}
@@ -173,7 +179,7 @@ void OS::dump_memory_to_file(const char *p_file) {
//Memory::dump_static_mem_to_file(p_file);
}
-static FileAccess *_OSPRF = nullptr;
+static Ref<FileAccess> _OSPRF;
static void _OS_printres(Object *p_obj) {
Resource *res = Object::cast_to<Resource>(p_obj);
@@ -182,7 +188,7 @@ static void _OS_printres(Object *p_obj) {
}
String str = vformat("%s - %s - %s", res->to_string(), res->get_name(), res->get_path());
- if (_OSPRF) {
+ if (_OSPRF.is_valid()) {
_OSPRF->store_line(str);
} else {
print_line(str);
@@ -190,24 +196,19 @@ static void _OS_printres(Object *p_obj) {
}
void OS::print_all_resources(String p_to_file) {
- ERR_FAIL_COND(!p_to_file.is_empty() && _OSPRF);
+ ERR_FAIL_COND(!p_to_file.is_empty() && _OSPRF.is_valid());
if (!p_to_file.is_empty()) {
Error err;
_OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err);
if (err != OK) {
- _OSPRF = nullptr;
+ _OSPRF.unref();
ERR_FAIL_MSG("Can't print all resources to file: " + String(p_to_file) + ".");
}
}
ObjectDB::debug_objects(_OS_printres);
- if (!p_to_file.is_empty()) {
- if (_OSPRF) {
- memdelete(_OSPRF);
- }
- _OSPRF = nullptr;
- }
+ _OSPRF.unref();
}
void OS::print_resources_in_use(bool p_short) {
@@ -332,7 +333,7 @@ void OS::ensure_user_data_dir() {
return;
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = da->make_dir_recursive(dd);
ERR_FAIL_COND_MSG(err != OK, "Error attempting to create data dir: " + dd + ".");
}
@@ -550,6 +551,8 @@ OS::OS() {
}
OS::~OS() {
- memdelete(_logger);
+ if (_logger) {
+ memdelete(_logger);
+ }
singleton = nullptr;
}
diff --git a/core/os/time.cpp b/core/os/time.cpp
index e339805475..2c6b142140 100644
--- a/core/os/time.cpp
+++ b/core/os/time.cpp
@@ -95,16 +95,16 @@ VARIANT_ENUM_CAST(Time::Weekday);
day = day_number_copy + 1; \
}
-#define VALIDATE_YMDHMS \
- ERR_FAIL_COND_V_MSG(month == 0, 0, "Invalid month value of: " + itos(month) + ", months are 1-indexed and cannot be 0. See the Time.Month enum for valid values."); \
- ERR_FAIL_COND_V_MSG(month > 12, 0, "Invalid month value of: " + itos(month) + ". See the Time.Month enum for valid values."); \
- ERR_FAIL_COND_V_MSG(hour > 23, 0, "Invalid hour value of: " + itos(hour) + "."); \
- ERR_FAIL_COND_V_MSG(minute > 59, 0, "Invalid minute value of: " + itos(minute) + "."); \
- ERR_FAIL_COND_V_MSG(second > 59, 0, "Invalid second value of: " + itos(second) + " (leap seconds are not supported)."); \
- /* Do this check after month is tested as valid. */ \
- ERR_FAIL_COND_V_MSG(day == 0, 0, "Invalid day value of: " + itos(month) + ", days are 1-indexed and cannot be 0."); \
- uint8_t days_in_this_month = MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month - 1]; \
- ERR_FAIL_COND_V_MSG(day > days_in_this_month, 0, "Invalid day value of: " + itos(day) + " which is larger than the maximum for this month, " + itos(days_in_this_month) + ".");
+#define VALIDATE_YMDHMS(ret) \
+ ERR_FAIL_COND_V_MSG(month == 0, ret, "Invalid month value of: " + itos(month) + ", months are 1-indexed and cannot be 0. See the Time.Month enum for valid values."); \
+ ERR_FAIL_COND_V_MSG(month > 12, ret, "Invalid month value of: " + itos(month) + ". See the Time.Month enum for valid values."); \
+ ERR_FAIL_COND_V_MSG(hour > 23, ret, "Invalid hour value of: " + itos(hour) + "."); \
+ ERR_FAIL_COND_V_MSG(minute > 59, ret, "Invalid minute value of: " + itos(minute) + "."); \
+ ERR_FAIL_COND_V_MSG(second > 59, ret, "Invalid second value of: " + itos(second) + " (leap seconds are not supported)."); \
+ /* Do this check after month is tested as valid. */ \
+ ERR_FAIL_COND_V_MSG(day == 0, ret, "Invalid day value of: " + itos(month) + ", days are 1-indexed and cannot be 0."); \
+ uint8_t days_in_this_month = MONTH_DAYS_TABLE[IS_LEAP_YEAR(year)][month - 1]; \
+ ERR_FAIL_COND_V_MSG(day > days_in_this_month, ret, "Invalid day value of: " + itos(day) + " which is larger than the maximum for this month, " + itos(days_in_this_month) + ".");
#define YMD_TO_DAY_NUMBER \
/* The day number since Unix epoch (0-index). Days before 1970 are negative. */ \
@@ -124,50 +124,54 @@ VARIANT_ENUM_CAST(Time::Weekday);
} \
}
-#define PARSE_ISO8601_STRING \
- int64_t year = UNIX_EPOCH_YEAR_AD; \
- Month month = MONTH_JANUARY; \
- uint8_t day = 1; \
- uint8_t hour = 0; \
- uint8_t minute = 0; \
- uint8_t second = 0; \
- { \
- bool has_date = false, has_time = false; \
- String date, time; \
- if (p_datetime.find_char('T') > 0) { \
- has_date = has_time = true; \
- PackedStringArray array = p_datetime.split("T"); \
- date = array[0]; \
- time = array[1]; \
- } else if (p_datetime.find_char(' ') > 0) { \
- has_date = has_time = true; \
- PackedStringArray array = p_datetime.split(" "); \
- date = array[0]; \
- time = array[1]; \
- } else if (p_datetime.find_char('-', 1) > 0) { \
- has_date = true; \
- date = p_datetime; \
- } else if (p_datetime.find_char(':') > 0) { \
- has_time = true; \
- time = p_datetime; \
- } \
- /* Set the variables from the contents of the string. */ \
- if (has_date) { \
- PackedInt32Array array = date.split_ints("-", false); \
- year = array[0]; \
- month = (Month)array[1]; \
- day = array[2]; \
- /* Handle negative years. */ \
- if (p_datetime.find_char('-') == 0) { \
- year *= -1; \
- } \
- } \
- if (has_time) { \
- PackedInt32Array array = time.split_ints(":", false); \
- hour = array[0]; \
- minute = array[1]; \
- second = array[2]; \
- } \
+#define PARSE_ISO8601_STRING(ret) \
+ int64_t year = UNIX_EPOCH_YEAR_AD; \
+ Month month = MONTH_JANUARY; \
+ uint8_t day = 1; \
+ uint8_t hour = 0; \
+ uint8_t minute = 0; \
+ uint8_t second = 0; \
+ { \
+ bool has_date = false, has_time = false; \
+ String date, time; \
+ if (p_datetime.find_char('T') > 0) { \
+ has_date = has_time = true; \
+ PackedStringArray array = p_datetime.split("T"); \
+ ERR_FAIL_COND_V_MSG(array.size() < 2, ret, "Invalid ISO 8601 date/time string."); \
+ date = array[0]; \
+ time = array[1]; \
+ } else if (p_datetime.find_char(' ') > 0) { \
+ has_date = has_time = true; \
+ PackedStringArray array = p_datetime.split(" "); \
+ ERR_FAIL_COND_V_MSG(array.size() < 2, ret, "Invalid ISO 8601 date/time string."); \
+ date = array[0]; \
+ time = array[1]; \
+ } else if (p_datetime.find_char('-', 1) > 0) { \
+ has_date = true; \
+ date = p_datetime; \
+ } else if (p_datetime.find_char(':') > 0) { \
+ has_time = true; \
+ time = p_datetime; \
+ } \
+ /* Set the variables from the contents of the string. */ \
+ if (has_date) { \
+ PackedInt32Array array = date.split_ints("-", false); \
+ ERR_FAIL_COND_V_MSG(array.size() < 3, ret, "Invalid ISO 8601 date string."); \
+ year = array[0]; \
+ month = (Month)array[1]; \
+ day = array[2]; \
+ /* Handle negative years. */ \
+ if (p_datetime.find_char('-') == 0) { \
+ year *= -1; \
+ } \
+ } \
+ if (has_time) { \
+ PackedInt32Array array = time.split_ints(":", false); \
+ ERR_FAIL_COND_V_MSG(array.size() < 3, ret, "Invalid ISO 8601 time string."); \
+ hour = array[0]; \
+ minute = array[1]; \
+ second = array[2]; \
+ } \
}
#define EXTRACT_FROM_DICTIONARY \
@@ -253,7 +257,7 @@ String Time::get_time_string_from_unix_time(int64_t p_unix_time_val) const {
}
Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday) const {
- PARSE_ISO8601_STRING
+ PARSE_ISO8601_STRING(Dictionary())
Dictionary dict;
dict[YEAR_KEY] = year;
dict[MONTH_KEY] = (uint8_t)month;
@@ -273,6 +277,7 @@ Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday
String Time::get_datetime_string_from_dict(const Dictionary p_datetime, bool p_use_space) const {
ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), "", "Invalid datetime Dictionary: Dictionary is empty.");
EXTRACT_FROM_DICTIONARY
+ VALIDATE_YMDHMS("")
// vformat only supports up to 6 arguments, so we need to split this up into 2 parts.
String timestamp = vformat("%04d-%02d-%02d", year, (uint8_t)month, day);
if (p_use_space) {
@@ -286,14 +291,14 @@ String Time::get_datetime_string_from_dict(const Dictionary p_datetime, bool p_u
int64_t Time::get_unix_time_from_datetime_dict(const Dictionary p_datetime) const {
ERR_FAIL_COND_V_MSG(p_datetime.is_empty(), 0, "Invalid datetime Dictionary: Dictionary is empty");
EXTRACT_FROM_DICTIONARY
- VALIDATE_YMDHMS
+ VALIDATE_YMDHMS(0)
YMD_TO_DAY_NUMBER
return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second;
}
int64_t Time::get_unix_time_from_datetime_string(String p_datetime) const {
- PARSE_ISO8601_STRING
- VALIDATE_YMDHMS
+ PARSE_ISO8601_STRING(-1)
+ VALIDATE_YMDHMS(0)
YMD_TO_DAY_NUMBER
return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second;
}
diff --git a/core/string/print_string.h b/core/string/print_string.h
index f19573ad45..f7d0f25030 100644
--- a/core/string/print_string.h
+++ b/core/string/print_string.h
@@ -61,6 +61,14 @@ extern bool _print_error_enabled;
extern void __print_line(String p_string);
extern void print_error(String p_string);
extern void print_verbose(String p_string);
-#define print_line(...) __print_line(stringify_variants(__VA_ARGS__))
+
+inline void print_line(Variant v) {
+ __print_line(stringify_variants(v));
+}
+
+template <typename... Args>
+void print_line(Variant p_var, Args... p_args) {
+ __print_line(stringify_variants(p_var, p_args...));
+}
#endif // PRINT_STRING_H
diff --git a/core/string/translation_po.cpp b/core/string/translation_po.cpp
index 1c991ee12d..3f94e064ec 100644
--- a/core/string/translation_po.cpp
+++ b/core/string/translation_po.cpp
@@ -35,7 +35,7 @@
#ifdef DEBUG_TRANSLATION_PO
void TranslationPO::print_translation_map() {
Error err;
- FileAccess *file = FileAccess::open("translation_map_print_test.txt", FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open("translation_map_print_test.txt", FileAccess::WRITE, &err);
if (err != OK) {
ERR_PRINT("Failed to open translation_map_print_test.txt");
return;
@@ -62,7 +62,6 @@ void TranslationPO::print_translation_map() {
file->store_line("");
}
}
- file->close();
}
#endif
diff --git a/core/templates/cowdata.h b/core/templates/cowdata.h
index 326616b607..f1ac32928f 100644
--- a/core/templates/cowdata.h
+++ b/core/templates/cowdata.h
@@ -86,13 +86,6 @@ private:
return reinterpret_cast<uint32_t *>(_ptr) - 1;
}
- _FORCE_INLINE_ T *_get_data() const {
- if (!_ptr) {
- return nullptr;
- }
- return reinterpret_cast<T *>(_ptr);
- }
-
_FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
return next_power_of_2(p_elements * sizeof(T));
}
@@ -128,11 +121,11 @@ public:
_FORCE_INLINE_ T *ptrw() {
_copy_on_write();
- return (T *)_get_data();
+ return _ptr;
}
_FORCE_INLINE_ const T *ptr() const {
- return _get_data();
+ return _ptr;
}
_FORCE_INLINE_ int size() const {
@@ -150,19 +143,19 @@ public:
_FORCE_INLINE_ void set(int p_index, const T &p_elem) {
ERR_FAIL_INDEX(p_index, size());
_copy_on_write();
- _get_data()[p_index] = p_elem;
+ _ptr[p_index] = p_elem;
}
_FORCE_INLINE_ T &get_m(int p_index) {
CRASH_BAD_INDEX(p_index, size());
_copy_on_write();
- return _get_data()[p_index];
+ return _ptr[p_index];
}
_FORCE_INLINE_ const T &get(int p_index) const {
CRASH_BAD_INDEX(p_index, size());
- return _get_data()[p_index];
+ return _ptr[p_index];
}
Error resize(int p_size);
@@ -249,7 +242,7 @@ uint32_t CowData<T>::_copy_on_write() {
} else {
for (uint32_t i = 0; i < current_size; i++) {
- memnew_placement(&_data[i], T(_get_data()[i]));
+ memnew_placement(&_data[i], T(_ptr[i]));
}
}
@@ -308,10 +301,8 @@ Error CowData<T>::resize(int p_size) {
// construct the newly created elements
if (!__has_trivial_constructor(T)) {
- T *elems = _get_data();
-
for (int i = *_get_size(); i < p_size; i++) {
- memnew_placement(&elems[i], T);
+ memnew_placement(&_ptr[i], T);
}
}
@@ -321,7 +312,7 @@ Error CowData<T>::resize(int p_size) {
if (!__has_trivial_destructor(T)) {
// deinitialize no longer needed elements
for (uint32_t i = p_size; i < *_get_size(); i++) {
- T *t = &_get_data()[i];
+ T *t = &_ptr[i];
t->~T();
}
}
diff --git a/core/templates/safe_list.h b/core/templates/safe_list.h
index ae31525dd0..e850f3bd5e 100644
--- a/core/templates/safe_list.h
+++ b/core/templates/safe_list.h
@@ -203,7 +203,7 @@ public:
}
// Calling this will cause zero to many deallocations.
- void maybe_cleanup() {
+ bool maybe_cleanup() {
SafeListNode *cursor = nullptr;
SafeListNode *new_graveyard_head = nullptr;
do {
@@ -212,7 +212,7 @@ public:
if (active_iterator_count.load() != 0) {
// It's not safe to clean up with an active iterator, because that iterator
// could be pointing to an element that we want to delete.
- return;
+ return false;
}
// Any iterator created after this point will never point to a deleted node.
// Swap it out with the current graveyard head.
@@ -225,6 +225,17 @@ public:
tmp->deletion_fn(tmp->val);
memdelete_allocator<SafeListNode, A>(tmp);
}
+ return true;
+ }
+
+ ~SafeList() {
+#ifdef DEBUG_ENABLED
+ if (!maybe_cleanup()) {
+ ERR_PRINT("There are still iterators around when destructing a SafeList. Memory will be leaked. This is a bug.");
+ }
+#else
+ maybe_cleanup();
+#endif
}
};
@@ -353,11 +364,11 @@ public:
}
// Calling this will cause zero to many deallocations.
- void maybe_cleanup() {
+ bool maybe_cleanup() {
SafeListNode *cursor = graveyard_head;
if (active_iterator_count != 0) {
// It's not safe to clean up with an active iterator, because that iterator could be pointing to an element that we want to delete.
- return;
+ return false;
}
graveyard_head = nullptr;
// Our graveyard list is now unreachable by any active iterators, detached from the main graveyard head and ready for deletion.
@@ -367,6 +378,17 @@ public:
tmp->deletion_fn(tmp->val);
memdelete_allocator<SafeListNode, A>(tmp);
}
+ return true;
+ }
+
+ ~SafeList() {
+#ifdef DEBUG_ENABLED
+ if (!maybe_cleanup()) {
+ ERR_PRINT("There are still iterators around when destructing a SafeList. Memory will be leaked. This is a bug.");
+ }
+#else
+ maybe_cleanup();
+#endif
}
};
diff --git a/core/variant/variant.h b/core/variant/variant.h
index ca18249f36..475bf7158d 100644
--- a/core/variant/variant.h
+++ b/core/variant/variant.h
@@ -511,6 +511,7 @@ public:
Variant recursive_duplicate(bool p_deep, int recursion_count) const;
static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst);
static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst);
+ static void sub(const Variant &a, const Variant &b, Variant &r_dst);
/* Built-In Methods */
diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp
index c11925fa8c..f1daf1de13 100644
--- a/core/variant/variant_call.cpp
+++ b/core/variant/variant_call.cpp
@@ -1656,8 +1656,8 @@ static void _register_variant_builtin_methods() {
bind_method(Color, darkened, sarray("amount"), varray());
bind_method(Color, blend, sarray("over"), varray());
bind_method(Color, get_luminance, sarray(), varray());
- bind_method(Color, to_linear, sarray(), varray());
- bind_method(Color, to_srgb, sarray(), varray());
+ bind_method(Color, srgb_to_linear, sarray(), varray());
+ bind_method(Color, linear_to_srgb, sarray(), varray());
bind_method(Color, is_equal_approx, sarray("to"), varray());
diff --git a/core/variant/variant_parser.h b/core/variant/variant_parser.h
index b297babd6f..07d89d30cb 100644
--- a/core/variant/variant_parser.h
+++ b/core/variant/variant_parser.h
@@ -49,7 +49,7 @@ public:
};
struct StreamFile : public Stream {
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
virtual char32_t get_char() override;
virtual bool is_utf8() const override;
diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp
index e604ff9567..705aa27be6 100644
--- a/core/variant/variant_setget.cpp
+++ b/core/variant/variant_setget.cpp
@@ -1868,6 +1868,110 @@ Variant Variant::recursive_duplicate(bool p_deep, int recursion_count) const {
}
}
+void Variant::sub(const Variant &a, const Variant &b, Variant &r_dst) {
+ if (a.type != b.type) {
+ return;
+ }
+
+ switch (a.type) {
+ case NIL: {
+ r_dst = Variant();
+ }
+ return;
+ case INT: {
+ int64_t va = a._data._int;
+ int64_t vb = b._data._int;
+ r_dst = int(va - vb);
+ }
+ return;
+ case FLOAT: {
+ double ra = a._data._float;
+ double rb = b._data._float;
+ r_dst = ra - rb;
+ }
+ return;
+ case VECTOR2: {
+ r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) - *reinterpret_cast<const Vector2 *>(b._data._mem);
+ }
+ return;
+ case VECTOR2I: {
+ int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x;
+ int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x;
+ int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y;
+ int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y;
+ r_dst = Vector2i(int32_t(vax - vbx), int32_t(vay - vby));
+ }
+ return;
+ case RECT2: {
+ const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem);
+ const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem);
+ r_dst = Rect2(ra->position - rb->position, ra->size - rb->size);
+ }
+ return;
+ case RECT2I: {
+ const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem);
+ const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem);
+
+ int32_t vax = ra->position.x;
+ int32_t vay = ra->position.y;
+ int32_t vbx = ra->size.x;
+ int32_t vby = ra->size.y;
+ int32_t vcx = rb->position.x;
+ int32_t vcy = rb->position.y;
+ int32_t vdx = rb->size.x;
+ int32_t vdy = rb->size.y;
+
+ r_dst = Rect2i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vcx - vdx), int32_t(vcy - vdy));
+ }
+ return;
+ case VECTOR3: {
+ r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) - *reinterpret_cast<const Vector3 *>(b._data._mem);
+ }
+ return;
+ case VECTOR3I: {
+ int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x;
+ int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x;
+ int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y;
+ int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y;
+ int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z;
+ int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z;
+ r_dst = Vector3i(int32_t(vax - vbx), int32_t(vay - vby), int32_t(vaz - vbz));
+ }
+ return;
+ case AABB: {
+ const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem);
+ const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem);
+ r_dst = ::AABB(ra->position - rb->position, ra->size - rb->size);
+ }
+ return;
+ case QUATERNION: {
+ Quaternion empty_rot;
+ const Quaternion *qa = reinterpret_cast<const Quaternion *>(a._data._mem);
+ const Quaternion *qb = reinterpret_cast<const Quaternion *>(b._data._mem);
+ r_dst = (*qb).inverse() * *qa;
+ }
+ return;
+ case COLOR: {
+ const Color *ca = reinterpret_cast<const Color *>(a._data._mem);
+ const Color *cb = reinterpret_cast<const Color *>(b._data._mem);
+ float new_r = ca->r - cb->r;
+ float new_g = ca->g - cb->g;
+ float new_b = ca->b - cb->b;
+ float new_a = ca->a - cb->a;
+ new_r = new_r > 1.0 ? 1.0 : new_r;
+ new_g = new_g > 1.0 ? 1.0 : new_g;
+ new_b = new_b > 1.0 ? 1.0 : new_b;
+ new_a = new_a > 1.0 ? 1.0 : new_a;
+ r_dst = Color(new_r, new_g, new_b, new_a);
+ }
+ return;
+ default: {
+ r_dst = a;
+ }
+ return;
+ }
+}
+
void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) {
if (a.type != b.type) {
if (a.is_num() && b.is_num()) {
diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml
index a2b310ca82..da6513a08b 100644
--- a/doc/classes/@GlobalScope.xml
+++ b/doc/classes/@GlobalScope.xml
@@ -2546,13 +2546,13 @@
The property is a translatable string.
</constant>
<constant name="PROPERTY_USAGE_GROUP" value="128" enum="PropertyUsageFlags">
- Used to group properties together in the editor.
+ Used to group properties together in the editor. See [EditorInspector].
</constant>
<constant name="PROPERTY_USAGE_CATEGORY" value="256" enum="PropertyUsageFlags">
Used to categorize properties together in the editor.
</constant>
<constant name="PROPERTY_USAGE_SUBGROUP" value="512" enum="PropertyUsageFlags">
- Used to group properties together in the editor in a subgroup (under a group).
+ Used to group properties together in the editor in a subgroup (under a group). See [EditorInspector].
</constant>
<constant name="PROPERTY_USAGE_NO_INSTANCE_STATE" value="2048" enum="PropertyUsageFlags">
The property does not save its state in [PackedScene].
diff --git a/doc/classes/AnimationLibrary.xml b/doc/classes/AnimationLibrary.xml
new file mode 100644
index 0000000000..0a731edadd
--- /dev/null
+++ b/doc/classes/AnimationLibrary.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="AnimationLibrary" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="add_animation">
+ <return type="int" enum="Error" />
+ <argument index="0" name="name" type="StringName" />
+ <argument index="1" name="animation" type="Animation" />
+ <description>
+ </description>
+ </method>
+ <method name="get_animation" qualifiers="const">
+ <return type="Animation" />
+ <argument index="0" name="name" type="StringName" />
+ <description>
+ </description>
+ </method>
+ <method name="get_animation_list" qualifiers="const">
+ <return type="StringName[]" />
+ <description>
+ </description>
+ </method>
+ <method name="has_animation" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="name" type="StringName" />
+ <description>
+ </description>
+ </method>
+ <method name="remove_animation">
+ <return type="void" />
+ <argument index="0" name="name" type="StringName" />
+ <description>
+ </description>
+ </method>
+ <method name="rename_animation">
+ <return type="void" />
+ <argument index="0" name="name" type="StringName" />
+ <argument index="1" name="newname" type="StringName" />
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="_data" type="Dictionary" setter="_set_data" getter="_get_data" default="{}">
+ </member>
+ </members>
+ <signals>
+ <signal name="animation_added">
+ <argument index="0" name="name" type="Animation" />
+ <description>
+ </description>
+ </signal>
+ <signal name="animation_removed">
+ <argument index="0" name="name" type="Animation" />
+ <description>
+ </description>
+ </signal>
+ <signal name="animation_renamed">
+ <argument index="0" name="name" type="Animation" />
+ <argument index="1" name="to_name" type="Animation" />
+ <description>
+ </description>
+ </signal>
+ </signals>
+</class>
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index b1d04ce1f2..625cf3c47c 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -14,12 +14,11 @@
<link title="Third Person Shooter Demo">https://godotengine.org/asset-library/asset/678</link>
</tutorials>
<methods>
- <method name="add_animation">
+ <method name="add_animation_library">
<return type="int" enum="Error" />
<argument index="0" name="name" type="StringName" />
- <argument index="1" name="animation" type="Animation" />
+ <argument index="1" name="library" type="AnimationLibrary" />
<description>
- Adds [code]animation[/code] to the player accessible with the key [code]name[/code].
</description>
</method>
<method name="advance">
@@ -63,6 +62,12 @@
Returns the name of [code]animation[/code] or an empty string if not found.
</description>
</method>
+ <method name="find_animation_library" qualifiers="const">
+ <return type="StringName" />
+ <argument index="0" name="animation" type="Animation" />
+ <description>
+ </description>
+ </method>
<method name="get_animation" qualifiers="const">
<return type="Animation" />
<argument index="0" name="name" type="StringName" />
@@ -70,6 +75,17 @@
Returns the [Animation] with key [code]name[/code] or [code]null[/code] if not found.
</description>
</method>
+ <method name="get_animation_library" qualifiers="const">
+ <return type="AnimationLibrary" />
+ <argument index="0" name="name" type="StringName" />
+ <description>
+ </description>
+ </method>
+ <method name="get_animation_library_list" qualifiers="const">
+ <return type="StringName[]" />
+ <description>
+ </description>
+ </method>
<method name="get_animation_list" qualifiers="const">
<return type="PackedStringArray" />
<description>
@@ -103,6 +119,12 @@
Returns [code]true[/code] if the [AnimationPlayer] stores an [Animation] with key [code]name[/code].
</description>
</method>
+ <method name="has_animation_library" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="name" type="StringName" />
+ <description>
+ </description>
+ </method>
<method name="is_playing" qualifiers="const">
<return type="bool" />
<description>
@@ -138,19 +160,17 @@
[b]Note:[/b] If a looped animation is currently playing, the queued animation will never play unless the looped animation is stopped somehow.
</description>
</method>
- <method name="remove_animation">
+ <method name="remove_animation_library">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<description>
- Removes the animation with key [code]name[/code].
</description>
</method>
- <method name="rename_animation">
+ <method name="rename_animation_library">
<return type="void" />
<argument index="0" name="name" type="StringName" />
<argument index="1" name="newname" type="StringName" />
<description>
- Renames an existing animation with key [code]name[/code] to [code]newname[/code].
</description>
</method>
<method name="seek">
diff --git a/doc/classes/Camera3D.xml b/doc/classes/Camera3D.xml
index f7a0d41626..5008cd826e 100644
--- a/doc/classes/Camera3D.xml
+++ b/doc/classes/Camera3D.xml
@@ -192,7 +192,7 @@
The camera's projection mode. In [constant PROJECTION_PERSPECTIVE] mode, objects' Z distance from the camera's local space scales their perceived size.
</member>
<member name="size" type="float" setter="set_size" getter="get_size" default="1.0">
- The camera's size measured as 1/2 the width or height. Only applicable in orthogonal mode. Since [member keep_aspect] locks on axis, [code]size[/code] sets the other axis' size length.
+ The camera's size measured as 1/2 the width or height. Only applicable in orthogonal and frustum modes. Since [member keep_aspect] locks on axis, [code]size[/code] sets the other axis' size length.
</member>
<member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset" default="0.0">
The vertical (Y) offset of the camera viewport.
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 5205a1db3b..6cd2da520f 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -103,8 +103,9 @@
<argument index="1" name="to" type="Vector2" />
<argument index="2" name="color" type="Color" />
<argument index="3" name="width" type="float" default="1.0" />
+ <argument index="4" name="antialiased" type="bool" default="false" />
<description>
- Draws a line from a 2D point to another, with a given color and width. See also [method draw_multiline] and [method draw_polyline].
+ Draws a line from a 2D point to another, with a given color and width. It can be optionally antialiased. See also [method draw_multiline] and [method draw_polyline].
</description>
</method>
<method name="draw_mesh">
@@ -191,7 +192,7 @@
<argument index="2" name="width" type="float" default="1.0" />
<argument index="3" name="antialiased" type="bool" default="false" />
<description>
- Draws interconnected line segments with a uniform [code]color[/code] and [code]width[/code]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline] instead. See also [method draw_polygon].
+ Draws interconnected line segments with a uniform [code]color[/code] and [code]width[/code] and optional antialiasing. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline] instead. See also [method draw_polygon].
</description>
</method>
<method name="draw_polyline_colors">
@@ -201,7 +202,7 @@
<argument index="2" name="width" type="float" default="1.0" />
<argument index="3" name="antialiased" type="bool" default="false" />
<description>
- Draws interconnected line segments with a uniform [code]width[/code] and segment-by-segment coloring. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline_colors] instead. See also [method draw_polygon].
+ Draws interconnected line segments with a uniform [code]width[/code] and segment-by-segment coloring, and optional antialiasing. Colors assigned to line segments match by index between [code]points[/code] and [code]colors[/code]. When drawing large amounts of lines, this is faster than using individual [method draw_line] calls. To draw disconnected lines, use [method draw_multiline_colors] instead. See also [method draw_polygon].
</description>
</method>
<method name="draw_primitive">
@@ -480,9 +481,6 @@
<member name="show_behind_parent" type="bool" setter="set_draw_behind_parent" getter="is_draw_behind_parent_enabled" default="false">
If [code]true[/code], the object draws behind its parent.
</member>
- <member name="show_on_top" type="bool" setter="_set_on_top" getter="_is_on_top">
- If [code]true[/code], the object draws on top of its parent.
- </member>
<member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="CanvasItem.TextureFilter" default="0">
The texture filtering mode to use on this [CanvasItem].
</member>
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
index 28060f6579..63d493248f 100644
--- a/doc/classes/CharacterBody2D.xml
+++ b/doc/classes/CharacterBody2D.xml
@@ -183,7 +183,7 @@
If [code]true[/code], during a jump against the ceiling, the body will slide, if [code]false[/code] it will be stopped and will fall vertically.
</member>
<member name="up_direction" type="Vector2" setter="set_up_direction" getter="get_up_direction" default="Vector2(0, -1)">
- Direction vector used to determine what is a wall and what is a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. Defaults to [code]Vector2.UP[/code]. If set to [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.
+ Vector pointing upwards, used to determine what is a wall and what is a floor (or a ceiling) when calling [method move_and_slide]. Defaults to [code]Vector2.UP[/code]. As the vector will be normalized it can't be equal to [constant Vector2.ZERO], if you want all collisions to be reported as walls, consider using [constant MOTION_MODE_FLOATING] as [member motion_mode].
</member>
<member name="velocity" type="Vector2" setter="set_velocity" getter="get_velocity" default="Vector2(0, 0)">
Current velocity vector in pixels per second, used and modified during calls to [method move_and_slide].
diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml
index 4895e2cff7..6c5cd62fe1 100644
--- a/doc/classes/CharacterBody3D.xml
+++ b/doc/classes/CharacterBody3D.xml
@@ -168,7 +168,7 @@
If [code]true[/code], during a jump against the ceiling, the body will slide, if [code]false[/code] it will be stopped and will fall vertically.
</member>
<member name="up_direction" type="Vector3" setter="set_up_direction" getter="get_up_direction" default="Vector3(0, 1, 0)">
- Direction vector used to determine what is a wall and what is a floor (or a ceiling), rather than a wall, when calling [method move_and_slide]. Defaults to [code]Vector3.UP[/code]. If set to [code]Vector3(0, 0, 0)[/code], everything is considered a wall. This is useful for topdown games.
+ Vector pointing upwards, used to determine what is a wall and what is a floor (or a ceiling) when calling [method move_and_slide]. Defaults to [code]Vector3.UP[/code]. As the vector will be normalized it can't be equal to [constant Vector3.ZERO], if you want all collisions to be reported as walls, consider using [constant MOTION_MODE_FLOATING] as [member motion_mode].
</member>
<member name="velocity" type="Vector3" setter="set_velocity" getter="get_velocity" default="Vector3(0, 0, 0)">
Current velocity vector (typically meters per second), used and modified during calls to [method move_and_slide].
diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml
index 606f5ca51f..462ab81587 100644
--- a/doc/classes/CheckBox.xml
+++ b/doc/classes/CheckBox.xml
@@ -54,23 +54,25 @@
The check icon to display when the [CheckBox] is checked.
</theme_item>
<theme_item name="checked_disabled" data_type="icon" type="Texture2D">
- The check icon to display when the [CheckBox] is checked and disabled.
+ The check icon to display when the [CheckBox] is checked and is disabled.
</theme_item>
<theme_item name="radio_checked" data_type="icon" type="Texture2D">
- If the [CheckBox] is configured as a radio button, the icon to display when the [CheckBox] is checked.
+ The check icon to display when the [CheckBox] is configured as a radio button and is checked.
</theme_item>
<theme_item name="radio_checked_disabled" data_type="icon" type="Texture2D">
+ The check icon to display when the [CheckBox] is configured as a radio button, is disabled, and is unchecked.
</theme_item>
<theme_item name="radio_unchecked" data_type="icon" type="Texture2D">
- If the [CheckBox] is configured as a radio button, the icon to display when the [CheckBox] is unchecked.
+ The check icon to display when the [CheckBox] is configured as a radio button and is unchecked.
</theme_item>
<theme_item name="radio_unchecked_disabled" data_type="icon" type="Texture2D">
+ The check icon to display when the [CheckBox] is configured as a radio button, is disabled, and is unchecked.
</theme_item>
<theme_item name="unchecked" data_type="icon" type="Texture2D">
The check icon to display when the [CheckBox] is unchecked.
</theme_item>
<theme_item name="unchecked_disabled" data_type="icon" type="Texture2D">
- The check icon to display when the [CheckBox] is unchecked and disabled.
+ The check icon to display when the [CheckBox] is unchecked and is disabled.
</theme_item>
<theme_item name="disabled" data_type="style" type="StyleBox">
The [StyleBox] to display as a background when the [CheckBox] is disabled.
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index 99bf9f7853..5d025985cc 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -5,6 +5,7 @@
</brief_description>
<description>
CollisionObject2D is the base class for 2D physics objects. It can hold any number of 2D collision [Shape2D]s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject2D can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods.
+ [b]Note:[/b] Only collisions between objects within the same canvas ([Viewport] canvas or [CanvasLayer]) are supported. The behavior of collisions between objects in different canvases is undefined.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Color.xml b/doc/classes/Color.xml
index 5b48804d9d..7b8a57ed22 100644
--- a/doc/classes/Color.xml
+++ b/doc/classes/Color.xml
@@ -183,7 +183,7 @@
<description>
Returns the luminance of the color in the [code][0.0, 1.0][/code] range.
This is useful when determining light or dark color. Colors with a luminance smaller than 0.5 can be generally considered dark.
- [b]Note:[/b] [method get_luminance] relies on the colour being in the linear color space to return an accurate relative luminance value. If the color is in the sRGB color space, use [method to_linear] to convert it to the linear color space first.
+ [b]Note:[/b] [method get_luminance] relies on the colour being in the linear color space to return an accurate relative luminance value. If the color is in the sRGB color space, use [method srgb_to_linear] to convert it to the linear color space first.
</description>
</method>
<method name="get_named_color" qualifiers="static">
@@ -321,6 +321,18 @@
[/codeblocks]
</description>
</method>
+ <method name="linear_to_srgb" qualifiers="const">
+ <return type="Color" />
+ <description>
+ Returns the color converted to the [url=https://en.wikipedia.org/wiki/SRGB]sRGB[/url] color space. This assumes the original color is in the linear color space. See also [method srgb_to_linear] which performs the opposite operation.
+ </description>
+ </method>
+ <method name="srgb_to_linear" qualifiers="const">
+ <return type="Color" />
+ <description>
+ Returns the color converted to the linear color space. This assumes the original color is in the sRGB color space. See also [method linear_to_srgb] which performs the opposite operation.
+ </description>
+ </method>
<method name="to_abgr32" qualifiers="const">
<return type="int" />
<description>
@@ -405,12 +417,6 @@
[/codeblocks]
</description>
</method>
- <method name="to_linear" qualifiers="const">
- <return type="Color" />
- <description>
- Returns the color converted to the linear color space. This assumes the original color is in the sRGB color space. See also [method to_srgb] which performs the opposite operation.
- </description>
- </method>
<method name="to_rgba32" qualifiers="const">
<return type="int" />
<description>
@@ -443,12 +449,6 @@
[/codeblocks]
</description>
</method>
- <method name="to_srgb" qualifiers="const">
- <return type="Color" />
- <description>
- Returns the color converted to the [url=https://en.wikipedia.org/wiki/SRGB]sRGB[/url] color space. This assumes the original color is in the linear color space. See also [method to_linear] which performs the opposite operation.
- </description>
- </method>
</methods>
<members>
<member name="a" type="float" setter="" getter="" default="1.0">
diff --git a/doc/classes/EditorInspector.xml b/doc/classes/EditorInspector.xml
index cd249ed319..365e1f13a9 100644
--- a/doc/classes/EditorInspector.xml
+++ b/doc/classes/EditorInspector.xml
@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorInspector" inherits="ScrollContainer" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- A tab used to edit properties of the selected node.
+ A control used to edit properties of an object.
</brief_description>
<description>
- The editor inspector is by default located on the right-hand side of the editor. It's used to edit the properties of the selected node. For example, you can select a node such as the Sprite2D then edit its transform through the inspector tool. The editor inspector is an essential tool in the game development workflow.
- [b]Note:[/b] This class shouldn't be instantiated directly. Instead, access the singleton using [method EditorInterface.get_inspector].
+ This is the control that implements property editing in the editor's Settings dialogs, the Inspector dock, etc. To get the [EditorInspector] used in the editor's Inspector dock, use [method EditorInterface.get_inspector].
+ [EditorInspector] will show properties in the same order as the array returned by [method Object.get_property_list].
+ If a property's name is path-like (i.e. if it contains forward slashes), [EditorInspector] will create nested sections for "directories" along the path. For example, if a property is named [code]highlighting/gdscript/node_path_color[/code], it will be shown as "Node Path Color" inside the "GDScript" section nested inside the "Highlighting" section.
+ If a property has [constant @GlobalScope.PROPERTY_USAGE_GROUP] usage, it will group subsequent properties whose name starts with the property's hint string. The group ends when a property does not start with that hint string or when a new group starts. An empty group name effectively ends the current group. [EditorInspector] will create a top-level section for each group. For example, if a property with group usage is named [code]Collide With[/code] and its hint string is [code]collide_with_[/code], a subsequent [code]collide_with_area[/code] property will be shown as "Area" inside the "Collide With" section.
+ If a property has [constant @GlobalScope.PROPERTY_USAGE_SUBGROUP] usage, a subgroup will be created in the same way as a group, and a second-level section will be created for each subgroup.
+ [b]Note:[/b] Unlike sections created from path-like property names, [EditorInspector] won't capitalize the name for sections created from groups. So properties with group usage usually use capitalized names instead of snake_cased names.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/EditorSceneFormatImporter.xml b/doc/classes/EditorSceneFormatImporter.xml
index 63c1498f20..0290d7207d 100644
--- a/doc/classes/EditorSceneFormatImporter.xml
+++ b/doc/classes/EditorSceneFormatImporter.xml
@@ -29,16 +29,8 @@
<method name="_get_option_visibility" qualifiers="virtual const">
<return type="Variant" />
<argument index="0" name="path" type="String" />
- <argument index="1" name="option" type="String" />
- <description>
- </description>
- </method>
- <method name="_import_animation" qualifiers="virtual">
- <return type="Animation" />
- <argument index="0" name="path" type="String" />
- <argument index="1" name="flags" type="int" />
- <argument index="2" name="options" type="Dictionary" />
- <argument index="3" name="bake_fps" type="int" />
+ <argument index="1" name="for_animation" type="bool" />
+ <argument index="2" name="option" type="String" />
<description>
</description>
</method>
@@ -63,5 +55,7 @@
</constant>
<constant name="IMPORT_USE_NAMED_SKIN_BINDS" value="16">
</constant>
+ <constant name="IMPORT_DISCARD_MESHES_AND_MATERIALS" value="32">
+ </constant>
</constants>
</class>
diff --git a/doc/classes/EditorScenePostImportPlugin.xml b/doc/classes/EditorScenePostImportPlugin.xml
index de9d5e067a..0fdbd5db1e 100644
--- a/doc/classes/EditorScenePostImportPlugin.xml
+++ b/doc/classes/EditorScenePostImportPlugin.xml
@@ -34,7 +34,8 @@
<method name="_get_internal_option_visibility" qualifiers="virtual const">
<return type="Variant" />
<argument index="0" name="category" type="int" />
- <argument index="1" name="option" type="String" />
+ <argument index="1" name="for_animation" type="bool" />
+ <argument index="2" name="option" type="String" />
<description>
Return true or false whether a given option should be visible. Return null to ignore.
</description>
@@ -42,7 +43,8 @@
<method name="_get_option_visibility" qualifiers="virtual const">
<return type="Variant" />
<argument index="0" name="path" type="String" />
- <argument index="1" name="option" type="String" />
+ <argument index="1" name="for_animation" type="bool" />
+ <argument index="2" name="option" type="String" />
<description>
Return true or false whether a given option should be visible. Return null to ignore.
</description>
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index 140015babf..da5b907fab 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -26,7 +26,7 @@
<argument index="1" name="src_rect" type="Rect2" />
<argument index="2" name="dst" type="Vector2" />
<description>
- Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dest[/code].
+ Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dest[/code], clipped accordingly to both image bounds. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src_rect[/code] with not positive size is treated as empty.
</description>
</method>
<method name="blend_rect_mask">
@@ -36,7 +36,7 @@
<argument index="2" name="src_rect" type="Rect2" />
<argument index="3" name="dst" type="Vector2" />
<description>
- Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image using [code]mask[/code] image at coordinates [code]dst[/code]. Alpha channels are required for both [code]src[/code] and [code]mask[/code]. [code]dst[/code] pixels and [code]src[/code] pixels will blend if the corresponding mask pixel's alpha value is not 0. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats.
+ Alpha-blends [code]src_rect[/code] from [code]src[/code] image to this image using [code]mask[/code] image at coordinates [code]dst[/code], clipped accordingly to both image bounds. Alpha channels are required for both [code]src[/code] and [code]mask[/code]. [code]dst[/code] pixels and [code]src[/code] pixels will blend if the corresponding mask pixel's alpha value is not 0. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats. [code]src_rect[/code] with not positive size is treated as empty.
</description>
</method>
<method name="blit_rect">
@@ -45,7 +45,7 @@
<argument index="1" name="src_rect" type="Rect2" />
<argument index="2" name="dst" type="Vector2" />
<description>
- Copies [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dst[/code].
+ Copies [code]src_rect[/code] from [code]src[/code] image to this image at coordinates [code]dst[/code], clipped accordingly to both image bounds. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src_rect[/code] with not positive size is treated as empty.
</description>
</method>
<method name="blit_rect_mask">
@@ -55,7 +55,7 @@
<argument index="2" name="src_rect" type="Rect2" />
<argument index="3" name="dst" type="Vector2" />
<description>
- Blits [code]src_rect[/code] area from [code]src[/code] image to this image at the coordinates given by [code]dst[/code]. [code]src[/code] pixel is copied onto [code]dst[/code] if the corresponding [code]mask[/code] pixel's alpha value is not 0. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats.
+ Blits [code]src_rect[/code] area from [code]src[/code] image to this image at the coordinates given by [code]dst[/code], clipped accordingly to both image bounds. [code]src[/code] pixel is copied onto [code]dst[/code] if the corresponding [code]mask[/code] pixel's alpha value is not 0. This image and [code]src[/code] image [b]must[/b] have the same format. [code]src[/code] image and [code]mask[/code] image [b]must[/b] have the same size (width and height) but they can have different formats. [code]src_rect[/code] with not positive size is treated as empty.
</description>
</method>
<method name="bump_map_to_normal_map">
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index a59666356c..e007dfd9b5 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -110,11 +110,11 @@
Sets the current velocity of the agent.
</description>
</method>
- <method name="free" qualifiers="const">
+ <method name="free_rid" qualifiers="const">
<return type="void" />
- <argument index="0" name="object" type="RID" />
+ <argument index="0" name="rid" type="RID" />
<description>
- Destroy the RID
+ Destroys the given RID.
</description>
</method>
<method name="map_create" qualifiers="const">
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 7d11a30647..c987bc9042 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -110,11 +110,11 @@
Sets the current velocity of the agent.
</description>
</method>
- <method name="free" qualifiers="const">
+ <method name="free_rid" qualifiers="const">
<return type="void" />
- <argument index="0" name="object" type="RID" />
+ <argument index="0" name="rid" type="RID" />
<description>
- Destroy the RID
+ Destroys the given RID.
</description>
</method>
<method name="map_create" qualifiers="const">
diff --git a/doc/classes/OptionButton.xml b/doc/classes/OptionButton.xml
index 25e41116a2..b7145ab923 100644
--- a/doc/classes/OptionButton.xml
+++ b/doc/classes/OptionButton.xml
@@ -30,8 +30,9 @@
</method>
<method name="add_separator">
<return type="void" />
+ <argument index="0" name="text" type="String" default="&quot;&quot;" />
<description>
- Adds a separator to the list of items. Separators help to group items. Separator also takes up an index and is appended at the end.
+ Adds a separator to the list of items. Separators help to group items, and can optionally be given a [code]text[/code] header. A separator also gets an index assigned, and is appended at the end of the item list.
</description>
</method>
<method name="clear">
@@ -89,6 +90,12 @@
[b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash. If you wish to hide it or any of its children, use their [member Window.visible] property.
</description>
</method>
+ <method name="get_selectable_item" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="from_last" type="bool" default="false" />
+ <description>
+ </description>
+ </method>
<method name="get_selected_id" qualifiers="const">
<return type="int" />
<description>
@@ -101,6 +108,11 @@
Gets the metadata of the selected item. Metadata for items can be set using [method set_item_metadata].
</description>
</method>
+ <method name="has_selectable_items" qualifiers="const">
+ <return type="bool" />
+ <description>
+ </description>
+ </method>
<method name="is_item_disabled" qualifiers="const">
<return type="bool" />
<argument index="0" name="idx" type="int" />
@@ -108,6 +120,12 @@
Returns [code]true[/code] if the item at index [code]idx[/code] is disabled.
</description>
</method>
+ <method name="is_item_separator" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="idx" type="int" />
+ <description>
+ </description>
+ </method>
<method name="remove_item">
<return type="void" />
<argument index="0" name="idx" type="int" />
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 4bcfc3c726..f8f16acb06 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -568,8 +568,11 @@
<theme_item name="font_separator_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)">
[Color] used for labeled separators' text. See [method add_separator].
</theme_item>
+ <theme_item name="font_separator_outline_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
+ The tint of text outline of the labeled separator.
+ </theme_item>
<theme_item name="hseparation" data_type="constant" type="int" default="4">
- The horizontal space between the item's name and the shortcut text/submenu arrow.
+ The horizontal space between the item's elements.
</theme_item>
<theme_item name="item_end_padding" data_type="constant" type="int" default="2">
</theme_item>
@@ -578,12 +581,21 @@
<theme_item name="outline_size" data_type="constant" type="int" default="0">
The size of the item text outline.
</theme_item>
+ <theme_item name="separator_outline_size" data_type="constant" type="int" default="0">
+ The size of the labeled separator text outline.
+ </theme_item>
<theme_item name="vseparation" data_type="constant" type="int" default="4">
The vertical space between each menu item.
</theme_item>
<theme_item name="font" data_type="font" type="Font">
[Font] used for the menu items.
</theme_item>
+ <theme_item name="font_separator" data_type="font" type="Font">
+ [Font] used for the labeled separator.
+ </theme_item>
+ <theme_item name="font_separator_size" data_type="font_size" type="int">
+ Font size of the labeled separator.
+ </theme_item>
<theme_item name="font_size" data_type="font_size" type="int">
Font size of the menu items.
</theme_item>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index f1a15a08dd..5bb83c8ffd 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -183,6 +183,7 @@
<argument index="2" name="to" type="Vector2" />
<argument index="3" name="color" type="Color" />
<argument index="4" name="width" type="float" default="1.0" />
+ <argument index="5" name="antialiased" type="bool" default="false" />
<description>
</description>
</method>
@@ -3932,10 +3933,10 @@
[FogVolume] will have no shape, will cover the whole world and will not be culled.
</constant>
<constant name="VIEWPORT_SCALING_3D_MODE_BILINEAR" value="0" enum="ViewportScaling3DMode">
- Enables bilinear scaling on 3D viewports. The amount of scaling can be set using [member Viewport.scaling_3d_scale]. Values less then [code]1.0[/code] will result in undersampling while values greater than [code]1.0[/code] will result in supersampling. A value of [code]1.0[/code] disables scaling.
+ Use bilinear scaling for the viewport's 3D buffer. The amount of scaling can be set using [member Viewport.scaling_3d_scale]. Values less then [code]1.0[/code] will result in undersampling while values greater than [code]1.0[/code] will result in supersampling. A value of [code]1.0[/code] disables scaling.
</constant>
<constant name="VIEWPORT_SCALING_3D_MODE_FSR" value="1" enum="ViewportScaling3DMode">
- Enables FSR upscaling on 3D viewports. The amount of scaling can be set using [member Viewport.scaling_3d_scale]. Values less then [code]1.0[/code] will be result in the viewport being upscaled using FSR. Values greater than [code]1.0[/code] are not supported and bilinear supersampling will be used instead. A value of [code]1.0[/code] disables scaling.
+ Use AMD FidelityFX Super Resolution 1.0 upscaling for the viewport's 3D buffer. The amount of scaling can be set using [member Viewport.scaling_3d_scale]. Values less then [code]1.0[/code] will be result in the viewport being upscaled using FSR. Values greater than [code]1.0[/code] are not supported and bilinear downsampling will be used instead. A value of [code]1.0[/code] disables scaling.
</constant>
<constant name="VIEWPORT_SCALING_3D_MODE_MAX" value="2" enum="ViewportScaling3DMode">
</constant>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index a882a6c66f..02b67a4a5b 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -94,6 +94,13 @@
Returns the vertical offset of the line found at the provided index.
</description>
</method>
+ <method name="get_menu" qualifiers="const">
+ <return type="PopupMenu" />
+ <description>
+ Returns the [PopupMenu] of this [RichTextLabel]. By default, this menu is displayed when right-clicking on the [RichTextLabel].
+ [b]Warning:[/b] This is a required internal node, removing and freeing it may cause a crash. If you wish to hide it or any of its children, use their [member Window.visible] property.
+ </description>
+ </method>
<method name="get_paragraph_count" qualifiers="const">
<return type="int" />
<description>
@@ -163,6 +170,12 @@
Installs a custom effect. [code]effect[/code] should be a valid [RichTextEffect].
</description>
</method>
+ <method name="is_menu_visible" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns whether the menu is visible. Use this instead of [code]get_menu().visible[/code] to improve performance (so the creation of the menu is avoided).
+ </description>
+ </method>
<method name="newline">
<return type="void" />
<description>
@@ -376,6 +389,13 @@
Scrolls the window's top line to match first line of the [code]paragraph[/code].
</description>
</method>
+ <method name="select_all">
+ <return type="void" />
+ <description>
+ Select all the text.
+ If [member selection_enabled] is [code]false[/code], no selection will occur.
+ </description>
+ </method>
<method name="set_cell_border_color">
<return type="void" />
<argument index="0" name="color" type="Color" />
@@ -426,6 +446,9 @@
If [code]true[/code], the label uses BBCode formatting.
</member>
<member name="clip_contents" type="bool" setter="set_clip_contents" getter="is_clipping_contents" overrides="Control" default="true" />
+ <member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled" default="false">
+ If [code]true[/code], a right-click displays the context menu.
+ </member>
<member name="custom_effects" type="Array" setter="set_effects" getter="get_effects" default="[]">
The currently installed custom effects. This is an array of [RichTextEffect]s.
To add a custom effect, it's more convenient to use [method install_effect].
@@ -462,6 +485,9 @@
<member name="selection_enabled" type="bool" setter="set_selection_enabled" getter="is_selection_enabled" default="false">
If [code]true[/code], the label allows text selection.
</member>
+ <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true">
+ If [code]true[/code], shortcut keys for context menu items are enabled, even if the context menu is disabled.
+ </member>
<member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0">
Set BiDi algorithm override for the structured text.
</member>
diff --git a/doc/classes/Signal.xml b/doc/classes/Signal.xml
index c5855e30a4..049e7f8777 100644
--- a/doc/classes/Signal.xml
+++ b/doc/classes/Signal.xml
@@ -6,6 +6,8 @@
<description>
</description>
<tutorials>
+ <link title="Using Signals">$DOCS_URL/getting_started/step_by_step/signals.html</link>
+ <link title="GDScript Basics">$DOCS_URL/tutorials/scripting/gdscript/gdscript_basics.html#signals</link>
</tutorials>
<constructors>
<constructor name="Signal">
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index b4339bef11..9ef800d7e1 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -1249,9 +1249,9 @@
<method name="shaped_text_get_word_breaks" qualifiers="const">
<return type="PackedInt32Array" />
<argument index="0" name="shaped" type="RID" />
- <argument index="1" name="grapheme_flags" type="int" />
+ <argument index="1" name="grapheme_flags" type="int" default="264" />
<description>
- Breaks text into words and returns array of character ranges.
+ Breaks text into words and returns array of character ranges. Use [code]grapheme_flags[/code] to set what characters are used for breaking (see [enum GraphemeFlag]).
</description>
</method>
<method name="shaped_text_hit_test_grapheme" qualifiers="const">
diff --git a/doc/classes/Time.xml b/doc/classes/Time.xml
index dd83fa54ff..d3aac5fa00 100644
--- a/doc/classes/Time.xml
+++ b/doc/classes/Time.xml
@@ -50,6 +50,7 @@
<description>
Converts the given ISO 8601 date and time string (YYYY-MM-DDTHH:MM:SS) to a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]hour[/code], [code]minute[/code], and [code]second[/code].
If [code]weekday[/code] is false, then the [code]weekday[/code] entry is excluded (the calculation is relatively expensive).
+ [b]Note:[/b] Any decimal fraction in the time string will be ignored silently.
</description>
</method>
<method name="get_datetime_dict_from_system" qualifiers="const">
@@ -171,12 +172,14 @@
<description>
Converts the given ISO 8601 date and/or time string to a Unix timestamp. The string can contain a date only, a time only, or both.
[b]Note:[/b] Unix timestamps are often in UTC. This method does not do any timezone conversion, so the timestamp will be in the same timezone as the given datetime string.
+ [b]Note:[/b] Any decimal fraction in the time string will be ignored silently.
</description>
</method>
<method name="get_unix_time_from_system" qualifiers="const">
<return type="float" />
<description>
Returns the current Unix timestamp in seconds based on the system time in UTC. This method is implemented by the operating system and always returns the time in UTC.
+ [b]Note:[/b] Unlike other methods that use integer timestamps, this method returns the timestamp as a [float] for sub-second precision.
</description>
</method>
</methods>
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index b8c39bee49..5abec4b437 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -179,8 +179,9 @@
<return type="Rect2" />
<argument index="0" name="item" type="TreeItem" />
<argument index="1" name="column" type="int" default="-1" />
+ <argument index="2" name="button_index" type="int" default="-1" />
<description>
- Returns the rectangle area for the specified [TreeItem]. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
+ Returns the rectangle area for the specified [TreeItem]. If [code]column[/code] is specified, only get the position and size of that column, otherwise get the rectangle containing all columns. If a button index is specified, the rectangle of that button will be returned.
</description>
</method>
<method name="get_item_at_position" qualifiers="const">
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index b5916f8c17..6f4720491d 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -332,10 +332,10 @@
Represents the size of the [enum ShadowAtlasQuadrantSubdiv] enum.
</constant>
<constant name="SCALING_3D_MODE_BILINEAR" value="0" enum="Scaling3DMode">
- Enables bilinear scaling on 3D viewports. The amount of scaling can be set using [member scaling_3d_scale]. Values less then [code]1.0[/code] will result in undersampling while values greater than [code]1.0[/code] will result in supersampling. A value of [code]1.0[/code] disables scaling.
+ Use bilinear scaling for the viewport's 3D buffer. The amount of scaling can be set using [member scaling_3d_scale]. Values less then [code]1.0[/code] will result in undersampling while values greater than [code]1.0[/code] will result in supersampling. A value of [code]1.0[/code] disables scaling.
</constant>
<constant name="SCALING_3D_MODE_FSR" value="1" enum="Scaling3DMode">
- Enables FSR upscaling on 3D viewports. The amount of scaling can be set using [member scaling_3d_scale]. Values less then [code]1.0[/code] will be result in the viewport being upscaled using FSR. Values greater than [code]1.0[/code] are not supported and bilinear supersampling will be used instead. A value of [code]1.0[/code] disables scaling.
+ Use AMD FidelityFX Super Resolution 1.0 upscaling for the viewport's 3D buffer. The amount of scaling can be set using [member scaling_3d_scale]. Values less then [code]1.0[/code] will be result in the viewport being upscaled using FSR. Values greater than [code]1.0[/code] are not supported and bilinear downsampling will be used instead. A value of [code]1.0[/code] disables scaling.
</constant>
<constant name="SCALING_3D_MODE_MAX" value="2" enum="Scaling3DMode">
Represents the size of the [enum Scaling3DMode] enum.
diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml
index 9853f906bc..87a65db192 100644
--- a/doc/classes/Window.xml
+++ b/doc/classes/Window.xml
@@ -349,6 +349,15 @@
<argument index="0" name="files" type="PackedStringArray" />
<description>
Emitted when files are dragged from the OS file manager and dropped in the game window. The argument is a list of file paths.
+ Note that this method only works with non-embedded windows, i.e. the main window and [Window]-derived nodes when [member Viewport.gui_embed_subwindows] is disabled in the main viewport.
+ Example usage:
+ [codeblock]
+ func _ready():
+ get_viewport().files_dropped.connect(on_files_dropped)
+
+ func on_files_dropped(files):
+ print(files)
+ [/codeblock]
</description>
</signal>
<signal name="focus_entered">
diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py
index 365beb434b..eba4cee33a 100755
--- a/doc/tools/make_rst.py
+++ b/doc/tools/make_rst.py
@@ -58,7 +58,7 @@ strings_l10n = {}
def print_error(error, state): # type: (str, State) -> None
print("ERROR: {}".format(error))
- state.errored = True
+ state.num_errors += 1
class TypeName:
@@ -163,8 +163,7 @@ class ClassDef:
class State:
def __init__(self): # type: () -> None
- # Has any error been reported?
- self.errored = False
+ self.num_errors = 0
self.classes = OrderedDict() # type: OrderedDict[str, ClassDef]
self.current_class = "" # type: str
@@ -194,7 +193,7 @@ class State:
property_name = property.attrib["name"]
if property_name in class_def.properties:
- print_error("Duplicate property '{}', file: {}".format(property_name, class_name), self)
+ print_error('{}.xml: Duplicate property "{}".'.format(class_name, property_name), self)
continue
type_name = TypeName.from_element(property)
@@ -305,7 +304,7 @@ class State:
constant_def = ConstantDef(constant_name, value, constant.text)
if enum is None:
if constant_name in class_def.constants:
- print_error("Duplicate constant '{}', file: {}".format(constant_name, class_name), self)
+ print_error('{}.xml: Duplicate constant "{}".'.format(class_name, constant_name), self)
continue
class_def.constants[constant_name] = constant_def
@@ -328,7 +327,7 @@ class State:
signal_name = signal.attrib["name"]
if signal_name in class_def.signals:
- print_error("Duplicate signal '{}', file: {}".format(signal_name, class_name), self)
+ print_error('{}.xml: Duplicate signal "{}".'.format(class_name, signal_name), self)
continue
params = parse_arguments(signal)
@@ -351,8 +350,8 @@ class State:
theme_item_id = "{}_{}".format(theme_item_data_name, theme_item_name)
if theme_item_id in class_def.theme_items:
print_error(
- "Duplicate theme property '{}' of type '{}', file: {}".format(
- theme_item_name, theme_item_data_name, class_name
+ '{}.xml: Duplicate theme item "{}" of type "{}".'.format(
+ class_name, theme_item_name, theme_item_data_name
),
self,
)
@@ -430,7 +429,7 @@ def main(): # type: () -> None
if entry.msgid in BASE_STRINGS:
strings_l10n[entry.msgid] = entry.msgstr
else:
- print("No PO file at '{}' for language '{}'.".format(lang_file, args.lang))
+ print('No PO file at "{}" for language "{}".'.format(lang_file, args.lang))
print("Checking for errors in the XML class reference...")
@@ -453,7 +452,7 @@ def main(): # type: () -> None
elif os.path.isfile(path):
if not path.endswith(".xml"):
- print("Got non-.xml file '{}' in input, skipping.".format(path))
+ print('Got non-.xml file "{}" in input, skipping.'.format(path))
continue
file_list.append(path)
@@ -465,17 +464,17 @@ def main(): # type: () -> None
try:
tree = ET.parse(cur_file)
except ET.ParseError as e:
- print_error("Parse error reading file '{}': {}".format(cur_file, e), state)
+ print_error("{}.xml: Parse error while reading the file: {}".format(cur_file, e), state)
continue
doc = tree.getroot()
if "version" not in doc.attrib:
- print_error("Version missing from 'doc', file: {}".format(cur_file), state)
+ print_error('{}.xml: "version" attribute missing from "doc".'.format(cur_file), state)
continue
name = doc.attrib["name"]
if name in classes:
- print_error("Duplicate class '{}'".format(name), state)
+ print_error('{}.xml: Duplicate class "{}".'.format(cur_file, name), state)
continue
classes[name] = (doc, cur_file)
@@ -484,7 +483,7 @@ def main(): # type: () -> None
try:
state.parse_class(data[0], data[1])
except Exception as e:
- print_error("Exception while parsing class '{}': {}".format(name, e), state)
+ print_error("{}.xml: Exception while parsing class: {}".format(name, e), state)
state.sort_classes()
@@ -499,12 +498,17 @@ def main(): # type: () -> None
state.current_class = class_name
make_rst_class(class_def, state, args.dry_run, args.output)
- if not state.errored:
- print("No errors found.")
+ if state.num_errors == 0:
+ print("No errors found in the class reference XML.")
if not args.dry_run:
print("Wrote reStructuredText files for each class to: %s" % args.output)
else:
- print("Errors were found in the class reference XML. Please check the messages above.")
+ if state.num_errors >= 2:
+ print(
+ "%d errors were found in the class reference XML. Please check the messages above." % state.num_errors
+ )
+ else:
+ print("1 error was found in the class reference XML. Please check the messages above.")
exit(1)
@@ -856,7 +860,7 @@ def escape_rst(text, until_pos=-1): # type: (str) -> str
def format_codeblock(code_type, post_text, indent_level, state): # types: str, str, int, state
end_pos = post_text.find("[/" + code_type + "]")
if end_pos == -1:
- print_error("[" + code_type + "] without a closing tag, file: {}".format(state.current_class), state)
+ print_error("{}.xml: [" + code_type + "] without a closing tag.".format(state.current_class), state)
return None
code_text = post_text[len("[" + code_type + "]") : end_pos]
@@ -875,9 +879,9 @@ def format_codeblock(code_type, post_text, indent_level, state): # types: str,
if to_skip > indent_level:
print_error(
- "Four spaces should be used for indentation within ["
+ "{}.xml: Four spaces should be used for indentation within ["
+ code_type
- + "], file: {}".format(state.current_class),
+ + "].".format(state.current_class),
state,
)
@@ -987,7 +991,7 @@ def rstize_text(text, state): # type: (str, State) -> str
if param.find(".") != -1:
ss = param.split(".")
if len(ss) > 2:
- print_error("Bad reference: '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Bad reference: "{}".'.format(state.current_class, param), state)
class_param, method_param = ss
else:
@@ -1000,33 +1004,31 @@ def rstize_text(text, state): # type: (str, State) -> str
if cmd.startswith("constructor"):
if method_param not in class_def.constructors:
print_error(
- "Unresolved constructor '{}', file: {}".format(param, state.current_class), state
+ '{}.xml: Unresolved constructor "{}".'.format(state.current_class, param), state
)
ref_type = "_constructor"
if cmd.startswith("method"):
if method_param not in class_def.methods:
- print_error("Unresolved method '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved method "{}".'.format(state.current_class, param), state)
ref_type = "_method"
if cmd.startswith("operator"):
if method_param not in class_def.operators:
- print_error("Unresolved operator '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved operator "{}".'.format(state.current_class, param), state)
ref_type = "_operator"
elif cmd.startswith("member"):
if method_param not in class_def.properties:
- print_error("Unresolved member '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved member "{}".'.format(state.current_class, param), state)
ref_type = "_property"
elif cmd.startswith("theme_item"):
if method_param not in class_def.theme_items:
- print_error(
- "Unresolved theme item '{}', file: {}".format(param, state.current_class), state
- )
+ print_error('{}.xml: Unresolved theme item "{}".'.format(state.current_class, param), state)
ref_type = "_theme_{}".format(class_def.theme_items[method_param].data_name)
elif cmd.startswith("signal"):
if method_param not in class_def.signals:
- print_error("Unresolved signal '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved signal "{}".'.format(state.current_class, param), state)
ref_type = "_signal"
elif cmd.startswith("constant"):
@@ -1052,13 +1054,13 @@ def rstize_text(text, state): # type: (str, State) -> str
break
if not found:
- print_error("Unresolved constant '{}', file: {}".format(param, state.current_class), state)
+ print_error('{}.xml: Unresolved constant "{}".'.format(state.current_class, param), state)
ref_type = "_constant"
else:
print_error(
- "Unresolved type reference '{}' in method reference '{}', file: {}".format(
- class_param, param, state.current_class
+ '{}.xml: Unresolved type reference "{}" in method reference "{}".'.format(
+ state.current_class, class_param, param
),
state,
)
@@ -1078,7 +1080,7 @@ def rstize_text(text, state): # type: (str, State) -> str
endurl_pos = text.find("[/url]", endq_pos + 1)
if endurl_pos == -1:
print_error(
- "Tag depth mismatch for [url]: no closing [/url], file: {}".format(state.current_class), state
+ "{}.xml: Tag depth mismatch for [url]: no closing [/url]".format(state.current_class), state
)
break
link_title = text[endq_pos + 1 : endurl_pos]
@@ -1203,7 +1205,9 @@ def rstize_text(text, state): # type: (str, State) -> str
previous_pos = pos
if tag_depth > 0:
- print_error("Tag depth mismatch: too many/little open/close tags, file: {}".format(state.current_class), state)
+ print_error(
+ "{}.xml: Tag depth mismatch: too many (or too little) open/close tags.".format(state.current_class), state
+ )
return text
@@ -1247,7 +1251,7 @@ def make_type(klass, state): # type: (str, State) -> str
link_type = link_type[:-2]
if link_type in state.classes:
return ":ref:`{}<class_{}>`".format(klass, link_type)
- print_error("Unresolved type '{}', file: {}".format(klass, state.current_class), state)
+ print_error('{}.xml: Unresolved type "{}".'.format(state.current_class, klass), state)
return klass
@@ -1271,7 +1275,7 @@ def make_enum(t, state): # type: (str, State) -> str
# Don't fail for `Vector3.Axis`, as this enum is a special case which is expected not to be resolved.
if "{}.{}".format(c, e) != "Vector3.Axis":
- print_error("Unresolved enum '{}', file: {}".format(t, state.current_class), state)
+ print_error('{}.xml: Unresolved enum "{}".'.format(state.current_class, t), state)
return t
@@ -1429,7 +1433,7 @@ def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str
else:
clear_name = "xxx"
- print_error("Unsupported operator type '{}', please add the missing rule.".format(dirty_name), state)
+ print_error('Unsupported operator type "{}", please add the missing rule.'.format(dirty_name), state)
return clear_name
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 1ddaf3d6a7..441b049b50 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -38,9 +38,9 @@
#include "core/config/project_settings.h"
#include "servers/rendering/rendering_server_default.h"
-#include "storage/canvas_texture_storage.h"
#include "storage/config.h"
#include "storage/material_storage.h"
+#include "storage/texture_storage.h"
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
@@ -116,9 +116,11 @@ void RasterizerCanvasGLES3::_update_transform_to_mat4(const Transform3D &p_trans
}
void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) {
- storage->frame.current_rt = nullptr;
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
+ texture_storage->frame.current_rt = nullptr;
- storage->_set_current_render_target(p_to_render_target);
+ texture_storage->_set_current_render_target(p_to_render_target);
Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse();
@@ -130,7 +132,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
//update canvas state uniform buffer
StateBuffer state_buffer;
- Size2i ssize = storage->render_target_get_size(p_to_render_target);
+ Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
@@ -149,11 +151,11 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
state_buffer.canvas_modulate[2] = p_modulate.b;
state_buffer.canvas_modulate[3] = p_modulate.a;
- Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
+ Size2 render_target_size = texture_storage->render_target_get_size(p_to_render_target);
state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
- state_buffer.time = storage->frame.time;
+ state_buffer.time = texture_storage->frame.time;
state_buffer.use_pixel_snap = p_snap_2d_vertices_to_pixel;
state_buffer.directional_light_count = 0; //directional_light_count;
@@ -166,7 +168,7 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0];
state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1];
- Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target);
+ Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_to_render_target);
Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale);
state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width;
@@ -881,19 +883,21 @@ void RasterizerCanvasGLES3::update() {
}
void RasterizerCanvasGLES3::canvas_begin() {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
state.using_transparent_rt = false;
- if (storage->frame.current_rt) {
- storage->bind_framebuffer(storage->frame.current_rt->fbo);
- state.using_transparent_rt = storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT];
+ if (texture_storage->frame.current_rt) {
+ glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->frame.current_rt->fbo);
+ state.using_transparent_rt = texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT];
}
- if (storage->frame.current_rt && storage->frame.current_rt->clear_requested) {
- const Color &col = storage->frame.current_rt->clear_color;
+ if (texture_storage->frame.current_rt && texture_storage->frame.current_rt->clear_requested) {
+ const Color &col = texture_storage->frame.current_rt->clear_color;
glClearColor(col.r, col.g, col.b, col.a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- storage->frame.current_rt->clear_requested = false;
+ texture_storage->frame.current_rt->clear_requested = false;
}
reset_canvas();
@@ -934,7 +938,7 @@ void RasterizerCanvasGLES3::_bind_canvas_texture(RID p_texture, RS::CanvasItemTe
ct = t->canvas_texture;
} else {
- ct = GLES3::CanvasTextureStorage::get_singleton()->get_canvas_texture(p_texture);
+ ct = GLES3::TextureStorage::get_singleton()->get_canvas_texture(p_texture);
}
if (!ct) {
@@ -1041,6 +1045,8 @@ void RasterizerCanvasGLES3::_set_uniforms() {
}
void RasterizerCanvasGLES3::reset_canvas() {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
@@ -1049,7 +1055,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
// Default to Mix.
glBlendEquation(GL_FUNC_ADD);
- if (storage->frame.current_rt && storage->frame.current_rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) {
+ if (texture_storage->frame.current_rt && texture_storage->frame.current_rt->flags[GLES3::TextureStorage::RENDER_TARGET_TRANSPARENT]) {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
@@ -1255,7 +1261,7 @@ void RasterizerCanvasGLES3::_allocate_instance_data_buffer() {
}
void RasterizerCanvasGLES3::initialize() {
- GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
// quad buffer
@@ -1450,8 +1456,8 @@ void fragment() {
material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
- default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
- canvas_texture_storage->canvas_texture_initialize(default_canvas_texture);
+ default_canvas_texture = texture_storage->canvas_texture_allocate();
+ texture_storage->canvas_texture_initialize(default_canvas_texture);
state.using_light = nullptr;
state.using_transparent_rt = false;
@@ -1465,18 +1471,20 @@ RasterizerCanvasGLES3 *RasterizerCanvasGLES3::get_singleton() {
return singleton;
}
-RasterizerCanvasGLES3::RasterizerCanvasGLES3() {
+RasterizerCanvasGLES3::RasterizerCanvasGLES3(RasterizerStorageGLES3 *p_storage) {
singleton = this;
+ storage = p_storage;
+ initialize();
}
RasterizerCanvasGLES3::~RasterizerCanvasGLES3() {
- GLES3::CanvasTextureStorage *canvas_texture_storage = GLES3::CanvasTextureStorage::get_singleton();
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
state.canvas_shader.version_free(state.canvas_shader_default_version);
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
- canvas_texture_storage->canvas_texture_free(default_canvas_texture);
+ texture_storage->canvas_texture_free(default_canvas_texture);
singleton = nullptr;
}
diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h
index 70066c5e2a..a962796b2f 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.h
+++ b/drivers/gles3/rasterizer_canvas_gles3.h
@@ -37,7 +37,6 @@
#include "rasterizer_storage_gles3.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
-#include "storage/canvas_texture_storage.h"
#include "storage/material_storage.h"
#include "storage/texture_storage.h"
@@ -220,8 +219,6 @@ public:
typedef void Texture;
- RasterizerSceneGLES3 *scene_render = nullptr;
-
RasterizerStorageGLES3 *storage = nullptr;
void _set_uniforms();
@@ -280,7 +277,7 @@ public:
void finalize();
static RasterizerCanvasGLES3 *get_singleton();
- RasterizerCanvasGLES3();
+ RasterizerCanvasGLES3(RasterizerStorageGLES3 *storage);
~RasterizerCanvasGLES3();
};
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 61aefc1192..a8133c1317 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -34,6 +34,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
+#include "storage/texture_storage.h"
#define _EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
#define _EXT_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
@@ -87,6 +88,8 @@
#endif
void RasterizerGLES3::begin_frame(double frame_step) {
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+
frame++;
delta = frame_step;
@@ -95,14 +98,14 @@ void RasterizerGLES3::begin_frame(double frame_step) {
double time_roll_over = GLOBAL_GET("rendering/limits/time/time_rollover_secs");
time_total = Math::fmod(time_total, time_roll_over);
- storage.frame.time = time_total;
- storage.frame.count++;
- storage.frame.delta = frame_step;
+ texture_storage->frame.time = time_total;
+ texture_storage->frame.count++;
+ texture_storage->frame.delta = frame_step;
- storage.update_dirty_resources();
+ storage->update_dirty_resources();
- storage.info.render_final = storage.info.render;
- storage.info.render.reset();
+ storage->info.render_final = storage->info.render;
+ storage->info.render.reset();
//scene->iteration();
}
@@ -193,10 +196,14 @@ typedef void (*DEBUGPROCARB)(GLenum source,
typedef void (*DebugMessageCallbackARB)(DEBUGPROCARB callback, const void *userParam);
void RasterizerGLES3::initialize() {
- print_verbose("Using OpenGL video driver");
+ print_line("OpenGL Renderer: " + RS::get_singleton()->get_video_adapter_name());
- texture_storage.set_main_thread_id(Thread::get_caller_id());
+ texture_storage->set_main_thread_id(Thread::get_caller_id());
+ // make sure the OS knows to only access the renderer from the main thread
+ OS::get_singleton()->set_render_main_thread_mode(OS::RENDER_MAIN_THREAD_ONLY);
+}
+RasterizerGLES3::RasterizerGLES3() {
#ifdef GLAD_ENABLED
if (!gladLoadGL()) {
ERR_PRINT("Error initializing GLAD");
@@ -248,30 +255,38 @@ void RasterizerGLES3::initialize() {
#endif // GLES_OVER_GL
#endif // CAN_DEBUG
- print_line("OpenGL Renderer: " + RS::get_singleton()->get_video_adapter_name());
- storage.initialize();
- canvas.initialize();
- // scene.initialize();
-
- // make sure the OS knows to only access the renderer from the main thread
- OS::get_singleton()->set_render_main_thread_mode(OS::RENDER_MAIN_THREAD_ONLY);
+ // OpenGL needs to be initialized before initializing the Rasterizers
+ config = memnew(GLES3::Config);
+ texture_storage = memnew(GLES3::TextureStorage);
+ material_storage = memnew(GLES3::MaterialStorage);
+ mesh_storage = memnew(GLES3::MeshStorage);
+ particles_storage = memnew(GLES3::ParticlesStorage);
+ light_storage = memnew(GLES3::LightStorage);
+ storage = memnew(RasterizerStorageGLES3);
+ canvas = memnew(RasterizerCanvasGLES3(storage));
+ scene = memnew(RasterizerSceneGLES3);
}
-RasterizerGLES3::RasterizerGLES3() {
- canvas.storage = &storage;
- canvas.scene_render = &scene;
- //storage.canvas = &canvas;
- //scene.storage = &storage;
- //storage.scene = &scene;
+RasterizerGLES3::~RasterizerGLES3() {
+ memdelete(scene);
+ memdelete(canvas);
+ memdelete(storage);
+ memdelete(light_storage);
+ memdelete(particles_storage);
+ memdelete(mesh_storage);
+ memdelete(material_storage);
+ memdelete(texture_storage);
+ memdelete(config);
}
void RasterizerGLES3::prepare_for_blitting_render_targets() {
}
void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect) {
- ERR_FAIL_COND(storage.frame.current_rt);
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ ERR_FAIL_COND(texture_storage->frame.current_rt);
- GLES3::RenderTarget *rt = storage.render_target_owner.get_or_null(p_render_target);
+ GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
ERR_FAIL_COND(!rt);
// TODO: do we need a keep 3d linear option?
@@ -282,16 +297,17 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->fbo);
}
glReadBuffer(GL_COLOR_ATTACHMENT0);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
glBlitFramebuffer(0, 0, rt->width, rt->height, 0, p_screen_rect.size.y, p_screen_rect.size.x, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
// is this p_screen useless in a multi window environment?
void RasterizerGLES3::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
// do this once off for all blits
- storage.bind_framebuffer_system();
+ GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
- storage.frame.current_rt = nullptr;
+ texture_storage->frame.current_rt = nullptr;
for (int i = 0; i < p_amount; i++) {
const BlitToScreen &blit = p_render_targets[i];
@@ -322,12 +338,12 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
}
glClear(GL_COLOR_BUFFER_BIT);
- canvas.canvas_begin();
+ canvas->canvas_begin();
- RID texture = texture_storage.texture_create();
+ RID texture = texture_storage->texture_create();
//texture_storage.texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0);
- texture_storage._texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D);
- texture_storage.texture_set_data(texture, p_image);
+ texture_storage->_texture_allocate_internal(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RenderingDevice::TEXTURE_TYPE_2D);
+ texture_storage->texture_set_data(texture, p_image);
Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
Rect2 screenrect;
@@ -349,13 +365,13 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor();
}
- GLES3::Texture *t = texture_storage.get_texture(texture);
- glActiveTexture(GL_TEXTURE0 + config.max_texture_image_units - 1);
+ GLES3::Texture *t = texture_storage->get_texture(texture);
+ glActiveTexture(GL_TEXTURE0 + config->max_texture_image_units - 1);
glBindTexture(GL_TEXTURE_2D, t->tex_id);
glBindTexture(GL_TEXTURE_2D, 0);
- canvas.canvas_end();
+ canvas->canvas_end();
- texture_storage.texture_free(texture);
+ texture_storage->texture_free(texture);
end_frame(true);
}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 2279a502a2..139695165e 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -37,12 +37,11 @@
#include "rasterizer_scene_gles3.h"
#include "rasterizer_storage_gles3.h"
#include "servers/rendering/renderer_compositor.h"
-#include "storage/canvas_texture_storage.h"
#include "storage/config.h"
-#include "storage/decal_atlas_storage.h"
+#include "storage/light_storage.h"
#include "storage/material_storage.h"
#include "storage/mesh_storage.h"
-#include "storage/render_target_storage.h"
+#include "storage/particles_storage.h"
#include "storage/texture_storage.h"
class RasterizerGLES3 : public RendererCompositor {
@@ -53,27 +52,27 @@ private:
double time_total = 0.0;
protected:
- GLES3::Config config;
- GLES3::CanvasTextureStorage canvas_texture_storage;
- GLES3::TextureStorage texture_storage;
- GLES3::DecalAtlasStorage decal_atlas_storage;
- GLES3::MaterialStorage material_storage;
- GLES3::MeshStorage mesh_storage;
- RasterizerStorageGLES3 storage;
- RasterizerCanvasGLES3 canvas;
- RasterizerSceneGLES3 scene;
+ GLES3::Config *config = nullptr;
+ GLES3::TextureStorage *texture_storage = nullptr;
+ GLES3::MaterialStorage *material_storage = nullptr;
+ GLES3::MeshStorage *mesh_storage = nullptr;
+ GLES3::ParticlesStorage *particles_storage = nullptr;
+ GLES3::LightStorage *light_storage = nullptr;
+ RasterizerStorageGLES3 *storage = nullptr;
+ RasterizerCanvasGLES3 *canvas = nullptr;
+ RasterizerSceneGLES3 *scene = nullptr;
void _blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect);
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; }
- RendererCanvasRender *get_canvas() { return &canvas; }
- RendererSceneRender *get_scene() { return &scene; }
+ RendererLightStorage *get_light_storage() { return light_storage; }
+ RendererMaterialStorage *get_material_storage() { return material_storage; }
+ RendererMeshStorage *get_mesh_storage() { return mesh_storage; }
+ RendererParticlesStorage *get_particles_storage() { return particles_storage; }
+ RendererTextureStorage *get_texture_storage() { return texture_storage; }
+ RendererStorage *get_storage() { return storage; }
+ RendererCanvasRender *get_canvas() { return canvas; }
+ RendererSceneRender *get_scene() { return scene; }
void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true);
@@ -100,7 +99,7 @@ public:
double get_frame_delta_time() const { return delta; }
RasterizerGLES3();
- ~RasterizerGLES3() {}
+ ~RasterizerGLES3();
};
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 3517d985f0..124c2330c2 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -38,8 +38,6 @@
#include "rasterizer_scene_gles3.h"
#include "servers/rendering/shader_language.h"
-GLuint RasterizerStorageGLES3::system_fbo = 0;
-
void RasterizerStorageGLES3::bind_quad_array() const {
//glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
//glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
@@ -58,209 +56,9 @@ RID RasterizerStorageGLES3::sky_create() {
void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) {
}
-/* Light API */
-
-RID RasterizerStorageGLES3::directional_light_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::directional_light_initialize(RID p_rid) {
-}
-
-RID RasterizerStorageGLES3::omni_light_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::omni_light_initialize(RID p_rid) {
-}
-
-RID RasterizerStorageGLES3::spot_light_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::spot_light_initialize(RID p_rid) {
-}
-
-RID RasterizerStorageGLES3::reflection_probe_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::reflection_probe_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::light_set_color(RID p_light, const Color &p_color) {
-}
-
-void RasterizerStorageGLES3::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
-}
-
-void RasterizerStorageGLES3::light_set_shadow(RID p_light, bool p_enabled) {
-}
-
-void RasterizerStorageGLES3::light_set_projector(RID p_light, RID p_texture) {
-}
-
-void RasterizerStorageGLES3::light_set_negative(RID p_light, bool p_enable) {
-}
-
-void RasterizerStorageGLES3::light_set_cull_mask(RID p_light, uint32_t p_mask) {
-}
-
-void RasterizerStorageGLES3::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
-}
-
-void RasterizerStorageGLES3::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
-}
-
-void RasterizerStorageGLES3::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
-}
-
-void RasterizerStorageGLES3::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
-}
-
-void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
-}
-
-void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
-}
-
-void RasterizerStorageGLES3::light_directional_set_blend_splits(RID p_light, bool p_enable) {
-}
-
-bool RasterizerStorageGLES3::light_directional_get_blend_splits(RID p_light) const {
- return false;
-}
-
-void RasterizerStorageGLES3::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
-}
-
-RS::LightDirectionalSkyMode RasterizerStorageGLES3::light_directional_get_sky_mode(RID p_light) const {
- return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
-}
-
-RS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) {
- return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
-}
-
-RS::LightOmniShadowMode RasterizerStorageGLES3::light_omni_get_shadow_mode(RID p_light) {
- return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
-}
-
-bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const {
- return false;
-}
-
-bool RasterizerStorageGLES3::light_has_projector(RID p_light) const {
- return false;
-}
-
-RS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
- return RS::LIGHT_OMNI;
-}
-
-AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
- return AABB();
-}
-
-float RasterizerStorageGLES3::light_get_param(RID p_light, RS::LightParam p_param) {
- return 0.0;
-}
-
-Color RasterizerStorageGLES3::light_get_color(RID p_light) {
- return Color();
-}
-
-RS::LightBakeMode RasterizerStorageGLES3::light_get_bake_mode(RID p_light) {
- return RS::LIGHT_BAKE_DISABLED;
-}
-
-uint32_t RasterizerStorageGLES3::light_get_max_sdfgi_cascade(RID p_light) {
- return 0;
-}
-
-uint64_t RasterizerStorageGLES3::light_get_version(RID p_light) const {
- return 0;
-}
-
-/* PROBE API */
-
-void RasterizerStorageGLES3::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
-}
-
-void RasterizerStorageGLES3::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
-}
-
-AABB RasterizerStorageGLES3::reflection_probe_get_aabb(RID p_probe) const {
- return AABB();
-}
-
-RS::ReflectionProbeUpdateMode RasterizerStorageGLES3::reflection_probe_get_update_mode(RID p_probe) const {
- return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE;
-}
-
-uint32_t RasterizerStorageGLES3::reflection_probe_get_cull_mask(RID p_probe) const {
- return 0;
-}
-
-Vector3 RasterizerStorageGLES3::reflection_probe_get_extents(RID p_probe) const {
- return Vector3();
-}
-
-Vector3 RasterizerStorageGLES3::reflection_probe_get_origin_offset(RID p_probe) const {
- return Vector3();
-}
-
-float RasterizerStorageGLES3::reflection_probe_get_origin_max_distance(RID p_probe) const {
- return 0.0;
-}
-
-bool RasterizerStorageGLES3::reflection_probe_renders_shadows(RID p_probe) const {
- return false;
-}
-
void RasterizerStorageGLES3::base_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 */
RID RasterizerStorageGLES3::voxel_gi_allocate() {
@@ -361,257 +159,12 @@ uint32_t RasterizerStorageGLES3::voxel_gi_get_version(RID p_voxel_gi) {
return 0;
}
-/* LIGHTMAP CAPTURE */
-RID RasterizerStorageGLES3::lightmap_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::lightmap_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
-}
-
-void RasterizerStorageGLES3::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
-}
-
-void RasterizerStorageGLES3::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
-}
-
-void RasterizerStorageGLES3::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
-}
-
-PackedVector3Array RasterizerStorageGLES3::lightmap_get_probe_capture_points(RID p_lightmap) const {
- return PackedVector3Array();
-}
-
-PackedColorArray RasterizerStorageGLES3::lightmap_get_probe_capture_sh(RID p_lightmap) const {
- return PackedColorArray();
-}
-
-PackedInt32Array RasterizerStorageGLES3::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
- return PackedInt32Array();
-}
-
-PackedInt32Array RasterizerStorageGLES3::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
- return PackedInt32Array();
-}
-
-AABB RasterizerStorageGLES3::lightmap_get_aabb(RID p_lightmap) const {
- return AABB();
-}
-
-void RasterizerStorageGLES3::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
-}
-
-bool RasterizerStorageGLES3::lightmap_is_interior(RID p_lightmap) const {
- return false;
-}
-
-void RasterizerStorageGLES3::lightmap_set_probe_capture_update_speed(float p_speed) {
-}
-
-float RasterizerStorageGLES3::lightmap_get_probe_capture_update_speed() const {
- return 0;
-}
-
/* OCCLUDER */
void RasterizerStorageGLES3::occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {
}
-/* PARTICLES */
-
-RID RasterizerStorageGLES3::particles_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::particles_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
-}
-
-void RasterizerStorageGLES3::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
-}
-
-void RasterizerStorageGLES3::particles_set_emitting(RID p_particles, bool p_emitting) {
-}
-
-void RasterizerStorageGLES3::particles_set_amount(RID p_particles, int p_amount) {
-}
-
-void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles, double p_lifetime) {
-}
-
-void RasterizerStorageGLES3::particles_set_one_shot(RID p_particles, bool p_one_shot) {
-}
-
-void RasterizerStorageGLES3::particles_set_pre_process_time(RID p_particles, double p_time) {
-}
-
-void RasterizerStorageGLES3::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
-}
-
-void RasterizerStorageGLES3::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
-}
-
-void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
-}
-
-void RasterizerStorageGLES3::particles_set_speed_scale(RID p_particles, double p_scale) {
-}
-
-void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
-}
-
-void RasterizerStorageGLES3::particles_set_process_material(RID p_particles, RID p_material) {
-}
-RID RasterizerStorageGLES3::particles_get_process_material(RID p_particles) const {
- return RID();
-}
-
-void RasterizerStorageGLES3::particles_set_fixed_fps(RID p_particles, int p_fps) {
-}
-
-void RasterizerStorageGLES3::particles_set_interpolate(RID p_particles, bool p_enable) {
-}
-
-void RasterizerStorageGLES3::particles_set_fractional_delta(RID p_particles, bool p_enable) {
-}
-
-void RasterizerStorageGLES3::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
-}
-
-void RasterizerStorageGLES3::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
-}
-
-void RasterizerStorageGLES3::particles_set_collision_base_size(RID p_particles, real_t p_size) {
-}
-
-void RasterizerStorageGLES3::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
-}
-
-void RasterizerStorageGLES3::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
-}
-
-void RasterizerStorageGLES3::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
-}
-
-void RasterizerStorageGLES3::particles_restart(RID p_particles) {
-}
-
-void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
-}
-
-void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles, int p_count) {
-}
-
-void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
-}
-
-void RasterizerStorageGLES3::particles_request_process(RID p_particles) {
-}
-
-AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
- return AABB();
-}
-
-AABB RasterizerStorageGLES3::particles_get_aabb(RID p_particles) const {
- return AABB();
-}
-
-void RasterizerStorageGLES3::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
-}
-
-bool RasterizerStorageGLES3::particles_get_emitting(RID p_particles) {
- return false;
-}
-
-int RasterizerStorageGLES3::particles_get_draw_passes(RID p_particles) const {
- return 0;
-}
-
-RID RasterizerStorageGLES3::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
- return RID();
-}
-
-void RasterizerStorageGLES3::particles_add_collision(RID p_particles, RID p_instance) {
-}
-
-void RasterizerStorageGLES3::particles_remove_collision(RID p_particles, RID p_instance) {
-}
-
-void RasterizerStorageGLES3::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
-}
-
-void RasterizerStorageGLES3::update_particles() {
-}
-
-bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const {
- return false;
-}
-
-/* PARTICLES COLLISION */
-
-RID RasterizerStorageGLES3::particles_collision_allocate() {
- return RID();
-}
-
-void RasterizerStorageGLES3::particles_collision_initialize(RID p_rid) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
-}
-
-void RasterizerStorageGLES3::particles_collision_height_field_update(RID p_particles_collision) {
-}
-
-void RasterizerStorageGLES3::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
-}
-
-AABB RasterizerStorageGLES3::particles_collision_get_aabb(RID p_particles_collision) const {
- return AABB();
-}
-
-bool RasterizerStorageGLES3::particles_collision_is_heightfield(RID p_particles_collision) const {
- return false;
-}
-
-RID RasterizerStorageGLES3::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
- return RID();
-}
-
-RID RasterizerStorageGLES3::particles_collision_instance_create(RID p_collision) {
- return RID();
-}
-
-void RasterizerStorageGLES3::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
-}
-
-void RasterizerStorageGLES3::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
-}
+/* FOG */
RID RasterizerStorageGLES3::fog_volume_allocate() {
return RID();
@@ -658,758 +211,6 @@ AABB RasterizerStorageGLES3::visibility_notifier_get_aabb(RID p_notifier) const
void RasterizerStorageGLES3::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
}
-/* RENDER TARGET */
-
-void RasterizerStorageGLES3::_set_current_render_target(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
-
- if (rt) {
- if (rt->allocate_is_dirty) {
- rt->allocate_is_dirty = false;
- _render_target_allocate(rt);
- }
-
- frame.current_rt = rt;
- ERR_FAIL_COND(!rt);
- frame.clear_request = false;
-
- glViewport(0, 0, rt->width, rt->height);
-
- _dims.rt_width = rt->width;
- _dims.rt_height = rt->height;
- _dims.win_width = rt->width;
- _dims.win_height = rt->height;
-
- } else {
- frame.current_rt = nullptr;
- frame.clear_request = false;
- bind_framebuffer_system();
- }
-}
-
-void RasterizerStorageGLES3::_render_target_allocate(GLES3::RenderTarget *rt) {
- // do not allocate a render target with no size
- if (rt->width <= 0 || rt->height <= 0) {
- return;
- }
-
- // do not allocate a render target that is attached to the screen
- if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
- rt->fbo = RasterizerStorageGLES3::system_fbo;
- return;
- }
-
- GLuint color_internal_format;
- GLuint color_format;
- GLuint color_type = GL_UNSIGNED_BYTE;
- Image::Format image_format;
-
- if (rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) {
-#ifdef GLES_OVER_GL
- color_internal_format = GL_RGBA8;
-#else
- color_internal_format = GL_RGBA;
-#endif
- color_format = GL_RGBA;
- image_format = Image::FORMAT_RGBA8;
- } else {
-#ifdef GLES_OVER_GL
- color_internal_format = GL_RGB8;
-#else
- color_internal_format = GL_RGB;
-#endif
- color_format = GL_RGB;
- image_format = Image::FORMAT_RGB8;
- }
-
- rt->used_dof_blur_near = false;
- rt->mip_maps_allocated = false;
-
- {
- /* Front FBO */
-
- GLES3::Texture *texture = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture);
- ERR_FAIL_COND(!texture);
-
- // framebuffer
- glGenFramebuffers(1, &rt->fbo);
- bind_framebuffer(rt->fbo);
-
- // color
- glGenTextures(1, &rt->color);
- glBindTexture(GL_TEXTURE_2D, rt->color);
-
- glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, nullptr);
-
- if (texture->flags & GLES3::TEXTURE_FLAG_FILTER) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
-
- // depth
-
- if (config->support_depth_texture) {
- glGenTextures(1, &rt->depth);
- glBindTexture(GL_TEXTURE_2D, rt->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
- } else {
- glGenRenderbuffers(1, &rt->depth);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
-
- glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
- }
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- glDeleteFramebuffers(1, &rt->fbo);
- if (config->support_depth_texture) {
- glDeleteTextures(1, &rt->depth);
- } else {
- glDeleteRenderbuffers(1, &rt->depth);
- }
-
- glDeleteTextures(1, &rt->color);
- rt->fbo = 0;
- rt->width = 0;
- rt->height = 0;
- rt->color = 0;
- rt->depth = 0;
- texture->tex_id = 0;
- texture->active = false;
- WARN_PRINT("Could not create framebuffer!!");
- return;
- }
-
- texture->format = image_format;
- texture->gl_format_cache = color_format;
- texture->gl_type_cache = GL_UNSIGNED_BYTE;
- texture->gl_internal_format_cache = color_internal_format;
- texture->tex_id = rt->color;
- texture->width = rt->width;
- texture->alloc_width = rt->width;
- texture->height = rt->height;
- texture->alloc_height = rt->height;
- texture->active = true;
-
- GLES3::TextureStorage::get_singleton()->texture_set_flags(rt->texture, texture->flags);
- }
-
- /* BACK FBO */
- /* For MSAA */
-
-#ifndef JAVASCRIPT_ENABLED
- if (rt->msaa >= RS::VIEWPORT_MSAA_2X && rt->msaa <= RS::VIEWPORT_MSAA_8X) {
- rt->multisample_active = true;
-
- static const int msaa_value[] = { 0, 2, 4, 8, 16 };
- int msaa = msaa_value[rt->msaa];
-
- int max_samples = 0;
- glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
- if (msaa > max_samples) {
- WARN_PRINT("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples));
- msaa = max_samples;
- }
-
- //regular fbo
- glGenFramebuffers(1, &rt->multisample_fbo);
- bind_framebuffer(rt->multisample_fbo);
-
- glGenRenderbuffers(1, &rt->multisample_depth);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config->depth_buffer_internalformat, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth);
-
- glGenRenderbuffers(1, &rt->multisample_color);
- glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_color);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- // Delete allocated resources and default to no MSAA
- WARN_PRINT_ONCE("Cannot allocate back framebuffer for MSAA");
- printf("err status: %x\n", status);
- rt->multisample_active = false;
-
- glDeleteFramebuffers(1, &rt->multisample_fbo);
- rt->multisample_fbo = 0;
-
- glDeleteRenderbuffers(1, &rt->multisample_depth);
- rt->multisample_depth = 0;
-
- glDeleteRenderbuffers(1, &rt->multisample_color);
- rt->multisample_color = 0;
- }
-
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- bind_framebuffer(0);
-
- } else
-#endif // JAVASCRIPT_ENABLED
- {
- rt->multisample_active = false;
- }
-
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- // copy texscreen buffers
- // if (!(rt->flags[RendererStorage::RENDER_TARGET_NO_SAMPLING])) {
- if (true) {
- glGenTextures(1, &rt->copy_screen_effect.color);
- glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color);
-
- if (rt->flags[RendererStorage::RENDER_TARGET_TRANSPARENT]) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- } else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glGenFramebuffers(1, &rt->copy_screen_effect.fbo);
- bind_framebuffer(rt->copy_screen_effect.fbo);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0);
-
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- _render_target_clear(rt);
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
- }
-
- // Allocate mipmap chains for post_process effects
- // if (!rt->flags[RendererStorage::RENDER_TARGET_NO_3D] && rt->width >= 2 && rt->height >= 2) {
- if (rt->width >= 2 && rt->height >= 2) {
- for (int i = 0; i < 2; i++) {
- ERR_FAIL_COND(rt->mip_maps[i].sizes.size());
- int w = rt->width;
- int h = rt->height;
-
- if (i > 0) {
- w >>= 1;
- h >>= 1;
- }
-
- int level = 0;
- int fb_w = w;
- int fb_h = h;
-
- while (true) {
- GLES3::RenderTarget::MipMaps::Size mm;
- mm.width = w;
- mm.height = h;
- rt->mip_maps[i].sizes.push_back(mm);
-
- w >>= 1;
- h >>= 1;
-
- if (w < 2 || h < 2) {
- break;
- }
-
- level++;
- }
-
- GLsizei width = fb_w;
- GLsizei height = fb_h;
-
- if (config->render_to_mipmap_supported) {
- glGenTextures(1, &rt->mip_maps[i].color);
- glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color);
-
- for (int l = 0; l < level + 1; l++) {
- glTexImage2D(GL_TEXTURE_2D, l, color_internal_format, width, height, 0, color_format, color_type, nullptr);
- width = MAX(1, (width / 2));
- height = MAX(1, (height / 2));
- }
-#ifdef GLES_OVER_GL
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
-#endif
- } else {
- // Can't render to specific levels of a mipmap in ES 2.0 or Webgl so create a texture for each level
- for (int l = 0; l < level + 1; l++) {
- glGenTextures(1, &rt->mip_maps[i].sizes.write[l].color);
- glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[l].color);
- glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, width, height, 0, color_format, color_type, nullptr);
- width = MAX(1, (width / 2));
- height = MAX(1, (height / 2));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- }
-
- glDisable(GL_SCISSOR_TEST);
- glColorMask(1, 1, 1, 1);
- glDepthMask(GL_TRUE);
-
- for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
- GLES3::RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j];
-
- glGenFramebuffers(1, &mm.fbo);
- bind_framebuffer(mm.fbo);
-
- if (config->render_to_mipmap_supported) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j);
- } else {
- glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color, 0);
- }
-
- bool used_depth = false;
- if (j == 0 && i == 0) { //use always
- if (config->support_depth_texture) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
- } else {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
- }
- used_depth = true;
- }
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- WARN_PRINT_ONCE("Cannot allocate mipmaps for 3D post processing effects");
- bind_framebuffer_system();
- return;
- }
-
- glClearColor(1.0, 0.0, 1.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- if (used_depth) {
- glClearDepth(1.0);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- }
-
- rt->mip_maps[i].levels = level;
-
- if (config->render_to_mipmap_supported) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- }
- rt->mip_maps_allocated = true;
- }
-
- bind_framebuffer_system();
-}
-
-void RasterizerStorageGLES3::_render_target_clear(GLES3::RenderTarget *rt) {
- // there is nothing to clear when DIRECT_TO_SCREEN is used
- if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
- return;
- }
-
- if (rt->fbo) {
- glDeleteFramebuffers(1, &rt->fbo);
- glDeleteTextures(1, &rt->color);
- rt->fbo = 0;
- }
-
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // clean up our texture
- GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture);
- memdelete(t);
-
- rt->external.fbo = 0;
- }
-
- if (rt->depth) {
- if (config->support_depth_texture) {
- glDeleteTextures(1, &rt->depth);
- } else {
- glDeleteRenderbuffers(1, &rt->depth);
- }
-
- rt->depth = 0;
- }
-
- GLES3::Texture *tex = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture);
- tex->alloc_height = 0;
- tex->alloc_width = 0;
- tex->width = 0;
- tex->height = 0;
- tex->active = false;
-
- if (rt->copy_screen_effect.color) {
- glDeleteFramebuffers(1, &rt->copy_screen_effect.fbo);
- rt->copy_screen_effect.fbo = 0;
-
- glDeleteTextures(1, &rt->copy_screen_effect.color);
- rt->copy_screen_effect.color = 0;
- }
-
- for (int i = 0; i < 2; i++) {
- if (rt->mip_maps[i].sizes.size()) {
- for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
- glDeleteFramebuffers(1, &rt->mip_maps[i].sizes[j].fbo);
- glDeleteTextures(1, &rt->mip_maps[i].sizes[j].color);
- }
-
- glDeleteTextures(1, &rt->mip_maps[i].color);
- rt->mip_maps[i].sizes.clear();
- rt->mip_maps[i].levels = 0;
- rt->mip_maps[i].color = 0;
- }
- }
-
- if (rt->multisample_active) {
- glDeleteFramebuffers(1, &rt->multisample_fbo);
- rt->multisample_fbo = 0;
-
- glDeleteRenderbuffers(1, &rt->multisample_depth);
- rt->multisample_depth = 0;
-
- glDeleteRenderbuffers(1, &rt->multisample_color);
-
- rt->multisample_color = 0;
- }
-}
-
-RID RasterizerStorageGLES3::render_target_create() {
- GLES3::RenderTarget *rt = memnew(GLES3::RenderTarget);
- GLES3::Texture *t = memnew(GLES3::Texture);
-
- t->type = RenderingDevice::TEXTURE_TYPE_2D;
- t->flags = 0;
- t->width = 0;
- t->height = 0;
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->format = Image::FORMAT_R8;
- t->target = GL_TEXTURE_2D;
- t->gl_format_cache = 0;
- t->gl_internal_format_cache = 0;
- t->gl_type_cache = 0;
- t->data_size = 0;
- t->total_data_size = 0;
- t->ignore_mipmaps = false;
- t->compressed = false;
- t->mipmaps = 1;
- t->active = true;
- t->tex_id = 0;
- t->render_target = rt;
-
- rt->texture = GLES3::TextureStorage::get_singleton()->make_rid(t);
- return render_target_owner.make_rid(rt);
-}
-
-void RasterizerStorageGLES3::render_target_set_position(RID p_render_target, int p_x, int p_y) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->x = p_x;
- rt->y = p_y;
-}
-
-void RasterizerStorageGLES3::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (p_width == rt->width && p_height == rt->height) {
- return;
- }
-
- _render_target_clear(rt);
-
- rt->width = p_width;
- rt->height = p_height;
-
- // print_line("render_target_set_size " + itos(p_render_target.get_id()) + ", w " + itos(p_width) + " h " + itos(p_height));
-
- rt->allocate_is_dirty = true;
- //_render_target_allocate(rt);
-}
-
-// TODO: convert to Size2i internally
-Size2i RasterizerStorageGLES3::render_target_get_size(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Size2());
-
- return Size2i(rt->width, rt->height);
-}
-
-RID RasterizerStorageGLES3::render_target_get_texture(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- if (rt->external.fbo == 0) {
- return rt->texture;
- } else {
- return rt->external.texture;
- }
-}
-
-void RasterizerStorageGLES3::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (p_texture_id == 0) {
- if (rt->external.fbo != 0) {
- // free this
- glDeleteFramebuffers(1, &rt->external.fbo);
-
- // and this
- if (rt->external.depth != 0) {
- glDeleteRenderbuffers(1, &rt->external.depth);
- }
-
- // clean up our texture
- GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture);
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->width = 0;
- t->height = 0;
- t->active = false;
- GLES3::TextureStorage::get_singleton()->texture_free(rt->external.texture);
- memdelete(t);
-
- rt->external.fbo = 0;
- rt->external.color = 0;
- rt->external.depth = 0;
- }
- } else {
- GLES3::Texture *t;
-
- if (rt->external.fbo == 0) {
- // create our fbo
- glGenFramebuffers(1, &rt->external.fbo);
- bind_framebuffer(rt->external.fbo);
-
- // allocate a texture
- t = memnew(GLES3::Texture);
-
- t->type = RenderingDevice::TEXTURE_TYPE_2D;
- t->flags = 0;
- t->width = 0;
- t->height = 0;
- t->alloc_height = 0;
- t->alloc_width = 0;
- t->format = Image::FORMAT_RGBA8;
- t->target = GL_TEXTURE_2D;
- t->gl_format_cache = 0;
- t->gl_internal_format_cache = 0;
- t->gl_type_cache = 0;
- t->data_size = 0;
- t->compressed = false;
- t->srgb = false;
- t->total_data_size = 0;
- t->ignore_mipmaps = false;
- t->mipmaps = 1;
- t->active = true;
- t->tex_id = 0;
- t->render_target = rt;
-
- rt->external.texture = GLES3::TextureStorage::get_singleton()->make_rid(t);
-
- } else {
- // bind our frame buffer
- bind_framebuffer(rt->external.fbo);
-
- // find our texture
- t = GLES3::TextureStorage::get_singleton()->get_texture(rt->external.texture);
- }
-
- // set our texture
- t->tex_id = p_texture_id;
- rt->external.color = p_texture_id;
-
- // size shouldn't be different
- t->width = rt->width;
- t->height = rt->height;
- t->alloc_height = rt->width;
- t->alloc_width = rt->height;
-
- // Switch our texture on our frame buffer
- {
- // set our texture as the destination for our framebuffer
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
-
- // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
- if (config->support_depth_texture) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
- } else {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
- }
- }
-
- // check status and unbind
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- bind_framebuffer_system();
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- printf("framebuffer fail, status: %x\n", status);
- }
-
- ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
- }
-}
-
-void RasterizerStorageGLES3::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as
- // those functions change how they operate depending on the value of DIRECT_TO_SCREEN
- if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
- _render_target_clear(rt);
- rt->flags[p_flag] = p_value;
- _render_target_allocate(rt);
- }
-
- rt->flags[p_flag] = p_value;
-
- switch (p_flag) {
- case RENDER_TARGET_TRANSPARENT:
- /*
- case RENDER_TARGET_HDR:
- case RENDER_TARGET_NO_3D:
- case RENDER_TARGET_NO_SAMPLING:
- case RENDER_TARGET_NO_3D_EFFECTS: */
- {
- //must reset for these formats
- _render_target_clear(rt);
- _render_target_allocate(rt);
- }
- break;
- default: {
- }
- }
-}
-
-bool RasterizerStorageGLES3::render_target_was_used(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
-
- return rt->used_in_frame;
-}
-
-void RasterizerStorageGLES3::render_target_clear_used(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->used_in_frame = false;
-}
-
-void RasterizerStorageGLES3::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (rt->msaa == p_msaa) {
- return;
- }
-
- _render_target_clear(rt);
- rt->msaa = p_msaa;
- _render_target_allocate(rt);
-}
-
-//RasterizerStorageGLES3::GLES3::RenderTarget * RasterizerStorageGLES3::render_target_get(RID p_render_target)
-//{
-// return render_target_owner.get_or_null(p_render_target);
-//}
-
-void RasterizerStorageGLES3::render_target_set_use_fxaa(RID p_render_target, bool p_fxaa) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->use_fxaa = p_fxaa;
-}
-
-void RasterizerStorageGLES3::render_target_set_use_debanding(RID p_render_target, bool p_debanding) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- if (p_debanding) {
- WARN_PRINT_ONCE("Debanding is not supported in the OpenGL backend. Switch to the Vulkan backend and make sure HDR is enabled.");
- }
-
- rt->use_debanding = p_debanding;
-}
-
-void RasterizerStorageGLES3::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->clear_requested = true;
- rt->clear_color = p_clear_color;
-
- // ERR_FAIL_COND(!frame.current_rt);
- // frame.clear_request = true;
- // frame.clear_request_color = p_color;
-}
-
-bool RasterizerStorageGLES3::render_target_is_clear_requested(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
- return rt->clear_requested;
-}
-Color RasterizerStorageGLES3::render_target_get_clear_request_color(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Color());
- return rt->clear_color;
-}
-
-void RasterizerStorageGLES3::render_target_disable_clear_request(RID p_render_target) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->clear_requested = false;
-}
-
-void RasterizerStorageGLES3::render_target_do_clear_request(RID p_render_target) {
-}
-
-void RasterizerStorageGLES3::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
-}
-
-Rect2i RasterizerStorageGLES3::render_target_get_sdf_rect(RID p_render_target) const {
- return Rect2i();
-}
-
-void RasterizerStorageGLES3::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
-}
-
/* CANVAS SHADOW */
RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
@@ -1425,7 +226,7 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
glActiveTexture(GL_TEXTURE0);
glGenFramebuffers(1, &cls->fbo);
- bind_framebuffer(cls->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
glGenRenderbuffers(1, &cls->depth);
glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
@@ -1452,7 +253,7 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
//printf("errnum: %x\n",status);
- bind_framebuffer_system();
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
if (status != GL_FRAMEBUFFER_COMPLETE) {
memdelete(cls);
@@ -1585,24 +386,14 @@ RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
}
bool RasterizerStorageGLES3::free(RID p_rid) {
- if (render_target_owner.owns(p_rid)) {
- GLES3::RenderTarget *rt = render_target_owner.get_or_null(p_rid);
- _render_target_clear(rt);
-
- GLES3::Texture *t = GLES3::TextureStorage::get_singleton()->get_texture(rt->texture);
- if (t) {
- GLES3::TextureStorage::get_singleton()->texture_free(rt->texture);
- memdelete(t);
- }
- render_target_owner.free(p_rid);
- memdelete(rt);
-
+ if (GLES3::TextureStorage::get_singleton()->owns_render_target(p_rid)) {
+ GLES3::TextureStorage::get_singleton()->render_target_free(p_rid);
return true;
} else if (GLES3::TextureStorage::get_singleton()->owns_texture(p_rid)) {
GLES3::TextureStorage::get_singleton()->texture_free(p_rid);
return true;
- } else if (GLES3::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
- GLES3::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid);
+ } else if (GLES3::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
+ GLES3::TextureStorage::get_singleton()->canvas_texture_free(p_rid);
return true;
} else if (sky_owner.owns(p_rid)) {
Sky *sky = sky_owner.get_or_null(p_rid);
@@ -1859,84 +650,11 @@ RenderingDevice::DeviceType RasterizerStorageGLES3::get_video_adapter_type() con
}
void RasterizerStorageGLES3::initialize() {
- RasterizerStorageGLES3::system_fbo = 0;
config = GLES3::Config::get_singleton();
- config->initialize();
-
- //determine formats for depth textures (or renderbuffers)
- if (config->support_depth_texture) {
- // Will use texture for depth
- // have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT,
- // as there is no extension to test for this.
- GLuint fbo;
- glGenFramebuffers(1, &fbo);
- bind_framebuffer(fbo);
- GLuint depth;
- glGenTextures(1, &depth);
- glBindTexture(GL_TEXTURE_2D, depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
-
- GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-
- bind_framebuffer_system();
- glDeleteFramebuffers(1, &fbo);
- glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &depth);
-
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- // If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT
- // This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT
-#ifdef GLES_OVER_GL
- config->depth_internalformat = GL_DEPTH_COMPONENT16;
-#else
- // OES_depth_texture extension only specifies GL_DEPTH_COMPONENT.
- config->depth_internalformat = GL_DEPTH_COMPONENT;
-#endif
- config->depth_type = GL_UNSIGNED_SHORT;
-
- glGenFramebuffers(1, &fbo);
- bind_framebuffer(fbo);
-
- glGenTextures(1, &depth);
- glBindTexture(GL_TEXTURE_2D, depth);
- glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
-
- status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- //if it fails again depth textures aren't supported, use rgba shadows and renderbuffer for depth
- config->support_depth_texture = false;
- config->use_rgba_3d_shadows = true;
- }
-
- bind_framebuffer_system();
- glDeleteFramebuffers(1, &fbo);
- glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &depth);
- }
- }
//picky requirements for these
config->support_shadow_cubemaps = config->support_depth_texture && config->support_write_depth && config->support_depth_cubemaps;
- frame.count = 0;
- frame.delta = 0;
- frame.current_rt = nullptr;
- frame.clear_request = false;
-
// the use skeleton software path should be used if either float texture is not supported,
// OR max_vertex_texture_image_units is zero
config->use_skeleton_software = (config->float_texture_supported == false) || (config->max_vertex_texture_image_units == 0);
@@ -2105,7 +823,7 @@ void RasterizerStorageGLES3::update_dirty_resources() {
}
RasterizerStorageGLES3::RasterizerStorageGLES3() {
- RasterizerStorageGLES3::system_fbo = 0;
+ initialize();
}
RasterizerStorageGLES3::~RasterizerStorageGLES3() {
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 105529ee3d..da1dd0e66b 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -40,10 +40,8 @@
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/shader_language.h"
-#include "storage/canvas_texture_storage.h"
#include "storage/config.h"
#include "storage/material_storage.h"
-#include "storage/render_target_storage.h"
#include "storage/texture_storage.h"
// class RasterizerCanvasGLES3;
@@ -54,8 +52,6 @@ public:
// RasterizerCanvasGLES3 *canvas;
// RasterizerSceneGLES3 *scene;
- static GLuint system_fbo;
-
GLES3::Config *config;
struct Resources {
@@ -118,6 +114,8 @@ public:
/////////////////////////////////////////////////////////////////////////////////////////
public:
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
+
/* SKY API */
// not sure if used in godot 4?
struct Sky {
@@ -132,78 +130,6 @@ public:
RID sky_create();
void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size);
- /* Light API */
-
- RID directional_light_allocate() override;
- void directional_light_initialize(RID p_rid) override;
- RID omni_light_allocate() override;
- void omni_light_initialize(RID p_rid) override;
- RID spot_light_allocate() override;
- void spot_light_initialize(RID p_rid) override;
- RID reflection_probe_allocate() override;
- void reflection_probe_initialize(RID p_rid) override;
-
- void light_set_color(RID p_light, const Color &p_color) override;
- void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
- void light_set_shadow(RID p_light, bool p_enabled) override;
- void light_set_projector(RID p_light, RID p_texture) override;
- void light_set_negative(RID p_light, bool p_enable) override;
- void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
- void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
- void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
- void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
- void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
-
- void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override;
-
- void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
- void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
- bool light_directional_get_blend_splits(RID p_light) const override;
- void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
- RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
-
- RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
- RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
-
- bool light_has_shadow(RID p_light) const override;
- bool light_has_projector(RID p_light) const override;
-
- RS::LightType light_get_type(RID p_light) const override;
- AABB light_get_aabb(RID p_light) const override;
- float light_get_param(RID p_light, RS::LightParam p_param) override;
- Color light_get_color(RID p_light) override;
- RS::LightBakeMode light_get_bake_mode(RID p_light) override;
- uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
- uint64_t light_get_version(RID p_light) const override;
-
- /* PROBE API */
-
- void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
- void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
- void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
- void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
- void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
- void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
- void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
- void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
- void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
- void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
- 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;
- uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
- Vector3 reflection_probe_get_extents(RID p_probe) const override;
- Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
- float reflection_probe_get_origin_max_distance(RID p_probe) const override;
- bool reflection_probe_renders_shadows(RID p_probe) const override;
-
- void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
-
/* VOXEL GI API */
RID voxel_gi_allocate() override;
@@ -245,104 +171,10 @@ public:
uint32_t voxel_gi_get_version(RID p_voxel_gi) override;
- /* LIGHTMAP CAPTURE */
- RID lightmap_allocate() override;
- void lightmap_initialize(RID p_rid) override;
- void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override;
- void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
- void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
- void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
- PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
- PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
- PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
- PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override;
- AABB lightmap_get_aabb(RID p_lightmap) const override;
- void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
- bool lightmap_is_interior(RID p_lightmap) const override;
- void lightmap_set_probe_capture_update_speed(float p_speed) override;
- float lightmap_get_probe_capture_update_speed() const override;
-
/* OCCLUDER */
void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices);
- /* PARTICLES */
-
- RID particles_allocate() override;
- void particles_initialize(RID p_rid) override;
- void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
- void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
- void particles_set_emitting(RID p_particles, bool p_emitting) override;
- void particles_set_amount(RID p_particles, int p_amount) override;
- void particles_set_lifetime(RID p_particles, double p_lifetime) override;
- void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
- void particles_set_pre_process_time(RID p_particles, double p_time) override;
- void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
- void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
- void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
- void particles_set_speed_scale(RID p_particles, double p_scale) override;
- void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
- void particles_set_process_material(RID p_particles, RID p_material) override;
- RID particles_get_process_material(RID p_particles) const override;
- void particles_set_fixed_fps(RID p_particles, int p_fps) override;
- void particles_set_interpolate(RID p_particles, bool p_enable) override;
- void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
- void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
- void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
- void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
-
- void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
-
- void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
- void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
-
- void particles_restart(RID p_particles) override;
-
- void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
-
- void particles_set_draw_passes(RID p_particles, int p_count) override;
- void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
-
- void particles_request_process(RID p_particles) override;
- AABB particles_get_current_aabb(RID p_particles) override;
- AABB particles_get_aabb(RID p_particles) const override;
-
- void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
-
- bool particles_get_emitting(RID p_particles) override;
- int particles_get_draw_passes(RID p_particles) const override;
- RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
-
- void particles_add_collision(RID p_particles, RID p_instance) override;
- void particles_remove_collision(RID p_particles, RID p_instance) override;
-
- void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
-
- void update_particles() override;
- bool particles_is_inactive(RID p_particles) const override;
-
- /* PARTICLES COLLISION */
-
- RID particles_collision_allocate() override;
- void particles_collision_initialize(RID p_rid) override;
- void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
- void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
- void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override;
- void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override;
- void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
- void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
- void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
- void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override;
- void particles_collision_height_field_update(RID p_particles_collision) override;
- void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override;
- AABB particles_collision_get_aabb(RID p_particles_collision) const override;
- bool particles_collision_is_heightfield(RID p_particles_collision) const override;
- RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
-
- RID particles_collision_instance_create(RID p_collision) override;
- void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
- void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
-
/* FOG VOLUMES */
RID fog_volume_allocate() override;
@@ -363,43 +195,6 @@ public:
AABB visibility_notifier_get_aabb(RID p_notifier) const override;
void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
- // RENDER TARGET
-
- mutable RID_PtrOwner<GLES3::RenderTarget> render_target_owner;
-
- void _render_target_clear(GLES3::RenderTarget *rt);
- void _render_target_allocate(GLES3::RenderTarget *rt);
- void _set_current_render_target(RID p_render_target);
-
- RID render_target_create() override;
- void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
- void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
- Size2i render_target_get_size(RID p_render_target);
- RID render_target_get_texture(RID p_render_target) override;
- void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
-
- void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
- bool render_target_was_used(RID p_render_target) override;
- void render_target_clear_used(RID p_render_target);
- void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa);
- void render_target_set_use_fxaa(RID p_render_target, bool p_fxaa);
- void render_target_set_use_debanding(RID p_render_target, bool p_debanding);
-
- // new
- void render_target_set_as_unused(RID p_render_target) override {
- render_target_clear_used(p_render_target);
- }
-
- void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
- bool render_target_is_clear_requested(RID p_render_target) override;
- Color render_target_get_clear_request_color(RID p_render_target) override;
- void render_target_disable_clear_request(RID p_render_target) override;
- void render_target_do_clear_request(RID p_render_target) override;
-
- void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
- Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
- void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
-
// access from canvas
// GLES3::RenderTarget * render_target_get(RID p_render_target);
@@ -439,24 +234,6 @@ public:
bool free(RID p_rid) override;
- struct Frame {
- GLES3::RenderTarget *current_rt;
-
- // these 2 may have been superseded by the equivalents in the render target.
- // these may be able to be removed.
- bool clear_request;
- Color clear_request_color;
-
- float time;
- float delta;
- uint64_t count;
-
- Frame() {
- // current_rt = nullptr;
- // clear_request = false;
- }
- } frame;
-
void initialize();
void finalize();
@@ -498,34 +275,9 @@ public:
return String();
}
- // make access easier to these
- struct Dimensions {
- // render target
- int rt_width;
- int rt_height;
-
- // window
- int win_width;
- int win_height;
- Dimensions() {
- rt_width = 0;
- rt_height = 0;
- win_width = 0;
- win_height = 0;
- }
- } _dims;
-
void buffer_orphan_and_upload(unsigned int p_buffer_size, unsigned int p_offset, unsigned int p_data_size, const void *p_data, GLenum p_target = GL_ARRAY_BUFFER, GLenum p_usage = GL_DYNAMIC_DRAW, bool p_optional_orphan = false) const;
bool safe_buffer_sub_data(unsigned int p_total_buffer_size, GLenum p_target, unsigned int p_offset, unsigned int p_data_size, const void *p_data, unsigned int &r_offset_after) const;
- void bind_framebuffer(GLuint framebuffer) {
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- }
-
- void bind_framebuffer_system() {
- glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- }
-
RasterizerStorageGLES3();
~RasterizerStorageGLES3();
};
diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp
index 4b0986cca1..1c946895a5 100644
--- a/drivers/gles3/shader_gles3.cpp
+++ b/drivers/gles3/shader_gles3.cpp
@@ -464,8 +464,8 @@ bool ShaderGLES3::_load_from_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
- FileAccessRef f = FileAccess::open(path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
+ if (f.is_null()) {
return false;
}
@@ -530,8 +530,8 @@ void ShaderGLES3::_save_to_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
- FileAccessRef f = FileAccess::open(path, FileAccess::WRITE);
- ERR_FAIL_COND(!f);
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
+ ERR_FAIL_COND(f.is_null());
f->store_buffer((const uint8_t *)shader_file_header, 4);
f->store_32(cache_file_version); //file version
uint32_t variant_count = variant_count;
@@ -541,8 +541,6 @@ void ShaderGLES3::_save_to_cache(Version *p_version) {
f->store_32(p_version->variant_data[i].size()); //stage count
f->store_buffer(p_version->variant_data[i].ptr(), p_version->variant_data[i].size());
}
-
- f->close();
#endif
}
@@ -642,8 +640,8 @@ void ShaderGLES3::initialize(const String &p_general_defines, int p_base_texture
base_sha256 = hash_build.as_string().sha256_text();
- DirAccessRef d = DirAccess::open(shader_cache_dir);
- ERR_FAIL_COND(!d);
+ Ref<DirAccess> d = DirAccess::open(shader_cache_dir);
+ ERR_FAIL_COND(d.is_null());
if (d->change_dir(name) != OK) {
Error err = d->make_dir(name);
ERR_FAIL_COND(err != OK);
diff --git a/drivers/gles3/storage/canvas_texture_storage.cpp b/drivers/gles3/storage/canvas_texture_storage.cpp
deleted file mode 100644
index fe12700c21..0000000000
--- a/drivers/gles3/storage/canvas_texture_storage.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*************************************************************************/
-/* canvas_texture_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 "canvas_texture_storage.h"
-
-using namespace GLES3;
-
-CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr;
-
-CanvasTextureStorage *CanvasTextureStorage::get_singleton() {
- return singleton;
-}
-
-CanvasTextureStorage::CanvasTextureStorage() {
- singleton = this;
-}
-
-CanvasTextureStorage::~CanvasTextureStorage() {
- singleton = nullptr;
-}
-
-RID CanvasTextureStorage::canvas_texture_allocate() {
- return canvas_texture_owner.allocate_rid();
-}
-
-void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) {
- canvas_texture_owner.initialize_rid(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_free(RID p_rid) {
- canvas_texture_owner.free(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- switch (p_channel) {
- case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
- ct->diffuse = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
- ct->normal_map = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
- ct->specular = p_texture;
- } break;
- }
-}
-
-void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->specular_color.r = p_specular_color.r;
- ct->specular_color.g = p_specular_color.g;
- ct->specular_color.b = p_specular_color.b;
- ct->specular_color.a = p_shininess;
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->texture_filter = p_filter;
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ct->texture_repeat = p_repeat;
-}
-
-#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 1f66401427..a83ad34d4c 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -39,14 +39,7 @@ Config *Config::singleton = nullptr;
Config::Config() {
singleton = this;
- should_orphan = true;
-}
-
-Config::~Config() {
- singleton = nullptr;
-}
-void Config::initialize() {
{
const GLubyte *extension_string = glGetString(GL_EXTENSIONS);
@@ -153,4 +146,8 @@ void Config::initialize() {
// should_orphan = GLOBAL_GET("rendering/options/api_usage_legacy/orphan_buffers");
}
+Config::~Config() {
+ singleton = nullptr;
+}
+
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index 25bd3fd9a1..11a7cc8499 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -103,7 +103,6 @@ public:
Config();
~Config();
- void initialize();
};
} // namespace GLES3
diff --git a/drivers/gles3/storage/decal_atlas_storage.cpp b/drivers/gles3/storage/decal_atlas_storage.cpp
deleted file mode 100644
index 7bac34ea19..0000000000
--- a/drivers/gles3/storage/decal_atlas_storage.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*************************************************************************/
-/* decal_atlas_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 "decal_atlas_storage.h"
-
-using namespace GLES3;
-
-RID DecalAtlasStorage::decal_allocate() {
- return RID();
-}
-
-void DecalAtlasStorage::decal_initialize(RID p_rid) {
-}
-
-void DecalAtlasStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
-}
-
-void DecalAtlasStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
-}
-
-void DecalAtlasStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
-}
-
-void DecalAtlasStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
-}
-
-void DecalAtlasStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
-}
-
-void DecalAtlasStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
-}
-
-void DecalAtlasStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
-}
-
-void DecalAtlasStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
-}
-
-void DecalAtlasStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
-}
-
-AABB DecalAtlasStorage::decal_get_aabb(RID p_decal) const {
- return AABB();
-}
-
-#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/decal_atlas_storage.h b/drivers/gles3/storage/decal_atlas_storage.h
deleted file mode 100644
index f5dc36b1fb..0000000000
--- a/drivers/gles3/storage/decal_atlas_storage.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*************************************************************************/
-/* decal_atlas_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 DECAL_ATLAS_STORAGE_GLES3_H
-#define DECAL_ATLAS_STORAGE_GLES3_H
-
-#ifdef GLES3_ENABLED
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
-
-namespace GLES3 {
-
-class DecalAtlasStorage : public RendererDecalAtlasStorage {
-public:
- virtual RID decal_allocate() override;
- virtual void decal_initialize(RID p_rid) override;
- virtual void decal_free(RID p_rid) override{};
-
- virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
- virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
- virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
- virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
- virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
- virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
- virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
- virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
- virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
-
- virtual AABB decal_get_aabb(RID p_decal) const override;
-
- virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
- virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-};
-
-} // namespace GLES3
-
-#endif // !GLES3_ENABLED
-
-#endif // !DECAL_ATLAS_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
new file mode 100644
index 0000000000..7395611d71
--- /dev/null
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -0,0 +1,316 @@
+/*************************************************************************/
+/* light_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 "light_storage.h"
+#include "config.h"
+
+using namespace GLES3;
+
+LightStorage *LightStorage::singleton = nullptr;
+
+LightStorage *LightStorage::get_singleton() {
+ return singleton;
+}
+
+LightStorage::LightStorage() {
+ singleton = this;
+}
+
+LightStorage::~LightStorage() {
+ singleton = nullptr;
+}
+
+/* Light API */
+
+RID LightStorage::directional_light_allocate() {
+ return RID();
+}
+
+void LightStorage::directional_light_initialize(RID p_rid) {
+}
+
+RID LightStorage::omni_light_allocate() {
+ return RID();
+}
+
+void LightStorage::omni_light_initialize(RID p_rid) {
+}
+
+RID LightStorage::spot_light_allocate() {
+ return RID();
+}
+
+void LightStorage::spot_light_initialize(RID p_rid) {
+}
+
+void LightStorage::light_free(RID p_rid) {
+}
+
+void LightStorage::light_set_color(RID p_light, const Color &p_color) {
+}
+
+void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
+}
+
+void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
+}
+
+void LightStorage::light_set_projector(RID p_light, RID p_texture) {
+}
+
+void LightStorage::light_set_negative(RID p_light, bool p_enable) {
+}
+
+void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+}
+
+void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
+}
+
+void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
+}
+
+void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
+}
+
+void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
+}
+
+void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
+}
+
+void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
+}
+
+void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
+}
+
+bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
+ return false;
+}
+
+void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
+}
+
+RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const {
+ return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
+}
+
+RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) {
+ return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+}
+
+RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
+ return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+}
+
+bool LightStorage::light_has_shadow(RID p_light) const {
+ return false;
+}
+
+bool LightStorage::light_has_projector(RID p_light) const {
+ return false;
+}
+
+RS::LightType LightStorage::light_get_type(RID p_light) const {
+ return RS::LIGHT_OMNI;
+}
+
+AABB LightStorage::light_get_aabb(RID p_light) const {
+ return AABB();
+}
+
+float LightStorage::light_get_param(RID p_light, RS::LightParam p_param) {
+ return 0.0;
+}
+
+Color LightStorage::light_get_color(RID p_light) {
+ return Color();
+}
+
+RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) {
+ return RS::LIGHT_BAKE_DISABLED;
+}
+
+uint32_t LightStorage::light_get_max_sdfgi_cascade(RID p_light) {
+ return 0;
+}
+
+uint64_t LightStorage::light_get_version(RID p_light) const {
+ return 0;
+}
+
+/* PROBE API */
+
+RID LightStorage::reflection_probe_allocate() {
+ return RID();
+}
+
+void LightStorage::reflection_probe_initialize(RID p_rid) {
+}
+
+void LightStorage::reflection_probe_free(RID p_rid) {
+}
+
+void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
+}
+
+void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+}
+
+void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
+}
+
+void LightStorage::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
+}
+
+void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
+}
+
+void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
+}
+
+void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+}
+
+void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+}
+
+void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
+}
+
+void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+}
+
+void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
+}
+
+void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+}
+
+void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+}
+
+AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
+ return AABB();
+}
+
+RS::ReflectionProbeUpdateMode LightStorage::reflection_probe_get_update_mode(RID p_probe) const {
+ return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE;
+}
+
+uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const {
+ return 0;
+}
+
+Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const {
+ return Vector3();
+}
+
+Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const {
+ return Vector3();
+}
+
+float LightStorage::reflection_probe_get_origin_max_distance(RID p_probe) const {
+ return 0.0;
+}
+
+bool LightStorage::reflection_probe_renders_shadows(RID p_probe) const {
+ return false;
+}
+
+void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
+}
+
+float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
+ return 0.0;
+}
+
+/* LIGHTMAP CAPTURE */
+
+RID LightStorage::lightmap_allocate() {
+ return RID();
+}
+
+void LightStorage::lightmap_initialize(RID p_rid) {
+}
+
+void LightStorage::lightmap_free(RID p_rid) {
+}
+
+void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
+}
+
+void LightStorage::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
+}
+
+void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
+}
+
+void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+}
+
+PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
+ return PackedVector3Array();
+}
+
+PackedColorArray LightStorage::lightmap_get_probe_capture_sh(RID p_lightmap) const {
+ return PackedColorArray();
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
+ return PackedInt32Array();
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
+ return PackedInt32Array();
+}
+
+AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const {
+ return AABB();
+}
+
+void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
+}
+
+bool LightStorage::lightmap_is_interior(RID p_lightmap) const {
+ return false;
+}
+
+void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {
+}
+
+float LightStorage::lightmap_get_probe_capture_update_speed() const {
+ return 0;
+}
+
+#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
new file mode 100644
index 0000000000..6f24e467bc
--- /dev/null
+++ b/drivers/gles3/storage/light_storage.h
@@ -0,0 +1,154 @@
+/*************************************************************************/
+/* light_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 LIGHT_STORAGE_GLES3_H
+#define LIGHT_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/renderer_compositor.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/storage/light_storage.h"
+
+namespace GLES3 {
+
+class LightStorage : public RendererLightStorage {
+private:
+ static LightStorage *singleton;
+
+public:
+ static LightStorage *get_singleton();
+
+ LightStorage();
+ virtual ~LightStorage();
+
+ /* Light API */
+
+ virtual RID directional_light_allocate() override;
+ virtual void directional_light_initialize(RID p_rid) override;
+ virtual RID omni_light_allocate() override;
+ virtual void omni_light_initialize(RID p_rid) override;
+ virtual RID spot_light_allocate() override;
+ virtual void spot_light_initialize(RID p_rid) override;
+
+ virtual void light_free(RID p_rid) override;
+
+ virtual void light_set_color(RID p_light, const Color &p_color) override;
+ virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
+ virtual void light_set_shadow(RID p_light, bool p_enabled) override;
+ virtual void light_set_projector(RID p_light, RID p_texture) override;
+ virtual void light_set_negative(RID p_light, bool p_enable) override;
+ virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
+ virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
+ virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
+ virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
+ virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
+
+ virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override;
+
+ virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
+ virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
+ virtual bool light_directional_get_blend_splits(RID p_light) const override;
+ virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
+ virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
+
+ virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
+ virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
+
+ virtual bool light_has_shadow(RID p_light) const override;
+ virtual bool light_has_projector(RID p_light) const override;
+
+ virtual RS::LightType light_get_type(RID p_light) const override;
+ virtual AABB light_get_aabb(RID p_light) const override;
+ virtual float light_get_param(RID p_light, RS::LightParam p_param) override;
+ virtual Color light_get_color(RID p_light) override;
+ virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override;
+ virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
+ virtual uint64_t light_get_version(RID p_light) const override;
+
+ /* PROBE API */
+
+ virtual RID reflection_probe_allocate() override;
+ virtual void reflection_probe_initialize(RID p_rid) override;
+ virtual void reflection_probe_free(RID p_rid) override;
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
+ virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
+ virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
+ virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override;
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+ virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
+
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
+ virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const override;
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
+
+ /* LIGHTMAP CAPTURE */
+
+ virtual RID lightmap_allocate() override;
+ virtual void lightmap_initialize(RID p_rid) override;
+ virtual void lightmap_free(RID p_rid) override;
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override;
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
+ virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override;
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const override;
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
+ virtual bool lightmap_is_interior(RID p_lightmap) const override;
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
+ virtual float lightmap_get_probe_capture_update_speed() const override;
+};
+
+} // namespace GLES3
+
+#endif // !GLES3_ENABLED
+
+#endif // !LIGHT_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/particles_storage.cpp b/drivers/gles3/storage/particles_storage.cpp
new file mode 100644
index 0000000000..9ed9fedd5a
--- /dev/null
+++ b/drivers/gles3/storage/particles_storage.cpp
@@ -0,0 +1,254 @@
+/*************************************************************************/
+/* particles_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 "particles_storage.h"
+
+using namespace GLES3;
+
+ParticlesStorage *ParticlesStorage::singleton = nullptr;
+
+ParticlesStorage *ParticlesStorage::get_singleton() {
+ return singleton;
+}
+
+ParticlesStorage::ParticlesStorage() {
+ singleton = this;
+}
+
+ParticlesStorage::~ParticlesStorage() {
+ singleton = nullptr;
+}
+
+/* PARTICLES */
+
+RID ParticlesStorage::particles_allocate() {
+ return RID();
+}
+
+void ParticlesStorage::particles_initialize(RID p_rid) {
+}
+
+void ParticlesStorage::particles_free(RID p_rid) {
+}
+
+void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
+}
+
+void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+}
+
+void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
+}
+
+void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
+}
+
+void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
+}
+
+void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) {
+}
+
+void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) {
+}
+
+void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
+}
+
+void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
+}
+
+void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
+}
+
+void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
+}
+
+void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
+}
+
+void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+}
+
+RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
+ return RID();
+}
+
+void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
+}
+
+void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
+}
+
+void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) {
+}
+
+void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+}
+
+void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+}
+
+void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
+}
+
+void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
+}
+
+void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+}
+
+void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+}
+
+void ParticlesStorage::particles_restart(RID p_particles) {
+}
+
+void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
+}
+
+void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_count) {
+}
+
+void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
+}
+
+void ParticlesStorage::particles_request_process(RID p_particles) {
+}
+
+AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
+ return AABB();
+}
+
+AABB ParticlesStorage::particles_get_aabb(RID p_particles) const {
+ return AABB();
+}
+
+void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
+}
+
+bool ParticlesStorage::particles_get_emitting(RID p_particles) {
+ return false;
+}
+
+int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
+ return 0;
+}
+
+RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+ return RID();
+}
+
+void ParticlesStorage::particles_add_collision(RID p_particles, RID p_instance) {
+}
+
+void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_instance) {
+}
+
+void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+}
+
+void ParticlesStorage::update_particles() {
+}
+
+bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
+ return false;
+}
+
+/* PARTICLES COLLISION */
+
+RID ParticlesStorage::particles_collision_allocate() {
+ return RID();
+}
+
+void ParticlesStorage::particles_collision_initialize(RID p_rid) {
+}
+
+void ParticlesStorage::particles_collision_free(RID p_rid) {
+}
+
+void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
+}
+
+void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
+}
+
+void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
+}
+
+void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
+}
+
+void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
+}
+
+void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
+}
+
+void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
+}
+
+void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
+}
+
+void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
+}
+
+void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
+}
+
+AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const {
+ return AABB();
+}
+
+bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const {
+ return false;
+}
+
+RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
+ return RID();
+}
+
+RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
+ return RID();
+}
+
+void ParticlesStorage::particles_collision_instance_free(RID p_rid) {
+}
+
+void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
+}
+
+void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+}
+
+#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/particles_storage.h b/drivers/gles3/storage/particles_storage.h
new file mode 100644
index 0000000000..cf47ada5d5
--- /dev/null
+++ b/drivers/gles3/storage/particles_storage.h
@@ -0,0 +1,140 @@
+/*************************************************************************/
+/* particles_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 PARTICLES_STORAGE_GLES3_H
+#define PARTICLES_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/particles_storage.h"
+
+namespace GLES3 {
+
+class ParticlesStorage : public RendererParticlesStorage {
+private:
+ static ParticlesStorage *singleton;
+
+public:
+ static ParticlesStorage *get_singleton();
+
+ ParticlesStorage();
+ virtual ~ParticlesStorage();
+
+ /* PARTICLES */
+
+ virtual RID particles_allocate() override;
+ virtual void particles_initialize(RID p_rid) override;
+ virtual void particles_free(RID p_rid) override;
+
+ virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
+ virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
+ virtual void particles_set_amount(RID p_particles, int p_amount) override;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
+ virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) override;
+ virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
+ virtual void particles_set_process_material(RID p_particles, RID p_material) override;
+ virtual RID particles_get_process_material(RID p_particles) const override;
+ virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override;
+ virtual void particles_set_interpolate(RID p_particles, bool p_enable) override;
+ virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
+ virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
+ virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
+
+ virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
+
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
+
+ virtual void particles_restart(RID p_particles) override;
+
+ virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
+
+ virtual void particles_set_draw_passes(RID p_particles, int p_count) override;
+ virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
+
+ virtual void particles_request_process(RID p_particles) override;
+ virtual AABB particles_get_current_aabb(RID p_particles) override;
+ virtual AABB particles_get_aabb(RID p_particles) const override;
+
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
+
+ virtual bool particles_get_emitting(RID p_particles) override;
+ virtual int particles_get_draw_passes(RID p_particles) const override;
+ virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
+
+ virtual void particles_add_collision(RID p_particles, RID p_instance) override;
+ virtual void particles_remove_collision(RID p_particles, RID p_instance) override;
+
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+
+ virtual void update_particles() override;
+ virtual bool particles_is_inactive(RID p_particles) const override;
+
+ /* PARTICLES COLLISION */
+
+ virtual RID particles_collision_allocate() override;
+ virtual void particles_collision_initialize(RID p_rid) override;
+ virtual void particles_collision_free(RID p_rid) override;
+
+ virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
+ virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override;
+ virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override;
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
+ virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override;
+ virtual void particles_collision_height_field_update(RID p_particles_collision) override;
+ virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override;
+ virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
+ virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
+ virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+
+ virtual RID particles_collision_instance_create(RID p_collision) override;
+ virtual void particles_collision_instance_free(RID p_rid) override;
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
+};
+
+} // namespace GLES3
+
+#endif // GLES3_ENABLED
+
+#endif // !PARTICLES_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/render_target_storage.h b/drivers/gles3/storage/render_target_storage.h
deleted file mode 100644
index 816cc76e40..0000000000
--- a/drivers/gles3/storage/render_target_storage.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*************************************************************************/
-/* render_target_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 RENDER_TARGET_STORAGE_GLES3_H
-#define RENDER_TARGET_STORAGE_GLES3_H
-
-#ifdef GLES3_ENABLED
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_storage.h" // included until we move stuff into storage/render_target_storage.h
-// #include "servers/rendering/storage/render_target_storage.h"
-
-// This must come first to avoid windows.h mess
-#include "platform_config.h"
-#ifndef OPENGL_INCLUDE_H
-#include <GLES3/gl3.h>
-#else
-#include OPENGL_INCLUDE_H
-#endif
-
-namespace GLES3 {
-
-// NOTE, this class currently is just a container for the the RenderTarget struct and is not yet implemented further, we'll do that next after we finish with TextureStorage
-
-struct RenderTarget {
- RID self;
- GLuint fbo = 0;
- GLuint color = 0;
- GLuint depth = 0;
-
- GLuint multisample_fbo = 0;
- GLuint multisample_color = 0;
- GLuint multisample_depth = 0;
- bool multisample_active = false;
-
- struct Effect {
- GLuint fbo = 0;
- int width = 0;
- int height = 0;
-
- GLuint color = 0;
- };
-
- Effect copy_screen_effect;
-
- struct MipMaps {
- struct Size {
- GLuint fbo = 0;
- GLuint color = 0;
- int width = 0;
- int height = 0;
- };
-
- Vector<Size> sizes;
- GLuint color = 0;
- int levels = 0;
- };
-
- MipMaps mip_maps[2];
-
- struct External {
- GLuint fbo = 0;
- GLuint color = 0;
- GLuint depth = 0;
- RID texture;
- } external;
-
- int x = 0;
- int y = 0;
- int width = 0;
- int height = 0;
-
- bool flags[RendererStorage::RENDER_TARGET_FLAG_MAX] = {};
-
- // instead of allocating sized render targets immediately,
- // defer this for faster startup
- bool allocate_is_dirty = false;
- bool used_in_frame = false;
- RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
-
- bool use_fxaa = false;
- bool use_debanding = false;
-
- RID texture;
-
- bool used_dof_blur_near = false;
- bool mip_maps_allocated = false;
-
- Color clear_color = Color(1, 1, 1, 1);
- bool clear_requested = false;
-
- RenderTarget() {
- for (int i = 0; i < RendererStorage::RENDER_TARGET_FLAG_MAX; ++i) {
- flags[i] = false;
- }
- external.fbo = 0;
- }
-};
-
-} // namespace GLES3
-
-#endif // !GLES3_ENABLED
-
-#endif // !RENDER_TARGET_STORAGE_GLES3_H
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index d199b1032e..2a63c7ccad 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -43,6 +43,81 @@ TextureStorage *TextureStorage::get_singleton() {
TextureStorage::TextureStorage() {
singleton = this;
+
+ system_fbo = 0;
+
+ frame.count = 0;
+ frame.delta = 0;
+ frame.current_rt = nullptr;
+ frame.clear_request = false;
+
+ Config *config = Config::get_singleton();
+
+ //determine formats for depth textures (or renderbuffers)
+ if (config->support_depth_texture) {
+ // Will use texture for depth
+ // have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT,
+ // as there is no extension to test for this.
+ GLuint fbo;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ GLuint depth;
+ glGenTextures(1, &depth);
+ glBindTexture(GL_TEXTURE_2D, depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+ glDeleteFramebuffers(1, &fbo);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &depth);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ // If it fails, test to see if it supports a framebuffer texture using UNSIGNED_SHORT
+ // This is needed because many OSX devices don't support either UNSIGNED_INT or UNSIGNED_SHORT
+#ifdef GLES_OVER_GL
+ config->depth_internalformat = GL_DEPTH_COMPONENT16;
+#else
+ // OES_depth_texture extension only specifies GL_DEPTH_COMPONENT.
+ config->depth_internalformat = GL_DEPTH_COMPONENT;
+#endif
+ config->depth_type = GL_UNSIGNED_SHORT;
+
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ glGenTextures(1, &depth);
+ glBindTexture(GL_TEXTURE_2D, depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
+
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ //if it fails again depth textures aren't supported, use rgba shadows and renderbuffer for depth
+ config->support_depth_texture = false;
+ config->use_rgba_3d_shadows = true;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+ glDeleteFramebuffers(1, &fbo);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &depth);
+ }
+ }
}
TextureStorage::~TextureStorage() {
@@ -65,6 +140,55 @@ bool TextureStorage::can_create_resources_async() const {
return false;
}
+/* Canvas Texture API */
+
+RID TextureStorage::canvas_texture_allocate() {
+ return canvas_texture_owner.allocate_rid();
+}
+
+void TextureStorage::canvas_texture_initialize(RID p_rid) {
+ canvas_texture_owner.initialize_rid(p_rid);
+}
+
+void TextureStorage::canvas_texture_free(RID p_rid) {
+ canvas_texture_owner.free(p_rid);
+}
+
+void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ switch (p_channel) {
+ case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
+ ct->diffuse = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
+ ct->normal_map = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
+ ct->specular = p_texture;
+ } break;
+ }
+}
+
+void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ct->specular_color.r = p_specular_color.r;
+ ct->specular_color.g = p_specular_color.g;
+ ct->specular_color.b = p_specular_color.b;
+ ct->specular_color.a = p_shininess;
+}
+
+void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ct->texture_filter = p_filter;
+}
+
+void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ct->texture_repeat = p_repeat;
+}
+
+/* Texture API */
+
static const GLenum _cube_side_enum[6] = {
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
@@ -1208,4 +1332,812 @@ void TextureStorage::textures_keep_original(bool p_enable) {
Config::get_singleton()->keep_original_textures = p_enable;
}
+/* DECAL API */
+
+RID TextureStorage::decal_allocate() {
+ return RID();
+}
+
+void TextureStorage::decal_initialize(RID p_rid) {
+}
+
+void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
+}
+
+void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
+}
+
+void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
+}
+
+void TextureStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
+}
+
+void TextureStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
+}
+
+void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
+}
+
+void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
+}
+
+void TextureStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
+}
+
+void TextureStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
+}
+
+AABB TextureStorage::decal_get_aabb(RID p_decal) const {
+ return AABB();
+}
+
+/* RENDER TARGET API */
+
+GLuint TextureStorage::system_fbo = 0;
+
+void TextureStorage::_set_current_render_target(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+
+ if (rt) {
+ if (rt->allocate_is_dirty) {
+ rt->allocate_is_dirty = false;
+ _render_target_allocate(rt);
+ }
+
+ frame.current_rt = rt;
+ ERR_FAIL_COND(!rt);
+ frame.clear_request = false;
+
+ glViewport(0, 0, rt->width, rt->height);
+
+ _dims.rt_width = rt->width;
+ _dims.rt_height = rt->height;
+ _dims.win_width = rt->width;
+ _dims.win_height = rt->height;
+
+ } else {
+ frame.current_rt = nullptr;
+ frame.clear_request = false;
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+ }
+}
+
+void TextureStorage::_render_target_allocate(RenderTarget *rt) {
+ Config *config = Config::get_singleton();
+
+ // do not allocate a render target with no size
+ if (rt->width <= 0 || rt->height <= 0) {
+ return;
+ }
+
+ // do not allocate a render target that is attached to the screen
+ if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ rt->fbo = system_fbo;
+ return;
+ }
+
+ GLuint color_internal_format;
+ GLuint color_format;
+ GLuint color_type = GL_UNSIGNED_BYTE;
+ Image::Format image_format;
+
+ if (rt->flags[TextureStorage::RENDER_TARGET_TRANSPARENT]) {
+#ifdef GLES_OVER_GL
+ color_internal_format = GL_RGBA8;
+#else
+ color_internal_format = GL_RGBA;
+#endif
+ color_format = GL_RGBA;
+ image_format = Image::FORMAT_RGBA8;
+ } else {
+#ifdef GLES_OVER_GL
+ color_internal_format = GL_RGB8;
+#else
+ color_internal_format = GL_RGB;
+#endif
+ color_format = GL_RGB;
+ image_format = Image::FORMAT_RGB8;
+ }
+
+ rt->used_dof_blur_near = false;
+ rt->mip_maps_allocated = false;
+
+ {
+ /* Front FBO */
+
+ Texture *texture = get_texture(rt->texture);
+ ERR_FAIL_COND(!texture);
+
+ // framebuffer
+ glGenFramebuffers(1, &rt->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
+
+ // color
+ glGenTextures(1, &rt->color);
+ glBindTexture(GL_TEXTURE_2D, rt->color);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, nullptr);
+
+ if (texture->flags & TEXTURE_FLAG_FILTER) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ } else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
+
+ // depth
+
+ if (config->support_depth_texture) {
+ glGenTextures(1, &rt->depth);
+ glBindTexture(GL_TEXTURE_2D, rt->depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, config->depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config->depth_type, nullptr);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ } else {
+ glGenRenderbuffers(1, &rt->depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
+
+ glRenderbufferStorage(GL_RENDERBUFFER, config->depth_buffer_internalformat, rt->width, rt->height);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ glDeleteFramebuffers(1, &rt->fbo);
+ if (config->support_depth_texture) {
+ glDeleteTextures(1, &rt->depth);
+ } else {
+ glDeleteRenderbuffers(1, &rt->depth);
+ }
+
+ glDeleteTextures(1, &rt->color);
+ rt->fbo = 0;
+ rt->width = 0;
+ rt->height = 0;
+ rt->color = 0;
+ rt->depth = 0;
+ texture->tex_id = 0;
+ texture->active = false;
+ WARN_PRINT("Could not create framebuffer!!");
+ return;
+ }
+
+ texture->format = image_format;
+ texture->gl_format_cache = color_format;
+ texture->gl_type_cache = GL_UNSIGNED_BYTE;
+ texture->gl_internal_format_cache = color_internal_format;
+ texture->tex_id = rt->color;
+ texture->width = rt->width;
+ texture->alloc_width = rt->width;
+ texture->height = rt->height;
+ texture->alloc_height = rt->height;
+ texture->active = true;
+
+ texture_set_flags(rt->texture, texture->flags);
+ }
+
+ /* BACK FBO */
+ /* For MSAA */
+
+#ifndef JAVASCRIPT_ENABLED
+ if (rt->msaa >= RS::VIEWPORT_MSAA_2X && rt->msaa <= RS::VIEWPORT_MSAA_8X) {
+ rt->multisample_active = true;
+
+ static const int msaa_value[] = { 0, 2, 4, 8, 16 };
+ int msaa = msaa_value[rt->msaa];
+
+ int max_samples = 0;
+ glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+ if (msaa > max_samples) {
+ WARN_PRINT("MSAA must be <= GL_MAX_SAMPLES, falling-back to GL_MAX_SAMPLES = " + itos(max_samples));
+ msaa = max_samples;
+ }
+
+ //regular fbo
+ glGenFramebuffers(1, &rt->multisample_fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->multisample_fbo);
+
+ glGenRenderbuffers(1, &rt->multisample_depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_depth);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config->depth_buffer_internalformat, rt->width, rt->height);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->multisample_depth);
+
+ glGenRenderbuffers(1, &rt->multisample_color);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->multisample_color);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, color_internal_format, rt->width, rt->height);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rt->multisample_color);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ // Delete allocated resources and default to no MSAA
+ WARN_PRINT_ONCE("Cannot allocate back framebuffer for MSAA");
+ printf("err status: %x\n", status);
+ rt->multisample_active = false;
+
+ glDeleteFramebuffers(1, &rt->multisample_fbo);
+ rt->multisample_fbo = 0;
+
+ glDeleteRenderbuffers(1, &rt->multisample_depth);
+ rt->multisample_depth = 0;
+
+ glDeleteRenderbuffers(1, &rt->multisample_color);
+ rt->multisample_color = 0;
+ }
+
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ } else
+#endif // JAVASCRIPT_ENABLED
+ {
+ rt->multisample_active = false;
+ }
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // copy texscreen buffers
+ // if (!(rt->flags[TextureStorage::RENDER_TARGET_NO_SAMPLING])) {
+ if (true) {
+ glGenTextures(1, &rt->copy_screen_effect.color);
+ glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color);
+
+ if (rt->flags[TextureStorage::RENDER_TARGET_TRANSPARENT]) {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ } else {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rt->width, rt->height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glGenFramebuffers(1, &rt->copy_screen_effect.fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0);
+
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ _render_target_clear(rt);
+ ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+ }
+ }
+
+ // Allocate mipmap chains for post_process effects
+ // if (!rt->flags[RendererStorage::RENDER_TARGET_NO_3D] && rt->width >= 2 && rt->height >= 2) {
+ if (rt->width >= 2 && rt->height >= 2) {
+ for (int i = 0; i < 2; i++) {
+ ERR_FAIL_COND(rt->mip_maps[i].sizes.size());
+ int w = rt->width;
+ int h = rt->height;
+
+ if (i > 0) {
+ w >>= 1;
+ h >>= 1;
+ }
+
+ int level = 0;
+ int fb_w = w;
+ int fb_h = h;
+
+ while (true) {
+ RenderTarget::MipMaps::Size mm;
+ mm.width = w;
+ mm.height = h;
+ rt->mip_maps[i].sizes.push_back(mm);
+
+ w >>= 1;
+ h >>= 1;
+
+ if (w < 2 || h < 2) {
+ break;
+ }
+
+ level++;
+ }
+
+ GLsizei width = fb_w;
+ GLsizei height = fb_h;
+
+ if (config->render_to_mipmap_supported) {
+ glGenTextures(1, &rt->mip_maps[i].color);
+ glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].color);
+
+ for (int l = 0; l < level + 1; l++) {
+ glTexImage2D(GL_TEXTURE_2D, l, color_internal_format, width, height, 0, color_format, color_type, nullptr);
+ width = MAX(1, (width / 2));
+ height = MAX(1, (height / 2));
+ }
+#ifdef GLES_OVER_GL
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
+#endif
+ } else {
+ // Can't render to specific levels of a mipmap in ES 2.0 or Webgl so create a texture for each level
+ for (int l = 0; l < level + 1; l++) {
+ glGenTextures(1, &rt->mip_maps[i].sizes.write[l].color);
+ glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[l].color);
+ glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, width, height, 0, color_format, color_type, nullptr);
+ width = MAX(1, (width / 2));
+ height = MAX(1, (height / 2));
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ }
+
+ glDisable(GL_SCISSOR_TEST);
+ glColorMask(1, 1, 1, 1);
+ glDepthMask(GL_TRUE);
+
+ for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
+ RenderTarget::MipMaps::Size &mm = rt->mip_maps[i].sizes.write[j];
+
+ glGenFramebuffers(1, &mm.fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
+
+ if (config->render_to_mipmap_supported) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].color, j);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->mip_maps[i].sizes[j].color, 0);
+ }
+
+ bool used_depth = false;
+ if (j == 0 && i == 0) { //use always
+ if (config->support_depth_texture) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ } else {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ }
+ used_depth = true;
+ }
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ WARN_PRINT_ONCE("Cannot allocate mipmaps for 3D post processing effects");
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+ return;
+ }
+
+ glClearColor(1.0, 0.0, 1.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ if (used_depth) {
+ glClearDepth(1.0);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ }
+
+ rt->mip_maps[i].levels = level;
+
+ if (config->render_to_mipmap_supported) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ }
+ rt->mip_maps_allocated = true;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+}
+
+void TextureStorage::_render_target_clear(RenderTarget *rt) {
+ Config *config = Config::get_singleton();
+
+ // there is nothing to clear when DIRECT_TO_SCREEN is used
+ if (rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ return;
+ }
+
+ if (rt->fbo) {
+ glDeleteFramebuffers(1, &rt->fbo);
+ glDeleteTextures(1, &rt->color);
+ rt->fbo = 0;
+ }
+
+ if (rt->external.fbo != 0) {
+ // free this
+ glDeleteFramebuffers(1, &rt->external.fbo);
+
+ // clean up our texture
+ Texture *t = get_texture(rt->external.texture);
+ t->alloc_height = 0;
+ t->alloc_width = 0;
+ t->width = 0;
+ t->height = 0;
+ t->active = false;
+ texture_free(rt->external.texture);
+ memdelete(t);
+
+ rt->external.fbo = 0;
+ }
+
+ if (rt->depth) {
+ if (config->support_depth_texture) {
+ glDeleteTextures(1, &rt->depth);
+ } else {
+ glDeleteRenderbuffers(1, &rt->depth);
+ }
+
+ rt->depth = 0;
+ }
+
+ Texture *tex = get_texture(rt->texture);
+ tex->alloc_height = 0;
+ tex->alloc_width = 0;
+ tex->width = 0;
+ tex->height = 0;
+ tex->active = false;
+
+ if (rt->copy_screen_effect.color) {
+ glDeleteFramebuffers(1, &rt->copy_screen_effect.fbo);
+ rt->copy_screen_effect.fbo = 0;
+
+ glDeleteTextures(1, &rt->copy_screen_effect.color);
+ rt->copy_screen_effect.color = 0;
+ }
+
+ for (int i = 0; i < 2; i++) {
+ if (rt->mip_maps[i].sizes.size()) {
+ for (int j = 0; j < rt->mip_maps[i].sizes.size(); j++) {
+ glDeleteFramebuffers(1, &rt->mip_maps[i].sizes[j].fbo);
+ glDeleteTextures(1, &rt->mip_maps[i].sizes[j].color);
+ }
+
+ glDeleteTextures(1, &rt->mip_maps[i].color);
+ rt->mip_maps[i].sizes.clear();
+ rt->mip_maps[i].levels = 0;
+ rt->mip_maps[i].color = 0;
+ }
+ }
+
+ if (rt->multisample_active) {
+ glDeleteFramebuffers(1, &rt->multisample_fbo);
+ rt->multisample_fbo = 0;
+
+ glDeleteRenderbuffers(1, &rt->multisample_depth);
+ rt->multisample_depth = 0;
+
+ glDeleteRenderbuffers(1, &rt->multisample_color);
+
+ rt->multisample_color = 0;
+ }
+}
+
+RID TextureStorage::render_target_create() {
+ RenderTarget *rt = memnew(RenderTarget);
+ Texture *t = memnew(Texture);
+
+ t->type = RenderingDevice::TEXTURE_TYPE_2D;
+ t->flags = 0;
+ t->width = 0;
+ t->height = 0;
+ t->alloc_height = 0;
+ t->alloc_width = 0;
+ t->format = Image::FORMAT_R8;
+ t->target = GL_TEXTURE_2D;
+ t->gl_format_cache = 0;
+ t->gl_internal_format_cache = 0;
+ t->gl_type_cache = 0;
+ t->data_size = 0;
+ t->total_data_size = 0;
+ t->ignore_mipmaps = false;
+ t->compressed = false;
+ t->mipmaps = 1;
+ t->active = true;
+ t->tex_id = 0;
+ t->render_target = rt;
+
+ rt->texture = make_rid(t);
+ return render_target_owner.make_rid(rt);
+}
+
+void TextureStorage::render_target_free(RID p_rid) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_rid);
+ _render_target_clear(rt);
+
+ Texture *t = get_texture(rt->texture);
+ if (t) {
+ texture_free(rt->texture);
+ memdelete(t);
+ }
+ render_target_owner.free(p_rid);
+ memdelete(rt);
+}
+
+void TextureStorage::render_target_set_position(RID p_render_target, int p_x, int p_y) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->x = p_x;
+ rt->y = p_y;
+}
+
+void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ if (p_width == rt->width && p_height == rt->height) {
+ return;
+ }
+
+ _render_target_clear(rt);
+
+ rt->width = p_width;
+ rt->height = p_height;
+
+ // print_line("render_target_set_size " + itos(p_render_target.get_id()) + ", w " + itos(p_width) + " h " + itos(p_height));
+
+ rt->allocate_is_dirty = true;
+ //_render_target_allocate(rt);
+}
+
+// TODO: convert to Size2i internally
+Size2i TextureStorage::render_target_get_size(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Size2());
+
+ return Size2i(rt->width, rt->height);
+}
+
+RID TextureStorage::render_target_get_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->external.fbo == 0) {
+ return rt->texture;
+ } else {
+ return rt->external.texture;
+ }
+}
+
+void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ Config *config = Config::get_singleton();
+
+ if (p_texture_id == 0) {
+ if (rt->external.fbo != 0) {
+ // free this
+ glDeleteFramebuffers(1, &rt->external.fbo);
+
+ // and this
+ if (rt->external.depth != 0) {
+ glDeleteRenderbuffers(1, &rt->external.depth);
+ }
+
+ // clean up our texture
+ Texture *t = get_texture(rt->external.texture);
+ t->alloc_height = 0;
+ t->alloc_width = 0;
+ t->width = 0;
+ t->height = 0;
+ t->active = false;
+ texture_free(rt->external.texture);
+ memdelete(t);
+
+ rt->external.fbo = 0;
+ rt->external.color = 0;
+ rt->external.depth = 0;
+ }
+ } else {
+ Texture *t;
+
+ if (rt->external.fbo == 0) {
+ // create our fbo
+ glGenFramebuffers(1, &rt->external.fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
+
+ // allocate a texture
+ t = memnew(Texture);
+
+ t->type = RenderingDevice::TEXTURE_TYPE_2D;
+ t->flags = 0;
+ t->width = 0;
+ t->height = 0;
+ t->alloc_height = 0;
+ t->alloc_width = 0;
+ t->format = Image::FORMAT_RGBA8;
+ t->target = GL_TEXTURE_2D;
+ t->gl_format_cache = 0;
+ t->gl_internal_format_cache = 0;
+ t->gl_type_cache = 0;
+ t->data_size = 0;
+ t->compressed = false;
+ t->srgb = false;
+ t->total_data_size = 0;
+ t->ignore_mipmaps = false;
+ t->mipmaps = 1;
+ t->active = true;
+ t->tex_id = 0;
+ t->render_target = rt;
+
+ rt->external.texture = make_rid(t);
+
+ } else {
+ // bind our frame buffer
+ glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo);
+
+ // find our texture
+ t = get_texture(rt->external.texture);
+ }
+
+ // set our texture
+ t->tex_id = p_texture_id;
+ rt->external.color = p_texture_id;
+
+ // size shouldn't be different
+ t->width = rt->width;
+ t->height = rt->height;
+ t->alloc_height = rt->width;
+ t->alloc_width = rt->height;
+
+ // Switch our texture on our frame buffer
+ {
+ // set our texture as the destination for our framebuffer
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0);
+
+ // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :)
+ if (config->support_depth_texture) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ } else {
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ }
+ }
+
+ // check status and unbind
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ printf("framebuffer fail, status: %x\n", status);
+ }
+
+ ERR_FAIL_COND(status != GL_FRAMEBUFFER_COMPLETE);
+ }
+}
+
+void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ // When setting DIRECT_TO_SCREEN, you need to clear before the value is set, but allocate after as
+ // those functions change how they operate depending on the value of DIRECT_TO_SCREEN
+ if (p_flag == RENDER_TARGET_DIRECT_TO_SCREEN && p_value != rt->flags[RENDER_TARGET_DIRECT_TO_SCREEN]) {
+ _render_target_clear(rt);
+ rt->flags[p_flag] = p_value;
+ _render_target_allocate(rt);
+ }
+
+ rt->flags[p_flag] = p_value;
+
+ switch (p_flag) {
+ case RENDER_TARGET_TRANSPARENT:
+ /*
+ case RENDER_TARGET_HDR:
+ case RENDER_TARGET_NO_3D:
+ case RENDER_TARGET_NO_SAMPLING:
+ case RENDER_TARGET_NO_3D_EFFECTS: */
+ {
+ //must reset for these formats
+ _render_target_clear(rt);
+ _render_target_allocate(rt);
+ }
+ break;
+ default: {
+ }
+ }
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->used_in_frame;
+}
+
+void TextureStorage::render_target_clear_used(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->used_in_frame = false;
+}
+
+void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ if (rt->msaa == p_msaa) {
+ return;
+ }
+
+ _render_target_clear(rt);
+ rt->msaa = p_msaa;
+ _render_target_allocate(rt);
+}
+
+void TextureStorage::render_target_set_use_fxaa(RID p_render_target, bool p_fxaa) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->use_fxaa = p_fxaa;
+}
+
+void TextureStorage::render_target_set_use_debanding(RID p_render_target, bool p_debanding) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ if (p_debanding) {
+ WARN_PRINT_ONCE("Debanding is not supported in the OpenGL backend. Switch to the Vulkan backend and make sure HDR is enabled.");
+ }
+
+ rt->use_debanding = p_debanding;
+}
+
+void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = true;
+ rt->clear_color = p_clear_color;
+
+ // ERR_FAIL_COND(!frame.current_rt);
+ // frame.clear_request = true;
+ // frame.clear_request_color = p_color;
+}
+
+bool TextureStorage::render_target_is_clear_requested(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+ return rt->clear_requested;
+}
+Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Color());
+ return rt->clear_color;
+}
+
+void TextureStorage::render_target_disable_clear_request(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_do_clear_request(RID p_render_target) {
+}
+
+void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
+}
+
+Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const {
+ return Rect2i();
+}
+
+void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
+}
+
#endif // GLES3_ENABLED
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 7656cdf67e..7a5140a290 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -33,13 +33,20 @@
#ifdef GLES3_ENABLED
-#include "canvas_texture_storage.h"
#include "config.h"
#include "core/os/os.h"
#include "core/templates/rid_owner.h"
-#include "render_target_storage.h"
+#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/storage/texture_storage.h"
+// This must come first to avoid windows.h mess
+#include "platform_config.h"
+#ifndef OPENGL_INCLUDE_H
+#include <GLES3/gl3.h>
+#else
+#include OPENGL_INCLUDE_H
+#endif
+
namespace GLES3 {
#define _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
@@ -90,6 +97,24 @@ enum OpenGLTextureFlags {
TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
};
+struct CanvasTexture {
+ RID diffuse;
+ RID normal_map;
+ RID specular;
+ Color specular_color = Color(1, 1, 1, 1);
+ float shininess = 1.0;
+
+ RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+ RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+
+ Size2i size_cache = Size2i(1, 1);
+ bool use_normal_cache = false;
+ bool use_specular_cache = false;
+ bool cleared_cache = true;
+};
+
+struct RenderTarget;
+
struct Texture {
RID self;
@@ -296,6 +321,81 @@ private:
RS::CanvasItemTextureRepeat state_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
};
+struct RenderTarget {
+ RID self;
+ GLuint fbo = 0;
+ GLuint color = 0;
+ GLuint depth = 0;
+
+ GLuint multisample_fbo = 0;
+ GLuint multisample_color = 0;
+ GLuint multisample_depth = 0;
+ bool multisample_active = false;
+
+ struct Effect {
+ GLuint fbo = 0;
+ int width = 0;
+ int height = 0;
+
+ GLuint color = 0;
+ };
+
+ Effect copy_screen_effect;
+
+ struct MipMaps {
+ struct Size {
+ GLuint fbo = 0;
+ GLuint color = 0;
+ int width = 0;
+ int height = 0;
+ };
+
+ Vector<Size> sizes;
+ GLuint color = 0;
+ int levels = 0;
+ };
+
+ MipMaps mip_maps[2];
+
+ struct External {
+ GLuint fbo = 0;
+ GLuint color = 0;
+ GLuint depth = 0;
+ RID texture;
+ } external;
+
+ int x = 0;
+ int y = 0;
+ int width = 0;
+ int height = 0;
+
+ bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX] = {};
+
+ // instead of allocating sized render targets immediately,
+ // defer this for faster startup
+ bool allocate_is_dirty = false;
+ bool used_in_frame = false;
+ RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+
+ bool use_fxaa = false;
+ bool use_debanding = false;
+
+ RID texture;
+
+ bool used_dof_blur_near = false;
+ bool mip_maps_allocated = false;
+
+ Color clear_color = Color(1, 1, 1, 1);
+ bool clear_requested = false;
+
+ RenderTarget() {
+ for (int i = 0; i < RendererTextureStorage::RENDER_TARGET_FLAG_MAX; ++i) {
+ flags[i] = false;
+ }
+ external.fbo = 0;
+ }
+};
+
class TextureStorage : public RendererTextureStorage {
private:
static TextureStorage *singleton;
@@ -303,6 +403,12 @@ private:
Thread::ID _main_thread_id = 0;
bool _is_main_thread();
+ /* Canvas Texture API */
+
+ RID_Owner<CanvasTexture, true> canvas_texture_owner;
+
+ /* Texture API */
+
mutable RID_PtrOwner<Texture> texture_owner;
Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const;
@@ -310,12 +416,50 @@ private:
void texture_set_proxy(RID p_texture, RID p_proxy);
+ /* Render Target API */
+
+ mutable RID_PtrOwner<RenderTarget> render_target_owner;
+
+ // make access easier to these
+ struct Dimensions {
+ // render target
+ int rt_width;
+ int rt_height;
+
+ // window
+ int win_width;
+ int win_height;
+ Dimensions() {
+ rt_width = 0;
+ rt_height = 0;
+ win_width = 0;
+ win_height = 0;
+ }
+ } _dims;
+
public:
static TextureStorage *get_singleton();
TextureStorage();
virtual ~TextureStorage();
+ /* Canvas Texture API */
+
+ CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
+ bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
+
+ virtual RID canvas_texture_allocate() override;
+ virtual void canvas_texture_initialize(RID p_rid) override;
+ virtual void canvas_texture_free(RID p_rid) override;
+
+ virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
+ virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
+
+ virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
+ virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
+
+ /* Texture API */
+
Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
RID make_rid(Texture *p_texture) { return texture_owner.make_rid(p_texture); };
@@ -380,6 +524,86 @@ public:
void texture_set_shrink_all_x2_on_set_data(bool p_enable);
RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const;
void textures_keep_original(bool p_enable);
+
+ /* DECAL API */
+
+ virtual RID decal_allocate() override;
+ virtual void decal_initialize(RID p_rid) override;
+ virtual void decal_free(RID p_rid) override{};
+
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
+
+ virtual AABB decal_get_aabb(RID p_decal) const override;
+
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+
+ /* RENDER TARGET API */
+
+ static GLuint system_fbo;
+
+ struct Frame {
+ GLES3::RenderTarget *current_rt;
+
+ // these 2 may have been superseded by the equivalents in the render target.
+ // these may be able to be removed.
+ bool clear_request;
+ Color clear_request_color;
+
+ float time;
+ float delta;
+ uint64_t count;
+
+ Frame() {
+ // current_rt = nullptr;
+ // clear_request = false;
+ }
+ } frame;
+
+ RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
+ bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
+
+ void _render_target_clear(RenderTarget *rt);
+ void _render_target_allocate(RenderTarget *rt);
+ void _set_current_render_target(RID p_render_target);
+
+ virtual RID render_target_create() override;
+ virtual void render_target_free(RID p_rid) override;
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
+ Size2i render_target_get_size(RID p_render_target);
+ virtual RID render_target_get_texture(RID p_render_target) override;
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+
+ virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
+ virtual bool render_target_was_used(RID p_render_target) override;
+ void render_target_clear_used(RID p_render_target);
+ void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa);
+ void render_target_set_use_fxaa(RID p_render_target, bool p_fxaa);
+ void render_target_set_use_debanding(RID p_render_target, bool p_debanding);
+
+ // new
+ void render_target_set_as_unused(RID p_render_target) override {
+ render_target_clear_used(p_render_target);
+ }
+
+ void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
+ bool render_target_is_clear_requested(RID p_render_target) override;
+ Color render_target_get_clear_request_color(RID p_render_target) override;
+ void render_target_disable_clear_request(RID p_render_target) override;
+ void render_target_do_clear_request(RID p_render_target) override;
+
+ void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
+ Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
+ void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
};
} // namespace GLES3
diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp
index 46e271f9c9..917bfec574 100644
--- a/drivers/png/image_loader_png.cpp
+++ b/drivers/png/image_loader_png.cpp
@@ -36,18 +36,16 @@
#include <string.h>
-Error ImageLoaderPNG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
+Error ImageLoaderPNG::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
const uint64_t buffer_size = f->get_length();
Vector<uint8_t> file_buffer;
Error err = file_buffer.resize(buffer_size);
if (err) {
- f->close();
return err;
}
{
uint8_t *writer = file_buffer.ptrw();
f->get_buffer(writer, buffer_size);
- f->close();
}
const uint8_t *reader = file_buffer.ptr();
return PNGDriverCommon::png_to_image(reader, buffer_size, p_force_linear, p_image);
diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h
index af3bcd5b66..522cc901d4 100644
--- a/drivers/png/image_loader_png.h
+++ b/drivers/png/image_loader_png.h
@@ -40,7 +40,7 @@ private:
static Ref<Image> load_mem_png(const uint8_t *p_png, int p_size);
public:
- virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderPNG();
};
diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp
index ca84fb6be9..8633d2dc4e 100644
--- a/drivers/png/resource_saver_png.cpp
+++ b/drivers/png/resource_saver_png.cpp
@@ -52,20 +52,16 @@ Error ResourceSaverPNG::save_image(const String &p_path, const Ref<Image> &p_img
Vector<uint8_t> buffer;
Error err = PNGDriverCommon::image_to_png(p_img, buffer);
ERR_FAIL_COND_V_MSG(err, err, "Can't convert image to PNG.");
- FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err, err, vformat("Can't save PNG at path: '%s'.", p_path));
const uint8_t *reader = buffer.ptr();
file->store_buffer(reader, buffer.size());
if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
- memdelete(file);
return ERR_CANT_CREATE;
}
- file->close();
- memdelete(file);
-
return OK;
}
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index af47173b41..7e6105f033 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -49,7 +49,7 @@
#include <mntent.h>
#endif
-DirAccess *DirAccessUnix::create_fs() {
+Ref<DirAccess> DirAccessUnix::create_fs() {
return memnew(DirAccessUnix);
}
@@ -374,7 +374,7 @@ Error DirAccessUnix::change_dir(String p_dir) {
return OK;
}
-String DirAccessUnix::get_current_dir(bool p_include_drive) {
+String DirAccessUnix::get_current_dir(bool p_include_drive) const {
String base = _get_root_path();
if (!base.is_empty()) {
String bd = current_dir.replace_first(base, "");
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index b4dc012db2..4fea7cd154 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -43,7 +43,7 @@
class DirAccessUnix : public DirAccess {
DIR *dir_stream = nullptr;
- static DirAccess *create_fs();
+ static Ref<DirAccess> create_fs();
String current_dir;
bool _cisdir;
@@ -67,7 +67,7 @@ public:
virtual bool drives_are_shortcuts();
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true); ///< return current dir location
+ virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
virtual Error make_dir(String p_dir);
virtual bool file_exists(String p_file);
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index ea442ad8bf..e0b2994b63 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -71,10 +71,7 @@ void FileAccessUnix::check_errors() const {
}
Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
- if (f) {
- fclose(f);
- }
- f = nullptr;
+ _close();
path_src = p_path;
path = fix_path(p_path);
@@ -148,7 +145,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
return OK;
}
-void FileAccessUnix::close() {
+void FileAccessUnix::_close() {
if (!f) {
return;
}
@@ -336,14 +333,14 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per
return FAILED;
}
-FileAccess *FileAccessUnix::create_libc() {
+Ref<FileAccess> FileAccessUnix::create_libc() {
return memnew(FileAccessUnix);
}
CloseNotificationFunc FileAccessUnix::close_notification_func = nullptr;
FileAccessUnix::~FileAccessUnix() {
- close();
+ _close();
}
#endif
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 8ebdcd2a2d..4340bbbc82 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -49,13 +49,13 @@ class FileAccessUnix : public FileAccess {
String path;
String path_src;
- static FileAccess *create_libc();
+ static Ref<FileAccess> create_libc();
+ void _close();
public:
static CloseNotificationFunc close_notification_func;
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual String get_path() const; /// returns the path for the current open file
diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp
index 260f7dd08b..400802686e 100644
--- a/drivers/vulkan/rendering_device_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_vulkan.cpp
@@ -4875,9 +4875,8 @@ Vector<uint8_t> RenderingDeviceVulkan::shader_compile_binary_from_spirv(const Ve
"Reflection of SPIR-V shader stage '" + String(shader_stage_names[p_spirv[i].shader_stage]) + "' failed obtaining push constants.");
#if 0
if (pconstants[0] == nullptr) {
- FileAccess *f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open("res://popo.spv", FileAccess::WRITE);
f->store_buffer((const uint8_t *)&SpirV[0], SpirV.size() * sizeof(uint32_t));
- memdelete(f);
}
#endif
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 6f3bad12c1..881575d245 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -185,7 +185,7 @@ Error DirAccessWindows::make_dir(String p_dir) {
return ERR_CANT_CREATE;
}
-String DirAccessWindows::get_current_dir(bool p_include_drive) {
+String DirAccessWindows::get_current_dir(bool p_include_drive) const {
String base = _get_root_path();
if (!base.is_empty()) {
String bd = current_dir.replace("\\", "/").replace_first(base, "");
diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h
index 78d37074e5..fbb07ddef8 100644
--- a/drivers/windows/dir_access_windows.h
+++ b/drivers/windows/dir_access_windows.h
@@ -64,7 +64,7 @@ public:
virtual String get_drive(int p_drive);
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true); ///< return current dir location
+ virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
virtual bool file_exists(String p_file);
virtual bool dir_exists(String p_dir);
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index 59dc1d8e77..1a66d19373 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -59,11 +59,10 @@ void FileAccessWindows::check_errors() const {
}
Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
+ _close();
+
path_src = p_path;
path = fix_path(p_path);
- if (f) {
- close();
- }
const WCHAR *mode_string;
@@ -134,7 +133,7 @@ Error FileAccessWindows::_open(const String &p_path, int p_mode_flags) {
}
}
-void FileAccessWindows::close() {
+void FileAccessWindows::_close() {
if (!f) {
return;
}
@@ -350,7 +349,7 @@ Error FileAccessWindows::_set_unix_permissions(const String &p_file, uint32_t p_
}
FileAccessWindows::~FileAccessWindows() {
- close();
+ _close();
}
#endif // WINDOWS_ENABLED
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 93d37c3b5a..5d67b6ca4f 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -48,9 +48,10 @@ class FileAccessWindows : public FileAccess {
String path_src;
String save_path;
+ void _close();
+
public:
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual String get_path() const; /// returns the path for the current open file
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index 96931efd3b..49c79d709b 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -61,29 +61,37 @@ static const char *_joy_axis_descriptions[(size_t)JoyAxis::MAX * 2] = {
TTRC("Joystick 4 Down"),
};
-String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event) {
+String InputEventConfigurationDialog::get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const {
ERR_FAIL_COND_V_MSG(p_event.is_null(), String(), "Provided event is not a valid instance of InputEvent");
- // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
- Ref<InputEventJoypadMotion> jpmotion = p_event;
- if (jpmotion.is_valid()) {
+ String text = p_event->as_text();
+
+ Ref<InputEventMouse> mouse = p_event;
+ Ref<InputEventJoypadMotion> jp_motion = p_event;
+ Ref<InputEventJoypadButton> jp_button = p_event;
+ if (jp_motion.is_valid()) {
+ // Joypad motion events will display slightly differently than what the event->as_text() provides. See #43660.
String desc = TTR("Unknown Joypad Axis");
- if (jpmotion->get_axis() < JoyAxis::MAX) {
- desc = RTR(_joy_axis_descriptions[2 * (size_t)jpmotion->get_axis() + (jpmotion->get_axis_value() < 0 ? 0 : 1)]);
+ if (jp_motion->get_axis() < JoyAxis::MAX) {
+ desc = RTR(_joy_axis_descriptions[2 * (size_t)jp_motion->get_axis() + (jp_motion->get_axis_value() < 0 ? 0 : 1)]);
}
- return vformat("Joypad Axis %s %s (%s)", itos((int64_t)jpmotion->get_axis()), jpmotion->get_axis_value() < 0 ? "-" : "+", desc);
- } else {
- return p_event->as_text();
+ text = vformat("Joypad Axis %s %s (%s)", itos((int64_t)jp_motion->get_axis()), jp_motion->get_axis_value() < 0 ? "-" : "+", desc);
+ }
+ if (p_include_device && (mouse.is_valid() || jp_button.is_valid() || jp_motion.is_valid())) {
+ String device_string = _get_device_string(p_event->get_device());
+ text += vformat(" - %s", device_string);
}
+
+ return text;
}
-void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) {
+void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event, bool p_update_input_list_selection) {
if (p_event.is_valid()) {
event = p_event;
// Update Label
- event_as_text->set_text(get_event_text(event));
+ event_as_text->set_text(get_event_text(event, true));
Ref<InputEventKey> k = p_event;
Ref<InputEventMouseButton> mb = p_event;
@@ -122,7 +130,7 @@ void InputEventConfigurationDialog::_set_event(const Ref<InputEvent> &p_event) {
additional_options_container->show();
// Update selected item in input list.
- if (k.is_valid() || joyb.is_valid() || joym.is_valid() || mb.is_valid()) {
+ if (p_update_input_list_selection && (k.is_valid() || joyb.is_valid() || joym.is_valid() || mb.is_valid())) {
TreeItem *category = input_list_tree->get_root()->get_first_child();
while (category) {
TreeItem *input_item = category->get_first_child();
@@ -234,10 +242,13 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> &
}
}
+ // Create an editable reference
+ Ref<InputEvent> received_event = p_event;
+
// Check what the type is and if it is allowed.
- Ref<InputEventKey> k = p_event;
- Ref<InputEventJoypadButton> joyb = p_event;
- Ref<InputEventJoypadMotion> joym = p_event;
+ Ref<InputEventKey> k = received_event;
+ Ref<InputEventJoypadButton> joyb = received_event;
+ Ref<InputEventJoypadMotion> joym = received_event;
int type = 0;
if (k.is_valid()) {
@@ -266,7 +277,7 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> &
}
if (k.is_valid()) {
- k->set_pressed(false); // to avoid serialisation of 'pressed' property - doesn't matter for actions anyway.
+ k->set_pressed(false); // To avoid serialisation of 'pressed' property - doesn't matter for actions anyway.
// Maintain physical keycode option state
if (physical_key_checkbox->is_pressed()) {
k->set_keycode(Key::NONE);
@@ -275,15 +286,17 @@ void InputEventConfigurationDialog::_listen_window_input(const Ref<InputEvent> &
}
}
- Ref<InputEventWithModifiers> mod = p_event;
+ Ref<InputEventWithModifiers> mod = received_event;
if (mod.is_valid()) {
// Maintain store command option state
mod->set_store_command(store_command_checkbox->is_pressed());
-
mod->set_window_id(0);
}
- _set_event(p_event);
+ // Maintain device selection.
+ received_event->set_device(_get_current_device());
+
+ _set_event(received_event);
set_input_as_handled();
}
@@ -331,7 +344,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventMouseButton> mb;
mb.instantiate();
mb->set_button_index(mouse_buttons[i]);
- String desc = get_event_text(mb);
+ String desc = get_event_text(mb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -354,7 +367,7 @@ void InputEventConfigurationDialog::_update_input_list() {
Ref<InputEventJoypadButton> joyb;
joyb.instantiate();
joyb->set_button_index((JoyButton)i);
- String desc = get_event_text(joyb);
+ String desc = get_event_text(joyb, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -380,7 +393,7 @@ void InputEventConfigurationDialog::_update_input_list() {
joym.instantiate();
joym->set_axis((JoyAxis)axis);
joym->set_axis_value(direction);
- String desc = get_event_text(joym);
+ String desc = get_event_text(joym, false);
if (!search_term.is_empty() && desc.findn(search_term) == -1) {
continue;
@@ -495,7 +508,7 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
k->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed());
k->set_store_command(store_command_checkbox->is_pressed());
- _set_event(k);
+ _set_event(k, false);
} break;
case InputEventConfigurationDialog::INPUT_MOUSE_BUTTON: {
MouseButton idx = (MouseButton)(int)selected->get_meta("__index");
@@ -510,12 +523,19 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
mb->set_meta_pressed(mod_checkboxes[MOD_META]->is_pressed());
mb->set_store_command(store_command_checkbox->is_pressed());
- _set_event(mb);
+ // Maintain selected device
+ mb->set_device(_get_current_device());
+
+ _set_event(mb, false);
} break;
case InputEventConfigurationDialog::INPUT_JOY_BUTTON: {
JoyButton idx = (JoyButton)(int)selected->get_meta("__index");
Ref<InputEventJoypadButton> jb = InputEventJoypadButton::create_reference(idx);
- _set_event(jb);
+
+ // Maintain selected device
+ jb->set_device(_get_current_device());
+
+ _set_event(jb, false);
} break;
case InputEventConfigurationDialog::INPUT_JOY_MOTION: {
JoyAxis axis = (JoyAxis)(int)selected->get_meta("__axis");
@@ -525,24 +545,35 @@ void InputEventConfigurationDialog::_input_list_item_selected() {
jm.instantiate();
jm->set_axis(axis);
jm->set_axis_value(value);
- _set_event(jm);
+
+ // Maintain selected device
+ jm->set_device(_get_current_device());
+
+ _set_event(jm, false);
} break;
}
}
-void InputEventConfigurationDialog::_set_current_device(int i_device) {
- device_id_option->select(i_device + 1);
+void InputEventConfigurationDialog::_device_selection_changed(int p_option_button_index) {
+ // Subtract 1 as option index 0 corresponds to "All Devices" (value of -1)
+ // and option index 1 corresponds to device 0, etc...
+ event->set_device(p_option_button_index - 1);
+ event_as_text->set_text(get_event_text(event, true));
+}
+
+void InputEventConfigurationDialog::_set_current_device(int p_device) {
+ device_id_option->select(p_device + 1);
}
int InputEventConfigurationDialog::_get_current_device() const {
return device_id_option->get_selected() - 1;
}
-String InputEventConfigurationDialog::_get_device_string(int i_device) const {
- if (i_device == InputMap::ALL_DEVICES) {
+String InputEventConfigurationDialog::_get_device_string(int p_device) const {
+ if (p_device == InputMap::ALL_DEVICES) {
return TTR("All Devices");
}
- return TTR("Device") + " " + itos(i_device);
+ return TTR("Device") + " " + itos(p_device);
}
void InputEventConfigurationDialog::_notification(int p_what) {
@@ -558,8 +589,6 @@ void InputEventConfigurationDialog::_notification(int p_what) {
icon_cache.joypad_button = get_theme_icon(SNAME("JoyButton"), SNAME("EditorIcons"));
icon_cache.joypad_axis = get_theme_icon(SNAME("JoyAxis"), SNAME("EditorIcons"));
- mouse_detection_rect->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor")));
-
_update_input_list();
} break;
}
@@ -588,9 +617,12 @@ void InputEventConfigurationDialog::popup_and_configure(const Ref<InputEvent> &p
// Switch to "Listen" tab
tab_container->set_current_tab(0);
+
+ // Select "All Devices" by default.
+ device_id_option->select(0);
}
- popup_centered();
+ popup_centered(Size2(0, 400) * EDSCALE);
}
Ref<InputEvent> InputEventConfigurationDialog::get_event() const {
@@ -622,8 +654,8 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
event_as_text = memnew(Label);
event_as_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
vb->add_child(event_as_text);
- // Mouse button detection rect (Mouse button event outside this ColorRect will be ignored)
- mouse_detection_rect = memnew(ColorRect);
+ // Mouse button detection rect (Mouse button event outside this rect will be ignored)
+ mouse_detection_rect = memnew(Panel);
mouse_detection_rect->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vb->add_child(mouse_detection_rect);
tab_container->add_child(vb);
@@ -673,12 +705,13 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() {
device_id_option = memnew(OptionButton);
device_id_option->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- device_container->add_child(device_id_option);
-
for (int i = -1; i < 8; i++) {
device_id_option->add_item(_get_device_string(i));
}
- _set_current_device(0);
+ device_id_option->connect("item_selected", callable_mp(this, &InputEventConfigurationDialog::_device_selection_changed));
+ _set_current_device(InputMap::ALL_DEVICES);
+ device_container->add_child(device_id_option);
+
device_container->hide();
additional_options_container->add_child(device_container);
@@ -1096,7 +1129,7 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
TreeItem *event_item = action_tree->create_item(action_item);
// First Column - Text
- event_item->set_text(0, event_config_dialog->get_event_text(event)); // Need to us the special description for JoypadMotion here, so don't use as_text() directly.
+ event_item->set_text(0, event_config_dialog->get_event_text(event, true));
event_item->set_meta("__event", event);
event_item->set_meta("__index", evnt_idx);
@@ -1136,7 +1169,7 @@ void ActionMapEditor::update_action_list(const Vector<ActionInfo> &p_action_info
void ActionMapEditor::show_message(const String &p_message) {
message->set_text(p_message);
- message->popup_centered(Size2(300, 100) * EDSCALE);
+ message->popup_centered();
}
void ActionMapEditor::use_external_search_box(LineEdit *p_searchbox) {
diff --git a/editor/action_map_editor.h b/editor/action_map_editor.h
index e96139e070..b676c55403 100644
--- a/editor/action_map_editor.h
+++ b/editor/action_map_editor.h
@@ -67,7 +67,7 @@ private:
// Listening for input
Label *event_as_text = nullptr;
- ColorRect *mouse_detection_rect = nullptr;
+ Panel *mouse_detection_rect = nullptr;
// List of All Key/Mouse/Joypad input options.
int allowed_input_types;
@@ -97,7 +97,7 @@ private:
CheckBox *physical_key_checkbox = nullptr;
- void _set_event(const Ref<InputEvent> &p_event);
+ void _set_event(const Ref<InputEvent> &p_event, bool p_update_input_list_selection = true);
void _tab_selected(int p_tab);
void _listen_window_input(const Ref<InputEvent> &p_event);
@@ -110,9 +110,10 @@ private:
void _store_command_toggled(bool p_checked);
void _physical_keycode_toggled(bool p_checked);
- void _set_current_device(int i_device);
+ void _device_selection_changed(int p_option_button_index);
+ void _set_current_device(int p_device);
int _get_current_device() const;
- String _get_device_string(int i_device) const;
+ String _get_device_string(int p_device) const;
protected:
void _notification(int p_what);
@@ -121,7 +122,7 @@ public:
// Pass an existing event to configure it. Alternatively, pass no event to start with a blank configuration.
void popup_and_configure(const Ref<InputEvent> &p_event = Ref<InputEvent>());
Ref<InputEvent> get_event() const;
- String get_event_text(const Ref<InputEvent> &p_event);
+ String get_event_text(const Ref<InputEvent> &p_event, bool p_include_device) const;
void set_allowed_input_types(int p_type_masks);
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index dc69a8cb08..685dde4d98 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -1961,11 +1961,21 @@ void AnimationTrackEdit::_notification(int p_what) {
int limit = timeline->get_name_limit();
+ if (track % 2 == 1) {
+ // Draw a background over odd lines to make long lists of tracks easier to read.
+ draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), Color(0.5, 0.5, 0.5, 0.05));
+ }
+
+ if (hovered) {
+ // Draw hover feedback.
+ draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), Color(0.5, 0.5, 0.5, 0.1));
+ }
+
if (has_focus()) {
Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
accent.a *= 0.7;
// Offside so the horizontal sides aren't cutoff.
- draw_rect(Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)), accent, false);
+ draw_style_box(get_theme_stylebox(SNAME("Focus"), SNAME("EditorStyles")), Rect2(Point2(1 * EDSCALE, 0), get_size() - Size2(1 * EDSCALE, 0)));
}
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
@@ -2236,7 +2246,16 @@ void AnimationTrackEdit::_notification(int p_what) {
}
} break;
+ case NOTIFICATION_MOUSE_ENTER:
+ hovered = true;
+ update();
+ break;
case NOTIFICATION_MOUSE_EXIT:
+ hovered = false;
+ // When the mouse cursor exits the track, we're no longer hovering any keyframe.
+ hovering_key_idx = -1;
+ update();
+ [[fallthrough]];
case NOTIFICATION_DRAG_END: {
cancel_drop();
} break;
@@ -2348,7 +2367,13 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
}
}
- draw_texture(icon_to_draw, ofs);
+ // Use a different color for the currently hovered key.
+ // The color multiplier is chosen to work with both dark and light editor themes,
+ // and on both unselected and selected key icons.
+ draw_texture(
+ icon_to_draw,
+ ofs,
+ p_index == hovering_key_idx ? get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")) : Color(1, 1, 1));
}
// Helper.
@@ -2935,6 +2960,59 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventMouseMotion> mm = p_event;
+ if (mm.is_valid()) {
+ const int previous_hovering_key_idx = hovering_key_idx;
+
+ // Hovering compressed keyframes for editing is not possible.
+ if (!animation->track_is_compressed(track)) {
+ const float scale = timeline->get_zoom_scale();
+ const int limit = timeline->get_name_limit();
+ const int limit_end = get_size().width - timeline->get_buttons_width();
+ // Left Border including space occupied by keyframes on t=0.
+ const int limit_start_hitbox = limit - type_icon->get_width();
+ const Point2 pos = mm->get_position();
+
+ if (pos.x >= limit_start_hitbox && pos.x <= limit_end) {
+ // Use the same logic as key selection to ensure that hovering accurately represents
+ // which key will be selected when clicking.
+ int key_idx = -1;
+ float key_distance = 1e20;
+
+ hovering_key_idx = -1;
+
+ // Hovering should happen in the opposite order of drawing for more accurate overlap hovering.
+ for (int i = animation->track_get_key_count(track) - 1; i >= 0; i--) {
+ Rect2 rect = get_key_rect(i, scale);
+ float offset = animation->track_get_key_time(track, i) - timeline->get_value();
+ offset = offset * scale + limit;
+ rect.position.x += offset;
+
+ if (rect.has_point(pos)) {
+ if (is_key_selectable_by_distance()) {
+ const float distance = ABS(offset - pos.x);
+ if (key_idx == -1 || distance < key_distance) {
+ key_idx = i;
+ key_distance = distance;
+ hovering_key_idx = i;
+ }
+ } else {
+ // First one does it.
+ hovering_key_idx = i;
+ break;
+ }
+ }
+ }
+
+ print_line(hovering_key_idx);
+
+ if (hovering_key_idx != previous_hovering_key_idx) {
+ // Required to draw keyframe hover feedback on the correct keyframe.
+ update();
+ }
+ }
+ }
+ }
+
if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE && moving_selection_attempt) {
if (!moving_selection) {
moving_selection = true;
diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h
index d025dd3d26..0f6d12b4d4 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -171,7 +171,9 @@ class AnimationTrackEdit : public Control {
PopupMenu *menu = nullptr;
+ bool hovered = false;
bool clicking_on_name = false;
+ int hovering_key_idx = -1;
void _zoom_changed();
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index f9858aa514..fbb61a1614 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -377,17 +377,17 @@ void CreateDialog::_confirmed() {
return;
}
- FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
- if (f) {
- f->store_line(selected_item);
-
- for (int i = 0; i < MIN(32, recent->get_item_count()); i++) {
- if (recent->get_item_text(i) != selected_item) {
- f->store_line(recent->get_item_text(i));
+ {
+ Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE);
+ if (f.is_valid()) {
+ f->store_line(selected_item);
+
+ for (int i = 0; i < MIN(32, recent->get_item_count()); i++) {
+ if (recent->get_item_text(i) != selected_item) {
+ f->store_line(recent->get_item_text(i));
+ }
}
}
-
- memdelete(f);
}
// To prevent, emitting an error from the transient window (shader dialog for example) hide this dialog before emitting the "create" signal.
@@ -647,25 +647,26 @@ void CreateDialog::_save_and_update_favorite_list() {
favorites->clear();
TreeItem *root = favorites->create_item();
- FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
- if (f) {
- for (int i = 0; i < favorite_list.size(); i++) {
- String l = favorite_list[i];
- String name = l.get_slicec(' ', 0);
- if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) {
- continue;
- }
- f->store_line(l);
+ {
+ Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE);
+ if (f.is_valid()) {
+ for (int i = 0; i < favorite_list.size(); i++) {
+ String l = favorite_list[i];
+ String name = l.get_slicec(' ', 0);
+ if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) {
+ continue;
+ }
+ f->store_line(l);
- if (_is_class_disabled_by_feature_profile(name)) {
- continue;
- }
+ if (_is_class_disabled_by_feature_profile(name)) {
+ continue;
+ }
- TreeItem *ti = favorites->create_item(root);
- ti->set_text(0, l);
- ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
+ TreeItem *ti = favorites->create_item(root);
+ ti->set_text(0, l);
+ ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
+ }
}
- memdelete(f);
}
emit_signal(SNAME("favorites_updated"));
@@ -673,8 +674,8 @@ void CreateDialog::_save_and_update_favorite_list() {
void CreateDialog::_load_favorites_and_history() {
String dir = EditorSettings::get_singleton()->get_project_settings_dir();
- FileAccess *f = FileAccess::open(dir.plus_file("create_recent." + base_type), FileAccess::READ);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(dir.plus_file("create_recent." + base_type), FileAccess::READ);
+ if (f.is_valid()) {
while (!f->eof_reached()) {
String l = f->get_line().strip_edges();
String name = l.get_slicec(' ', 0);
@@ -683,12 +684,10 @@ void CreateDialog::_load_favorites_and_history() {
recent->add_item(l, EditorNode::get_singleton()->get_class_icon(name, icon_fallback));
}
}
-
- memdelete(f);
}
f = FileAccess::open(dir.plus_file("favorites." + base_type), FileAccess::READ);
- if (f) {
+ if (f.is_valid()) {
while (!f->eof_reached()) {
String l = f->get_line().strip_edges();
@@ -696,8 +695,6 @@ void CreateDialog::_load_favorites_and_history() {
favorite_list.push_back(l);
}
}
-
- memdelete(f);
}
}
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index 1e8753acc0..3a3b35f8a5 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -164,7 +164,7 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) {
switch (file_dialog_purpose) {
case SAVE_MONITORS_CSV: {
Error err;
- FileAccessRef file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
if (err != OK) {
ERR_PRINT("Failed to open " + p_file);
@@ -209,7 +209,7 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) {
} break;
case SAVE_VRAM_CSV: {
Error err;
- FileAccessRef file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
if (err != OK) {
ERR_PRINT("Failed to open " + p_file);
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 95b3a02631..35f40a159a 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -749,7 +749,7 @@ void OrphanResourcesDialog::_find_to_delete(TreeItem *p_item, List<String> &path
}
void OrphanResourcesDialog::_delete_confirm() {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (const String &E : paths) {
da->remove(E);
EditorFileSystem::get_singleton()->update_file(E);
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index adad8fdba8..16cbc0f34d 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -1035,8 +1035,8 @@ static Error _parse_methods(Ref<XMLParser> &parser, Vector<DocData::MethodDoc> &
Error DocTools::load_classes(const String &p_dir) {
Error err;
- DirAccessRef da = DirAccess::open(p_dir, &err);
- if (!da) {
+ Ref<DirAccess> da = DirAccess::open(p_dir, &err);
+ if (da.is_null()) {
return err;
}
@@ -1063,8 +1063,8 @@ Error DocTools::load_classes(const String &p_dir) {
Error DocTools::erase_classes(const String &p_dir) {
Error err;
- DirAccessRef da = DirAccess::open(p_dir, &err);
- if (!da) {
+ Ref<DirAccess> da = DirAccess::open(p_dir, &err);
+ if (da.is_null()) {
return err;
}
@@ -1273,7 +1273,7 @@ Error DocTools::_load(Ref<XMLParser> parser) {
return OK;
}
-static void _write_string(FileAccess *f, int p_tablevel, const String &p_string) {
+static void _write_string(Ref<FileAccess> f, int p_tablevel, const String &p_string) {
if (p_string.is_empty()) {
return;
}
@@ -1284,7 +1284,7 @@ static void _write_string(FileAccess *f, int p_tablevel, const String &p_string)
f->store_string(tab + p_string + "\n");
}
-static void _write_method_doc(FileAccess *f, const String &p_name, Vector<DocData::MethodDoc> &p_method_docs) {
+static void _write_method_doc(Ref<FileAccess> f, const String &p_name, Vector<DocData::MethodDoc> &p_method_docs) {
if (!p_method_docs.is_empty()) {
p_method_docs.sort();
_write_string(f, 1, "<" + p_name + "s>");
@@ -1350,7 +1350,7 @@ Error DocTools::save_classes(const String &p_default_path, const Map<String, Str
Error err;
String save_file = save_path.plus_file(c.name + ".xml");
- FileAccessRef f = FileAccess::open(save_file, FileAccess::WRITE, &err);
+ Ref<FileAccess> f = FileAccess::open(save_file, FileAccess::WRITE, &err);
ERR_CONTINUE_MSG(err != OK, "Can't write doc file: " + save_file + ".");
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index 2537c4d4a8..7dcb9a4088 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -64,8 +64,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
package_path = p_path;
Set<String> files_sorted;
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
unzFile pkg = unzOpen2(p_path.utf8().get_data(), &io);
if (!pkg) {
@@ -238,8 +237,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
}
void EditorAssetInstaller::ok_pressed() {
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
unzFile pkg = unzOpen2(package_path.utf8().get_data(), &io);
if (!pkg) {
@@ -280,7 +278,7 @@ void EditorAssetInstaller::ok_pressed() {
dirpath = dirpath.substr(0, dirpath.length() - 1);
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->make_dir(dirpath);
} else {
Vector<uint8_t> data;
@@ -291,10 +289,9 @@ void EditorAssetInstaller::ok_pressed() {
unzReadCurrentFile(pkg, data.ptrw(), data.size());
unzCloseCurrentFile(pkg);
- FileAccess *f = FileAccess::open(path, FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_buffer(data.ptr(), data.size());
- memdelete(f);
} else {
failed_files.push_back(path);
}
diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp
index 9fabde93ef..8494991892 100644
--- a/editor/editor_dir_dialog.cpp
+++ b/editor/editor_dir_dialog.cpp
@@ -156,8 +156,8 @@ void EditorDirDialog::_make_dir_confirm() {
String dir = ti->get_metadata(0);
- DirAccessRef d = DirAccess::open(dir);
- ERR_FAIL_COND_MSG(!d, "Cannot open directory '" + dir + "'.");
+ Ref<DirAccess> d = DirAccess::open(dir);
+ ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + dir + "'.");
const String stripped_dirname = makedirname->get_text().strip_edges();
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index a1081fcbfb..58a9175df1 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -327,12 +327,12 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
}
}
- FileAccessEncrypted *fae = nullptr;
- FileAccess *ftmp = pd->f;
+ Ref<FileAccessEncrypted> fae;
+ Ref<FileAccess> ftmp = pd->f;
if (sd.encrypted) {
- fae = memnew(FileAccessEncrypted);
- ERR_FAIL_COND_V(!fae, ERR_SKIP);
+ fae.instantiate();
+ ERR_FAIL_COND_V(fae.is_null(), ERR_SKIP);
Error err = fae->open_and_parse(ftmp, p_key, FileAccessEncrypted::MODE_WRITE_AES256, false);
ERR_FAIL_COND_V(err != OK, ERR_SKIP);
@@ -342,9 +342,9 @@ Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_pa
// Store file content.
ftmp->store_buffer(p_data.ptr(), p_data.size());
- if (fae) {
- fae->release();
- memdelete(fae);
+ if (fae.is_valid()) {
+ ftmp.unref();
+ fae.unref();
}
int pad = _get_pad(PCK_PADDING, pd->f->get_position());
@@ -480,7 +480,7 @@ void EditorExportPlatform::_export_find_dependencies(const String &p_path, Set<S
}
}
-void EditorExportPlatform::_edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude) {
+void EditorExportPlatform::_edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude) {
da->list_dir_begin();
String cur_dir = da->get_current_dir().replace("\\", "/");
if (!cur_dir.ends_with("/")) {
@@ -542,10 +542,9 @@ void EditorExportPlatform::_edit_filter_list(Set<String> &r_list, const String &
filters.push_back(f);
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- ERR_FAIL_NULL(da);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ ERR_FAIL_COND(da.is_null());
_edit_files_with_filter(da, filters, r_list, exclude);
- memdelete(da);
}
void EditorExportPlugin::set_export_preset(const Ref<EditorExportPreset> &p_preset) {
@@ -1130,12 +1129,12 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
EditorProgress ep("savepack", TTR("Packing"), 102, true);
// Create the temporary export directory if it doesn't exist.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->make_dir_recursive(EditorPaths::get_singleton()->get_cache_dir());
String tmppath = EditorPaths::get_singleton()->get_cache_dir().plus_file("packtmp");
- FileAccess *ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!ftmp, ERR_CANT_CREATE, "Cannot create file '" + tmppath + "'.");
+ Ref<FileAccess> ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(ftmp.is_null(), ERR_CANT_CREATE, "Cannot create file '" + tmppath + "'.");
PackData pd;
pd.ep = &ep;
@@ -1144,7 +1143,9 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
Error err = export_project_files(p_preset, p_debug, _save_pack_file, &pd, _add_shared_object);
- memdelete(ftmp); //close tmp file
+ // Close temp file.
+ pd.f.unref();
+ ftmp.unref();
if (err != OK) {
DirAccess::remove_file_or_error(tmppath);
@@ -1154,19 +1155,19 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
pd.file_ofs.sort(); //do sort, so we can do binary search later
- FileAccess *f;
+ Ref<FileAccess> f;
int64_t embed_pos = 0;
if (!p_embed) {
// Regular output to separate PCK file
f = FileAccess::open(p_path, FileAccess::WRITE);
- if (!f) {
+ if (f.is_null()) {
DirAccess::remove_file_or_error(tmppath);
ERR_FAIL_V(ERR_CANT_CREATE);
}
} else {
// Append to executable
f = FileAccess::open(p_path, FileAccess::READ_WRITE);
- if (!f) {
+ if (f.is_null()) {
DirAccess::remove_file_or_error(tmppath);
ERR_FAIL_V(ERR_FILE_CANT_OPEN);
}
@@ -1211,8 +1212,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
f->store_32(pd.file_ofs.size()); //amount of files
- FileAccessEncrypted *fae = nullptr;
- FileAccess *fhead = f;
+ Ref<FileAccessEncrypted> fae;
+ Ref<FileAccess> fhead = f;
if (enc_pck && enc_directory) {
String script_key = p_preset->get_script_encryption_key().to_lower();
@@ -1243,8 +1244,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
key.write[i] = v;
}
}
- fae = memnew(FileAccessEncrypted);
- ERR_FAIL_COND_V(!fae, ERR_SKIP);
+ fae.instantiate();
+ ERR_FAIL_COND_V(fae.is_null(), ERR_SKIP);
err = fae->open_and_parse(f, key, FileAccessEncrypted::MODE_WRITE_AES256, false);
ERR_FAIL_COND_V(err != OK, ERR_SKIP);
@@ -1272,9 +1273,9 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
fhead->store_32(flags);
}
- if (fae) {
- fae->release();
- memdelete(fae);
+ if (fae.is_valid()) {
+ fhead.unref();
+ fae.unref();
}
int header_padding = _get_pad(PCK_PADDING, f->get_position());
@@ -1290,8 +1291,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
// Save the rest of the data.
ftmp = FileAccess::open(tmppath, FileAccess::READ);
- if (!ftmp) {
- memdelete(f);
+ if (ftmp.is_null()) {
DirAccess::remove_file_or_error(tmppath);
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't open file to read from path '" + String(tmppath) + "'.");
}
@@ -1307,7 +1307,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
f->store_buffer(buf, got);
}
- memdelete(ftmp);
+ ftmp.unref(); // Close temp file.
if (p_embed) {
// Ensure embedded data ends at a 64-bit multiple
@@ -1326,7 +1326,6 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
}
}
- memdelete(f);
DirAccess::remove_file_or_error(tmppath);
return OK;
@@ -1335,8 +1334,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b
Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) {
EditorProgress ep("savezip", TTR("Packing"), 102, true);
- FileAccess *src_f;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io);
ZipData zd;
@@ -1839,7 +1837,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
return ERR_FILE_NOT_FOUND;
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->make_dir_recursive(p_path.get_base_dir());
Error err = da->copy(template_path, p_path, get_chmod_flags());
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 4d5aebc770..236f4d129c 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -184,7 +184,7 @@ private:
};
struct PackData {
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
Vector<SavedData> file_ofs;
EditorProgress *ep = nullptr;
Vector<SharedObject> *so_files = nullptr;
@@ -207,7 +207,7 @@ private:
static Error _save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
static Error _save_zip_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total, const Vector<String> &p_enc_in_filters, const Vector<String> &p_enc_ex_filters, const Vector<uint8_t> &p_key);
- void _edit_files_with_filter(DirAccess *da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude);
+ void _edit_files_with_filter(Ref<DirAccess> &da, const Vector<String> &p_filters, Set<String> &r_list, bool exclude);
void _edit_filter_list(Set<String> &r_list, const String &p_filter, bool exclude);
static Error _add_shared_object(void *p_userdata, const SharedObject &p_so);
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index cf45848ed3..a20f112b2a 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -198,13 +198,12 @@ Error EditorFeatureProfile::save_to_file(const String &p_path) {
data["disabled_features"] = dis_features;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
JSON json;
String text = json.stringify(data, "\t");
f->store_string(text);
- f->close();
return OK;
}
@@ -350,8 +349,8 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr
}
Vector<String> profiles;
- DirAccessRef d = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
- ERR_FAIL_COND_MSG(!d, "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
+ Ref<DirAccess> d = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
+ ERR_FAIL_COND_MSG(d.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
d->list_dir_begin();
while (true) {
@@ -453,8 +452,8 @@ void EditorFeatureProfileManager::_profile_action(int p_action) {
void EditorFeatureProfileManager::_erase_selected_profile() {
String selected = _get_selected_profile();
ERR_FAIL_COND(selected.is_empty());
- DirAccessRef da = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
- ERR_FAIL_COND_MSG(!da, "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
+ Ref<DirAccess> da = DirAccess::open(EditorSettings::get_singleton()->get_feature_profiles_dir());
+ ERR_FAIL_COND_MSG(da.is_null(), "Cannot open directory '" + EditorSettings::get_singleton()->get_feature_profiles_dir() + "'.");
da->remove(selected + ".profile");
if (selected == current_profile) {
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index ca3e70830c..dca69ffd5f 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -1065,7 +1065,6 @@ void EditorFileDialog::set_access(Access p_access) {
if (access == p_access) {
return;
}
- memdelete(dir_access);
switch (p_access) {
case ACCESS_FILESYSTEM: {
dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
@@ -1853,5 +1852,4 @@ EditorFileDialog::~EditorFileDialog() {
if (unregister_func) {
unregister_func(this);
}
- memdelete(dir_access);
}
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index fffe7ffcc5..db2a2ab09f 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -111,7 +111,7 @@ private:
LineEdit *file = nullptr;
OptionButton *filter = nullptr;
AcceptDialog *error_dialog = nullptr;
- DirAccess *dir_access = nullptr;
+ Ref<DirAccess> dir_access;
ConfirmationDialog *confirm_save = nullptr;
DependencyRemoveDialog *dep_remove_dialog = nullptr;
ConfirmationDialog *global_remove_dialog = nullptr;
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 2b98a4b02a..099dfe69d5 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -218,81 +218,80 @@ void EditorFileSystem::_scan_filesystem() {
String project = ProjectSettings::get_singleton()->get_resource_path();
String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
- FileAccess *f = FileAccess::open(fscache, FileAccess::READ);
-
- bool first = true;
- if (f) {
- //read the disk cache
- while (!f->eof_reached()) {
- String l = f->get_line().strip_edges();
- if (first) {
- if (first_scan) {
- // only use this on first scan, afterwards it gets ignored
- // this is so on first reimport we synchronize versions, then
- // we don't care until editor restart. This is for usability mainly so
- // your workflow is not killed after changing a setting by forceful reimporting
- // everything there is.
- filesystem_settings_version_for_import = l.strip_edges();
- if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) {
- revalidate_import_files = true;
+ {
+ Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ);
+
+ bool first = true;
+ if (f.is_valid()) {
+ //read the disk cache
+ while (!f->eof_reached()) {
+ String l = f->get_line().strip_edges();
+ if (first) {
+ if (first_scan) {
+ // only use this on first scan, afterwards it gets ignored
+ // this is so on first reimport we synchronize versions, then
+ // we don't care until editor restart. This is for usability mainly so
+ // your workflow is not killed after changing a setting by forceful reimporting
+ // everything there is.
+ filesystem_settings_version_for_import = l.strip_edges();
+ if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) {
+ revalidate_import_files = true;
+ }
}
+ first = false;
+ continue;
+ }
+ if (l.is_empty()) {
+ continue;
}
- first = false;
- continue;
- }
- if (l.is_empty()) {
- continue;
- }
- if (l.begins_with("::")) {
- Vector<String> split = l.split("::");
- ERR_CONTINUE(split.size() != 3);
- String name = split[1];
+ if (l.begins_with("::")) {
+ Vector<String> split = l.split("::");
+ ERR_CONTINUE(split.size() != 3);
+ String name = split[1];
- cpath = name;
+ cpath = name;
- } else {
- Vector<String> split = l.split("::");
- ERR_CONTINUE(split.size() != 9);
- String name = split[0];
- String file;
-
- file = name;
- name = cpath.plus_file(name);
-
- FileCache fc;
- fc.type = split[1];
- fc.uid = split[2].to_int();
- fc.modification_time = split[3].to_int();
- fc.import_modification_time = split[4].to_int();
- fc.import_valid = split[5].to_int() != 0;
- fc.import_group_file = split[6].strip_edges();
- fc.script_class_name = split[7].get_slice("<>", 0);
- fc.script_class_extends = split[7].get_slice("<>", 1);
- fc.script_class_icon_path = split[7].get_slice("<>", 2);
-
- String deps = split[8].strip_edges();
- if (deps.length()) {
- Vector<String> dp = deps.split("<>");
- for (int i = 0; i < dp.size(); i++) {
- String path = dp[i];
- fc.deps.push_back(path);
+ } else {
+ Vector<String> split = l.split("::");
+ ERR_CONTINUE(split.size() != 9);
+ String name = split[0];
+ String file;
+
+ file = name;
+ name = cpath.plus_file(name);
+
+ FileCache fc;
+ fc.type = split[1];
+ fc.uid = split[2].to_int();
+ fc.modification_time = split[3].to_int();
+ fc.import_modification_time = split[4].to_int();
+ fc.import_valid = split[5].to_int() != 0;
+ fc.import_group_file = split[6].strip_edges();
+ fc.script_class_name = split[7].get_slice("<>", 0);
+ fc.script_class_extends = split[7].get_slice("<>", 1);
+ fc.script_class_icon_path = split[7].get_slice("<>", 2);
+
+ String deps = split[8].strip_edges();
+ if (deps.length()) {
+ Vector<String> dp = deps.split("<>");
+ for (int i = 0; i < dp.size(); i++) {
+ String path = dp[i];
+ fc.deps.push_back(path);
+ }
}
- }
- file_cache[name] = fc;
+ file_cache[name] = fc;
+ }
}
}
-
- f->close();
- memdelete(f);
}
String update_cache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
if (FileAccess::exists(update_cache)) {
{
- FileAccessRef f2 = FileAccess::open(update_cache, FileAccess::READ);
+ Ref<FileAccess> f2 = FileAccess::open(update_cache, FileAccess::READ);
String l = f2->get_line().strip_edges();
while (!l.is_empty()) {
file_cache.erase(l); //erase cache for this, so it gets updated
@@ -300,7 +299,7 @@ void EditorFileSystem::_scan_filesystem() {
}
}
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
d->remove(update_cache); //bye bye update cache
}
@@ -314,14 +313,12 @@ void EditorFileSystem::_scan_filesystem() {
new_filesystem = memnew(EditorFileSystemDirectory);
new_filesystem->parent = nullptr;
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
d->change_dir("res://");
_scan_new_dir(new_filesystem, d, sp);
file_cache.clear(); //clear caches, no longer needed
- memdelete(d);
-
if (!first_scan) {
//on the first scan this is done from the main thread after re-importing
_save_filesystem_cache();
@@ -335,13 +332,11 @@ void EditorFileSystem::_save_filesystem_cache() {
String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME);
- FileAccess *f = FileAccess::open(fscache, FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!f, "Cannot create file '" + fscache + "'. Check user write permissions.");
+ Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions.");
f->store_line(filesystem_settings_version_for_import);
_save_filesystem_cache(filesystem, f);
- f->close();
- memdelete(f);
}
void EditorFileSystem::_thread_func(void *_userdata) {
@@ -364,9 +359,9 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
}
Error err;
- FileAccess *f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path + ".import", FileAccess::READ, &err);
- if (!f) { //no import file, do reimport
+ if (f.is_null()) { //no import file, do reimport
return true;
}
@@ -400,7 +395,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
break;
} else if (err != OK) {
ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import:" + itos(lines) + "' error '" + error_text + "'.");
- memdelete(f);
return false; //parse error, try reimport manually (Avoid reimport loop on broken file)
}
@@ -431,8 +425,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
}
}
- memdelete(f);
-
if (importer_name == "keep") {
return false; //keep mode, do not reimport
}
@@ -453,8 +445,8 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
// Read the md5's from a separate file (so the import parameters aren't dependent on the file version
String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(p_path);
- FileAccess *md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err);
- if (!md5s) { // No md5's stored for this resource
+ Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::READ, &err);
+ if (md5s.is_null()) { // No md5's stored for this resource
return true;
}
@@ -472,7 +464,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
break;
} else if (err != OK) {
ERR_PRINT("ResourceFormatImporter::load - '" + p_path + ".import.md5:" + itos(lines) + "' error '" + error_text + "'.");
- memdelete(md5s);
return false; // parse error
}
if (!assign.is_empty()) {
@@ -485,7 +476,6 @@ bool EditorFileSystem::_test_for_reimport(const String &p_path, bool p_only_impo
}
}
}
- memdelete(md5s);
//imported files are gone, reimport
for (const String &E : to_check) {
@@ -742,7 +732,7 @@ EditorFileSystem::ScanProgress EditorFileSystem::ScanProgress::get_sub(int p_cur
return sp;
}
-void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress) {
+void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAccess> &da, const ScanProgress &p_progress) {
List<String> dirs;
List<String> files;
@@ -967,7 +957,7 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
//then scan files and directories and check what's different
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
Error ret = da->change_dir(cd);
ERR_FAIL_COND_MSG(ret != OK, "Cannot change to '" + cd + "' folder.");
@@ -998,10 +988,9 @@ void EditorFileSystem::_scan_fs_changes(EditorFileSystemDirectory *p_dir, const
efd->parent = p_dir;
efd->name = f;
- DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
d->change_dir(cd.plus_file(f));
_scan_new_dir(efd, d, p_progress.get_sub(1, 1));
- memdelete(d);
ItemAction ia;
ia.action = ItemAction::ACTION_DIR_ADD;
@@ -1137,7 +1126,7 @@ void EditorFileSystem::_delete_internal_files(String p_file) {
if (FileAccess::exists(p_file + ".import")) {
List<String> paths;
ResourceFormatImporter::get_singleton()->get_internal_resource_path_list(p_file, &paths);
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (const String &E : paths) {
da->remove(E);
}
@@ -1282,7 +1271,7 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem() {
return filesystem;
}
-void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, FileAccess *p_file) {
+void EditorFileSystem::_save_filesystem_cache(EditorFileSystemDirectory *p_dir, Ref<FileAccess> p_file) {
if (!p_dir) {
return; //none
}
@@ -1467,8 +1456,8 @@ EditorFileSystemDirectory *EditorFileSystem::get_filesystem_path(const String &p
void EditorFileSystem::_save_late_updated_files() {
//files that already existed, and were modified, need re-scanning for dependencies upon project restart. This is done via saving this special file
String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file("filesystem_update4");
- FileAccessRef f = FileAccess::open(fscache, FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!f, "Cannot create file '" + fscache + "'. Check user write permissions.");
+ Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + fscache + "'. Check user write permissions.");
for (Set<String>::Element *E = late_update_files.front(); E; E = E->next()) {
f->store_line(E->get());
}
@@ -1713,78 +1702,78 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector
for (const KeyValue<String, Map<StringName, Variant>> &E : source_file_options) {
const String &file = E.key;
String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file);
- FileAccessRef f = FileAccess::open(file + ".import", FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!f, ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
-
- //write manually, as order matters ([remap] has to go first for performance).
- f->store_line("[remap]");
- f->store_line("");
- f->store_line("importer=\"" + importer->get_importer_name() + "\"");
- int version = importer->get_format_version();
- if (version > 0) {
- f->store_line("importer_version=" + itos(version));
- }
- if (!importer->get_resource_type().is_empty()) {
- f->store_line("type=\"" + importer->get_resource_type() + "\"");
- }
-
Vector<String> dest_paths;
+ {
+ Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'.");
+
+ //write manually, as order matters ([remap] has to go first for performance).
+ f->store_line("[remap]");
+ f->store_line("");
+ f->store_line("importer=\"" + importer->get_importer_name() + "\"");
+ int version = importer->get_format_version();
+ if (version > 0) {
+ f->store_line("importer_version=" + itos(version));
+ }
+ if (!importer->get_resource_type().is_empty()) {
+ f->store_line("type=\"" + importer->get_resource_type() + "\"");
+ }
- if (err == OK) {
- String path = base_path + "." + importer->get_save_extension();
- f->store_line("path=\"" + path + "\"");
- dest_paths.push_back(path);
- }
-
- f->store_line("group_file=" + Variant(p_group_file).get_construct_string());
-
- if (err == OK) {
- f->store_line("valid=true");
- } else {
- f->store_line("valid=false");
- }
- f->store_line("[deps]\n");
+ if (err == OK) {
+ String path = base_path + "." + importer->get_save_extension();
+ f->store_line("path=\"" + path + "\"");
+ dest_paths.push_back(path);
+ }
- f->store_line("");
+ f->store_line("group_file=" + Variant(p_group_file).get_construct_string());
- f->store_line("source_file=" + Variant(file).get_construct_string());
- if (dest_paths.size()) {
- Array dp;
- for (int i = 0; i < dest_paths.size(); i++) {
- dp.push_back(dest_paths[i]);
+ if (err == OK) {
+ f->store_line("valid=true");
+ } else {
+ f->store_line("valid=false");
}
- f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
- }
- f->store_line("[params]");
- f->store_line("");
+ f->store_line("[deps]\n");
- //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+ f->store_line("");
- List<ResourceImporter::ImportOption> options;
- importer->get_import_options(file, &options);
- //set default values
- for (const ResourceImporter::ImportOption &F : options) {
- String base = F.option.name;
- Variant v = F.default_value;
- if (source_file_options[file].has(base)) {
- v = source_file_options[file][base];
+ f->store_line("source_file=" + Variant(file).get_construct_string());
+ if (dest_paths.size()) {
+ Array dp;
+ for (int i = 0; i < dest_paths.size(); i++) {
+ dp.push_back(dest_paths[i]);
+ }
+ f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
+ }
+ f->store_line("[params]");
+ f->store_line("");
+
+ //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+
+ List<ResourceImporter::ImportOption> options;
+ importer->get_import_options(file, &options);
+ //set default values
+ for (const ResourceImporter::ImportOption &F : options) {
+ String base = F.option.name;
+ Variant v = F.default_value;
+ if (source_file_options[file].has(base)) {
+ v = source_file_options[file][base];
+ }
+ String value;
+ VariantWriter::write_to_string(v, value);
+ f->store_line(base + "=" + value);
}
- String value;
- VariantWriter::write_to_string(v, value);
- f->store_line(base + "=" + value);
}
- f->close();
-
// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
- FileAccessRef md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!md5s, ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'.");
+ {
+ Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(md5s.is_null(), ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'.");
- md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\"");
- if (dest_paths.size()) {
- md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\"");
+ if (dest_paths.size()) {
+ md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ }
}
- md5s->close();
EditorFileSystemDirectory *fs = nullptr;
int cpos = -1;
@@ -1930,106 +1919,104 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName
//as import is complete, save the .import file
- FileAccess *f = FileAccess::open(p_file + ".import", FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!f, "Cannot open file from path '" + p_file + ".import'.");
-
- //write manually, as order matters ([remap] has to go first for performance).
- f->store_line("[remap]");
- f->store_line("");
- f->store_line("importer=\"" + importer->get_importer_name() + "\"");
- int version = importer->get_format_version();
- if (version > 0) {
- f->store_line("importer_version=" + itos(version));
- }
- if (!importer->get_resource_type().is_empty()) {
- f->store_line("type=\"" + importer->get_resource_type() + "\"");
- }
-
- if (uid == ResourceUID::INVALID_ID) {
- uid = ResourceUID::get_singleton()->create_id();
- }
+ Vector<String> dest_paths;
+ {
+ Ref<FileAccess> f = FileAccess::open(p_file + ".import", FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + p_file + ".import'.");
- f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
+ //write manually, as order matters ([remap] has to go first for performance).
+ f->store_line("[remap]");
+ f->store_line("");
+ f->store_line("importer=\"" + importer->get_importer_name() + "\"");
+ int version = importer->get_format_version();
+ if (version > 0) {
+ f->store_line("importer_version=" + itos(version));
+ }
+ if (!importer->get_resource_type().is_empty()) {
+ f->store_line("type=\"" + importer->get_resource_type() + "\"");
+ }
- Vector<String> dest_paths;
+ if (uid == ResourceUID::INVALID_ID) {
+ uid = ResourceUID::get_singleton()->create_id();
+ }
- if (err == OK) {
- if (importer->get_save_extension().is_empty()) {
- //no path
- } else if (import_variants.size()) {
- //import with variants
- for (const String &E : import_variants) {
- String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension();
+ f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
- f->store_line("path." + E + "=\"" + path + "\"");
+ if (err == OK) {
+ if (importer->get_save_extension().is_empty()) {
+ //no path
+ } else if (import_variants.size()) {
+ //import with variants
+ for (const String &E : import_variants) {
+ String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension();
+
+ f->store_line("path." + E + "=\"" + path + "\"");
+ dest_paths.push_back(path);
+ }
+ } else {
+ String path = base_path + "." + importer->get_save_extension();
+ f->store_line("path=\"" + path + "\"");
dest_paths.push_back(path);
}
+
} else {
- String path = base_path + "." + importer->get_save_extension();
- f->store_line("path=\"" + path + "\"");
- dest_paths.push_back(path);
+ f->store_line("valid=false");
}
- } else {
- f->store_line("valid=false");
- }
+ if (metadata != Variant()) {
+ f->store_line("metadata=" + metadata.get_construct_string());
+ }
- if (metadata != Variant()) {
- f->store_line("metadata=" + metadata.get_construct_string());
- }
+ f->store_line("");
- f->store_line("");
+ f->store_line("[deps]\n");
- f->store_line("[deps]\n");
+ if (gen_files.size()) {
+ Array genf;
+ for (const String &E : gen_files) {
+ genf.push_back(E);
+ dest_paths.push_back(E);
+ }
- if (gen_files.size()) {
- Array genf;
- for (const String &E : gen_files) {
- genf.push_back(E);
- dest_paths.push_back(E);
+ String value;
+ VariantWriter::write_to_string(genf, value);
+ f->store_line("files=" + value);
+ f->store_line("");
}
- String value;
- VariantWriter::write_to_string(genf, value);
- f->store_line("files=" + value);
- f->store_line("");
- }
-
- f->store_line("source_file=" + Variant(p_file).get_construct_string());
+ f->store_line("source_file=" + Variant(p_file).get_construct_string());
- if (dest_paths.size()) {
- Array dp;
- for (int i = 0; i < dest_paths.size(); i++) {
- dp.push_back(dest_paths[i]);
+ if (dest_paths.size()) {
+ Array dp;
+ for (int i = 0; i < dest_paths.size(); i++) {
+ dp.push_back(dest_paths[i]);
+ }
+ f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
}
- f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
- }
- f->store_line("[params]");
- f->store_line("");
+ f->store_line("[params]");
+ f->store_line("");
- //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
+ //store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
- for (const ResourceImporter::ImportOption &E : opts) {
- String base = E.option.name;
- String value;
- VariantWriter::write_to_string(params[base], value);
- f->store_line(base + "=" + value);
+ for (const ResourceImporter::ImportOption &E : opts) {
+ String base = E.option.name;
+ String value;
+ VariantWriter::write_to_string(params[base], value);
+ f->store_line(base + "=" + value);
+ }
}
- f->close();
- memdelete(f);
-
// Store the md5's of the various files. These are stored separately so that the .import files can be version controlled.
- FileAccess *md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!md5s, "Cannot open MD5 file '" + base_path + ".md5'.");
+ {
+ Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(md5s.is_null(), "Cannot open MD5 file '" + base_path + ".md5'.");
- md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\"");
- if (dest_paths.size()) {
- md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\"");
+ if (dest_paths.size()) {
+ md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n");
+ }
}
- md5s->close();
- memdelete(md5s);
//update modified times, to avoid reimport
fs->files[cpos]->modified_time = FileAccess::get_modified_time(p_file);
@@ -2342,14 +2329,14 @@ bool EditorFileSystem::_scan_extensions() {
String extension_list_config_file = NativeExtension::get_extension_list_config_file();
if (extensions.size()) {
if (extensions_added.size() || extensions_removed.size()) { //extensions were added or removed
- FileAccessRef f = FileAccess::open(extension_list_config_file, FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(extension_list_config_file, FileAccess::WRITE);
for (const String &E : extensions) {
f->store_line(E);
}
}
} else {
if (loaded_extensions.size() || FileAccess::exists(extension_list_config_file)) { //extensions were removed
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(extension_list_config_file);
}
}
@@ -2438,7 +2425,7 @@ EditorFileSystem::EditorFileSystem() {
new_filesystem = nullptr;
// This should probably also work on Unix and use the string it returns for FAT32 or exFAT
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT");
scan_total = 0;
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index 05b55d4e1b..81811d2eb0 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -213,7 +213,7 @@ class EditorFileSystem : public Node {
};
void _save_filesystem_cache();
- void _save_filesystem_cache(EditorFileSystemDirectory *p_dir, FileAccess *p_file);
+ void _save_filesystem_cache(EditorFileSystemDirectory *p_dir, Ref<FileAccess> p_file);
bool _find_file(const String &p_file, EditorFileSystemDirectory **r_d, int &r_file_pos) const;
@@ -225,7 +225,7 @@ class EditorFileSystem : public Node {
Set<String> valid_extensions;
Set<String> import_extensions;
- void _scan_new_dir(EditorFileSystemDirectory *p_dir, DirAccess *da, const ScanProgress &p_progress);
+ void _scan_new_dir(EditorFileSystemDirectory *p_dir, Ref<DirAccess> &da, const ScanProgress &p_progress);
Thread thread_sources;
bool scanning_changes = false;
diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp
index 8d6ebd1154..548f05217e 100644
--- a/editor/editor_folding.cpp
+++ b/editor/editor_folding.cpp
@@ -131,7 +131,7 @@ void EditorFolding::_fill_folds(const Node *p_root, const Node *p_node, Array &p
void EditorFolding::save_scene_folding(const Node *p_scene, const String &p_path) {
ERR_FAIL_NULL(p_scene);
- FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+ Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
if (!file_check->file_exists(p_path)) { //This can happen when creating scene from FilesystemDock. It has path, but no file.
return;
}
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index 66fe3c4838..3e18499b97 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -218,7 +218,7 @@ Ref<FontData> load_cached_internal_font(const uint8_t *p_data, size_t p_size, Te
}
void editor_register_fonts(Ref<Theme> p_theme) {
- DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
/* Custom font */
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index d5085942c3..30f3748fa4 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -2682,7 +2682,7 @@ void EditorInspector::update_tree() {
{
const int dot = name_override.find(".");
if (dot != -1) {
- feature_tag = name_override.right(dot);
+ feature_tag = name_override.substr(dot);
name_override = name_override.substr(0, dot);
}
}
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index ee2d72c5b0..8d45f90ed6 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -168,7 +168,7 @@ void EditorLog::_copy_request() {
String text = log->get_selected_text();
if (text.is_empty()) {
- text = log->get_text();
+ text = log->get_parsed_text();
}
if (!text.is_empty()) {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index a80c7853f5..6fe6309eed 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -416,7 +416,7 @@ void EditorNode::_version_control_menu_option(int p_idx) {
void EditorNode::_update_title() {
const String appname = ProjectSettings::get_singleton()->get("application/config/name");
- String title = (appname.is_empty() ? "Unnamed Project" : appname) + String(" - ") + VERSION_NAME;
+ String title = (appname.is_empty() ? TTR("Unnamed Project") : appname) + String(" - ") + VERSION_NAME;
const String edited = editor_data.get_edited_scene_root() ? editor_data.get_edited_scene_root()->get_scene_file_path() : String();
if (!edited.is_empty()) {
// Display the edited scene name before the program name so that it can be seen in the OS task bar.
@@ -935,7 +935,7 @@ void EditorNode::_fs_changed() {
}
if (export_preset.is_null()) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists("res://export_presets.cfg")) {
export_error = vformat(
"Invalid export preset name: %s.\nThe following presets were detected in this project's `export_presets.cfg`:\n\n",
@@ -1058,7 +1058,7 @@ void EditorNode::_scan_external_changes() {
// Check if any edited scene has changed.
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (editor_data.get_scene_path(i) == "" || !da->file_exists(editor_data.get_scene_path(i))) {
continue;
}
@@ -5478,7 +5478,7 @@ void EditorNode::_global_menu_new_window(const Variant &p_tag) {
}
}
-void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
+void EditorNode::_dropped_files(const Vector<String> &p_files) {
String to_path = ProjectSettings::get_singleton()->globalize_path(FileSystemDock::get_singleton()->get_selected_path());
_add_dropped_files_recursive(p_files, to_path);
@@ -5487,7 +5487,7 @@ void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
}
void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, String to_path) {
- DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < p_files.size(); i++) {
String from = p_files[i];
@@ -5496,7 +5496,7 @@ void EditorNode::_add_dropped_files_recursive(const Vector<String> &p_files, Str
if (dir->dir_exists(from)) {
Vector<String> sub_files;
- DirAccessRef sub_dir = DirAccess::open(from);
+ Ref<DirAccess> sub_dir = DirAccess::open(from);
sub_dir->list_dir_begin();
String next_file = sub_dir->get_next();
@@ -5997,18 +5997,22 @@ EditorNode::EditorNode() {
import_scene.instantiate();
ResourceFormatImporter::get_singleton()->add_importer(import_scene);
+ Ref<ResourceImporterScene> import_animation;
+ import_animation = Ref<ResourceImporterScene>(memnew(ResourceImporterScene(true)));
+ ResourceFormatImporter::get_singleton()->add_importer(import_animation);
+
{
Ref<EditorSceneFormatImporterCollada> import_collada;
import_collada.instantiate();
- import_scene->add_importer(import_collada);
+ ResourceImporterScene::add_importer(import_collada);
Ref<EditorOBJImporter> import_obj2;
import_obj2.instantiate();
- import_scene->add_importer(import_obj2);
+ ResourceImporterScene::add_importer(import_obj2);
Ref<EditorSceneFormatImporterESCN> import_escn;
import_escn.instantiate();
- import_scene->add_importer(import_escn);
+ ResourceImporterScene::add_importer(import_escn);
}
Ref<ResourceImporterBitMap> import_bitmap;
@@ -7245,6 +7249,7 @@ EditorNode::EditorNode() {
EditorNode::~EditorNode() {
EditorInspector::cleanup_plugins();
EditorTranslationParser::get_singleton()->clean_parsers();
+ ResourceImporterScene::clean_up_importer_plugins();
remove_print_handler(&print_handler);
EditorHelp::cleanup_doc();
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 685714cb47..c6c1f09938 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -575,7 +575,7 @@ private:
void _open_recent_scene(int p_idx);
void _global_menu_scene(const Variant &p_tag);
void _global_menu_new_window(const Variant &p_tag);
- void _dropped_files(const Vector<String> &p_files, int p_screen);
+ void _dropped_files(const Vector<String> &p_files);
void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path);
void _update_from_settings();
diff --git a/editor/editor_paths.cpp b/editor/editor_paths.cpp
index 7b454055e0..a5c2fe093c 100644
--- a/editor/editor_paths.cpp
+++ b/editor/editor_paths.cpp
@@ -97,7 +97,7 @@ EditorPaths::EditorPaths() {
exe_path = exe_path.plus_file("../../..").simplify_path();
}
{
- DirAccessRef d = DirAccess::create_for_path(exe_path);
+ Ref<DirAccess> d = DirAccess::create_for_path(exe_path);
if (d->file_exists(exe_path + "/._sc_")) {
self_contained = true;
@@ -141,7 +141,7 @@ EditorPaths::EditorPaths() {
// Validate or create each dir and its relevant subdirectories.
- DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
// Data dir.
{
@@ -197,7 +197,7 @@ EditorPaths::EditorPaths() {
// Nothing to create, use shared editor data dir for shader cache.
Engine::get_singleton()->set_shader_cache_path(data_dir);
} else {
- DirAccessRef dir_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> dir_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (dir_res->change_dir(project_data_dir) != OK) {
dir_res->make_dir_recursive(project_data_dir);
if (dir_res->change_dir(project_data_dir) != OK) {
@@ -210,10 +210,9 @@ EditorPaths::EditorPaths() {
String project_data_gdignore_file_path = project_data_dir.plus_file(".gdignore");
if (!FileAccess::exists(project_data_gdignore_file_path)) {
// Add an empty .gdignore file to avoid scan.
- FileAccessRef f = FileAccess::open(project_data_gdignore_file_path, FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(project_data_gdignore_file_path, FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_line("");
- f->close();
} else {
ERR_PRINT("Failed to create file " + project_data_gdignore_file_path);
}
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 5166200ee3..6596c245bc 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -763,20 +763,20 @@ void EditorPlugin::remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_p
void EditorPlugin::add_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer, bool p_first_priority) {
ERR_FAIL_COND(!p_importer.is_valid());
- ResourceImporterScene::get_singleton()->add_importer(p_importer, p_first_priority);
+ ResourceImporterScene::add_importer(p_importer, p_first_priority);
}
void EditorPlugin::remove_scene_format_importer_plugin(const Ref<EditorSceneFormatImporter> &p_importer) {
ERR_FAIL_COND(!p_importer.is_valid());
- ResourceImporterScene::get_singleton()->remove_importer(p_importer);
+ ResourceImporterScene::remove_importer(p_importer);
}
void EditorPlugin::add_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin, bool p_first_priority) {
- ResourceImporterScene::get_singleton()->add_post_importer_plugin(p_plugin, p_first_priority);
+ ResourceImporterScene::add_post_importer_plugin(p_plugin, p_first_priority);
}
void EditorPlugin::remove_scene_post_import_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin) {
- ResourceImporterScene::get_singleton()->remove_post_importer_plugin(p_plugin);
+ ResourceImporterScene::remove_post_importer_plugin(p_plugin);
}
int find(const PackedStringArray &a, const String &v) {
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index b6f48c7536..b728ce64c9 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -161,7 +161,7 @@ void EditorPluginSettings::_cell_button_pressed(Object *p_item, int p_column, in
}
Vector<String> EditorPluginSettings::_get_plugins(const String &p_dir) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
Error err = da->change_dir(p_dir);
if (err != OK) {
return Vector<String>();
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 2bc92427e5..8541918e88 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -199,14 +199,12 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
if (has_small_texture) {
ResourceSaver::save(cache_base + "_small.png", r_small_texture);
}
- FileAccess *f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!f, "Cannot create file '" + cache_base + ".txt'. Check user write permissions.");
+ Ref<FileAccess> f = FileAccess::open(cache_base + ".txt", FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot create file '" + cache_base + ".txt'. Check user write permissions.");
f->store_line(itos(thumbnail_size));
f->store_line(itos(has_small_texture));
f->store_line(itos(FileAccess::get_modified_time(p_item.path)));
f->store_line(FileAccess::get_md5(p_item.path));
- f->close();
- memdelete(f);
}
}
}
@@ -251,8 +249,8 @@ void EditorResourcePreview::_iterate() {
//does not have it, try to load a cached thumbnail
String file = cache_base + ".txt";
- FileAccess *f = FileAccess::open(file, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(file, FileAccess::READ);
+ if (f.is_null()) {
// No cache found, generate
_generate_preview(texture, small_texture, item, cache_base);
} else {
@@ -265,33 +263,31 @@ void EditorResourcePreview::_iterate() {
if (tsize != thumbnail_size) {
cache_valid = false;
- memdelete(f);
+ f.unref();
} else if (last_modtime != modtime) {
String last_md5 = f->get_line();
String md5 = FileAccess::get_md5(item.path);
- memdelete(f);
+ f.unref();
if (last_md5 != md5) {
cache_valid = false;
-
} else {
//update modified time
- f = FileAccess::open(file, FileAccess::WRITE);
- if (!f) {
+ Ref<FileAccess> f2 = FileAccess::open(file, FileAccess::WRITE);
+ if (f2.is_null()) {
// Not returning as this would leave the thread hanging and would require
// some proper cleanup/disabling of resource preview generation.
ERR_PRINT("Cannot create file '" + file + "'. Check user write permissions.");
} else {
- f->store_line(itos(thumbnail_size));
- f->store_line(itos(has_small_texture));
- f->store_line(itos(modtime));
- f->store_line(md5);
- memdelete(f);
+ f2->store_line(itos(thumbnail_size));
+ f2->store_line(itos(has_small_texture));
+ f2->store_line(itos(modtime));
+ f2->store_line(md5);
}
}
} else {
- memdelete(f);
+ f.unref();
}
if (cache_valid) {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 4ddc66ed98..48f04694aa 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -722,7 +722,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
/* Extra config */
- EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "project_manager/sorting_order", 0, "Name,Path,Last Edited")
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "project_manager/sorting_order", 0, "Last Edited,Name,Path")
if (p_extra_config.is_valid()) {
if (p_extra_config->has_section("init_projects") && p_extra_config->has_section_key("init_projects", "list")) {
@@ -842,7 +842,7 @@ void EditorSettings::create() {
if (EditorPaths::get_singleton()->are_paths_valid()) {
// Validate editor config file.
- DirAccessRef dir = DirAccess::open(EditorPaths::get_singleton()->get_config_dir());
+ Ref<DirAccess> dir = DirAccess::open(EditorPaths::get_singleton()->get_config_dir());
String config_file_name = "editor_settings-" + itos(VERSION_MAJOR) + ".tres";
config_file_path = EditorPaths::get_singleton()->get_config_dir().plus_file(config_file_name);
if (!dir->file_exists(config_file_name)) {
@@ -1151,12 +1151,11 @@ void EditorSettings::set_favorites(const Vector<String> &p_favorites) {
} else {
favorites_file = get_project_settings_dir().plus_file("favorites");
}
- FileAccess *f = FileAccess::open(favorites_file, FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::WRITE);
+ if (f.is_valid()) {
for (int i = 0; i < favorites.size(); i++) {
f->store_line(favorites[i]);
}
- memdelete(f);
}
}
@@ -1172,12 +1171,11 @@ void EditorSettings::set_recent_dirs(const Vector<String> &p_recent_dirs) {
} else {
recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs");
}
- FileAccess *f = FileAccess::open(recent_dirs_file, FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(recent_dirs_file, FileAccess::WRITE);
+ if (f.is_valid()) {
for (int i = 0; i < recent_dirs.size(); i++) {
f->store_line(recent_dirs[i]);
}
- memdelete(f);
}
}
@@ -1195,24 +1193,22 @@ void EditorSettings::load_favorites_and_recent_dirs() {
favorites_file = get_project_settings_dir().plus_file("favorites");
recent_dirs_file = get_project_settings_dir().plus_file("recent_dirs");
}
- FileAccess *f = FileAccess::open(favorites_file, FileAccess::READ);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(favorites_file, FileAccess::READ);
+ if (f.is_valid()) {
String line = f->get_line().strip_edges();
while (!line.is_empty()) {
favorites.push_back(line);
line = f->get_line().strip_edges();
}
- memdelete(f);
}
f = FileAccess::open(recent_dirs_file, FileAccess::READ);
- if (f) {
+ if (f.is_valid()) {
String line = f->get_line().strip_edges();
while (!line.is_empty()) {
recent_dirs.push_back(line);
line = f->get_line().strip_edges();
}
- memdelete(f);
}
}
@@ -1227,8 +1223,8 @@ bool EditorSettings::is_dark_theme() {
void EditorSettings::list_text_editor_themes() {
String themes = "Default,Godot 2,Custom";
- DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
- if (d) {
+ Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir());
+ if (d.is_valid()) {
List<String> custom_themes;
d->list_dir_begin();
String file = d->get_next();
@@ -1293,8 +1289,8 @@ bool EditorSettings::import_text_editor_theme(String p_file) {
return false;
}
- DirAccessRef d = DirAccess::open(get_text_editor_themes_dir());
- if (d) {
+ Ref<DirAccess> d = DirAccess::open(get_text_editor_themes_dir());
+ if (d.is_valid()) {
d->copy(p_file, get_text_editor_themes_dir().plus_file(p_file.get_file()));
return true;
}
@@ -1345,8 +1341,8 @@ Vector<String> EditorSettings::get_script_templates(const String &p_extension, c
if (!p_custom_path.is_empty()) {
template_dir = p_custom_path;
}
- DirAccessRef d = DirAccess::open(template_dir);
- if (d) {
+ Ref<DirAccess> d = DirAccess::open(template_dir);
+ if (d.is_valid()) {
d->list_dir_begin();
String file = d->get_next();
while (!file.is_empty()) {
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 1fea759a90..f4082746d8 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -1220,10 +1220,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), SNAME("EditorIcons")));
theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
- // H/VSplitContainer
- theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon(SNAME("GuiVsplitBg"), SNAME("EditorIcons")), 1, 1, 1, 1));
- theme->set_stylebox("bg", "HSplitContainer", make_stylebox(theme->get_icon(SNAME("GuiHsplitBg"), SNAME("EditorIcons")), 1, 1, 1, 1));
-
theme->set_icon("grabber", "VSplitContainer", theme->get_icon(SNAME("GuiVsplitter"), SNAME("EditorIcons")));
theme->set_icon("grabber", "HSplitContainer", theme->get_icon(SNAME("GuiHsplitter"), SNAME("EditorIcons")));
diff --git a/editor/editor_translation.cpp b/editor/editor_translation.cpp
index f64adcf0a1..b08e5807e7 100644
--- a/editor/editor_translation.cpp
+++ b/editor/editor_translation.cpp
@@ -59,7 +59,8 @@ void load_editor_translations(const String &p_locale) {
int ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
- FileAccessMemory *fa = memnew(FileAccessMemory);
+ Ref<FileAccessMemory> fa;
+ fa.instantiate();
fa->open_custom(data.ptr(), data.size());
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
@@ -84,7 +85,8 @@ void load_doc_translations(const String &p_locale) {
int ret = Compression::decompress(data.ptrw(), dtl->uncomp_size, dtl->data, dtl->comp_size, Compression::MODE_DEFLATE);
ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt.");
- FileAccessMemory *fa = memnew(FileAccessMemory);
+ Ref<FileAccessMemory> fa;
+ fa.instantiate();
fa->open_custom(data.ptr(), data.size());
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa);
diff --git a/editor/editor_vcs_interface.cpp b/editor/editor_vcs_interface.cpp
index 0954779300..3f2012cc16 100644
--- a/editor/editor_vcs_interface.cpp
+++ b/editor/editor_vcs_interface.cpp
@@ -168,21 +168,19 @@ void EditorVCSInterface::set_singleton(EditorVCSInterface *p_singleton) {
void EditorVCSInterface::create_vcs_metadata_files(VCSMetadata p_vcs_metadata_type, String &p_dir) {
if (p_vcs_metadata_type == VCSMetadata::GIT) {
- FileAccess *f = FileAccess::open(p_dir.plus_file(".gitignore"), FileAccess::WRITE);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_dir.plus_file(".gitignore"), FileAccess::WRITE);
+ if (f.is_null()) {
ERR_FAIL_MSG(TTR("Couldn't create .gitignore in project path."));
} else {
f->store_line("# Godot 4+ specific ignores");
f->store_line(".godot/");
- memdelete(f);
}
f = FileAccess::open(p_dir.plus_file(".gitattributes"), FileAccess::WRITE);
- if (!f) {
+ if (f.is_null()) {
ERR_FAIL_MSG(TTR("Couldn't create .gitattributes in project path."));
} else {
f->store_line("# Normalize EOL for all files that Git considers text files.");
f->store_line("* text=auto eol=lf");
- memdelete(f);
}
}
}
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index f93c2df13d..b34b08b5de 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -44,7 +44,7 @@
void ExportTemplateManager::_update_template_status() {
// Fetch installed templates from the file system.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
Error err = da->change_dir(templates_dir);
@@ -194,7 +194,7 @@ void ExportTemplateManager::_download_template_completed(int p_status, int p_cod
bool ret = _install_file_selected(path, true);
if (ret) {
// Clean up downloaded file.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = da->remove(path);
if (err != OK) {
EditorNode::get_singleton()->add_io_error(TTR("Cannot remove temporary file:") + "\n" + path + "\n");
@@ -374,10 +374,7 @@ void ExportTemplateManager::_install_file() {
}
bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_skip_progress) {
- // unzClose() will take care of closing the file stored in the unzFile,
- // so we don't need to `memdelete(fa)` in this method.
- FileAccess *fa = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&fa);
+ zlib_filefunc_def io = zipio_create_io();
unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
if (!pkg) {
@@ -407,9 +404,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
// Read.
unzOpenCurrentFile(pkg);
ret = unzReadCurrentFile(pkg, data.ptrw(), data.size());
- if (ret != UNZ_OK) {
- break;
- }
+ ERR_BREAK_MSG(ret < 0, vformat("An error occurred while attempting to read from file: %s. This file will not be used.", file));
unzCloseCurrentFile(pkg);
String data_str;
@@ -441,7 +436,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
return false;
}
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String template_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(version);
Error err = d->make_dir_recursive(template_path);
if (err != OK) {
@@ -481,9 +476,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
// Read
unzOpenCurrentFile(pkg);
ret = unzReadCurrentFile(pkg, data.ptrw(), data.size());
- if (ret != UNZ_OK) {
- break;
- }
+ ERR_BREAK_MSG(ret < 0, vformat("An error occurred while attempting to read from file: %s. This file will not be used.", file));
unzCloseCurrentFile(pkg);
String base_dir = file_path.get_base_dir().trim_suffix("/");
@@ -492,8 +485,8 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
base_dir = base_dir.substr(contents_dir.length(), file_path.length()).trim_prefix("/");
file = base_dir.plus_file(file);
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_CONTINUE(!da);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_CONTINUE(da.is_null());
String output_dir = template_path.plus_file(base_dir);
@@ -508,16 +501,16 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_
}
String to_write = template_path.plus_file(file);
- FileAccessRef f = FileAccess::open(to_write, FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(to_write, FileAccess::WRITE);
- if (!f) {
+ if (f.is_null()) {
ret = unzGoToNextFile(pkg);
fc++;
ERR_CONTINUE_MSG(true, "Can't open file from path '" + String(to_write) + "'.");
}
f->store_buffer(data.ptr(), data.size());
-
+ f.unref(); // close file.
#ifndef WINDOWS_ENABLED
FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
#endif
@@ -542,7 +535,7 @@ void ExportTemplateManager::_uninstall_template(const String &p_version) {
}
void ExportTemplateManager::_uninstall_template_confirmed() {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
const String &templates_dir = EditorSettings::get_singleton()->get_templates_dir();
Error err = da->change_dir(templates_dir);
@@ -656,17 +649,16 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
// To support custom Android builds, we install the Java source code and buildsystem
// from android_source.zip to the project's res://android folder.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE);
// Make res://android dir (if it does not exist).
da->make_dir("android");
{
// Add version, to ensure building won't work if template and Godot version don't match.
- FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::WRITE);
- ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+ Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::WRITE);
+ ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
f->store_line(VERSION_FULL_CONFIG);
- f->close();
}
// Create the android plugins directory.
@@ -677,16 +669,14 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
ERR_FAIL_COND_V(err != OK, err);
{
// Add an empty .gdignore file to avoid scan.
- FileAccessRef f = FileAccess::open("res://android/build/.gdignore", FileAccess::WRITE);
- ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+ Ref<FileAccess> f = FileAccess::open("res://android/build/.gdignore", FileAccess::WRITE);
+ ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
f->store_line("");
- f->close();
}
// Uncompress source template.
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android sources not in ZIP format.");
@@ -731,10 +721,10 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_
}
String to_write = String("res://android/build").plus_file(path);
- FileAccess *f = FileAccess::open(to_write, FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(to_write, FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_buffer(data.ptr(), data.size());
- memdelete(f);
+ f.unref(); // close file.
#ifndef WINDOWS_ENABLED
FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF);
#endif
diff --git a/editor/fileserver/editor_file_server.cpp b/editor/fileserver/editor_file_server.cpp
index 30dc9180e3..46fb767c00 100644
--- a/editor/fileserver/editor_file_server.cpp
+++ b/editor/fileserver/editor_file_server.cpp
@@ -46,7 +46,6 @@ void EditorFileServer::_close_client(ClientData *cd) {
cd->efs->to_wait.insert(cd->thread);
}
while (cd->files.size()) {
- memdelete(cd->files.front()->get());
cd->files.erase(cd->files.front());
}
memdelete(cd);
@@ -181,8 +180,8 @@ void EditorFileServer::_subthread_start(void *s) {
break;
}
- FileAccess *fa = FileAccess::open(s2, FileAccess::READ);
- if (!fa) {
+ Ref<FileAccess> fa = FileAccess::open(s2, FileAccess::READ);
+ if (fa.is_null()) {
//not found, continue
encode_uint32(id, buf4);
cd->connection->put_data(buf4, 4);
@@ -249,7 +248,6 @@ void EditorFileServer::_subthread_start(void *s) {
case FileAccessNetwork::COMMAND_CLOSE: {
print_verbose("CLOSED");
ERR_CONTINUE(!cd->files.has(id));
- memdelete(cd->files[id]);
cd->files.erase(id);
} break;
}
diff --git a/editor/fileserver/editor_file_server.h b/editor/fileserver/editor_file_server.h
index a1bb7ecf4e..ccebd1465d 100644
--- a/editor/fileserver/editor_file_server.h
+++ b/editor/fileserver/editor_file_server.h
@@ -49,7 +49,7 @@ class EditorFileServer : public Object {
struct ClientData {
Thread *thread = nullptr;
Ref<StreamPeerTCP> connection;
- Map<int, FileAccess *> files;
+ Map<int, Ref<FileAccess>> files;
EditorFileServer *efs = nullptr;
bool quit = false;
};
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index bbbdd85a5a..778c5c33ff 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -225,7 +225,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
Vector<String> favorite_paths = EditorSettings::get_singleton()->get_favorites();
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
bool fav_changed = false;
for (int i = favorite_paths.size() - 1; i >= 0; i--) {
if (da->dir_exists(favorite_paths[i]) || da->file_exists(favorite_paths[i])) {
@@ -539,7 +539,7 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa
if (target_path.ends_with("/")) {
target_path = target_path.substr(0, target_path.length() - 1);
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(p_path)) {
path = target_path;
} else if (da->dir_exists(p_path)) {
@@ -989,7 +989,7 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
{
List<String> importer_exts;
- ResourceImporterScene::get_singleton()->get_recognized_extensions(&importer_exts);
+ ResourceImporterScene::get_scene_singleton()->get_recognized_extensions(&importer_exts);
String extension = fpath.get_extension();
for (const String &E : importer_exts) {
if (extension.nocasecmp_to(E) == 0) {
@@ -1000,7 +1000,27 @@ void FileSystemDock::_select_file(const String &p_path, bool p_select_in_favorit
}
if (is_imported) {
- ResourceImporterScene::get_singleton()->show_advanced_options(fpath);
+ ResourceImporterScene::get_scene_singleton()->show_advanced_options(fpath);
+ } else {
+ EditorNode::get_singleton()->open_request(fpath);
+ }
+ } else if (ResourceLoader::get_resource_type(fpath) == "AnimationLibrary") {
+ bool is_imported = false;
+
+ {
+ List<String> importer_exts;
+ ResourceImporterScene::get_animation_singleton()->get_recognized_extensions(&importer_exts);
+ String extension = fpath.get_extension();
+ for (const String &E : importer_exts) {
+ if (extension.nocasecmp_to(E) == 0) {
+ is_imported = true;
+ break;
+ }
+ }
+ }
+
+ if (is_imported) {
+ ResourceImporterScene::get_animation_singleton()->show_advanced_options(fpath);
} else {
EditorNode::get_singleton()->open_request(fpath);
}
@@ -1183,7 +1203,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
_get_all_items_in_dir(EditorFileSystem::get_singleton()->get_filesystem_path(old_path), file_changed_paths, folder_changed_paths);
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Moving " + old_path + " -> " + new_path);
Error err = da->rename(old_path, new_path);
if (err == OK) {
@@ -1241,7 +1261,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
return;
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
print_verbose("Duplicating " + old_path + " -> " + new_path);
Error err = p_item.is_file ? da->copy(old_path, new_path) : da->copy_dir(old_path, new_path);
if (err == OK) {
@@ -1260,7 +1280,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
cfg->save(new_path + ".import");
} else if (p_item.is_file && (old_path.get_extension() == "tscn" || old_path.get_extension() == "tres")) {
// FIXME: Quick hack to fix text resources. This should be fixed properly.
- FileAccessRef file = FileAccess::open(old_path, FileAccess::READ, &err);
+ Ref<FileAccess> file = FileAccess::open(old_path, FileAccess::READ, &err);
if (err == OK) {
PackedStringArray lines = file->get_as_utf8_string().split("\n");
String line = lines[0];
@@ -1269,7 +1289,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin
line = line.substr(0, line.find(" uid")) + "]";
lines.write[0] = line;
- FileAccessRef file2 = FileAccess::open(new_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> file2 = FileAccess::open(new_path, FileAccess::WRITE, &err);
if (err == OK) {
file2->store_string(String("\n").join(lines));
}
@@ -1429,7 +1449,7 @@ void FileSystemDock::_make_dir_confirm() {
}
print_verbose("Making folder " + dir_name + " in " + directory);
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
Error err = da->change_dir(directory);
ERR_FAIL_COND_MSG(err != OK, "Cannot open directory '" + directory + "'.");
@@ -1479,7 +1499,7 @@ void FileSystemDock::_make_scene_confirm() {
scene_name = directory.plus_file(scene_name);
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(scene_name)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
return;
@@ -1494,7 +1514,7 @@ void FileSystemDock::_file_removed(String p_file) {
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_file.get_base_dir();
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
while (!da->dir_exists(path)) {
path = path.get_base_dir();
}
@@ -1507,7 +1527,7 @@ void FileSystemDock::_folder_removed(String p_folder) {
// Find the closest parent directory available, in case multiple items were deleted along the same path.
path = p_folder.get_base_dir();
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
while (!da->dir_exists(path)) {
path = path.get_base_dir();
}
@@ -1546,7 +1566,7 @@ void FileSystemDock::_rename_operation_confirm() {
}
// Present a more user friendly warning for name conflict.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
// Workaround case insensitivity on Windows.
if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) {
@@ -1599,7 +1619,7 @@ void FileSystemDock::_duplicate_operation_confirm() {
String new_path = base_dir.plus_file(new_name);
// Present a more user friendly warning for name conflict
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
return;
@@ -2354,7 +2374,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
int exist_counter = 1;
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
while (da->file_exists(new_path) || da->dir_exists(new_path)) {
exist_counter++;
new_path = vformat(new_path_base, exist_counter);
@@ -2831,7 +2851,7 @@ void FileSystemDock::_get_imported_files(const String &p_path, Vector<String> &f
return;
}
- DirAccessRef da = DirAccess::open(p_path);
+ Ref<DirAccess> da = DirAccess::open(p_path);
da->list_dir_begin();
String n = da->get_next();
while (!n.is_empty()) {
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index 0dfaaaa1f4..41191271a1 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -211,8 +211,8 @@ float FindInFiles::get_progress() const {
}
void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) {
- DirAccessRef dir = DirAccess::open(path);
- if (!dir) {
+ Ref<DirAccess> dir = DirAccess::open(path);
+ if (dir.is_null()) {
print_verbose("Cannot open directory! " + path);
return;
}
@@ -253,8 +253,8 @@ void FindInFiles::_scan_dir(String path, PackedStringArray &out_folders) {
}
void FindInFiles::_scan_file(String fpath) {
- FileAccessRef f = FileAccess::open(fpath, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(fpath, FileAccess::READ);
+ if (f.is_null()) {
print_verbose(String("Cannot open file ") + fpath);
return;
}
@@ -274,8 +274,6 @@ void FindInFiles::_scan_file(String fpath) {
emit_signal(SNAME(SIGNAL_RESULT_FOUND), fpath, line_number, begin, end, line);
}
}
-
- f->close();
}
void FindInFiles::_bind_methods() {
@@ -873,7 +871,7 @@ void FindInFilesPanel::_on_replace_all_clicked() {
// Same as get_line, but preserves line ending characters.
class ConservativeGetLine {
public:
- String get_line(FileAccess *f) {
+ String get_line(Ref<FileAccess> f) {
_line_buffer.clear();
char32_t c = f->get_8();
@@ -908,8 +906,8 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result>
// If there are unsaved changes, the user will be asked on focus,
// however that means either losing changes or losing replaces.
- FileAccessRef f = FileAccess::open(fpath, FileAccess::READ);
- ERR_FAIL_COND_MSG(!f, "Cannot open file from path '" + fpath + "'.");
+ Ref<FileAccess> f = FileAccess::open(fpath, FileAccess::READ);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + fpath + "'.");
String buffer;
int current_line = 1;
@@ -958,8 +956,6 @@ void FindInFilesPanel::apply_replaces_in_file(String fpath, const Vector<Result>
ERR_FAIL_COND_MSG(err != OK, "Cannot create file in path '" + fpath + "'.");
f->store_string(buffer);
-
- f->close();
}
String FindInFilesPanel::get_replace_text() {
diff --git a/editor/icons/AnimationLibrary.svg b/editor/icons/AnimationLibrary.svg
new file mode 100644
index 0000000000..0bac67d302
--- /dev/null
+++ b/editor/icons/AnimationLibrary.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14.519 2.006A6 6 0 0 0 8.599 8a6 6 0 0 0 5.92 5.994v-1.01a1 1 0 0 1-.92-.984 1 1 0 0 1 .92-.984V4.984a1 1 0 0 1-.92-.984 1 1 0 0 1 .92-.984Zm-3.432 2.996a1 1 0 0 1 .547.133 1 1 0 0 1 .367 1.365 1 1 0 0 1-1.367.365A1 1 0 0 1 10.27 5.5a1 1 0 0 1 .818-.498ZM11.111 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365 1 1 0 0 1-1.365-.365 1 1 0 0 1 .365-1.365A1 1 0 0 1 11.111 9Z" style="fill:#e0e0e0;fill-opacity:1"/><path d="M11.094 2.104a6 6 0 0 0-5.92 5.994 6 6 0 0 0 5.92 5.994v-.023a5.795 6.506 0 0 1-2.89-3.104 1 1 0 0 1-1.36-.367 1 1 0 0 1 .365-1.365 1 1 0 0 1 .475-.135 5.795 6.506 0 0 1-.076-.984 5.795 6.506 0 0 1 .082-1.027 1 1 0 0 1-.48-.124 1 1 0 0 1-.366-1.365 1 1 0 0 1 .818-.498 1 1 0 0 1 .547.133 1 1 0 0 1 .004.002 5.795 6.506 0 0 1 2.881-3.076z" style="fill:#e0e0e0;fill-opacity:1"/><path d="M7.616 2.104a6 6 0 0 0-5.92 5.994 6 6 0 0 0 5.92 5.994v-.023a5.795 6.506 0 0 1-2.89-3.104 1 1 0 0 1-1.36-.367 1 1 0 0 1 .366-1.365 1 1 0 0 1 .474-.135 5.795 6.506 0 0 1-.076-.984 5.795 6.506 0 0 1 .082-1.027 1 1 0 0 1-.48-.124 1 1 0 0 1-.366-1.365 1 1 0 0 1 .819-.498 1 1 0 0 1 .547.133 1 1 0 0 1 .003.002 5.795 6.506 0 0 1 2.881-3.076z" style="fill:#e0e0e0;fill-opacity:1"/></svg>
diff --git a/editor/icons/ArrayOccluder3D.svg b/editor/icons/ArrayOccluder3D.svg
new file mode 100644
index 0000000000..ac45821897
--- /dev/null
+++ b/editor/icons/ArrayOccluder3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1c-1.104569 0-2 .8954305-2 2s.895431 2 2 2 2-.8954305 2-2-.895431-2-2-2zm-2 7v3h-3v2h3v3h2v-3h3v-2h-3v-3zm-8 3c-1.1045695 0-2 .895431-2 2s.8954305 2 2 2 2-.895431 2-2-.8954305-2-2-2z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/BoxOccluder3D.svg b/editor/icons/BoxOccluder3D.svg
new file mode 100644
index 0000000000..3cee3db532
--- /dev/null
+++ b/editor/icons/BoxOccluder3D.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m8 .88867188-.5058594.25390622a4.5 4.5 0 0 1 1.3789063 2.2988281l3.0664061 1.5332032-3.5546874 1.7753906a4.5 4.5 0 0 1 -1.6796875 1.6601562l.2949219.1464844v3.9414064l-4-2.001953v-1.7636721a4.5 4.5 0 0 1 -2-1.4179688v4.2968749l7 3.5 7-3.5v-7.2226561zm5 5.66796872v3.9394534l-4 2.001953v-3.9414064z"/><path d="m8 .88867188-.5058594.25390622a4.5 4.5 0 0 1 1.5058594 3.3574219 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -3.5-1.6855469v4.2968749l7 3.5 7-3.5v-7.2226561z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/GuiVsplitBg.svg b/editor/icons/GuiVsplitBg.svg
deleted file mode 100644
index 9844fc2018..0000000000
--- a/editor/icons/GuiVsplitBg.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="8" viewBox="0 0 8 7.9999995" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h8v8h-8z" fill-opacity=".098039"/></svg>
diff --git a/editor/icons/Occluder3D.svg b/editor/icons/Occluder3D.svg
index 850e2651af..c91a77781b 100644
--- a/editor/icons/Occluder3D.svg
+++ b/editor/icons/Occluder3D.svg
@@ -1 +1 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.90625 1a7 7 0 0 0 -1.2988281.1386719 4.5 4.5 0 0 1 3.3925781 4.3613281 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -4.359375-3.3886719 7 7 0 0 0 -.140625 1.3886719 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7 7 7 0 0 0 -.09375 0z" fill="#ffca5f" stroke-width=".365215"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13 1a2 2 0 0 0 -1.730469 1h-3.0273435a4.5 4.5 0 0 1 .7285156 2h2.3007809a2 2 0 0 0 .728516.7304688v5.8554692l-3.6933594-3.6933599a4.5 4.5 0 0 1 -1.4140625 1.4140625l3.6933599 3.6933594h-5.8574224a2 2 0 0 0 -.7285156-.730469v-2.3046872a4.5 4.5 0 0 1 -2-.7285157v3.0351559a2 2 0 0 0 -1 1.728516 2 2 0 0 0 2 2 2 2 0 0 0 1.7304688-1h6.5410152a2 2 0 0 0 1.728516 1 2 2 0 0 0 2-2 2 2 0 0 0 -1.03125-1.75h.03125v-6.5214844a2 2 0 0 0 1-1.7285156 2 2 0 0 0 -2-2z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/PolygonOccluder3D.svg b/editor/icons/PolygonOccluder3D.svg
new file mode 100644
index 0000000000..fc87e5e086
--- /dev/null
+++ b/editor/icons/PolygonOccluder3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#ffca5f" stroke-linejoin="round"><path d="m8.2421875 2a4.5 4.5 0 0 1 .7578125 2.5 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -2.5-.7636719v5.7636719h12l-6-6 6-6z" stroke-width="2"/><path d="m7.328125 1c.6472144.5230929 1.136703 1.2154082 1.4140625 2h2.8437505l-2.7675786 2.767578c-.2943505.9927946-.9220914 1.8536963-1.7773438 2.4375.0343146.1879491.1217471.3621363.2519532.501953l4.2929692 4.292969h-8.585938v-4.267578c-.785054-.2784421-1.4774185-.7693178-2-1.417969v6.685547c.0000552.552262.4477381.999945 1 1h12c.890637-.00035 1.336587-1.077036.707031-1.707031l-5.2929685-5.292969 5.2929685-5.292969c.629556-.6299945.183606-1.7066812-.707031-1.707031z"/></g></svg>
diff --git a/editor/icons/QuadOccluder3D.svg b/editor/icons/QuadOccluder3D.svg
new file mode 100644
index 0000000000..16da6f420f
--- /dev/null
+++ b/editor/icons/QuadOccluder3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.328125 1c.6472144.5230929 1.136703 1.2154082 1.4140625 2h4.2578125v8.585938l-4.6933594-4.6933599c-.3593282.5714479-.8426146 1.0547343-1.4140625 1.4140625l4.6933599 4.6933594h-8.585938v-4.2675781c-.785054-.2784421-1.4774185-.7693176-2-1.4179688v7.6855469h14v-14z" fill="#ffca5f"/></svg>
diff --git a/editor/icons/SphereOccluder3D.svg b/editor/icons/SphereOccluder3D.svg
new file mode 100644
index 0000000000..850e2651af
--- /dev/null
+++ b/editor/icons/SphereOccluder3D.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.90625 1a7 7 0 0 0 -1.2988281.1386719 4.5 4.5 0 0 1 3.3925781 4.3613281 4.5 4.5 0 0 1 -4.5 4.5 4.5 4.5 0 0 1 -4.359375-3.3886719 7 7 0 0 0 -.140625 1.3886719 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0 -7-7 7 7 0 0 0 -.09375 0z" fill="#ffca5f" stroke-width=".365215"/></svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 69fa64c24c..013dcb5deb 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -1801,7 +1801,14 @@ Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint3
name = state.animations[i]->get_name();
}
- ap->add_animation(name, state.animations[i]);
+ Ref<AnimationLibrary> library;
+ if (!ap->has_animation_library("")) {
+ library.instantiate();
+ ap->add_animation_library("", library);
+ } else {
+ library = ap->get_animation_library("");
+ }
+ library->add_animation(name, state.animations[i]);
}
state.scene->add_child(ap, true);
ap->set_owner(state.scene);
@@ -1810,26 +1817,5 @@ Node *EditorSceneFormatImporterCollada::import_scene(const String &p_path, uint3
return state.scene;
}
-Ref<Animation> EditorSceneFormatImporterCollada::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) {
- ColladaImport state;
-
- state.use_mesh_builtin_materials = false;
-
- Error err = state.load(p_path, Collada::IMPORT_FLAG_ANIMATION, p_flags & EditorSceneFormatImporter::IMPORT_GENERATE_TANGENT_ARRAYS);
- ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot load animation from file '" + p_path + "'.");
-
- state.create_animations(true);
- if (state.scene) {
- memdelete(state.scene);
- }
-
- if (state.animations.size() == 0) {
- return Ref<Animation>();
- }
- Ref<Animation> anim = state.animations[0];
-
- return anim;
-}
-
EditorSceneFormatImporterCollada::EditorSceneFormatImporterCollada() {
}
diff --git a/editor/import/editor_import_collada.h b/editor/import/editor_import_collada.h
index c32d785d1c..be3f74d821 100644
--- a/editor/import/editor_import_collada.h
+++ b/editor/import/editor_import_collada.h
@@ -40,7 +40,6 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps = nullptr, Error *r_err = nullptr) override;
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override;
EditorSceneFormatImporterCollada();
};
diff --git a/editor/import/resource_importer_csv_translation.cpp b/editor/import/resource_importer_csv_translation.cpp
index f0ee14bdcb..ee6500a643 100644
--- a/editor/import/resource_importer_csv_translation.cpp
+++ b/editor/import/resource_importer_csv_translation.cpp
@@ -88,9 +88,8 @@ Error ResourceImporterCSVTranslation::import(const String &p_source_file, const
break;
}
- FileAccessRef f = FileAccess::open(p_source_file, FileAccess::READ);
-
- ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open file from path '" + p_source_file + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_INVALID_PARAMETER, "Cannot open file from path '" + p_source_file + "'.");
Vector<String> line = f->get_csv_line(delimiter);
ERR_FAIL_COND_V(line.size() <= 1, ERR_PARSE_ERROR);
diff --git a/editor/import/resource_importer_image.cpp b/editor/import/resource_importer_image.cpp
index e6a822d827..8514df76bb 100644
--- a/editor/import/resource_importer_image.cpp
+++ b/editor/import/resource_importer_image.cpp
@@ -71,10 +71,9 @@ void ResourceImporterImage::get_import_options(const String &p_path, List<Import
}
Error ResourceImporterImage::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
- FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ);
-
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file from path '" + p_source_file + "'.");
uint64_t len = f->get_length();
Vector<uint8_t> data;
@@ -82,10 +81,8 @@ Error ResourceImporterImage::import(const String &p_source_file, const String &p
f->get_buffer(data.ptrw(), len);
- memdelete(f);
-
f = FileAccess::open(p_save_path + ".image", FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_CREATE, "Cannot create file in path '" + p_save_path + ".image'.");
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, "Cannot create file in path '" + p_save_path + ".image'.");
//save the header GDIM
const uint8_t header[4] = { 'G', 'D', 'I', 'M' };
@@ -95,8 +92,6 @@ Error ResourceImporterImage::import(const String &p_source_file, const String &p
//SAVE the actual image
f->store_buffer(data.ptr(), len);
- memdelete(f);
-
return OK;
}
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index 9ddee9c058..7c0c99cd29 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -257,7 +257,7 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
}
}
- FileAccessRef f = FileAccess::open(p_to_path, FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(p_to_path, FileAccess::WRITE);
f->store_8('G');
f->store_8('S');
f->store_8('T');
@@ -280,8 +280,6 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
for (int i = 0; i < mipmap_images.size(); i++) {
ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
}
-
- f->close();
}
Error ResourceImporterLayeredTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 9042f1e32c..88837d089a 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -44,8 +44,8 @@ uint32_t EditorOBJImporter::get_import_flags() const {
}
static Error _parse_material_library(const String &p_path, Map<String, Ref<StandardMaterial3D>> &material_map, List<String> *r_missing_deps) {
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Couldn't open MTL file '%s', it may not exist or not be readable.", p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open MTL file '%s', it may not exist or not be readable.", p_path));
Ref<StandardMaterial3D> current;
String current_name;
@@ -203,8 +203,8 @@ static Error _parse_material_library(const String &p_path, Map<String, Ref<Stand
}
static Error _parse_obj(const String &p_path, List<Ref<Mesh>> &r_meshes, bool p_single_mesh, bool p_generate_tangents, bool p_optimize, Vector3 p_scale_mesh, Vector3 p_offset_mesh, List<String> *r_missing_deps) {
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Couldn't open OBJ file '%s', it may not exist or not be readable.", p_path));
Ref<ArrayMesh> mesh;
mesh.instantiate();
@@ -457,10 +457,6 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, co
return scene;
}
-Ref<Animation> EditorOBJImporter::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) {
- return Ref<Animation>();
-}
-
void EditorOBJImporter::get_extensions(List<String> *r_extensions) const {
r_extensions->push_back("obj");
}
diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h
index d7e3f0209d..1b5e8bbdc1 100644
--- a/editor/import/resource_importer_obj.h
+++ b/editor/import/resource_importer_obj.h
@@ -40,7 +40,6 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override;
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override;
EditorOBJImporter();
};
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index e7c605aaf0..bdb0c3c493 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -87,26 +87,13 @@ Node *EditorSceneFormatImporter::import_scene(const String &p_path, uint32_t p_f
ERR_FAIL_V(nullptr);
}
-Ref<Animation> EditorSceneFormatImporter::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) {
- Dictionary options_dict;
- for (const KeyValue<StringName, Variant> &elem : p_options) {
- options_dict[elem.key] = elem.value;
- }
- Ref<Animation> ret;
- if (GDVIRTUAL_CALL(_import_animation, p_path, p_flags, options_dict, p_bake_fps, ret)) {
- return ret;
- }
-
- ERR_FAIL_V(nullptr);
-}
-
void EditorSceneFormatImporter::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) {
GDVIRTUAL_CALL(_get_import_options, p_path);
}
-Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) {
+Variant EditorSceneFormatImporter::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) {
Variant ret;
- GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret);
+ GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret);
return ret;
}
@@ -114,15 +101,15 @@ void EditorSceneFormatImporter::_bind_methods() {
GDVIRTUAL_BIND(_get_import_flags);
GDVIRTUAL_BIND(_get_extensions);
GDVIRTUAL_BIND(_import_scene, "path", "flags", "options", "bake_fps");
- GDVIRTUAL_BIND(_import_animation, "path", "flags", "options", "bake_fps");
GDVIRTUAL_BIND(_get_import_options, "path");
- GDVIRTUAL_BIND(_get_option_visibility, "path", "option");
+ GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option");
BIND_CONSTANT(IMPORT_SCENE);
BIND_CONSTANT(IMPORT_ANIMATION);
BIND_CONSTANT(IMPORT_FAIL_ON_MISSING_DEPENDENCIES);
BIND_CONSTANT(IMPORT_GENERATE_TANGENT_ARRAYS);
BIND_CONSTANT(IMPORT_USE_NAMED_SKIN_BINDS);
+ BIND_CONSTANT(IMPORT_DISCARD_MESHES_AND_MATERIALS);
}
/////////////////////////////////
@@ -179,10 +166,10 @@ void EditorScenePostImportPlugin::get_internal_import_options(InternalImportCate
GDVIRTUAL_CALL(_get_internal_import_options, p_category);
current_option_list = nullptr;
}
-Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const {
+Variant EditorScenePostImportPlugin::get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const {
current_options = &p_options;
Variant ret;
- GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_option, ret);
+ GDVIRTUAL_CALL(_get_internal_option_visibility, p_category, p_for_animation, p_option, ret);
current_options = nullptr;
return ret;
}
@@ -205,10 +192,10 @@ void EditorScenePostImportPlugin::get_import_options(const String &p_path, List<
GDVIRTUAL_CALL(_get_import_options, p_path);
current_option_list = nullptr;
}
-Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const {
+Variant EditorScenePostImportPlugin::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const {
current_options = &p_options;
Variant ret;
- GDVIRTUAL_CALL(_get_option_visibility, p_path, p_option, ret);
+ GDVIRTUAL_CALL(_get_option_visibility, p_path, p_for_animation, p_option, ret);
current_options = nullptr;
return ret;
}
@@ -231,11 +218,11 @@ void EditorScenePostImportPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_import_option_advanced", "type", "name", "default_value", "hint", "hint_string", "usage_flags"), &EditorScenePostImportPlugin::add_import_option_advanced, DEFVAL(PROPERTY_HINT_NONE), DEFVAL(""), DEFVAL(PROPERTY_USAGE_DEFAULT));
GDVIRTUAL_BIND(_get_internal_import_options, "category");
- GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "option");
+ GDVIRTUAL_BIND(_get_internal_option_visibility, "category", "for_animation", "option");
GDVIRTUAL_BIND(_get_internal_option_update_view_required, "category", "option");
GDVIRTUAL_BIND(_internal_process, "category", "base_node", "node", "resource");
GDVIRTUAL_BIND(_get_import_options, "path");
- GDVIRTUAL_BIND(_get_option_visibility, "path", "option");
+ GDVIRTUAL_BIND(_get_option_visibility, "path", "for_animation", "option");
GDVIRTUAL_BIND(_pre_process, "scene");
GDVIRTUAL_BIND(_post_process, "scene");
@@ -251,11 +238,11 @@ void EditorScenePostImportPlugin::_bind_methods() {
/////////////////////////////////////////////////////////
String ResourceImporterScene::get_importer_name() const {
- return "scene";
+ return animation_importer ? "animation_library" : "scene";
}
String ResourceImporterScene::get_visible_name() const {
- return "Scene";
+ return animation_importer ? "Animation Library" : "Scene";
}
void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions) const {
@@ -265,11 +252,11 @@ void ResourceImporterScene::get_recognized_extensions(List<String> *p_extensions
}
String ResourceImporterScene::get_save_extension() const {
- return "scn";
+ return animation_importer ? "res" : "scn";
}
String ResourceImporterScene::get_resource_type() const {
- return "PackedScene";
+ return animation_importer ? "AnimationLibrary" : "PackedScene";
}
int ResourceImporterScene::get_format_version() const {
@@ -277,26 +264,34 @@ int ResourceImporterScene::get_format_version() const {
}
bool ResourceImporterScene::get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const {
- if (p_option.begins_with("animation/")) {
+ if (animation_importer) {
+ if (p_option == "animation/import") { // Option ignored, animation always imported.
+ return false;
+ }
+ } else if (p_option.begins_with("animation/")) {
if (p_option != "animation/import" && !bool(p_options["animation/import"])) {
return false;
}
}
+ if (animation_importer && (p_option.begins_with("nodes/") || p_option.begins_with("meshes/") || p_option.begins_with("skins/"))) {
+ return false; // Nothing to do here for animations.
+ }
+
if (p_option == "meshes/lightmap_texel_size" && int(p_options["meshes/light_baking"]) != 2) {
// Only display the lightmap texel size import option when using the Static Lightmaps light baking mode.
return false;
}
for (int i = 0; i < post_importer_plugins.size(); i++) {
- Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, p_option, p_options);
+ Variant ret = post_importer_plugins.write[i]->get_option_visibility(p_path, animation_importer, p_option, p_options);
if (ret.get_type() == Variant::BOOL) {
return ret;
}
}
for (Ref<EditorSceneFormatImporter> importer : importers) {
- Variant ret = importer->get_option_visibility(p_path, p_option, p_options);
+ Variant ret = importer->get_option_visibility(p_path, animation_importer, p_option, p_options);
if (ret.get_type() == Variant::BOOL) {
return ret;
}
@@ -473,7 +468,9 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, Map<Ref<I
if (_teststr(animname, loop_strings[i])) {
anim->set_loop_mode(Animation::LoopMode::LOOP_LINEAR);
animname = _fixstr(animname, loop_strings[i]);
- ap->rename_animation(E, animname);
+
+ Ref<AnimationLibrary> library = ap->get_animation_library(ap->find_animation_library(anim));
+ library->rename_animation(E, animname);
}
}
}
@@ -1019,7 +1016,8 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, Map<Ref<
Ref<Animation> saved_anim = _save_animation_to_file(anim, save, path, keep_custom);
if (saved_anim != anim) {
- ap->add_animation(name, saved_anim); //replace
+ Ref<AnimationLibrary> al = ap->get_animation_library(ap->find_animation_library(anim));
+ al->add_animation(name, saved_anim); //replace
}
}
}
@@ -1109,6 +1107,7 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
}
Ref<Animation> default_anim = anim->get_animation("default");
+ Ref<AnimationLibrary> al = anim->get_animation_library(anim->find_animation(default_anim));
for (int i = 0; i < p_clips.size(); i += 7) {
String name = p_clips[i];
@@ -1246,15 +1245,16 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
new_anim->set_loop_mode(loop_mode);
new_anim->set_length(to - from);
- anim->add_animation(name, new_anim);
+
+ al->add_animation(name, new_anim);
Ref<Animation> saved_anim = _save_animation_to_file(new_anim, save_to_file, save_to_path, keep_current);
if (saved_anim != new_anim) {
- anim->add_animation(name, saved_anim);
+ al->add_animation(name, saved_anim);
}
}
- anim->remove_animation("default"); //remove default (no longer needed)
+ al->remove_animation("default"); // Remove default (no longer needed).
}
void ResourceImporterScene::_optimize_animations(AnimationPlayer *anim, float p_max_lin_error, float p_max_ang_error, float p_max_angle) {
@@ -1477,7 +1477,7 @@ bool ResourceImporterScene::get_internal_option_visibility(InternalImportCategor
}
for (int i = 0; i < post_importer_plugins.size(); i++) {
- Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), p_option, p_options);
+ Variant ret = post_importer_plugins.write[i]->get_internal_option_visibility(EditorScenePostImportPlugin::InternalImportCategory(p_category), animation_importer, p_option, p_options);
if (ret.get_type() == Variant::BOOL) {
return ret;
}
@@ -1969,8 +1969,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
int import_flags = 0;
- if (bool(p_options["animation/import"])) {
+ if (animation_importer) {
import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION;
+ import_flags |= EditorSceneFormatImporter::IMPORT_DISCARD_MESHES_AND_MATERIALS;
+ } else {
+ if (bool(p_options["animation/import"])) {
+ import_flags |= EditorSceneFormatImporter::IMPORT_ANIMATION;
+ }
}
if (bool(p_options["skins/use_named_skins"])) {
@@ -2086,14 +2091,13 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
_generate_meshes(scene, mesh_data, gen_lods, create_shadow_meshes, LightBakeMode(light_bake_mode), lightmap_texel_size, src_lightmap_cache, mesh_lightmap_caches);
if (mesh_lightmap_caches.size()) {
- FileAccessRef f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(p_source_file + ".unwrap_cache", FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_32(mesh_lightmap_caches.size());
for (int i = 0; i < mesh_lightmap_caches.size(); i++) {
String md5 = String::md5(mesh_lightmap_caches[i].ptr());
f->store_buffer(mesh_lightmap_caches[i].ptr(), mesh_lightmap_caches[i].size());
}
- f->close();
}
}
err = OK;
@@ -2135,11 +2139,35 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
progress.step(TTR("Saving..."), 104);
- Ref<PackedScene> packer = memnew(PackedScene);
- packer->pack(scene);
- print_verbose("Saving scene to: " + p_save_path + ".scn");
- err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'.");
+ if (animation_importer) {
+ Ref<AnimationLibrary> library;
+ for (int i = 0; i < scene->get_child_count(); i++) {
+ AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(scene->get_child(i));
+ if (ap) {
+ List<StringName> libs;
+ ap->get_animation_library_list(&libs);
+ if (libs.size()) {
+ library = ap->get_animation_library(libs.front()->get());
+ break;
+ }
+ }
+ }
+
+ if (!library.is_valid()) {
+ library.instantiate(); // Will be empty
+ }
+
+ print_verbose("Saving animation to: " + p_save_path + ".scn");
+ err = ResourceSaver::save(p_save_path + ".res", library); //do not take over, let the changed files reload themselves
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save animation to file '" + p_save_path + ".res'.");
+
+ } else {
+ Ref<PackedScene> packer = memnew(PackedScene);
+ packer->pack(scene);
+ print_verbose("Saving scene to: " + p_save_path + ".scn");
+ err = ResourceSaver::save(p_save_path + ".scn", packer); //do not take over, let the changed files reload themselves
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save scene to file '" + p_save_path + ".scn'.");
+ }
memdelete(scene);
@@ -2149,17 +2177,26 @@ Error ResourceImporterScene::import(const String &p_source_file, const String &p
return OK;
}
-ResourceImporterScene *ResourceImporterScene::singleton = nullptr;
+ResourceImporterScene *ResourceImporterScene::scene_singleton = nullptr;
+ResourceImporterScene *ResourceImporterScene::animation_singleton = nullptr;
+
+Vector<Ref<EditorSceneFormatImporter>> ResourceImporterScene::importers;
+Vector<Ref<EditorScenePostImportPlugin>> ResourceImporterScene::post_importer_plugins;
bool ResourceImporterScene::ResourceImporterScene::has_advanced_options() const {
return true;
}
void ResourceImporterScene::ResourceImporterScene::show_advanced_options(const String &p_path) {
- SceneImportSettings::get_singleton()->open_settings(p_path);
+ SceneImportSettings::get_singleton()->open_settings(p_path, animation_importer);
}
-ResourceImporterScene::ResourceImporterScene() {
- singleton = this;
+ResourceImporterScene::ResourceImporterScene(bool p_animation_import) {
+ if (p_animation_import) {
+ animation_singleton = this;
+ } else {
+ scene_singleton = this;
+ }
+ animation_importer = p_animation_import;
}
void ResourceImporterScene::add_importer(Ref<EditorSceneFormatImporter> p_importer, bool p_first_priority) {
@@ -2188,6 +2225,11 @@ void ResourceImporterScene::remove_importer(Ref<EditorSceneFormatImporter> p_imp
importers.erase(p_importer);
}
+void ResourceImporterScene::clean_up_importer_plugins() {
+ importers.clear();
+ post_importer_plugins.clear();
+}
+
///////////////////////////////////////
uint32_t EditorSceneFormatImporterESCN::get_import_flags() const {
@@ -2208,7 +2250,3 @@ Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t
return scene;
}
-
-Ref<Animation> EditorSceneFormatImporterESCN::import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) {
- ERR_FAIL_V(Ref<Animation>());
-}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index a819be682d..368f68ae8f 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -56,9 +56,8 @@ protected:
GDVIRTUAL0RC(int, _get_import_flags)
GDVIRTUAL0RC(Vector<String>, _get_extensions)
GDVIRTUAL4R(Object *, _import_scene, String, uint32_t, Dictionary, uint32_t)
- GDVIRTUAL4R(Ref<Animation>, _import_animation, String, uint32_t, Dictionary, uint32_t)
GDVIRTUAL1(_get_import_options, String)
- GDVIRTUAL2RC(Variant, _get_option_visibility, String, String)
+ GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String)
public:
enum ImportFlags {
@@ -67,14 +66,14 @@ public:
IMPORT_FAIL_ON_MISSING_DEPENDENCIES = 4,
IMPORT_GENERATE_TANGENT_ARRAYS = 8,
IMPORT_USE_NAMED_SKIN_BINDS = 16,
+ IMPORT_DISCARD_MESHES_AND_MATERIALS = 32, //used for optimizing animation import
};
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr);
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps);
virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options);
- virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options);
+ virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options);
EditorSceneFormatImporter() {}
};
@@ -118,11 +117,11 @@ private:
protected:
GDVIRTUAL1(_get_internal_import_options, int)
- GDVIRTUAL2RC(Variant, _get_internal_option_visibility, int, String)
+ GDVIRTUAL3RC(Variant, _get_internal_option_visibility, int, bool, String)
GDVIRTUAL2RC(Variant, _get_internal_option_update_view_required, int, String)
GDVIRTUAL4(_internal_process, int, Node *, Node *, RES)
GDVIRTUAL1(_get_import_options, String)
- GDVIRTUAL2RC(Variant, _get_option_visibility, String, String)
+ GDVIRTUAL3RC(Variant, _get_option_visibility, String, bool, String)
GDVIRTUAL1(_pre_process, Node *)
GDVIRTUAL1(_post_process, Node *)
@@ -134,13 +133,13 @@ public:
void add_import_option_advanced(Variant::Type p_type, const String &p_name, Variant p_default_value, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = String(), int p_usage_flags = PROPERTY_USAGE_DEFAULT);
virtual void get_internal_import_options(InternalImportCategory p_category, List<ResourceImporter::ImportOption> *r_options);
- virtual Variant get_internal_option_visibility(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const;
+ virtual Variant get_internal_option_visibility(InternalImportCategory p_category, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual Variant get_internal_option_update_view_required(InternalImportCategory p_category, const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual void internal_process(InternalImportCategory p_category, Node *p_base_scene, Node *p_node, RES p_resource, const Dictionary &p_options);
virtual void get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options);
- virtual Variant get_option_visibility(const String &p_path, const String &p_option, const Map<StringName, Variant> &p_options) const;
+ virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option, const Map<StringName, Variant> &p_options) const;
virtual void pre_process(Node *p_scene, const Map<StringName, Variant> &p_options);
virtual void post_process(Node *p_scene, const Map<StringName, Variant> &p_options);
@@ -153,9 +152,11 @@ VARIANT_ENUM_CAST(EditorScenePostImportPlugin::InternalImportCategory)
class ResourceImporterScene : public ResourceImporter {
GDCLASS(ResourceImporterScene, ResourceImporter);
- Vector<Ref<EditorSceneFormatImporter>> importers;
+ static Vector<Ref<EditorSceneFormatImporter>> importers;
+ static Vector<Ref<EditorScenePostImportPlugin>> post_importer_plugins;
- static ResourceImporterScene *singleton;
+ static ResourceImporterScene *scene_singleton;
+ static ResourceImporterScene *animation_singleton;
enum LightBakeMode {
LIGHT_BAKE_DISABLED,
@@ -225,18 +226,21 @@ class ResourceImporterScene : public ResourceImporter {
void _optimize_track_usage(AnimationPlayer *p_player, AnimationImportTracks *p_track_actions);
- mutable Vector<Ref<EditorScenePostImportPlugin>> post_importer_plugins;
+ bool animation_importer = false;
public:
- static ResourceImporterScene *get_singleton() { return singleton; }
+ static ResourceImporterScene *get_scene_singleton() { return scene_singleton; }
+ static ResourceImporterScene *get_animation_singleton() { return animation_singleton; }
- void add_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin, bool p_first_priority = false);
- void remove_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin);
+ static void add_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin, bool p_first_priority = false);
+ static void remove_post_importer_plugin(const Ref<EditorScenePostImportPlugin> &p_plugin);
const Vector<Ref<EditorSceneFormatImporter>> &get_importers() const { return importers; }
- void add_importer(Ref<EditorSceneFormatImporter> p_importer, bool p_first_priority = false);
- void remove_importer(Ref<EditorSceneFormatImporter> p_importer);
+ static void add_importer(Ref<EditorSceneFormatImporter> p_importer, bool p_first_priority = false);
+ static void remove_importer(Ref<EditorSceneFormatImporter> p_importer);
+
+ static void clean_up_importer_plugins();
virtual String get_importer_name() const override;
virtual String get_visible_name() const override;
@@ -283,7 +287,7 @@ public:
virtual bool can_import_threaded() const override { return false; }
- ResourceImporterScene();
+ ResourceImporterScene(bool p_animation_import = false);
template <class M>
static Vector<Ref<Shape3D>> get_collision_shapes(const Ref<Mesh> &p_mesh, const M &p_options);
@@ -299,7 +303,6 @@ public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override;
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override;
};
#include "scene/resources/box_shape_3d.h"
diff --git a/editor/import/resource_importer_shader_file.cpp b/editor/import/resource_importer_shader_file.cpp
index cc34259a2d..1d70a47daa 100644
--- a/editor/import/resource_importer_shader_file.cpp
+++ b/editor/import/resource_importer_shader_file.cpp
@@ -82,7 +82,7 @@ static String _include_function(const String &p_path, void *userpointer) {
include = base_path->plus_file(include);
}
- FileAccessRef file_inc = FileAccess::open(include, FileAccess::READ, &err);
+ Ref<FileAccess> file_inc = FileAccess::open(include, FileAccess::READ, &err);
if (err != OK) {
return String();
}
@@ -93,7 +93,7 @@ Error ResourceImporterShaderFile::import(const String &p_source_file, const Stri
/* STEP 1, Read shader code */
Error err;
- FileAccessRef file = FileAccess::open(p_source_file, FileAccess::READ, &err);
+ Ref<FileAccess> file = FileAccess::open(p_source_file, FileAccess::READ, &err);
ERR_FAIL_COND_V(err != OK, ERR_CANT_OPEN);
ERR_FAIL_COND_V(!file.operator->(), ERR_CANT_OPEN);
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index e2fa624fc6..de51a28c5a 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -229,7 +229,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo
}
}
-void ResourceImporterTexture::save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
+void ResourceImporterTexture::save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) {
switch (p_compress_mode) {
case COMPRESS_LOSSLESS: {
bool lossless_force_png = ProjectSettings::get_singleton()->get("rendering/textures/lossless_compression/force_png") ||
@@ -322,8 +322,8 @@ void ResourceImporterTexture::save_to_ctex_format(FileAccess *f, const Ref<Image
}
void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel) {
- FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE);
- ERR_FAIL_NULL(f);
+ Ref<FileAccess> f = FileAccess::open(p_to_path, FileAccess::WRITE);
+ ERR_FAIL_COND(f.is_null());
f->store_8('G');
f->store_8('S');
f->store_8('T');
@@ -399,8 +399,6 @@ void ResourceImporterTexture::_save_ctex(const Ref<Image> &p_image, const String
Image::UsedChannels used_channels = image->detect_used_channels(csource);
save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality);
-
- memdelete(f);
}
Error ResourceImporterTexture::import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) {
diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h
index b3a68260fc..b932c598a2 100644
--- a/editor/import/resource_importer_texture.h
+++ b/editor/import/resource_importer_texture.h
@@ -77,7 +77,7 @@ protected:
void _save_ctex(const Ref<Image> &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref<Image> &p_normal, Image::RoughnessChannel p_roughness_channel);
public:
- static void save_to_ctex_format(FileAccess *f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
+ static void save_to_ctex_format(Ref<FileAccess> f, const Ref<Image> &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);
static ResourceImporterTexture *get_singleton() { return singleton; }
virtual String get_importer_name() const override;
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 68d1d23dd8..154970f7ed 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -97,7 +97,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
/* STEP 1, READ WAVE FILE */
Error err;
- FileAccess *file = FileAccess::open(p_source_file, FileAccess::READ, &err);
+ Ref<FileAccess> file = FileAccess::open(p_source_file, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'.");
@@ -107,8 +107,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
file->get_buffer((uint8_t *)&riff, 4); //RIFF
if (riff[0] != 'R' || riff[1] != 'I' || riff[2] != 'F' || riff[3] != 'F') {
- file->close();
- memdelete(file);
ERR_FAIL_V(ERR_FILE_UNRECOGNIZED);
}
@@ -122,8 +120,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
file->get_buffer((uint8_t *)&wave, 4); //RIFF
if (wave[0] != 'W' || wave[1] != 'A' || wave[2] != 'V' || wave[3] != 'E') {
- file->close();
- memdelete(file);
ERR_FAIL_V_MSG(ERR_FILE_UNRECOGNIZED, "Not a WAV file (no WAVE RIFF header).");
}
@@ -166,15 +162,11 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
//Consider revision for engine version 3.0
compression_code = file->get_16();
if (compression_code != 1 && compression_code != 3) {
- file->close();
- memdelete(file);
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Format not supported for WAVE file (not PCM). Save WAVE files as uncompressed PCM instead.");
}
format_channels = file->get_16();
if (format_channels != 1 && format_channels != 2) {
- file->close();
- memdelete(file);
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Format not supported for WAVE file (not stereo or mono).");
}
@@ -185,8 +177,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
format_bits = file->get_16(); // bits per sample
if (format_bits % 8 || format_bits == 0) {
- file->close();
- memdelete(file);
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Invalid amount of bits in the sample (should be one of 8, 16, 24 or 32).");
}
@@ -206,8 +196,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
frames = chunksize;
if (format_channels == 0) {
- file->close();
- memdelete(file);
ERR_FAIL_COND_V(format_channels == 0, ERR_INVALID_DATA);
}
frames /= format_channels;
@@ -254,8 +242,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
}
if (file->eof_reached()) {
- file->close();
- memdelete(file);
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Premature end of file.");
}
}
@@ -295,9 +281,6 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
file->seek(file_pos + chunksize);
}
- file->close();
- memdelete(file);
-
// STEP 2, APPLY CONVERSIONS
bool is16 = format_bits != 8;
diff --git a/editor/import/scene_import_settings.cpp b/editor/import/scene_import_settings.cpp
index 302bc98499..4e53a644ee 100644
--- a/editor/import/scene_import_settings.cpp
+++ b/editor/import/scene_import_settings.cpp
@@ -47,6 +47,8 @@ class SceneImportSettingsData : public Object {
Map<StringName, Variant> current;
Map<StringName, Variant> defaults;
List<ResourceImporter::ImportOption> options;
+ bool hide_options = false;
+ String path;
ResourceImporterScene::InternalImportCategory category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX;
@@ -60,8 +62,26 @@ class SceneImportSettingsData : public Object {
current[p_name] = p_value;
- if (ResourceImporterScene::get_singleton()->get_internal_option_update_view_required(category, p_name, current)) {
- SceneImportSettings::get_singleton()->update_view();
+ if (SceneImportSettings::get_singleton()->is_editing_animation()) {
+ if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
+ if (ResourceImporterScene::get_animation_singleton()->get_option_visibility(path, p_name, current)) {
+ SceneImportSettings::get_singleton()->update_view();
+ }
+ } else {
+ if (ResourceImporterScene::get_animation_singleton()->get_internal_option_update_view_required(category, p_name, current)) {
+ SceneImportSettings::get_singleton()->update_view();
+ }
+ }
+ } else {
+ if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
+ if (ResourceImporterScene::get_scene_singleton()->get_option_visibility(path, p_name, current)) {
+ SceneImportSettings::get_singleton()->update_view();
+ }
+ } else {
+ if (ResourceImporterScene::get_scene_singleton()->get_internal_option_update_view_required(category, p_name, current)) {
+ SceneImportSettings::get_singleton()->update_view();
+ }
+ }
}
return true;
@@ -82,9 +102,30 @@ class SceneImportSettingsData : public Object {
return false;
}
void _get_property_list(List<PropertyInfo> *p_list) const {
+ if (hide_options) {
+ return;
+ }
for (const ResourceImporter::ImportOption &E : options) {
- if (ResourceImporterScene::get_singleton()->get_internal_option_visibility(category, E.option.name, current)) {
- p_list->push_back(E.option);
+ if (SceneImportSettings::get_singleton()->is_editing_animation()) {
+ if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
+ if (ResourceImporterScene::get_animation_singleton()->get_option_visibility(path, E.option.name, current)) {
+ p_list->push_back(E.option);
+ }
+ } else {
+ if (ResourceImporterScene::get_animation_singleton()->get_internal_option_visibility(category, E.option.name, current)) {
+ p_list->push_back(E.option);
+ }
+ }
+ } else {
+ if (category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
+ if (ResourceImporterScene::get_scene_singleton()->get_option_visibility(path, E.option.name, current)) {
+ p_list->push_back(E.option);
+ }
+ } else {
+ if (ResourceImporterScene::get_scene_singleton()->get_internal_option_visibility(category, E.option.name, current)) {
+ p_list->push_back(E.option);
+ }
+ }
}
}
}
@@ -326,7 +367,9 @@ void SceneImportSettings::_fill_scene(Node *p_node, TreeItem *p_parent_item) {
}
MeshInstance3D *mesh_node = Object::cast_to<MeshInstance3D>(p_node);
if (mesh_node && mesh_node->get_mesh().is_valid()) {
- _fill_mesh(scene_tree, mesh_node->get_mesh(), item);
+ if (!editing_animation) {
+ _fill_mesh(scene_tree, mesh_node->get_mesh(), item);
+ }
// Add the collider view.
MeshInstance3D *collider_view = memnew(MeshInstance3D);
@@ -365,6 +408,9 @@ void SceneImportSettings::_update_scene() {
}
void SceneImportSettings::_update_view_gizmos() {
+ if (!is_visible()) {
+ return;
+ }
for (const KeyValue<String, NodeData> &e : node_map) {
bool generate_collider = false;
if (e.value.settings.has(SNAME("generate/physics"))) {
@@ -378,6 +424,7 @@ void SceneImportSettings::_update_view_gizmos() {
}
TypedArray<Node> descendants = mesh_node->find_nodes("collider_view", "MeshInstance3D");
+
CRASH_COND_MSG(descendants.is_empty(), "This is unreachable, since the collider view is always created even when the collision is not used! If this is triggered there is a bug on the function `_fill_scene`.");
MeshInstance3D *collider_view = static_cast<MeshInstance3D *>(descendants[0].operator Object *());
@@ -460,7 +507,11 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var
if (d.has(p_import_id)) {
d = d[p_import_id];
List<ResourceImporterScene::ImportOption> options;
- ResourceImporterScene::get_singleton()->get_internal_import_options(p_category, &options);
+ if (editing_animation) {
+ ResourceImporterScene::get_animation_singleton()->get_internal_import_options(p_category, &options);
+ } else {
+ ResourceImporterScene::get_scene_singleton()->get_internal_import_options(p_category, &options);
+ }
for (const ResourceImporterScene::ImportOption &E : options) {
String key = E.option.name;
if (d.has(key)) {
@@ -472,21 +523,32 @@ void SceneImportSettings::_load_default_subresource_settings(Map<StringName, Var
}
void SceneImportSettings::update_view() {
- _update_view_gizmos();
+ update_view_timer->start();
}
-void SceneImportSettings::open_settings(const String &p_path) {
+void SceneImportSettings::open_settings(const String &p_path, bool p_for_animation) {
if (scene) {
memdelete(scene);
scene = nullptr;
}
+
+ editing_animation = p_for_animation;
scene_import_settings_data->settings = nullptr;
- scene = ResourceImporterScene::get_singleton()->pre_import(p_path);
+ scene_import_settings_data->path = p_path;
+
+ scene = ResourceImporterScene::get_scene_singleton()->pre_import(p_path); // Use the scene singleton here because we want to see the full thing.
if (scene == nullptr) {
EditorNode::get_singleton()->show_warning(TTR("Error opening scene"));
return;
}
+ // Visibility
+ data_mode->set_tab_hidden(1, p_for_animation);
+ data_mode->set_tab_hidden(2, p_for_animation);
+
+ action_menu->get_popup()->set_item_disabled(action_menu->get_popup()->get_item_id(ACTION_EXTRACT_MATERIALS), p_for_animation);
+ action_menu->get_popup()->set_item_disabled(action_menu->get_popup()->get_item_id(ACTION_CHOOSE_MESH_SAVE_PATHS), p_for_animation);
+
base_path = p_path;
material_set.clear();
@@ -540,7 +602,11 @@ void SceneImportSettings::open_settings(const String &p_path) {
_update_view_gizmos();
_update_camera();
- set_title(vformat(TTR("Advanced Import Settings for '%s'"), base_path.get_file()));
+ if (p_for_animation) {
+ set_title(vformat(TTR("Advanced Import Settings for AnimationLibrary '%s'"), base_path.get_file()));
+ } else {
+ set_title(vformat(TTR("Advanced Import Settings for Scene '%s'"), base_path.get_file()));
+ }
}
SceneImportSettings *SceneImportSettings::singleton = nullptr;
@@ -551,6 +617,7 @@ SceneImportSettings *SceneImportSettings::get_singleton() {
void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
selecting = true;
+ scene_import_settings_data->hide_options = false;
if (p_type == "Node") {
node_selected->hide(); //always hide just in case
@@ -585,10 +652,12 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
scene_import_settings_data->settings = &nd.settings;
if (mi) {
scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MESH_3D_NODE;
+ scene_import_settings_data->hide_options = editing_animation;
} else if (Object::cast_to<AnimationPlayer>(nd.node)) {
scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_ANIMATION_NODE;
} else {
scene_import_settings_data->category = ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_NODE;
+ scene_import_settings_data->hide_options = editing_animation;
}
}
} else if (p_type == "Animation") {
@@ -671,24 +740,36 @@ void SceneImportSettings::_select(Tree *p_from, String p_type, String p_id) {
List<ResourceImporter::ImportOption> options;
- if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
- ResourceImporterScene::get_singleton()->get_import_options(base_path, &options);
+ if (editing_animation) {
+ if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
+ ResourceImporterScene::get_animation_singleton()->get_import_options(base_path, &options);
+ } else {
+ ResourceImporterScene::get_animation_singleton()->get_internal_import_options(scene_import_settings_data->category, &options);
+ }
+
} else {
- ResourceImporterScene::get_singleton()->get_internal_import_options(scene_import_settings_data->category, &options);
+ if (scene_import_settings_data->category == ResourceImporterScene::INTERNAL_IMPORT_CATEGORY_MAX) {
+ ResourceImporterScene::get_scene_singleton()->get_import_options(base_path, &options);
+ } else {
+ ResourceImporterScene::get_scene_singleton()->get_internal_import_options(scene_import_settings_data->category, &options);
+ }
}
scene_import_settings_data->defaults.clear();
scene_import_settings_data->current.clear();
- for (const ResourceImporter::ImportOption &E : options) {
- scene_import_settings_data->defaults[E.option.name] = E.default_value;
- //needed for visibility toggling (fails if something is missing)
- if (scene_import_settings_data->settings->has(E.option.name)) {
- scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name];
- } else {
- scene_import_settings_data->current[E.option.name] = E.default_value;
+ if (scene_import_settings_data->settings) {
+ for (const ResourceImporter::ImportOption &E : options) {
+ scene_import_settings_data->defaults[E.option.name] = E.default_value;
+ //needed for visibility toggling (fails if something is missing)
+ if (scene_import_settings_data->settings->has(E.option.name)) {
+ scene_import_settings_data->current[E.option.name] = (*scene_import_settings_data->settings)[E.option.name];
+ } else {
+ scene_import_settings_data->current[E.option.name] = E.default_value;
+ }
}
}
+
scene_import_settings_data->options = options;
inspector->edit(scene_import_settings_data);
scene_import_settings_data->notify_property_list_changed();
@@ -836,7 +917,7 @@ void SceneImportSettings::_re_import() {
main_settings["_subresources"] = subresources;
}
- EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, "scene", main_settings);
+ EditorFileSystem::get_singleton()->reimport_file_with_custom_parameters(base_path, editing_animation ? "animation_library" : "scene", main_settings);
}
void SceneImportSettings::_notification(int p_what) {
@@ -1282,6 +1363,11 @@ SceneImportSettings::SceneImportSettings() {
item_save_path->connect("file_selected", callable_mp(this, &SceneImportSettings::_save_path_changed));
save_path->connect("dir_selected", callable_mp(this, &SceneImportSettings::_save_dir_callback));
+
+ update_view_timer = memnew(Timer);
+ update_view_timer->set_wait_time(0.2);
+ update_view_timer->connect("timeout", callable_mp(this, &SceneImportSettings::_update_view_gizmos));
+ add_child(update_view_timer);
}
SceneImportSettings::~SceneImportSettings() {
diff --git a/editor/import/scene_import_settings.h b/editor/import/scene_import_settings.h
index 3cf708740b..55cfba3275 100644
--- a/editor/import/scene_import_settings.h
+++ b/editor/import/scene_import_settings.h
@@ -189,12 +189,17 @@ class SceneImportSettings : public ConfirmationDialog {
void _load_default_subresource_settings(Map<StringName, Variant> &settings, const String &p_type, const String &p_import_id, ResourceImporterScene::InternalImportCategory p_category);
+ bool editing_animation = false;
+
+ Timer *update_view_timer;
+
protected:
void _notification(int p_what);
public:
+ bool is_editing_animation() const { return editing_animation; }
void update_view();
- void open_settings(const String &p_path);
+ void open_settings(const String &p_path, bool p_for_animation = false);
static SceneImportSettings *get_singleton();
SceneImportSettings();
~SceneImportSettings();
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index 02cc95e14a..755bf7ce07 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -50,8 +50,8 @@ void PluginConfigDialog::_on_confirmed() {
String path = "res://addons/" + subfolder_edit->get_text();
if (!_edit_mode) {
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- if (!d || d->make_dir_recursive(path) != OK) {
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ if (d.is_null() || d->make_dir_recursive(path) != OK) {
return;
}
}
@@ -137,7 +137,7 @@ void PluginConfigDialog::_on_required_text_changed(const String &) {
subfolder_validation->set_texture(invalid_icon);
subfolder_validation->set_tooltip(TTR("Subfolder name is not a valid folder name."));
} else {
- DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
String path = "res://addons/" + subfolder_edit->get_text();
if (dir->dir_exists(path) && !_edit_mode) { // Only show this error if in "create" mode.
is_valid = false;
diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp
new file mode 100644
index 0000000000..2e9a82a7c2
--- /dev/null
+++ b/editor/plugins/animation_library_editor.cpp
@@ -0,0 +1,689 @@
+/*************************************************************************/
+/* animation_library_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 "animation_library_editor.h"
+#include "editor/editor_file_dialog.h"
+#include "editor/editor_node.h"
+#include "editor/editor_scale.h"
+
+void AnimationLibraryEditor::set_animation_player(Object *p_player) {
+ player = p_player;
+}
+
+void AnimationLibraryEditor::_add_library() {
+ add_library_dialog->set_title(TTR("Library Name:"));
+ add_library_name->set_text("");
+ add_library_dialog->popup_centered();
+ add_library_name->grab_focus();
+ adding_animation = false;
+ adding_animation_to_library = StringName();
+ _add_library_validate("");
+}
+
+void AnimationLibraryEditor::_add_library_validate(const String &p_name) {
+ String error;
+
+ if (adding_animation) {
+ Ref<AnimationLibrary> al = player->call("get_animation_library", adding_animation_to_library);
+ ERR_FAIL_COND(al.is_null());
+ if (p_name == "") {
+ error = TTR("Animation name can't be empty.");
+
+ } else if (String(p_name).contains("/") || String(p_name).contains(":") || String(p_name).contains(",") || String(p_name).contains("[")) {
+ error = TTR("Animation name contains invalid characters: '/', ':', ',' or '['.");
+ } else if (al->has_animation(p_name)) {
+ error = TTR("Animation with the same name already exists.");
+ }
+
+ } else {
+ if (p_name == "" && bool(player->call("has_animation_library", ""))) {
+ error = TTR("Enter a library name.");
+ } else if (String(p_name).contains("/") || String(p_name).contains(":") || String(p_name).contains(",") || String(p_name).contains("[")) {
+ error = TTR("Library name contains invalid characters: '/', ':', ',' or '['.");
+ } else if (bool(player->call("has_animation_library", p_name))) {
+ error = TTR("Library with the same name already exists.");
+ }
+ }
+
+ if (error != "") {
+ add_library_validate->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
+ add_library_validate->set_text(error);
+ add_library_dialog->get_ok_button()->set_disabled(true);
+ } else {
+ add_library_validate->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor")));
+ if (p_name == "") {
+ add_library_validate->set_text(TTR("Global library will be created."));
+ } else {
+ add_library_validate->set_text(TTR("Library name is valid."));
+ }
+ add_library_dialog->get_ok_button()->set_disabled(false);
+ }
+}
+
+void AnimationLibraryEditor::_add_library_confirm() {
+ if (adding_animation) {
+ String anim_name = add_library_name->get_text();
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ Ref<AnimationLibrary> al = player->call("get_animation_library", adding_animation_to_library);
+ ERR_FAIL_COND(!al.is_valid());
+
+ Ref<Animation> anim;
+ anim.instantiate();
+
+ undo_redo->create_action(vformat(TTR("Add Animation to Library: %s"), anim_name));
+ undo_redo->add_do_method(al.ptr(), "add_animation", anim_name, anim);
+ undo_redo->add_undo_method(al.ptr(), "remove_animation", anim_name);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+
+ } else {
+ String lib_name = add_library_name->get_text();
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ Ref<AnimationLibrary> al;
+ al.instantiate();
+
+ undo_redo->create_action(vformat(TTR("Add Animation Library: %s"), lib_name));
+ undo_redo->add_do_method(player, "add_animation_library", lib_name, al);
+ undo_redo->add_undo_method(player, "remove_animation_library", lib_name);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ }
+}
+
+void AnimationLibraryEditor::_load_library() {
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("AnimationLibrary", &extensions);
+
+ file_dialog->set_title(TTR("Load Animation"));
+ file_dialog->clear_filters();
+ for (const String &K : extensions) {
+ file_dialog->add_filter("*." + K);
+ }
+
+ file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ file_dialog->set_current_file("");
+ file_dialog->popup_centered_ratio();
+
+ file_dialog_action = FILE_DIALOG_ACTION_OPEN_LIBRARY;
+}
+
+void AnimationLibraryEditor::_file_popup_selected(int p_id) {
+ Ref<AnimationLibrary> al = player->call("get_animation_library", file_dialog_library);
+ Ref<Animation> anim;
+ if (file_dialog_animation != StringName()) {
+ anim = al->get_animation(file_dialog_animation);
+ ERR_FAIL_COND(anim.is_null());
+ }
+ switch (p_id) {
+ case FILE_MENU_SAVE_LIBRARY: {
+ if (al->get_path().is_resource_file()) {
+ EditorNode::get_singleton()->save_resource(al);
+ break;
+ }
+ [[fallthrough]];
+ }
+ case FILE_MENU_SAVE_AS_LIBRARY: {
+ file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ file_dialog->set_title(TTR("Save Library"));
+ if (al->get_path().is_resource_file()) {
+ file_dialog->set_current_path(al->get_path());
+ } else {
+ file_dialog->set_current_file(String(file_dialog_library) + ".res");
+ }
+ file_dialog->clear_filters();
+ List<String> exts;
+ ResourceLoader::get_recognized_extensions_for_type("AnimationLibrary", &exts);
+ for (const String &K : exts) {
+ file_dialog->add_filter("*." + K);
+ }
+
+ file_dialog->popup_centered_ratio();
+ file_dialog_action = FILE_DIALOG_ACTION_SAVE_LIBRARY;
+ } break;
+ case FILE_MENU_MAKE_LIBRARY_UNIQUE: {
+ StringName lib_name = file_dialog_library;
+
+ Ref<AnimationLibrary> ald = al->duplicate();
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo->create_action(vformat(TTR("Make Animation Library Unique: %s"), lib_name));
+ undo_redo->add_do_method(player, "remove_animation_library", lib_name);
+ undo_redo->add_do_method(player, "add_animation_library", lib_name, ald);
+ undo_redo->add_undo_method(player, "remove_animation_library", lib_name);
+ undo_redo->add_undo_method(player, "add_animation_library", lib_name, al);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+
+ } break;
+ case FILE_MENU_EDIT_LIBRARY: {
+ EditorNode::get_singleton()->push_item(al.ptr());
+ } break;
+
+ case FILE_MENU_SAVE_ANIMATION: {
+ if (anim->get_path().is_resource_file()) {
+ EditorNode::get_singleton()->save_resource(anim);
+ break;
+ }
+ [[fallthrough]];
+ }
+ case FILE_MENU_SAVE_AS_ANIMATION: {
+ file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
+ file_dialog->set_title(TTR("Save Animation"));
+ if (anim->get_path().is_resource_file()) {
+ file_dialog->set_current_path(anim->get_path());
+ } else {
+ file_dialog->set_current_file(String(file_dialog_animation) + ".res");
+ }
+ file_dialog->clear_filters();
+ List<String> exts;
+ ResourceLoader::get_recognized_extensions_for_type("Animation", &exts);
+ for (const String &K : exts) {
+ file_dialog->add_filter("*." + K);
+ }
+
+ file_dialog->popup_centered_ratio();
+ file_dialog_action = FILE_DIALOG_ACTION_SAVE_ANIMATION;
+ } break;
+ case FILE_MENU_MAKE_ANIMATION_UNIQUE: {
+ StringName anim_name = file_dialog_animation;
+
+ Ref<Animation> animd = anim->duplicate();
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo->create_action(vformat(TTR("Make Animation Unique: %s"), anim_name));
+ undo_redo->add_do_method(al.ptr(), "remove_animation", anim_name);
+ undo_redo->add_do_method(al.ptr(), "add_animation", anim_name, animd);
+ undo_redo->add_undo_method(al.ptr(), "remove_animation", anim_name);
+ undo_redo->add_undo_method(al.ptr(), "add_animation", anim_name, anim);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ } break;
+ case FILE_MENU_EDIT_ANIMATION: {
+ EditorNode::get_singleton()->push_item(anim.ptr());
+ } break;
+ }
+}
+void AnimationLibraryEditor::_load_file(String p_path) {
+ switch (file_dialog_action) {
+ case FILE_DIALOG_ACTION_OPEN_LIBRARY: {
+ Ref<AnimationLibrary> al = ResourceLoader::load(p_path);
+ if (al.is_null()) {
+ error_dialog->set_text(TTR("Invalid AnimationLibrary file."));
+ error_dialog->popup_centered();
+ return;
+ }
+
+ TypedArray<StringName> libs = player->call("get_animation_library_list");
+ for (int i = 0; i < libs.size(); i++) {
+ const StringName K = libs[i];
+ Ref<AnimationLibrary> al2 = player->call("get_animation_library", K);
+ if (al2 == al) {
+ error_dialog->set_text(TTR("This library is already added to the player."));
+ error_dialog->popup_centered();
+
+ return;
+ }
+ }
+
+ String name = p_path.get_file().get_basename();
+
+ int attempt = 1;
+
+ while (bool(player->call("has_animation_library", name))) {
+ attempt++;
+ name = p_path.get_file().get_basename() + " " + itos(attempt);
+ }
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ undo_redo->create_action(vformat(TTR("Add Animation Library: %s"), name));
+ undo_redo->add_do_method(player, "add_animation_library", name, al);
+ undo_redo->add_undo_method(player, "remove_animation_library", name);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ } break;
+ case FILE_DIALOG_ACTION_OPEN_ANIMATION: {
+ Ref<Animation> anim = ResourceLoader::load(p_path);
+ if (anim.is_null()) {
+ error_dialog->set_text(TTR("Invalid Animation file."));
+ error_dialog->popup_centered();
+ return;
+ }
+
+ Ref<AnimationLibrary> al = player->call("get_animation_library", adding_animation_to_library);
+ List<StringName> anims;
+ al->get_animation_list(&anims);
+ for (const StringName &K : anims) {
+ Ref<Animation> a2 = al->get_animation(K);
+ if (a2 == anim) {
+ error_dialog->set_text(TTR("This animation is already added to the library."));
+ error_dialog->popup_centered();
+ return;
+ }
+ }
+
+ String name = p_path.get_file().get_basename();
+
+ int attempt = 1;
+
+ while (al->has_animation(name)) {
+ attempt++;
+ name = p_path.get_file().get_basename() + " " + itos(attempt);
+ }
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ undo_redo->create_action(vformat(TTR("Load Animation into Library: %s"), name));
+ undo_redo->add_do_method(al.ptr(), "add_animation", name, anim);
+ undo_redo->add_undo_method(al.ptr(), "remove_animation", name);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ } break;
+
+ case FILE_DIALOG_ACTION_SAVE_LIBRARY: {
+ Ref<AnimationLibrary> al = player->call("get_animation_library", file_dialog_library);
+ String prev_path = al->get_path();
+ EditorNode::get_singleton()->save_resource_in_path(al, p_path);
+
+ if (al->get_path() != prev_path) { // Save successful.
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ undo_redo->create_action(vformat(TTR("Save Animation library to File: %s"), file_dialog_library));
+ undo_redo->add_do_method(al.ptr(), "set_path", al->get_path());
+ undo_redo->add_undo_method(al.ptr(), "set_path", prev_path);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ }
+
+ } break;
+ case FILE_DIALOG_ACTION_SAVE_ANIMATION: {
+ Ref<AnimationLibrary> al = player->call("get_animation_library", file_dialog_library);
+ Ref<Animation> anim;
+ if (file_dialog_animation != StringName()) {
+ anim = al->get_animation(file_dialog_animation);
+ ERR_FAIL_COND(anim.is_null());
+ }
+ String prev_path = anim->get_path();
+ EditorNode::get_singleton()->save_resource_in_path(anim, p_path);
+ if (anim->get_path() != prev_path) { // Save successful.
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ undo_redo->create_action(vformat(TTR("Save Animation to File: %s"), file_dialog_animation));
+ undo_redo->add_do_method(anim.ptr(), "set_path", anim->get_path());
+ undo_redo->add_undo_method(anim.ptr(), "set_path", prev_path);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ }
+ } break;
+ }
+}
+
+void AnimationLibraryEditor::_item_renamed() {
+ TreeItem *ti = tree->get_edited();
+ String text = ti->get_text(0);
+ String old_text = ti->get_metadata(0);
+ bool restore_text = false;
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ if (String(text).contains("/") || String(text).contains(":") || String(text).contains(",") || String(text).contains("[")) {
+ restore_text = true;
+ } else {
+ if (ti->get_parent() == tree->get_root()) {
+ // Renamed library
+
+ if (player->call("has_animation_library", text)) {
+ restore_text = true;
+ } else {
+ undo_redo->create_action(vformat(TTR("Rename Animation Library: %s"), text));
+ undo_redo->add_do_method(player, "rename_animation_library", old_text, text);
+ undo_redo->add_undo_method(player, "rename_animation_library", text, old_text);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ updating = true;
+ undo_redo->commit_action();
+ updating = false;
+ ti->set_metadata(0, text);
+ if (text == "") {
+ ti->set_suffix(0, TTR("[Global]"));
+ } else {
+ ti->set_suffix(0, "");
+ }
+ }
+ } else {
+ // Renamed anim
+ StringName library = ti->get_parent()->get_metadata(0);
+ Ref<AnimationLibrary> al = player->call("get_animation_library", library);
+
+ if (al.is_valid()) {
+ if (al->has_animation(text)) {
+ restore_text = true;
+ } else {
+ undo_redo->create_action(vformat(TTR("Rename Animation: %s"), text));
+ undo_redo->add_do_method(al.ptr(), "rename_animation", old_text, text);
+ undo_redo->add_undo_method(al.ptr(), "rename_animation", text, old_text);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ updating = true;
+ undo_redo->commit_action();
+ updating = false;
+
+ ti->set_metadata(0, text);
+ }
+ } else {
+ restore_text = true;
+ }
+ }
+ }
+
+ if (restore_text) {
+ ti->set_text(0, old_text);
+ }
+}
+
+void AnimationLibraryEditor::_button_pressed(TreeItem *p_item, int p_column, int p_button) {
+ if (p_item->get_parent() == tree->get_root()) {
+ // Library
+ StringName lib_name = p_item->get_metadata(0);
+ Ref<AnimationLibrary> al = player->call("get_animation_library", lib_name);
+ switch (p_button) {
+ case LIB_BUTTON_ADD: {
+ add_library_dialog->set_title(TTR("Animation Name:"));
+ add_library_name->set_text("");
+ add_library_dialog->popup_centered();
+ add_library_name->grab_focus();
+ adding_animation = true;
+ adding_animation_to_library = p_item->get_metadata(0);
+ _add_library_validate("");
+ } break;
+ case LIB_BUTTON_LOAD: {
+ adding_animation_to_library = p_item->get_metadata(0);
+ List<String> extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Animation", &extensions);
+
+ file_dialog->clear_filters();
+ for (const String &K : extensions) {
+ file_dialog->add_filter("*." + K);
+ }
+
+ file_dialog->set_title(TTR("Load Animation"));
+ file_dialog->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ file_dialog->set_current_file("");
+ file_dialog->popup_centered_ratio();
+
+ file_dialog_action = FILE_DIALOG_ACTION_OPEN_ANIMATION;
+
+ } break;
+ case LIB_BUTTON_PASTE: {
+ Ref<Animation> anim = EditorSettings::get_singleton()->get_resource_clipboard();
+ if (!anim.is_valid()) {
+ error_dialog->set_text(TTR("No animation resource in clipboard!"));
+ error_dialog->popup_centered();
+ return;
+ }
+
+ anim = anim->duplicate(); // Users simply dont care about referencing, so making a copy works better here.
+
+ String base_name;
+ if (anim->get_name() != "") {
+ base_name = anim->get_name();
+ } else {
+ base_name = TTR("Pasted Animation");
+ }
+
+ String name = base_name;
+ int attempt = 1;
+ while (al->has_animation(name)) {
+ attempt++;
+ name = base_name + " " + itos(attempt);
+ }
+
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+
+ undo_redo->create_action(vformat(TTR("Add Animation to Library: %s"), name));
+ undo_redo->add_do_method(al.ptr(), "add_animation", name, anim);
+ undo_redo->add_undo_method(al.ptr(), "remove_animation", name);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+
+ } break;
+ case LIB_BUTTON_FILE: {
+ file_popup->clear();
+ file_popup->add_item(TTR("Save"), FILE_MENU_SAVE_LIBRARY);
+ file_popup->add_item(TTR("Save As"), FILE_MENU_SAVE_AS_LIBRARY);
+ file_popup->add_separator();
+ file_popup->add_item(TTR("Make Unique"), FILE_MENU_MAKE_LIBRARY_UNIQUE);
+ file_popup->add_separator();
+ file_popup->add_item(TTR("Open in Inspector"), FILE_MENU_EDIT_LIBRARY);
+ Rect2 pos = tree->get_item_rect(p_item, 1, 0);
+ Vector2 popup_pos = tree->get_screen_position() + pos.position + Vector2(0, pos.size.height);
+ file_popup->popup(Rect2(popup_pos, Size2()));
+
+ file_dialog_animation = StringName();
+ file_dialog_library = lib_name;
+ } break;
+ case LIB_BUTTON_DELETE: {
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo->create_action(vformat(TTR("Remove Animation Library: %s"), lib_name));
+ undo_redo->add_do_method(player, "remove_animation_library", lib_name);
+ undo_redo->add_undo_method(player, "add_animation_library", lib_name, al);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ } break;
+ }
+
+ } else {
+ // Animation
+ StringName lib_name = p_item->get_parent()->get_metadata(0);
+ StringName anim_name = p_item->get_metadata(0);
+ Ref<AnimationLibrary> al = player->call("get_animation_library", lib_name);
+ Ref<Animation> anim = al->get_animation(anim_name);
+ ERR_FAIL_COND(!anim.is_valid());
+ switch (p_button) {
+ case ANIM_BUTTON_COPY: {
+ if (anim->get_name() == "") {
+ anim->set_name(anim_name); // Keep the name around
+ }
+ EditorSettings::get_singleton()->set_resource_clipboard(anim);
+ } break;
+ case ANIM_BUTTON_FILE: {
+ file_popup->clear();
+ file_popup->add_item(TTR("Save"), FILE_MENU_SAVE_ANIMATION);
+ file_popup->add_item(TTR("Save As"), FILE_MENU_SAVE_AS_ANIMATION);
+ file_popup->add_separator();
+ file_popup->add_item(TTR("Make Unique"), FILE_MENU_MAKE_ANIMATION_UNIQUE);
+ file_popup->add_separator();
+ file_popup->add_item(TTR("Open in Inspector"), FILE_MENU_EDIT_ANIMATION);
+ Rect2 pos = tree->get_item_rect(p_item, 1, 0);
+ Vector2 popup_pos = tree->get_screen_position() + pos.position + Vector2(0, pos.size.height);
+ file_popup->popup(Rect2(popup_pos, Size2()));
+
+ file_dialog_animation = anim_name;
+ file_dialog_library = lib_name;
+
+ } break;
+ case ANIM_BUTTON_DELETE: {
+ UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
+ undo_redo->create_action(vformat(TTR("Remove Animation from Library: %s"), anim_name));
+ undo_redo->add_do_method(al.ptr(), "remove_animation", anim_name);
+ undo_redo->add_undo_method(al.ptr(), "add_animation", anim_name, anim);
+ undo_redo->add_do_method(this, "_update_editor", player);
+ undo_redo->add_undo_method(this, "_update_editor", player);
+ undo_redo->commit_action();
+ } break;
+ }
+ }
+}
+
+void AnimationLibraryEditor::update_tree() {
+ if (updating) {
+ return;
+ }
+
+ tree->clear();
+ ERR_FAIL_COND(!player);
+
+ Color ss_color = get_theme_color(SNAME("prop_subsection"), SNAME("Editor"));
+
+ TreeItem *root = tree->create_item();
+ TypedArray<StringName> libs = player->call("get_animation_library_list");
+
+ for (int i = 0; i < libs.size(); i++) {
+ const StringName K = libs[i];
+ TreeItem *libitem = tree->create_item(root);
+ libitem->set_text(0, K);
+ if (K == StringName()) {
+ libitem->set_suffix(0, TTR("[Global]"));
+ } else {
+ libitem->set_suffix(0, "");
+ }
+ libitem->set_editable(0, true);
+ libitem->set_metadata(0, K);
+ libitem->set_icon(0, get_theme_icon("AnimationLibrary", "EditorIcons"));
+ libitem->add_button(0, get_theme_icon("Add", "EditorIcons"), LIB_BUTTON_ADD, false, TTR("Add Animation to Library"));
+ libitem->add_button(0, get_theme_icon("Load", "EditorIcons"), LIB_BUTTON_LOAD, false, TTR("Load animation from file and add to library"));
+ libitem->add_button(0, get_theme_icon("ActionPaste", "EditorIcons"), LIB_BUTTON_PASTE, false, TTR("Paste Animation to Library from clipboard"));
+ Ref<AnimationLibrary> al = player->call("get_animation_library", K);
+ if (al->get_path().is_resource_file()) {
+ libitem->set_text(1, al->get_path().get_file());
+ libitem->set_tooltip(1, al->get_path());
+ } else {
+ libitem->set_text(1, TTR("[built-in]"));
+ }
+ libitem->add_button(1, get_theme_icon("Save", "EditorIcons"), LIB_BUTTON_FILE, false, TTR("Save animation library to resource on disk"));
+ libitem->add_button(1, get_theme_icon("Remove", "EditorIcons"), LIB_BUTTON_DELETE, false, TTR("Remove animation library"));
+
+ libitem->set_custom_bg_color(0, ss_color);
+
+ List<StringName> animations;
+ al->get_animation_list(&animations);
+ for (const StringName &L : animations) {
+ TreeItem *anitem = tree->create_item(libitem);
+ anitem->set_text(0, L);
+ anitem->set_editable(0, true);
+ anitem->set_metadata(0, L);
+ anitem->set_icon(0, get_theme_icon("Animation", "EditorIcons"));
+ anitem->add_button(0, get_theme_icon("ActionCopy", "EditorIcons"), ANIM_BUTTON_COPY, false, TTR("Copy animation to clipboard"));
+ Ref<Animation> anim = al->get_animation(L);
+
+ if (anim->get_path().is_resource_file()) {
+ anitem->set_text(1, anim->get_path().get_file());
+ anitem->set_tooltip(1, anim->get_path());
+ } else {
+ anitem->set_text(1, TTR("[built-in]"));
+ }
+ anitem->add_button(1, get_theme_icon("Save", "EditorIcons"), ANIM_BUTTON_FILE, false, TTR("Save animation to resource on disk"));
+ anitem->add_button(1, get_theme_icon("Remove", "EditorIcons"), ANIM_BUTTON_DELETE, false, TTR("Remove animation from Library"));
+ }
+ }
+}
+
+void AnimationLibraryEditor::show_dialog() {
+ update_tree();
+ popup_centered_ratio(0.5);
+}
+
+void AnimationLibraryEditor::_update_editor(Object *p_player) {
+ emit_signal("update_editor", p_player);
+}
+
+void AnimationLibraryEditor::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("_update_editor", "player"), &AnimationLibraryEditor::_update_editor);
+ ADD_SIGNAL(MethodInfo("update_editor"));
+}
+
+AnimationLibraryEditor::AnimationLibraryEditor() {
+ set_title(TTR("Edit Animation Libraries"));
+
+ file_dialog = memnew(EditorFileDialog);
+ add_child(file_dialog);
+ file_dialog->connect("file_selected", callable_mp(this, &AnimationLibraryEditor::_load_file));
+
+ add_library_dialog = memnew(ConfirmationDialog);
+ VBoxContainer *dialog_vb = memnew(VBoxContainer);
+ add_library_name = memnew(LineEdit);
+ dialog_vb->add_child(add_library_name);
+ add_library_name->connect("text_changed", callable_mp(this, &AnimationLibraryEditor::_add_library_validate));
+ add_child(add_library_dialog);
+
+ add_library_validate = memnew(Label);
+ dialog_vb->add_child(add_library_validate);
+ add_library_dialog->add_child(dialog_vb);
+ add_library_dialog->connect("confirmed", callable_mp(this, &AnimationLibraryEditor::_add_library_confirm));
+ add_library_dialog->register_text_enter(add_library_name);
+
+ VBoxContainer *vb = memnew(VBoxContainer);
+ HBoxContainer *hb = memnew(HBoxContainer);
+ hb->add_spacer(true);
+ Button *b = memnew(Button(TTR("Add Library")));
+ b->connect("pressed", callable_mp(this, &AnimationLibraryEditor::_add_library));
+ hb->add_child(b);
+ b = memnew(Button(TTR("Load Library")));
+ b->connect("pressed", callable_mp(this, &AnimationLibraryEditor::_load_library));
+ hb->add_child(b);
+ vb->add_child(hb);
+ tree = memnew(Tree);
+ vb->add_child(tree);
+
+ tree->set_columns(2);
+ tree->set_column_titles_visible(true);
+ tree->set_column_title(0, TTR("Resource"));
+ tree->set_column_title(1, TTR("Storage"));
+ tree->set_column_expand(0, true);
+ tree->set_column_custom_minimum_width(1, EDSCALE * 250);
+ tree->set_column_expand(1, false);
+ tree->set_hide_root(true);
+ tree->set_hide_folding(true);
+ tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+
+ tree->connect("item_edited", callable_mp(this, &AnimationLibraryEditor::_item_renamed));
+ tree->connect("button_pressed", callable_mp(this, &AnimationLibraryEditor::_button_pressed));
+
+ file_popup = memnew(PopupMenu);
+ add_child(file_popup);
+ file_popup->connect("id_pressed", callable_mp(this, &AnimationLibraryEditor::_file_popup_selected));
+
+ add_child(vb);
+
+ error_dialog = memnew(AcceptDialog);
+ error_dialog->set_title(TTR("Error:"));
+ add_child(error_dialog);
+}
diff --git a/drivers/gles3/storage/canvas_texture_storage.h b/editor/plugins/animation_library_editor.h
index 5930e927fe..5bd4e8d9e2 100644
--- a/drivers/gles3/storage/canvas_texture_storage.h
+++ b/editor/plugins/animation_library_editor.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* canvas_texture_storage.h */
+/* animation_library_editor.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,60 +28,92 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CANVAS_TEXTURE_STORAGE_GLES3_H
-#define CANVAS_TEXTURE_STORAGE_GLES3_H
-
-#ifdef GLES3_ENABLED
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-
-namespace GLES3 {
-
-struct CanvasTexture {
- RID diffuse;
- RID normal_map;
- RID specular;
- Color specular_color = Color(1, 1, 1, 1);
- float shininess = 1.0;
-
- RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
- RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
-
- Size2i size_cache = Size2i(1, 1);
- bool use_normal_cache = false;
- bool use_specular_cache = false;
- bool cleared_cache = true;
-};
-
-class CanvasTextureStorage : public RendererCanvasTextureStorage {
-private:
- static CanvasTextureStorage *singleton;
-
- RID_Owner<CanvasTexture, true> canvas_texture_owner;
+#ifndef ANIMATION_LIBRARY_EDITOR_H
+#define ANIMATION_LIBRARY_EDITOR_H
+
+#include "editor/animation_track_editor.h"
+#include "editor/editor_plugin.h"
+#include "scene/animation/animation_player.h"
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tree.h"
+
+class EditorFileDialog;
+
+class AnimationLibraryEditor : public AcceptDialog {
+ GDCLASS(AnimationLibraryEditor, AcceptDialog)
+
+ enum {
+ LIB_BUTTON_ADD,
+ LIB_BUTTON_LOAD,
+ LIB_BUTTON_PASTE,
+ LIB_BUTTON_FILE,
+ LIB_BUTTON_DELETE,
+ };
+ enum {
+ ANIM_BUTTON_COPY,
+ ANIM_BUTTON_FILE,
+ ANIM_BUTTON_DELETE,
+ };
+
+ enum FileMenuAction {
+ FILE_MENU_SAVE_LIBRARY,
+ FILE_MENU_SAVE_AS_LIBRARY,
+ FILE_MENU_MAKE_LIBRARY_UNIQUE,
+ FILE_MENU_EDIT_LIBRARY,
+
+ FILE_MENU_SAVE_ANIMATION,
+ FILE_MENU_SAVE_AS_ANIMATION,
+ FILE_MENU_MAKE_ANIMATION_UNIQUE,
+ FILE_MENU_EDIT_ANIMATION,
+ };
+
+ enum FileDialogAction {
+ FILE_DIALOG_ACTION_OPEN_LIBRARY,
+ FILE_DIALOG_ACTION_SAVE_LIBRARY,
+ FILE_DIALOG_ACTION_OPEN_ANIMATION,
+ FILE_DIALOG_ACTION_SAVE_ANIMATION,
+ };
+
+ FileDialogAction file_dialog_action = FILE_DIALOG_ACTION_OPEN_ANIMATION;
+
+ StringName file_dialog_animation;
+ StringName file_dialog_library;
+
+ AcceptDialog *error_dialog = nullptr;
+ bool adding_animation = false;
+ StringName adding_animation_to_library;
+ EditorFileDialog *file_dialog = nullptr;
+ ConfirmationDialog *add_library_dialog = nullptr;
+ LineEdit *add_library_name = nullptr;
+ Label *add_library_validate = nullptr;
+ PopupMenu *file_popup = nullptr;
+
+ Tree *tree = nullptr;
+
+ Object *player = nullptr;
+
+ void _add_library();
+ void _add_library_validate(const String &p_name);
+ void _add_library_confirm();
+ void _load_library();
+ void _load_file(String p_path);
+
+ void _item_renamed();
+ void _button_pressed(TreeItem *p_item, int p_column, int p_button);
+
+ void _file_popup_selected(int p_id);
+
+ bool updating = false;
+
+protected:
+ void _update_editor(Object *p_player);
+ static void _bind_methods();
public:
- static CanvasTextureStorage *get_singleton();
-
- CanvasTextureStorage();
- virtual ~CanvasTextureStorage();
-
- CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
- bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
-
- virtual RID canvas_texture_allocate() override;
- virtual void canvas_texture_initialize(RID p_rid) override;
- virtual void canvas_texture_free(RID p_rid) override;
-
- virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
- virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
-
- virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
- virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
+ void set_animation_player(Object *p_player);
+ void show_dialog();
+ void update_tree();
+ AnimationLibraryEditor();
};
-} // namespace GLES3
-
-#endif // !GLES3_ENABLED
-
-#endif // !CANVAS_TEXTURE_STORAGE_GLES3_H
+#endif // ANIMATIONPLAYERLIBRARYEDITOR_H
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index af7c092d03..17a1bd1048 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -47,6 +47,8 @@
#include "scene/scene_string_names.h"
#include "servers/rendering_server.h"
+///////////////////////////////////
+
void AnimationPlayerEditor::_node_removed(Node *p_node) {
if (player && player == p_node) {
player = nullptr;
@@ -148,9 +150,7 @@ void AnimationPlayerEditor::_notification(int p_what) {
#define ITEM_ICON(m_item, m_icon) tool_anim->get_popup()->set_item_icon(tool_anim->get_popup()->get_item_index(m_item), get_theme_icon(SNAME(m_icon), SNAME("EditorIcons")))
ITEM_ICON(TOOL_NEW_ANIM, "New");
- ITEM_ICON(TOOL_LOAD_ANIM, "Load");
- ITEM_ICON(TOOL_SAVE_ANIM, "Save");
- ITEM_ICON(TOOL_SAVE_AS_ANIM, "Save");
+ ITEM_ICON(TOOL_ANIM_LIBRARY, "AnimationLibrary");
ITEM_ICON(TOOL_DUPLICATE_ANIM, "Duplicate");
ITEM_ICON(TOOL_RENAME_ANIM, "Rename");
ITEM_ICON(TOOL_EDIT_TRANSITIONS, "Blend");
@@ -166,7 +166,7 @@ void AnimationPlayerEditor::_autoplay_pressed() {
if (updating) {
return;
}
- if (animation->get_item_count() == 0) {
+ if (animation->has_selectable_items() == 0) {
return;
}
@@ -192,10 +192,7 @@ void AnimationPlayerEditor::_autoplay_pressed() {
}
void AnimationPlayerEditor::_play_pressed() {
- String current;
- if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
- current = animation->get_item_text(animation->get_selected());
- }
+ String current = _get_current();
if (!current.is_empty()) {
if (current == player->get_assigned_animation()) {
@@ -209,10 +206,7 @@ void AnimationPlayerEditor::_play_pressed() {
}
void AnimationPlayerEditor::_play_from_pressed() {
- String current;
- if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
- current = animation->get_item_text(animation->get_selected());
- }
+ String current = _get_current();
if (!current.is_empty()) {
float time = player->get_current_animation_position();
@@ -229,12 +223,15 @@ void AnimationPlayerEditor::_play_from_pressed() {
stop->set_pressed(false);
}
-void AnimationPlayerEditor::_play_bw_pressed() {
+String AnimationPlayerEditor::_get_current() const {
String current;
- if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
+ if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count() && !animation->is_item_separator(animation->get_selected())) {
current = animation->get_item_text(animation->get_selected());
}
-
+ return current;
+}
+void AnimationPlayerEditor::_play_bw_pressed() {
+ String current = _get_current();
if (!current.is_empty()) {
if (current == player->get_assigned_animation()) {
player->stop(); //so it won't blend with itself
@@ -247,10 +244,7 @@ void AnimationPlayerEditor::_play_bw_pressed() {
}
void AnimationPlayerEditor::_play_bw_from_pressed() {
- String current;
- if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
- current = animation->get_item_text(animation->get_selected());
- }
+ String current = _get_current();
if (!current.is_empty()) {
float time = player->get_current_animation_position();
@@ -282,10 +276,7 @@ void AnimationPlayerEditor::_animation_selected(int p_which) {
}
// when selecting an animation, the idea is that the only interesting behavior
// ui-wise is that it should play/blend the next one if currently playing
- String current;
- if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
- current = animation->get_item_text(animation->get_selected());
- }
+ String current = _get_current();
if (!current.is_empty()) {
player->set_assigned_animation(current);
@@ -330,6 +321,20 @@ void AnimationPlayerEditor::_animation_new() {
break;
}
+ List<StringName> libraries;
+ player->get_animation_library_list(&libraries);
+ library->clear();
+ for (const StringName &K : libraries) {
+ library->add_item((K == StringName()) ? String(TTR("[Global]")) : String(K));
+ library->set_item_metadata(0, String(K));
+ }
+
+ if (libraries.size() > 1) {
+ library->show();
+ } else {
+ library->hide();
+ }
+
name->set_text(base);
name_dialog->popup_centered(Size2(300, 90));
name->select_all();
@@ -337,7 +342,7 @@ void AnimationPlayerEditor::_animation_new() {
}
void AnimationPlayerEditor::_animation_rename() {
- if (animation->get_item_count() == 0) {
+ if (!animation->has_selectable_items()) {
return;
}
int selected = animation->get_selected();
@@ -349,84 +354,11 @@ void AnimationPlayerEditor::_animation_rename() {
name_dialog->popup_centered(Size2(300, 90));
name->select_all();
name->grab_focus();
-}
-
-void AnimationPlayerEditor::_animation_load() {
- ERR_FAIL_COND(!player);
- file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES);
- file->clear_filters();
- List<String> extensions;
-
- ResourceLoader::get_recognized_extensions_for_type("Animation", &extensions);
- for (const String &E : extensions) {
- file->add_filter("*." + E + " ; " + E.to_upper());
- }
-
- file->popup_file_dialog();
-}
-
-void AnimationPlayerEditor::_animation_save_in_path(const Ref<Resource> &p_resource, const String &p_path) {
- int flg = 0;
- if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) {
- flg |= ResourceSaver::FLAG_COMPRESS;
- }
-
- String path = ProjectSettings::get_singleton()->localize_path(p_path);
- Error err = ResourceSaver::save(path, p_resource, flg | ResourceSaver::FLAG_REPLACE_SUBRESOURCE_PATHS);
-
- if (err != OK) {
- EditorNode::get_singleton()->show_warning(TTR("Error saving resource!"));
- return;
- }
-
- ((Resource *)p_resource.ptr())->set_path(path);
- EditorNode::get_singleton()->emit_signal(SNAME("resource_saved"), p_resource);
-}
-
-void AnimationPlayerEditor::_animation_save(const Ref<Resource> &p_resource) {
- if (p_resource->get_path().is_resource_file()) {
- _animation_save_in_path(p_resource, p_resource->get_path());
- } else {
- _animation_save_as(p_resource);
- }
-}
-
-void AnimationPlayerEditor::_animation_save_as(const Ref<Resource> &p_resource) {
- file->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE);
-
- List<String> extensions;
- ResourceSaver::get_recognized_extensions(p_resource, &extensions);
- file->clear_filters();
- for (int i = 0; i < extensions.size(); i++) {
- file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper());
- }
-
- String path;
- //file->set_current_path(current_path);
- if (!p_resource->get_path().is_empty()) {
- path = p_resource->get_path();
- if (extensions.size()) {
- if (extensions.find(p_resource->get_path().get_extension().to_lower()) == nullptr) {
- path = p_resource->get_path().get_base_dir() + p_resource->get_name() + "." + extensions.front()->get();
- }
- }
- } else {
- if (extensions.size()) {
- if (!p_resource->get_name().is_empty()) {
- path = p_resource->get_name() + "." + extensions.front()->get().to_lower();
- } else {
- String resource_name_snake_case = p_resource->get_class().camelcase_to_underscore();
- path = "new_" + resource_name_snake_case + "." + extensions.front()->get().to_lower();
- }
- }
- }
- file->set_current_path(path);
- file->set_title(TTR("Save Resource As..."));
- file->popup_file_dialog();
+ library->hide();
}
void AnimationPlayerEditor::_animation_remove() {
- if (animation->get_item_count() == 0) {
+ if (!animation->has_selectable_items()) {
return;
}
@@ -440,6 +372,9 @@ void AnimationPlayerEditor::_animation_remove_confirmed() {
String current = animation->get_item_text(animation->get_selected());
Ref<Animation> anim = player->get_animation(current);
+ Ref<AnimationLibrary> al = player->get_animation_library(player->find_animation_library(anim));
+ ERR_FAIL_COND(al.is_null());
+
undo_redo->create_action(TTR("Remove Animation"));
if (player->get_autoplay() == current) {
undo_redo->add_do_method(player, "set_autoplay", "");
@@ -447,11 +382,11 @@ void AnimationPlayerEditor::_animation_remove_confirmed() {
// Avoid having the autoplay icon linger around if there is only one animation in the player.
undo_redo->add_do_method(this, "_animation_player_changed", player);
}
- undo_redo->add_do_method(player, "remove_animation", current);
- undo_redo->add_undo_method(player, "add_animation", current, anim);
+ undo_redo->add_do_method(al.ptr(), "remove_animation", current);
+ undo_redo->add_undo_method(al.ptr(), "add_animation", current, anim);
undo_redo->add_do_method(this, "_animation_player_changed", player);
undo_redo->add_undo_method(this, "_animation_player_changed", player);
- if (animation->get_item_count() == 1) {
+ if (animation->has_selectable_items() && animation->get_selectable_item(false) == animation->get_selectable_item(true)) { // Last item remaining.
undo_redo->add_do_method(this, "_stop_onion_skinning");
undo_redo->add_undo_method(this, "_start_onion_skinning");
}
@@ -498,7 +433,7 @@ void AnimationPlayerEditor::_animation_name_edited() {
return;
}
- if (name_dialog_op == TOOL_RENAME_ANIM && animation->get_item_count() > 0 && animation->get_item_text(animation->get_selected()) == new_name) {
+ if (name_dialog_op == TOOL_RENAME_ANIM && animation->has_selectable_items() && animation->get_item_text(animation->get_selected()) == new_name) {
name_dialog->hide();
return;
}
@@ -514,10 +449,13 @@ void AnimationPlayerEditor::_animation_name_edited() {
String current = animation->get_item_text(animation->get_selected());
Ref<Animation> anim = player->get_animation(current);
+ Ref<AnimationLibrary> al = player->get_animation_library(player->find_animation_library(anim));
+ ERR_FAIL_COND(al.is_null());
+
undo_redo->create_action(TTR("Rename Animation"));
- undo_redo->add_do_method(player, "rename_animation", current, new_name);
+ undo_redo->add_do_method(al.ptr(), "rename_animation", current, new_name);
undo_redo->add_do_method(anim.ptr(), "set_name", new_name);
- undo_redo->add_undo_method(player, "rename_animation", new_name, current);
+ undo_redo->add_undo_method(al.ptr(), "rename_animation", new_name, current);
undo_redo->add_undo_method(anim.ptr(), "set_name", current);
undo_redo->add_do_method(this, "_animation_player_changed", player);
undo_redo->add_undo_method(this, "_animation_player_changed", player);
@@ -530,15 +468,35 @@ void AnimationPlayerEditor::_animation_name_edited() {
Ref<Animation> new_anim = Ref<Animation>(memnew(Animation));
new_anim->set_name(new_name);
+ Ref<AnimationLibrary> al;
+ if (library->is_visible()) {
+ al = player->get_animation_library(library->get_item_metadata(library->get_selected()));
+ } else {
+ if (player->has_animation_library("")) {
+ al = player->get_animation_library("");
+ }
+ }
+
undo_redo->create_action(TTR("Add Animation"));
- undo_redo->add_do_method(player, "add_animation", new_name, new_anim);
- undo_redo->add_undo_method(player, "remove_animation", new_name);
+
+ bool lib_added = false;
+ if (al.is_null()) {
+ al.instantiate();
+ lib_added = true;
+ undo_redo->add_do_method(player, "add_animation_library", "", al);
+ }
+
+ undo_redo->add_do_method(al.ptr(), "add_animation", new_name, new_anim);
+ undo_redo->add_undo_method(al.ptr(), "remove_animation", new_name);
undo_redo->add_do_method(this, "_animation_player_changed", player);
undo_redo->add_undo_method(this, "_animation_player_changed", player);
- if (animation->get_item_count() == 0) {
+ if (!animation->has_selectable_items()) {
undo_redo->add_do_method(this, "_start_onion_skinning");
undo_redo->add_undo_method(this, "_stop_onion_skinning");
}
+ if (lib_added) {
+ undo_redo->add_undo_method(player, "remove_animation_library", "");
+ }
undo_redo->commit_action();
_select_anim_by_name(new_name);
@@ -551,9 +509,11 @@ void AnimationPlayerEditor::_animation_name_edited() {
Ref<Animation> new_anim = _animation_clone(anim);
new_anim->set_name(new_name);
+ Ref<AnimationLibrary> library = player->get_animation_library(player->find_animation_library(anim));
+
undo_redo->create_action(TTR("Duplicate Animation"));
- undo_redo->add_do_method(player, "add_animation", new_name, new_anim);
- undo_redo->add_undo_method(player, "remove_animation", new_name);
+ undo_redo->add_do_method(library.ptr(), "add_animation", new_name, new_anim);
+ undo_redo->add_undo_method(library.ptr(), "remove_animation", new_name);
undo_redo->add_do_method(player, "animation_set_next", new_name, player->animation_get_next(current));
undo_redo->add_do_method(this, "_animation_player_changed", player);
undo_redo->add_undo_method(this, "_animation_player_changed", player);
@@ -567,7 +527,7 @@ void AnimationPlayerEditor::_animation_name_edited() {
}
void AnimationPlayerEditor::_blend_editor_next_changed(const int p_idx) {
- if (animation->get_item_count() == 0) {
+ if (!animation->has_selectable_items()) {
return;
}
@@ -588,7 +548,7 @@ void AnimationPlayerEditor::_animation_blend() {
blend_editor.tree->clear();
- if (animation->get_item_count() == 0) {
+ if (!animation->has_selectable_items()) {
return;
}
@@ -643,7 +603,7 @@ void AnimationPlayerEditor::_blend_edited() {
return;
}
- if (animation->get_item_count() == 0) {
+ if (!animation->has_selectable_items()) {
return;
}
@@ -722,16 +682,16 @@ void AnimationPlayerEditor::set_state(const Dictionary &p_state) {
}
void AnimationPlayerEditor::_animation_resource_edit() {
- if (animation->get_item_count()) {
- String current = animation->get_item_text(animation->get_selected());
+ String current = _get_current();
+ if (current != String()) {
Ref<Animation> anim = player->get_animation(current);
EditorNode::get_singleton()->edit_resource(anim);
}
}
void AnimationPlayerEditor::_animation_edit() {
- if (animation->get_item_count()) {
- String current = animation->get_item_text(animation->get_selected());
+ String current = _get_current();
+ if (current != String()) {
Ref<Animation> anim = player->get_animation(current);
track_editor->set_animation(anim);
@@ -745,51 +705,6 @@ void AnimationPlayerEditor::_animation_edit() {
}
}
-void AnimationPlayerEditor::_save_animation(String p_file) {
- String current = animation->get_item_text(animation->get_selected());
- if (!current.is_empty()) {
- Ref<Animation> anim = player->get_animation(current);
-
- ERR_FAIL_COND(!Object::cast_to<Resource>(*anim));
-
- RES current_res = RES(Object::cast_to<Resource>(*anim));
-
- _animation_save_in_path(current_res, p_file);
- }
-}
-
-void AnimationPlayerEditor::_load_animations(Vector<String> p_files) {
- ERR_FAIL_COND(!player);
-
- for (int i = 0; i < p_files.size(); i++) {
- String file = p_files[i];
-
- Ref<Resource> res = ResourceLoader::load(file, "Animation");
- ERR_FAIL_COND_MSG(res.is_null(), "Cannot load Animation from file '" + file + "'.");
- ERR_FAIL_COND_MSG(!res->is_class("Animation"), "Loaded resource from file '" + file + "' is not Animation.");
- if (file.rfind("/") != -1) {
- file = file.substr(file.rfind("/") + 1, file.length());
- }
- if (file.rfind("\\") != -1) {
- file = file.substr(file.rfind("\\") + 1, file.length());
- }
-
- if (file.contains(".")) {
- file = file.substr(0, file.find("."));
- }
-
- undo_redo->create_action(TTR("Load Animation"));
- undo_redo->add_do_method(player, "add_animation", file, res);
- undo_redo->add_undo_method(player, "remove_animation", file);
- if (player->has_animation(file)) {
- undo_redo->add_undo_method(player, "add_animation", file, player->get_animation(file));
- }
- undo_redo->add_do_method(this, "_animation_player_changed", player);
- undo_redo->add_undo_method(this, "_animation_player_changed", player);
- undo_redo->commit_action();
- }
-}
-
void AnimationPlayerEditor::_scale_changed(const String &p_scale) {
player->set_speed_scale(p_scale.to_float());
}
@@ -824,49 +739,67 @@ void AnimationPlayerEditor::_update_animation() {
void AnimationPlayerEditor::_update_player() {
updating = true;
- List<StringName> animlist;
- if (player) {
- player->get_animation_list(&animlist);
- }
animation->clear();
-#define ITEM_DISABLED(m_item, m_disabled) tool_anim->get_popup()->set_item_disabled(tool_anim->get_popup()->get_item_index(m_item), m_disabled)
-
- ITEM_DISABLED(TOOL_SAVE_ANIM, animlist.size() == 0);
- ITEM_DISABLED(TOOL_SAVE_AS_ANIM, animlist.size() == 0);
- ITEM_DISABLED(TOOL_DUPLICATE_ANIM, animlist.size() == 0);
- ITEM_DISABLED(TOOL_RENAME_ANIM, animlist.size() == 0);
- ITEM_DISABLED(TOOL_EDIT_TRANSITIONS, animlist.size() == 0);
- ITEM_DISABLED(TOOL_COPY_ANIM, animlist.size() == 0);
- ITEM_DISABLED(TOOL_REMOVE_ANIM, animlist.size() == 0);
-
- stop->set_disabled(animlist.size() == 0);
- play->set_disabled(animlist.size() == 0);
- play_bw->set_disabled(animlist.size() == 0);
- play_bw_from->set_disabled(animlist.size() == 0);
- play_from->set_disabled(animlist.size() == 0);
- frame->set_editable(animlist.size() != 0);
- animation->set_disabled(animlist.size() == 0);
- autoplay->set_disabled(animlist.size() == 0);
- tool_anim->set_disabled(player == nullptr);
- onion_toggle->set_disabled(animlist.size() == 0);
- onion_skinning->set_disabled(animlist.size() == 0);
- pin->set_disabled(player == nullptr);
-
if (!player) {
AnimationPlayerEditor::get_singleton()->get_track_editor()->update_keying();
return;
}
+ List<StringName> libraries;
+ if (player) {
+ player->get_animation_library_list(&libraries);
+ }
+
int active_idx = -1;
- for (const StringName &E : animlist) {
- animation->add_item(E);
+ bool no_anims_found = true;
- if (player->get_assigned_animation() == E) {
- active_idx = animation->get_item_count() - 1;
+ for (const StringName &K : libraries) {
+ if (K != StringName()) {
+ animation->add_separator(K);
+ }
+
+ Ref<AnimationLibrary> library = player->get_animation_library(K);
+ List<StringName> animlist;
+ library->get_animation_list(&animlist);
+
+ for (const StringName &E : animlist) {
+ String path = K;
+ if (path != "") {
+ path += "/";
+ }
+ path += E;
+ animation->add_item(path);
+ if (player->get_assigned_animation() == path) {
+ active_idx = animation->get_selectable_item(true);
+ }
+ no_anims_found = false;
}
}
+#define ITEM_CHECK_DISABLED(m_item) tool_anim->get_popup()->set_item_disabled(tool_anim->get_popup()->get_item_index(m_item), no_anims_found)
+
+ ITEM_CHECK_DISABLED(TOOL_DUPLICATE_ANIM);
+ ITEM_CHECK_DISABLED(TOOL_RENAME_ANIM);
+ ITEM_CHECK_DISABLED(TOOL_EDIT_TRANSITIONS);
+ ITEM_CHECK_DISABLED(TOOL_REMOVE_ANIM);
+ ITEM_CHECK_DISABLED(TOOL_EDIT_RESOURCE);
+
+#undef ITEM_CHECK_DISABLED
+
+ stop->set_disabled(no_anims_found);
+ play->set_disabled(no_anims_found);
+ play_bw->set_disabled(no_anims_found);
+ play_bw_from->set_disabled(no_anims_found);
+ play_from->set_disabled(no_anims_found);
+ frame->set_editable(!no_anims_found);
+ animation->set_disabled(no_anims_found);
+ autoplay->set_disabled(no_anims_found);
+ tool_anim->set_disabled(player == nullptr);
+ onion_toggle->set_disabled(no_anims_found);
+ onion_skinning->set_disabled(no_anims_found);
+ pin->set_disabled(player == nullptr);
+
_update_animation_list_icons();
updating = false;
@@ -874,16 +807,16 @@ void AnimationPlayerEditor::_update_player() {
animation->select(active_idx);
autoplay->set_pressed(animation->get_item_text(active_idx) == player->get_autoplay());
_animation_selected(active_idx);
-
- } else if (animation->get_item_count() > 0) {
- animation->select(0);
- autoplay->set_pressed(animation->get_item_text(0) == player->get_autoplay());
- _animation_selected(0);
+ } else if (animation->has_selectable_items()) {
+ int item = animation->get_selectable_item();
+ animation->select(item);
+ autoplay->set_pressed(animation->get_item_text(item) == player->get_autoplay());
+ _animation_selected(item);
} else {
_animation_selected(0);
}
- if (animation->get_item_count()) {
+ if (!no_anims_found) {
String current = animation->get_item_text(animation->get_selected());
Ref<Animation> anim = player->get_animation(current);
track_editor->set_animation(anim);
@@ -899,6 +832,9 @@ void AnimationPlayerEditor::_update_player() {
void AnimationPlayerEditor::_update_animation_list_icons() {
for (int i = 0; i < animation->get_item_count(); i++) {
String name = animation->get_item_text(i);
+ if (animation->is_item_disabled(i) || animation->is_item_separator(i)) {
+ continue;
+ }
Ref<Texture2D> icon;
if (name == player->get_autoplay()) {
@@ -925,7 +861,7 @@ void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
_update_player();
if (onion.enabled) {
- if (animation->get_item_count() > 0) {
+ if (animation->has_selectable_items()) {
_start_onion_skinning();
} else {
_stop_onion_skinning();
@@ -940,6 +876,8 @@ void AnimationPlayerEditor::edit(AnimationPlayer *p_player) {
track_editor->show_select_node_warning(true);
}
+
+ library_editor->set_animation_player(player);
}
void AnimationPlayerEditor::forward_force_draw_over_viewport(Control *p_overlay) {
@@ -993,7 +931,7 @@ void AnimationPlayerEditor::forward_force_draw_over_viewport(Control *p_overlay)
}
void AnimationPlayerEditor::_animation_duplicate() {
- if (!animation->get_item_count()) {
+ if (!animation->has_selectable_items()) {
return;
}
@@ -1031,29 +969,6 @@ Ref<Animation> AnimationPlayerEditor::_animation_clone(Ref<Animation> p_anim) {
return new_anim;
}
-void AnimationPlayerEditor::_animation_paste(Ref<Animation> p_anim) {
- String name = p_anim->get_name();
- if (name.is_empty()) {
- name = TTR("Pasted Animation");
- }
-
- int idx = 1;
- String base = name;
- while (player->has_animation(name)) {
- idx++;
- name = base + " " + itos(idx);
- }
-
- undo_redo->create_action(TTR("Paste Animation"));
- undo_redo->add_do_method(player, "add_animation", name, p_anim);
- undo_redo->add_undo_method(player, "remove_animation", name);
- undo_redo->add_do_method(this, "_animation_player_changed", player);
- undo_redo->add_undo_method(this, "_animation_player_changed", player);
- undo_redo->commit_action();
-
- _select_anim_by_name(name);
-}
-
void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set, bool p_timeline_only) {
if (updating || !player || player->is_playing()) {
return;
@@ -1095,6 +1010,9 @@ void AnimationPlayerEditor::_animation_player_changed(Object *p_pl) {
if (blend_editor.dialog->is_visible()) {
_animation_blend(); // Update.
}
+ if (library_editor->is_visible()) {
+ library_editor->update_tree();
+ }
}
}
@@ -1134,10 +1052,7 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos, bool p_drag,
}
void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
- String current;
- if (animation->get_selected() >= 0 && animation->get_selected() < animation->get_item_count()) {
- current = animation->get_item_text(animation->get_selected());
- }
+ String current = _get_current();
Ref<Animation> anim;
if (!current.is_empty()) {
@@ -1148,18 +1063,9 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
case TOOL_NEW_ANIM: {
_animation_new();
} break;
- case TOOL_LOAD_ANIM: {
- _animation_load();
- } break;
- case TOOL_SAVE_ANIM: {
- if (anim.is_valid()) {
- _animation_save(anim);
- }
- } break;
- case TOOL_SAVE_AS_ANIM: {
- if (anim.is_valid()) {
- _animation_save_as(anim);
- }
+ case TOOL_ANIM_LIBRARY: {
+ library_editor->set_animation_player(player);
+ library_editor->show_dialog();
} break;
case TOOL_DUPLICATE_ANIM: {
_animation_duplicate();
@@ -1173,47 +1079,10 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) {
case TOOL_REMOVE_ANIM: {
_animation_remove();
} break;
- case TOOL_COPY_ANIM: {
- if (!animation->get_item_count()) {
- error_dialog->set_text(TTR("No animation to copy!"));
- error_dialog->popup_centered();
- return;
- }
-
- String current2 = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim2 = player->get_animation(current2);
- EditorSettings::get_singleton()->set_resource_clipboard(anim2);
- } break;
- case TOOL_PASTE_ANIM: {
- Ref<Animation> anim2 = EditorSettings::get_singleton()->get_resource_clipboard();
- if (!anim2.is_valid()) {
- error_dialog->set_text(TTR("No animation resource in clipboard!"));
- error_dialog->popup_centered();
- return;
- }
- Ref<Animation> new_anim = _animation_clone(anim2);
- _animation_paste(new_anim);
- } break;
- case TOOL_PASTE_ANIM_REF: {
- Ref<Animation> anim2 = EditorSettings::get_singleton()->get_resource_clipboard();
- if (!anim2.is_valid()) {
- error_dialog->set_text(TTR("No animation resource in clipboard!"));
- error_dialog->popup_centered();
- return;
- }
-
- _animation_paste(anim2);
- } break;
case TOOL_EDIT_RESOURCE: {
- if (!animation->get_item_count()) {
- error_dialog->set_text(TTR("No animation to edit!"));
- error_dialog->popup_centered();
- return;
+ if (anim.is_valid()) {
+ EditorNode::get_singleton()->edit_resource(anim);
}
-
- String current2 = animation->get_item_text(animation->get_selected());
- Ref<Animation> anim2 = player->get_animation(current2);
- EditorNode::get_singleton()->edit_resource(anim2);
} break;
}
}
@@ -1300,7 +1169,7 @@ void AnimationPlayerEditor::shortcut_input(const Ref<InputEvent> &p_ev) {
}
void AnimationPlayerEditor::_editor_visibility_changed() {
- if (is_visible() && animation->get_item_count() > 0) {
+ if (is_visible() && animation->has_selectable_items()) {
_start_onion_skinning();
}
}
@@ -1536,7 +1405,6 @@ void AnimationPlayerEditor::_pin_pressed() {
void AnimationPlayerEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_animation_new"), &AnimationPlayerEditor::_animation_new);
ClassDB::bind_method(D_METHOD("_animation_rename"), &AnimationPlayerEditor::_animation_rename);
- ClassDB::bind_method(D_METHOD("_animation_load"), &AnimationPlayerEditor::_animation_load);
ClassDB::bind_method(D_METHOD("_animation_remove"), &AnimationPlayerEditor::_animation_remove);
ClassDB::bind_method(D_METHOD("_animation_blend"), &AnimationPlayerEditor::_animation_blend);
ClassDB::bind_method(D_METHOD("_animation_edit"), &AnimationPlayerEditor::_animation_edit);
@@ -1623,13 +1491,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
tool_anim->set_text(TTR("Animation"));
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/new_animation", TTR("New")), TOOL_NEW_ANIM);
tool_anim->get_popup()->add_separator();
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/open_animation", TTR("Load")), TOOL_LOAD_ANIM);
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_animation", TTR("Save")), TOOL_SAVE_ANIM);
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/save_as_animation", TTR("Save As...")), TOOL_SAVE_AS_ANIM);
- tool_anim->get_popup()->add_separator();
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/copy_animation", TTR("Copy")), TOOL_COPY_ANIM);
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/paste_animation", TTR("Paste")), TOOL_PASTE_ANIM);
- tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/paste_animation_as_reference", TTR("Paste As Reference")), TOOL_PASTE_ANIM_REF);
+ tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/animation_libraries", TTR("Manage Animations...")), TOOL_ANIM_LIBRARY);
tool_anim->get_popup()->add_separator();
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/duplicate_animation", TTR("Duplicate...")), TOOL_DUPLICATE_ANIM);
tool_anim->get_popup()->add_separator();
@@ -1638,6 +1500,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/open_animation_in_inspector", TTR("Open in Inspector")), TOOL_EDIT_RESOURCE);
tool_anim->get_popup()->add_separator();
tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/remove_animation", TTR("Remove")), TOOL_REMOVE_ANIM);
+ tool_anim->set_disabled(true);
hb->add_child(tool_anim);
animation = memnew(OptionButton);
@@ -1705,8 +1568,14 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
name_title = memnew(Label(TTR("Animation Name:")));
vb->add_child(name_title);
+ HBoxContainer *name_hb = memnew(HBoxContainer);
name = memnew(LineEdit);
- vb->add_child(name);
+ name_hb->add_child(name);
+ name->set_h_size_flags(SIZE_EXPAND_FILL);
+ library = memnew(OptionButton);
+ name_hb->add_child(library);
+ library->hide();
+ vb->add_child(name_hb);
name_dialog->register_text_enter(name);
error_dialog = memnew(ConfirmationDialog);
@@ -1742,8 +1611,6 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
animation->connect("item_selected", callable_mp(this, &AnimationPlayerEditor::_animation_selected));
- file->connect("file_selected", callable_mp(this, &AnimationPlayerEditor::_save_animation));
- file->connect("files_selected", callable_mp(this, &AnimationPlayerEditor::_load_animations));
frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed), make_binds(true, false));
scale->connect("text_submitted", callable_mp(this, &AnimationPlayerEditor::_scale_changed));
@@ -1759,6 +1626,10 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
_update_player();
+ library_editor = memnew(AnimationLibraryEditor);
+ add_child(library_editor);
+ library_editor->connect("update_editor", callable_mp(this, &AnimationPlayerEditor::_animation_player_changed));
+
// Onion skinning.
track_editor->connect("visibility_changed", callable_mp(this, &AnimationPlayerEditor::_editor_visibility_changed));
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 4f6a9c534f..0cc04460ca 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -33,6 +33,7 @@
#include "editor/animation_track_editor.h"
#include "editor/editor_plugin.h"
+#include "editor/plugins/animation_library_editor.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/slider.h"
@@ -40,7 +41,6 @@
#include "scene/gui/texture_button.h"
#include "scene/gui/tree.h"
-class EditorFileDialog;
class AnimationPlayerEditorPlugin;
class AnimationPlayerEditor : public VBoxContainer {
@@ -51,16 +51,11 @@ class AnimationPlayerEditor : public VBoxContainer {
enum {
TOOL_NEW_ANIM,
- TOOL_LOAD_ANIM,
- TOOL_SAVE_ANIM,
- TOOL_SAVE_AS_ANIM,
+ TOOL_ANIM_LIBRARY,
TOOL_DUPLICATE_ANIM,
TOOL_RENAME_ANIM,
TOOL_EDIT_TRANSITIONS,
TOOL_REMOVE_ANIM,
- TOOL_COPY_ANIM,
- TOOL_PASTE_ANIM,
- TOOL_PASTE_ANIM_REF,
TOOL_EDIT_RESOURCE
};
@@ -103,8 +98,10 @@ class AnimationPlayerEditor : public VBoxContainer {
SpinBox *frame = nullptr;
LineEdit *scale = nullptr;
LineEdit *name = nullptr;
+ OptionButton *library = nullptr;
Label *name_title = nullptr;
UndoRedo *undo_redo = nullptr;
+
Ref<Texture2D> autoplay_icon;
Ref<Texture2D> reset_icon;
Ref<ImageTexture> autoplay_reset_icon;
@@ -114,6 +111,8 @@ class AnimationPlayerEditor : public VBoxContainer {
EditorFileDialog *file = nullptr;
ConfirmationDialog *delete_dialog = nullptr;
+ AnimationLibraryEditor *library_editor = nullptr;
+
struct BlendEditor {
AcceptDialog *dialog = nullptr;
Tree *tree = nullptr;
@@ -173,11 +172,6 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_new();
void _animation_rename();
void _animation_name_edited();
- void _animation_load();
-
- void _animation_save_in_path(const Ref<Resource> &p_resource, const String &p_path);
- void _animation_save(const Ref<Resource> &p_resource);
- void _animation_save_as(const Ref<Resource> &p_resource);
void _animation_remove();
void _animation_remove_confirmed();
@@ -185,11 +179,8 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_edit();
void _animation_duplicate();
Ref<Animation> _animation_clone(const Ref<Animation> p_anim);
- void _animation_paste(const Ref<Animation> p_anim);
void _animation_resource_edit();
void _scale_changed(const String &p_scale);
- void _save_animation(String p_file);
- void _load_animations(Vector<String> p_files);
void _seek_value_changed(float p_value, bool p_set = false, bool p_timeline_only = false);
void _blend_editor_next_changed(const int p_idx);
@@ -219,6 +210,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _stop_onion_skinning();
void _pin_pressed();
+ String _get_current() const;
~AnimationPlayerEditor();
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 405ece1471..157eed02f4 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -729,9 +729,8 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
if (use_cache) {
String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
- FileAccess *file = FileAccess::open(cache_filename_base + ".data", FileAccess::READ);
-
- if (file) {
+ Ref<FileAccess> file = FileAccess::open(cache_filename_base + ".data", FileAccess::READ);
+ if (file.is_valid()) {
PackedByteArray cached_data;
int len = file->get_32();
cached_data.resize(len);
@@ -740,8 +739,6 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PackedB
file->get_buffer(w, len);
image_data = cached_data;
- file->close();
- memdelete(file);
}
}
@@ -808,23 +805,17 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
if (headers[i].findn("ETag:") == 0) { // Save etag
String cache_filename_base = EditorPaths::get_singleton()->get_cache_dir().plus_file("assetimage_" + image_queue[p_queue_id].image_url.md5_text());
String new_etag = headers[i].substr(headers[i].find(":") + 1, headers[i].length()).strip_edges();
- FileAccess *file;
-
- file = FileAccess::open(cache_filename_base + ".etag", FileAccess::WRITE);
- if (file) {
+ Ref<FileAccess> file = FileAccess::open(cache_filename_base + ".etag", FileAccess::WRITE);
+ if (file.is_valid()) {
file->store_line(new_etag);
- file->close();
- memdelete(file);
}
int len = p_data.size();
const uint8_t *r = p_data.ptr();
file = FileAccess::open(cache_filename_base + ".data", FileAccess::WRITE);
- if (file) {
+ if (file.is_valid()) {
file->store_32(len);
file->store_buffer(r, len);
- file->close();
- memdelete(file);
}
break;
@@ -858,11 +849,9 @@ void EditorAssetLibrary::_update_image_queue() {
Vector<String> headers;
if (FileAccess::exists(cache_filename_base + ".etag") && FileAccess::exists(cache_filename_base + ".data")) {
- FileAccess *file = FileAccess::open(cache_filename_base + ".etag", FileAccess::READ);
- if (file) {
+ Ref<FileAccess> file = FileAccess::open(cache_filename_base + ".etag", FileAccess::READ);
+ if (file.is_valid()) {
headers.push_back("If-None-Match: " + file->get_line());
- file->close();
- memdelete(file);
}
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index a90e151adb..8d0db697e2 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -2298,7 +2298,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
}
add_node_menu->reset_size();
- add_node_menu->set_position(get_screen_transform().xform(b->get_position()));
+ add_node_menu->set_position(viewport->get_screen_transform().xform(b->get_position()));
add_node_menu->popup();
node_create_position = transform.affine_inverse().xform(b->get_position());
return true;
diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp
index b4a7081ebc..fb0e260388 100644
--- a/editor/plugins/input_event_editor_plugin.cpp
+++ b/editor/plugins/input_event_editor_plugin.cpp
@@ -33,6 +33,15 @@
void InputEventConfigContainer::_bind_methods() {
}
+void InputEventConfigContainer::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE:
+ case NOTIFICATION_THEME_CHANGED: {
+ open_config_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons")));
+ } break;
+ }
+}
+
void InputEventConfigContainer::_configure_pressed() {
config_dialog->popup_and_configure(input_event);
}
@@ -47,12 +56,6 @@ void InputEventConfigContainer::_config_dialog_confirmed() {
_event_changed();
}
-Size2 InputEventConfigContainer::get_minimum_size() const {
- // Don't bother with a minimum x size for the control - we don't want the inspector
- // to jump in size if a long text is placed in the label (e.g. Joypad Axis description)
- return Size2(0, HBoxContainer::get_minimum_size().y);
-}
-
void InputEventConfigContainer::set_event(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
Ref<InputEventMouseButton> m = p_event;
@@ -75,29 +78,26 @@ void InputEventConfigContainer::set_event(const Ref<InputEvent> &p_event) {
}
InputEventConfigContainer::InputEventConfigContainer() {
- MarginContainer *mc = memnew(MarginContainer);
- mc->add_theme_constant_override("margin_left", 10);
- mc->add_theme_constant_override("margin_right", 10);
- mc->add_theme_constant_override("margin_top", 10);
- mc->add_theme_constant_override("margin_bottom", 10);
- add_child(mc);
-
- HBoxContainer *hb = memnew(HBoxContainer);
- mc->add_child(hb);
+ input_event_text = memnew(Label);
+ input_event_text->set_h_size_flags(SIZE_EXPAND_FILL);
+ input_event_text->set_autowrap_mode(Label::AutowrapMode::AUTOWRAP_WORD_SMART);
+ input_event_text->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+ add_child(input_event_text);
open_config_button = memnew(Button);
open_config_button->set_text(TTR("Configure"));
open_config_button->connect("pressed", callable_mp(this, &InputEventConfigContainer::_configure_pressed));
- hb->add_child(open_config_button);
+ add_child(open_config_button);
- input_event_text = memnew(Label);
- hb->add_child(input_event_text);
+ add_child(memnew(Control));
config_dialog = memnew(InputEventConfigurationDialog);
config_dialog->connect("confirmed", callable_mp(this, &InputEventConfigContainer::_config_dialog_confirmed));
add_child(config_dialog);
}
+///////////////////////
+
bool EditorInspectorPluginInputEvent::can_handle(Object *p_object) {
Ref<InputEventKey> k = Ref<InputEventKey>(p_object);
Ref<InputEventMouseButton> m = Ref<InputEventMouseButton>(p_object);
@@ -115,6 +115,8 @@ void EditorInspectorPluginInputEvent::parse_begin(Object *p_object) {
add_custom_control(picker_controls);
}
+///////////////////////
+
InputEventEditorPlugin::InputEventEditorPlugin() {
Ref<EditorInspectorPluginInputEvent> plugin;
plugin.instantiate();
diff --git a/editor/plugins/input_event_editor_plugin.h b/editor/plugins/input_event_editor_plugin.h
index 3c658a86e9..344f176e78 100644
--- a/editor/plugins/input_event_editor_plugin.h
+++ b/editor/plugins/input_event_editor_plugin.h
@@ -35,8 +35,8 @@
#include "editor/editor_inspector.h"
#include "editor/editor_plugin.h"
-class InputEventConfigContainer : public HBoxContainer {
- GDCLASS(InputEventConfigContainer, HBoxContainer);
+class InputEventConfigContainer : public VBoxContainer {
+ GDCLASS(InputEventConfigContainer, VBoxContainer);
Label *input_event_text = nullptr;
Button *open_config_button = nullptr;
@@ -50,10 +50,10 @@ class InputEventConfigContainer : public HBoxContainer {
void _event_changed();
protected:
+ void _notification(int p_what);
static void _bind_methods();
public:
- virtual Size2 get_minimum_size() const override;
void set_event(const Ref<InputEvent> &p_event);
InputEventConfigContainer();
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 855fc2b2a9..f2ca1fcfeb 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -7120,7 +7120,9 @@ void Node3DEditor::_request_gizmo(Object *p_obj) {
}
}
}
- sp->update_gizmos();
+ if (!sp->get_gizmos().is_empty()) {
+ sp->update_gizmos();
+ }
}
}
diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp
index 27b35d803c..936eb747b0 100644
--- a/editor/plugins/ot_features_plugin.cpp
+++ b/editor/plugins/ot_features_plugin.cpp
@@ -145,8 +145,11 @@ void OpenTypeFeaturesAdd::setup(Object *p_object) {
void OpenTypeFeaturesAdd::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_THEME_CHANGED:
case NOTIFICATION_ENTER_TREE: {
+ connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu));
+ [[fallthrough]];
+ }
+ case NOTIFICATION_THEME_CHANGED: {
set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons")));
} break;
}
@@ -173,7 +176,6 @@ OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() {
menu_cu->set_name("CUMenu");
menu->add_child(menu_cu);
- connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu));
menu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
menu_cv->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
menu_ss->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature));
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 0f45415c4d..906edb006c 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1091,13 +1091,13 @@ void ScriptEditor::_file_dialog_action(String p_file) {
switch (file_dialog_option) {
case FILE_NEW_TEXTFILE: {
Error err;
- FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
- if (err) {
- EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!"));
- break;
+ {
+ Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+ if (err) {
+ EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!"));
+ break;
+ }
}
- file->close();
- memdelete(file);
if (EditorFileSystem::get_singleton()) {
if (textfile_extensions.has(p_file.get_extension())) {
@@ -2211,17 +2211,16 @@ Error ScriptEditor::_save_text_file(Ref<TextFile> p_text_file, const String &p_p
String source = sqscr->get_text();
Error err;
- FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ {
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'.");
+ ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'.");
- file->store_string(source);
- if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
- memdelete(file);
- return ERR_CANT_CREATE;
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
}
- file->close();
- memdelete(file);
if (ResourceSaver::get_timestamp_on_save()) {
p_text_file->set_last_modified_time(FileAccess::get_modified_time(p_path));
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 87b5b829e0..27160f8c86 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -43,6 +43,11 @@
#include "scene/gui/margin_container.h"
#include "scene/gui/panel_container.h"
+static void _draw_shadowed_line(Control *p_control, const Point2 &p_from, const Size2 &p_size, const Size2 &p_shadow_offset, Color p_color, Color p_shadow_color) {
+ p_control->draw_line(p_from, p_from + p_size, p_color);
+ p_control->draw_line(p_from + p_shadow_offset, p_from + p_size + p_shadow_offset, p_shadow_color);
+}
+
void SpriteFramesEditor::gui_input(const Ref<InputEvent> &p_event) {
}
@@ -58,46 +63,62 @@ void SpriteFramesEditor::_open_sprite_sheet() {
}
int SpriteFramesEditor::_sheet_preview_position_to_frame_index(const Point2 &p_position) {
- if (p_position.x < 0 || p_position.y < 0) {
- return -1;
- }
+ const Size2i offset = _get_offset();
+ const Size2i frame_size = _get_frame_size();
+ const Size2i separation = _get_separation();
+ const Size2i block_size = frame_size + separation;
+ const Point2i position = p_position / sheet_zoom - offset;
- Size2i texture_size = split_sheet_preview->get_texture()->get_size();
- int h = split_sheet_h->get_value();
- int v = split_sheet_v->get_value();
- if (h > texture_size.width || v > texture_size.height) {
- return -1;
+ if (position.x % block_size.x > frame_size.x || position.y % block_size.y > frame_size.y) {
+ return -1; // Gap between frames.
}
- int x = int(p_position.x / sheet_zoom) / (texture_size.width / h);
- int y = int(p_position.y / sheet_zoom) / (texture_size.height / v);
- if (x >= h || y >= v) {
- return -1;
+ const Point2i frame = position / block_size;
+ const Size2i frame_count = _get_frame_count();
+ if (frame.x < 0 || frame.y < 0 || frame.x >= frame_count.x || frame.y >= frame_count.y) {
+ return -1; // Out of bound.
}
- return h * y + x;
+
+ return frame_count.x * frame.y + frame.x;
}
void SpriteFramesEditor::_sheet_preview_draw() {
- Size2i texture_size = split_sheet_preview->get_texture()->get_size();
- int h = split_sheet_h->get_value();
- int v = split_sheet_v->get_value();
-
- real_t width = (texture_size.width / h) * sheet_zoom;
- real_t height = (texture_size.height / v) * sheet_zoom;
- const float a = 0.3;
-
- real_t y_end = v * height;
- for (int i = 0; i <= h; i++) {
- real_t x = i * width;
- split_sheet_preview->draw_line(Point2(x, 0), Point2(x, y_end), Color(1, 1, 1, a));
- split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, y_end), Color(0, 0, 0, a));
+ const Size2i frame_count = _get_frame_count();
+ const Size2i separation = _get_separation();
+
+ const Size2 draw_offset = Size2(_get_offset()) * sheet_zoom;
+ const Size2 draw_sep = Size2(separation) * sheet_zoom;
+ const Size2 draw_frame_size = Size2(_get_frame_size()) * sheet_zoom;
+ const Size2 draw_size = draw_frame_size * frame_count + draw_sep * (frame_count - Size2i(1, 1));
+
+ const Color line_color = Color(1, 1, 1, 0.3);
+ const Color shadow_color = Color(0, 0, 0, 0.3);
+
+ // Vertical lines.
+ _draw_shadowed_line(split_sheet_preview, draw_offset, Vector2(0, draw_size.y), Vector2(1, 0), line_color, shadow_color);
+ for (int i = 0; i < frame_count.x - 1; i++) {
+ const Point2 start = draw_offset + Vector2(i * draw_sep.x + (i + 1) * draw_frame_size.x, 0);
+ if (separation.x == 0) {
+ _draw_shadowed_line(split_sheet_preview, start, Vector2(0, draw_size.y), Vector2(1, 0), line_color, shadow_color);
+ } else {
+ const Size2 size = Size2(draw_sep.x, draw_size.y);
+ split_sheet_preview->draw_rect(Rect2(start, size), line_color);
+ }
}
- real_t x_end = h * width;
- for (int i = 0; i <= v; i++) {
- real_t y = i * height;
- split_sheet_preview->draw_line(Point2(0, y), Point2(x_end, y), Color(1, 1, 1, a));
- split_sheet_preview->draw_line(Point2(0, y + 1), Point2(x_end, y + 1), Color(0, 0, 0, a));
+ _draw_shadowed_line(split_sheet_preview, draw_offset + Vector2(draw_size.x, 0), Vector2(0, draw_size.y), Vector2(1, 0), line_color, shadow_color);
+
+ // Horizontal lines.
+ _draw_shadowed_line(split_sheet_preview, draw_offset, Vector2(draw_size.x, 0), Vector2(0, 1), line_color, shadow_color);
+ for (int i = 0; i < frame_count.y - 1; i++) {
+ const Point2 start = draw_offset + Vector2(0, i * draw_sep.y + (i + 1) * draw_frame_size.y);
+ if (separation.y == 0) {
+ _draw_shadowed_line(split_sheet_preview, start, Vector2(draw_size.x, 0), Vector2(0, 1), line_color, shadow_color);
+ } else {
+ const Size2 size = Size2(draw_size.x, draw_sep.y);
+ split_sheet_preview->draw_rect(Rect2(start, size), line_color);
+ }
}
+ _draw_shadowed_line(split_sheet_preview, draw_offset + Vector2(0, draw_size.y), Vector2(draw_size.x, 0), Vector2(0, 1), line_color, shadow_color);
if (frames_selected.size() == 0) {
split_sheet_dialog->get_ok_button()->set_disabled(true);
@@ -105,22 +126,20 @@ void SpriteFramesEditor::_sheet_preview_draw() {
return;
}
- Color accent = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
+ Color accent = get_theme_color("accent_color", "Editor");
for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
- int idx = E->get();
- int xp = idx % h;
- int yp = idx / h;
- real_t x = xp * width;
- real_t y = yp * height;
-
- split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 0.35), true);
- split_sheet_preview->draw_rect(Rect2(x + 0, y + 0, width - 0, height - 0), Color(0, 0, 0, 1), false);
- split_sheet_preview->draw_rect(Rect2(x + 1, y + 1, width - 2, height - 2), Color(0, 0, 0, 1), false);
- split_sheet_preview->draw_rect(Rect2(x + 2, y + 2, width - 4, height - 4), accent, false);
- split_sheet_preview->draw_rect(Rect2(x + 3, y + 3, width - 6, height - 6), accent, false);
- split_sheet_preview->draw_rect(Rect2(x + 4, y + 4, width - 8, height - 8), Color(0, 0, 0, 1), false);
- split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 1), false);
+ const int idx = E->get();
+ const int x = idx % frame_count.x;
+ const int y = idx / frame_count.x;
+ const Point2 pos = draw_offset + Point2(x, y) * (draw_frame_size + draw_sep);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(5, 5), draw_frame_size - Size2(10, 10)), Color(0, 0, 0, 0.35), true);
+ split_sheet_preview->draw_rect(Rect2(pos, draw_frame_size), Color(0, 0, 0, 1), false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(1, 1), draw_frame_size - Size2(2, 2)), Color(0, 0, 0, 1), false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(2, 2), draw_frame_size - Size2(4, 4)), accent, false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(3, 3), draw_frame_size - Size2(6, 6)), accent, false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(4, 4), draw_frame_size - Size2(8, 8)), Color(0, 0, 0, 1), false);
+ split_sheet_preview->draw_rect(Rect2(pos + Size2(5, 5), draw_frame_size - Size2(10, 10)), Color(0, 0, 0, 1), false);
}
split_sheet_dialog->get_ok_button()->set_disabled(false);
@@ -223,10 +242,10 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) {
}
void SpriteFramesEditor::_sheet_add_frames() {
- Size2i texture_size = split_sheet_preview->get_texture()->get_size();
- int frame_count_x = split_sheet_h->get_value();
- int frame_count_y = split_sheet_v->get_value();
- Size2 frame_size(texture_size.width / frame_count_x, texture_size.height / frame_count_y);
+ const Size2i frame_count = _get_frame_count();
+ const Size2i frame_size = _get_frame_size();
+ const Size2i offset = _get_offset();
+ const Size2i separation = _get_separation();
undo_redo->create_action(TTR("Add Frame"));
@@ -234,12 +253,12 @@ void SpriteFramesEditor::_sheet_add_frames() {
for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) {
int idx = E->get();
- Point2 frame_coords(idx % frame_count_x, idx / frame_count_x);
+ const Point2 frame_coords(idx % frame_count.x, idx / frame_count.x);
Ref<AtlasTexture> at;
at.instantiate();
at->set_atlas(split_sheet_preview->get_texture());
- at->set_region(Rect2(frame_coords * frame_size, frame_size));
+ at->set_region(Rect2(offset + frame_coords * (frame_size + separation), frame_size));
undo_redo->add_do_method(frames, "add_frame", edited_anim, at, -1);
undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc);
@@ -293,7 +312,57 @@ void SpriteFramesEditor::_sheet_select_clear_all_frames() {
split_sheet_preview->update();
}
-void SpriteFramesEditor::_sheet_spin_changed(double) {
+void SpriteFramesEditor::_sheet_spin_changed(double p_value, int p_dominant_param) {
+ if (updating_split_settings) {
+ return;
+ }
+ updating_split_settings = true;
+
+ if (p_dominant_param != PARAM_USE_CURRENT) {
+ dominant_param = p_dominant_param;
+ }
+
+ const Size2i texture_size = split_sheet_preview->get_texture()->get_size();
+ const Size2i size = texture_size - _get_offset();
+
+ switch (dominant_param) {
+ case PARAM_SIZE: {
+ const Size2i frame_size = _get_frame_size();
+
+ const Size2i offset_max = texture_size - frame_size;
+ split_sheet_offset_x->set_max(offset_max.x);
+ split_sheet_offset_y->set_max(offset_max.y);
+
+ const Size2i sep_max = size - frame_size * 2;
+ split_sheet_sep_x->set_max(sep_max.x);
+ split_sheet_sep_y->set_max(sep_max.y);
+
+ const Size2i separation = _get_separation();
+ const Size2i count = (size + separation) / (frame_size + separation);
+ split_sheet_h->set_value(count.x);
+ split_sheet_v->set_value(count.y);
+ } break;
+
+ case PARAM_FRAME_COUNT: {
+ const Size2i count = _get_frame_count();
+
+ const Size2i offset_max = texture_size - count;
+ split_sheet_offset_x->set_max(offset_max.x);
+ split_sheet_offset_y->set_max(offset_max.y);
+
+ const Size2i gap_count = count - Size2i(1, 1);
+ split_sheet_sep_x->set_max(gap_count.x == 0 ? size.x : (size.x - count.x) / gap_count.x);
+ split_sheet_sep_y->set_max(gap_count.y == 0 ? size.y : (size.y - count.y) / gap_count.y);
+
+ const Size2i separation = _get_separation();
+ const Size2i frame_size = (size - separation * gap_count) / count;
+ split_sheet_size_x->set_value(frame_size.x);
+ split_sheet_size_y->set_value(frame_size.y);
+ } break;
+ }
+
+ updating_split_settings = false;
+
frames_selected.clear();
last_frame_selected = -1;
split_sheet_preview->update();
@@ -311,10 +380,29 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) {
bool new_texture = texture != split_sheet_preview->get_texture();
split_sheet_preview->set_texture(texture);
if (new_texture) {
- //different texture, reset to 4x4
+ // Reset spin max.
+ const Size2i size = texture->get_size();
+ split_sheet_size_x->set_max(size.x);
+ split_sheet_size_y->set_max(size.y);
+ split_sheet_sep_x->set_max(size.x);
+ split_sheet_sep_y->set_max(size.y);
+ split_sheet_offset_x->set_max(size.x);
+ split_sheet_offset_y->set_max(size.y);
+
+ // Different texture, reset to 4x4.
+ dominant_param = PARAM_FRAME_COUNT;
+ updating_split_settings = true;
split_sheet_h->set_value(4);
split_sheet_v->set_value(4);
- //reset zoom
+ split_sheet_size_x->set_value(size.x / 4);
+ split_sheet_size_y->set_value(size.y / 4);
+ split_sheet_sep_x->set_value(0);
+ split_sheet_sep_y->set_value(0);
+ split_sheet_offset_x->set_value(0);
+ split_sheet_offset_y->set_value(0);
+ updating_split_settings = false;
+
+ // Reset zoom.
_sheet_zoom_reset();
}
split_sheet_dialog->popup_centered_ratio(0.65);
@@ -392,6 +480,22 @@ void SpriteFramesEditor::_file_load_request(const Vector<String> &p_path, int p_
undo_redo->commit_action();
}
+Size2i SpriteFramesEditor::_get_frame_count() const {
+ return Size2i(split_sheet_h->get_value(), split_sheet_v->get_value());
+}
+
+Size2i SpriteFramesEditor::_get_frame_size() const {
+ return Size2i(split_sheet_size_x->get_value(), split_sheet_size_y->get_value());
+}
+
+Size2i SpriteFramesEditor::_get_offset() const {
+ return Size2i(split_sheet_offset_x->get_value(), split_sheet_offset_y->get_value());
+}
+
+Size2i SpriteFramesEditor::_get_separation() const {
+ return Size2i(split_sheet_sep_x->get_value(), split_sheet_sep_y->get_value());
+}
+
void SpriteFramesEditor::_load_pressed() {
ERR_FAIL_COND(!frames->has_animation(edited_anim));
loading_scene = false;
@@ -1210,23 +1314,66 @@ SpriteFramesEditor::SpriteFramesEditor() {
HBoxContainer *split_sheet_hb = memnew(HBoxContainer);
- Label *ss_label = memnew(Label(TTR("Horizontal:")));
- split_sheet_hb->add_child(ss_label);
+ split_sheet_hb->add_child(memnew(Label(TTR("Horizontal:"))));
split_sheet_h = memnew(SpinBox);
split_sheet_h->set_min(1);
split_sheet_h->set_max(128);
split_sheet_h->set_step(1);
split_sheet_hb->add_child(split_sheet_h);
- split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed));
+ split_sheet_h->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT));
- ss_label = memnew(Label(TTR("Vertical:")));
- split_sheet_hb->add_child(ss_label);
+ split_sheet_hb->add_child(memnew(Label(TTR("Vertical:"))));
split_sheet_v = memnew(SpinBox);
split_sheet_v->set_min(1);
split_sheet_v->set_max(128);
split_sheet_v->set_step(1);
split_sheet_hb->add_child(split_sheet_v);
- split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed));
+ split_sheet_v->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_FRAME_COUNT));
+
+ split_sheet_hb->add_child(memnew(VSeparator));
+ split_sheet_hb->add_child(memnew(Label(TTR("Size:"))));
+ split_sheet_size_x = memnew(SpinBox);
+ split_sheet_size_x->set_min(1);
+ split_sheet_size_x->set_step(1);
+ split_sheet_size_x->set_suffix("px");
+ split_sheet_size_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE));
+ split_sheet_hb->add_child(split_sheet_size_x);
+ split_sheet_size_y = memnew(SpinBox);
+ split_sheet_size_y->set_min(1);
+ split_sheet_size_y->set_step(1);
+ split_sheet_size_y->set_suffix("px");
+ split_sheet_size_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_SIZE));
+ split_sheet_hb->add_child(split_sheet_size_y);
+
+ split_sheet_hb->add_child(memnew(VSeparator));
+ split_sheet_hb->add_child(memnew(Label(TTR("Separation:"))));
+ split_sheet_sep_x = memnew(SpinBox);
+ split_sheet_sep_x->set_min(0);
+ split_sheet_sep_x->set_step(1);
+ split_sheet_sep_x->set_suffix("px");
+ split_sheet_sep_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_sep_x);
+ split_sheet_sep_y = memnew(SpinBox);
+ split_sheet_sep_y->set_min(0);
+ split_sheet_sep_y->set_step(1);
+ split_sheet_sep_y->set_suffix("px");
+ split_sheet_sep_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_sep_y);
+
+ split_sheet_hb->add_child(memnew(VSeparator));
+ split_sheet_hb->add_child(memnew(Label(TTR("Offset:"))));
+ split_sheet_offset_x = memnew(SpinBox);
+ split_sheet_offset_x->set_min(0);
+ split_sheet_offset_x->set_step(1);
+ split_sheet_offset_x->set_suffix("px");
+ split_sheet_offset_x->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_offset_x);
+ split_sheet_offset_y = memnew(SpinBox);
+ split_sheet_offset_y->set_min(0);
+ split_sheet_offset_y->set_step(1);
+ split_sheet_offset_y->set_suffix("px");
+ split_sheet_offset_y->connect("value_changed", callable_mp(this, &SpriteFramesEditor::_sheet_spin_changed), varray(PARAM_USE_CURRENT));
+ split_sheet_hb->add_child(split_sheet_offset_y);
split_sheet_hb->add_spacer();
diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h
index b0213012a2..9a00fe5771 100644
--- a/editor/plugins/sprite_frames_editor_plugin.h
+++ b/editor/plugins/sprite_frames_editor_plugin.h
@@ -48,6 +48,13 @@ class EditorFileDialog;
class SpriteFramesEditor : public HSplitContainer {
GDCLASS(SpriteFramesEditor, HSplitContainer);
+ enum {
+ PARAM_USE_CURRENT, // Used in callbacks to indicate `dominant_param` should be not updated.
+ PARAM_FRAME_COUNT, // Keep "Horizontal" & "Vertial" values.
+ PARAM_SIZE, // Keep "Size" values.
+ };
+ int dominant_param = PARAM_FRAME_COUNT;
+
Button *load = nullptr;
Button *load_sheet = nullptr;
Button *_delete = nullptr;
@@ -86,6 +93,12 @@ class SpriteFramesEditor : public HSplitContainer {
TextureRect *split_sheet_preview = nullptr;
SpinBox *split_sheet_h = nullptr;
SpinBox *split_sheet_v = nullptr;
+ SpinBox *split_sheet_size_x = nullptr;
+ SpinBox *split_sheet_size_y = nullptr;
+ SpinBox *split_sheet_sep_x = nullptr;
+ SpinBox *split_sheet_sep_y = nullptr;
+ SpinBox *split_sheet_offset_x = nullptr;
+ SpinBox *split_sheet_offset_y = nullptr;
Button *split_sheet_zoom_out = nullptr;
Button *split_sheet_zoom_reset = nullptr;
Button *split_sheet_zoom_in = nullptr;
@@ -103,6 +116,11 @@ class SpriteFramesEditor : public HSplitContainer {
float max_sheet_zoom;
float min_sheet_zoom;
+ Size2i _get_frame_count() const;
+ Size2i _get_frame_size() const;
+ Size2i _get_offset() const;
+ Size2i _get_separation() const;
+
void _load_pressed();
void _file_load_request(const Vector<String> &p_path, int p_at_pos = -1);
void _copy_pressed();
@@ -128,6 +146,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _zoom_reset();
bool updating;
+ bool updating_split_settings = false; // Skip SpinBox/Range callback when setting value by code.
UndoRedo *undo_redo = nullptr;
@@ -139,7 +158,7 @@ class SpriteFramesEditor : public HSplitContainer {
void _prepare_sprite_sheet(const String &p_file);
int _sheet_preview_position_to_frame_index(const Vector2 &p_position);
void _sheet_preview_draw();
- void _sheet_spin_changed(double);
+ void _sheet_spin_changed(double p_value, int p_dominant_param);
void _sheet_preview_input(const Ref<InputEvent> &p_event);
void _sheet_scroll_input(const Ref<InputEvent> &p_event);
void _sheet_add_frames();
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index a7c06ada5c..15f03fd46d 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -70,7 +70,7 @@ void TexturePreview::_update_metadata_label_text() {
format = texture->get_class();
}
- metadata_label->set_text(itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format);
+ metadata_label->set_text(vformat(String::utf8("%s×%s %s"), itos(texture->get_width()), itos(texture->get_height()), format));
}
TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp
index 5afd460831..0835d0212f 100644
--- a/editor/pot_generator.cpp
+++ b/editor/pot_generator.cpp
@@ -93,7 +93,7 @@ void POTGenerator::generate_pot(const String &p_file) {
void POTGenerator::_write_to_pot(const String &p_file) {
Error err;
- FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err);
if (err != OK) {
ERR_PRINT("Failed to open " + p_file);
return;
@@ -155,11 +155,9 @@ void POTGenerator::_write_to_pot(const String &p_file) {
}
}
}
-
- file->close();
}
-void POTGenerator::_write_msgid(FileAccess *r_file, const String &p_id, bool p_plural) {
+void POTGenerator::_write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural) {
// Split \\n and \n.
Vector<String> temp = p_id.split("\\n");
Vector<String> msg_lines;
diff --git a/editor/pot_generator.h b/editor/pot_generator.h
index 2b42c681e5..e7a5f90cee 100644
--- a/editor/pot_generator.h
+++ b/editor/pot_generator.h
@@ -49,7 +49,7 @@ class POTGenerator {
OrderedHashMap<String, Vector<MsgidData>> all_translation_strings;
void _write_to_pot(const String &p_file);
- void _write_msgid(FileAccess *r_file, const String &p_id, bool p_plural);
+ void _write_msgid(Ref<FileAccess> r_file, const String &p_id, bool p_plural);
void _add_new_msgid(const String &p_msgid, const String &p_context, const String &p_plural, const String &p_location);
#ifdef DEBUG_POT
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 501cb88547..4ca0f18f0e 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -147,7 +147,7 @@ private:
}
String _test_path() {
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String valid_path, valid_install_path;
if (d->change_dir(project_path->get_text()) == OK) {
valid_path = project_path->get_text();
@@ -186,8 +186,7 @@ private:
if (mode == MODE_IMPORT || mode == MODE_RENAME) {
if (!valid_path.is_empty() && !d->file_exists("project.godot")) {
if (valid_path.ends_with(".zip")) {
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
unzFile pkg = unzOpen2(valid_path.utf8().get_data(), &io);
if (!pkg) {
@@ -383,7 +382,7 @@ private:
return;
}
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (d->change_dir(project_path->get_text()) == OK) {
if (!d->dir_exists(project_name_no_edges)) {
if (d->make_dir(project_name_no_edges) == OK) {
@@ -500,8 +499,7 @@ private:
zip_path = project_path->get_text();
}
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
unzFile pkg = unzOpen2(zip_path.utf8().get_data(), &io);
if (!pkg) {
@@ -549,7 +547,7 @@ private:
path = path.substr(0, path.length() - 1);
String rel_path = path.substr(zip_root.length());
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->make_dir(dir.plus_file(rel_path));
} else {
Vector<uint8_t> data;
@@ -559,16 +557,12 @@ private:
//read
unzOpenCurrentFile(pkg);
ret = unzReadCurrentFile(pkg, data.ptrw(), data.size());
- if (ret != UNZ_OK) {
- break;
- }
+ ERR_BREAK_MSG(ret < 0, vformat("An error occurred while attempting to read from file: %s. This file will not be used.", rel_path));
unzCloseCurrentFile(pkg);
- FileAccess *f = FileAccess::open(dir.plus_file(rel_path), FileAccess::WRITE);
-
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(dir.plus_file(rel_path), FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_buffer(data.ptr(), data.size());
- memdelete(f);
} else {
failed_files.push_back(rel_path);
}
@@ -615,7 +609,7 @@ private:
void _remove_created_folder() {
if (!created_folder_path.is_empty()) {
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
d->remove(created_folder_path);
create_dir->set_disabled(false);
@@ -719,7 +713,7 @@ public:
project_path->set_text(fav_dir);
fdialog->set_current_dir(fav_dir);
} else {
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
project_path->set_text(d->get_current_dir());
fdialog->set_current_dir(d->get_current_dir());
}
@@ -1125,7 +1119,7 @@ struct ProjectListComparator {
};
ProjectList::ProjectList() {
- _order_option = FilterOption::NAME;
+ _order_option = FilterOption::EDIT_DATE;
_scroll_children = memnew(VBoxContainer);
_scroll_children->set_h_size_flags(Control::SIZE_EXPAND_FILL);
add_child(_scroll_children);
@@ -2280,7 +2274,7 @@ void ProjectManager::_run_project() {
}
void ProjectManager::_scan_dir(const String &path, List<String> *r_projects) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error error = da->change_dir(path);
ERR_FAIL_COND_MSG(error != OK, "Could not scan directory at: " + path);
da->list_dir_begin();
@@ -2402,14 +2396,14 @@ void ProjectManager::_install_project(const String &p_zip_path, const String &p_
npdialog->show_dialog();
}
-void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
+void ProjectManager::_files_dropped(PackedStringArray p_files) {
if (p_files.size() == 1 && p_files[0].ends_with(".zip")) {
const String file = p_files[0].get_file();
_install_project(p_files[0], file.substr(0, file.length() - 4).capitalize());
return;
}
Set<String> folders_set;
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < p_files.size(); i++) {
String file = p_files[i];
folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
@@ -2422,7 +2416,7 @@ void ProjectManager::_files_dropped(PackedStringArray p_files, int p_screen) {
bool confirm = true;
if (folders.size() == 1) {
- DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (dir->change_dir(folders[0]) == OK) {
dir->list_dir_begin();
String file = dir->get_next();
@@ -2610,9 +2604,9 @@ ProjectManager::ProjectManager() {
hb->add_child(filter_option);
Vector<String> sort_filter_titles;
+ sort_filter_titles.push_back(TTR("Last Edited"));
sort_filter_titles.push_back(TTR("Name"));
sort_filter_titles.push_back(TTR("Path"));
- sort_filter_titles.push_back(TTR("Last Edited"));
for (int i = 0; i < sort_filter_titles.size(); i++) {
filter_option->add_item(sort_filter_titles[i]);
@@ -2849,7 +2843,7 @@ ProjectManager::ProjectManager() {
_load_recent_projects();
- DirAccessRef dir_access = DirAccess::create(DirAccess::AccessType::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir_access = DirAccess::create(DirAccess::AccessType::ACCESS_FILESYSTEM);
String default_project_path = EditorSettings::get_singleton()->get("filesystem/directories/default_project_path");
if (!dir_access->dir_exists(default_project_path)) {
diff --git a/editor/project_manager.h b/editor/project_manager.h
index 9cea6e163f..a68cc4350c 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -42,9 +42,9 @@ class ProjectDialog;
class ProjectList;
enum FilterOption {
+ EDIT_DATE,
NAME,
PATH,
- EDIT_DATE,
};
class ProjectManager : public Control {
@@ -127,7 +127,7 @@ class ProjectManager : public Control {
void _dim_window();
virtual void shortcut_input(const Ref<InputEvent> &p_ev) override;
- void _files_dropped(PackedStringArray p_files, int p_screen);
+ void _files_dropped(PackedStringArray p_files);
void _version_button_pressed();
void _on_order_option_changed(int p_idx);
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 71ea625013..03f65cdf52 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -3149,9 +3149,8 @@ void SceneTreeDock::_update_create_root_dialog() {
favorite_nodes->get_child(i)->queue_delete();
}
- FileAccess *f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ);
-
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites.Node"), FileAccess::READ);
+ if (f.is_valid()) {
while (!f->eof_reached()) {
String l = f->get_line().strip_edges();
@@ -3168,8 +3167,6 @@ void SceneTreeDock::_update_create_root_dialog() {
button->connect("pressed", callable_mp(this, &SceneTreeDock::_favorite_root_selected), make_binds(l));
}
}
-
- memdelete(f);
}
if (!favorite_nodes->is_visible_in_tree()) {
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 72f77c859b..7d063e13f9 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -246,7 +246,7 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
}
{
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->change_dir(p.get_base_dir()) != OK) {
return TTR("Base path is invalid.");
}
@@ -254,7 +254,7 @@ String ScriptCreateDialog::_validate_path(const String &p_path, bool p_file_must
{
// Check if file exists.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (da->dir_exists(p)) {
return TTR("A directory with the same name exists.");
} else if (p_file_must_exist && !da->file_exists(p)) {
@@ -547,7 +547,7 @@ void ScriptCreateDialog::_path_changed(const String &p_path) {
}
// Check if file exists.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
if (da->file_exists(p)) {
is_new_script_created = false;
@@ -824,8 +824,8 @@ Vector<ScriptLanguage::ScriptTemplate> ScriptCreateDialog::_get_user_templates(c
String dir_path = p_dir.plus_file(p_object);
- DirAccessRef d = DirAccess::open(dir_path);
- if (d) {
+ Ref<DirAccess> d = DirAccess::open(dir_path);
+ if (d.is_valid()) {
d->list_dir_begin();
String file = d->get_next();
while (file != String()) {
@@ -858,7 +858,7 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL
// Parse file for meta-information and script content
Error err;
- FileAccess *file = FileAccess::open(p_path.plus_file(p_filename), FileAccess::READ, &err);
+ Ref<FileAccess> file = FileAccess::open(p_path.plus_file(p_filename), FileAccess::READ, &err);
if (!err) {
while (!file->eof_reached()) {
String line = file->get_line();
@@ -890,8 +890,6 @@ ScriptLanguage::ScriptTemplate ScriptCreateDialog::_parse_template(const ScriptL
script_template.content += line.replace("\t", "_TS_") + "\n";
}
}
- file->close();
- memdelete(file);
}
script_template.content = script_template.content.lstrip("\n");
diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp
index dbc78e846c..f07ec161c2 100644
--- a/editor/shader_create_dialog.cpp
+++ b/editor/shader_create_dialog.cpp
@@ -313,7 +313,7 @@ void ShaderCreateDialog::_path_changed(const String &p_path) {
return;
}
- DirAccessRef f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
String p = ProjectSettings::get_singleton()->localize_path(p_path.strip_edges());
if (f->file_exists(p)) {
is_new_shader_created = false;
@@ -371,12 +371,12 @@ String ShaderCreateDialog::_validate_path(const String &p_path) {
return TTR("Path is not local.");
}
- DirAccessRef d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (d->change_dir(p.get_base_dir()) != OK) {
return TTR("Invalid base path.");
}
- DirAccessRef f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> f = DirAccess::create(DirAccess::ACCESS_RESOURCES);
if (f->dir_exists(p)) {
return TTR("A directory with the same name exists.");
}
diff --git a/main/main.cpp b/main/main.cpp
index a99654542a..f20ec94fa5 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -2112,8 +2112,8 @@ bool Main::start() {
}
{
- DirAccessRef da = DirAccess::open(doc_tool_path);
- ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path.");
+ Ref<DirAccess> da = DirAccess::open(doc_tool_path);
+ ERR_FAIL_COND_V_MSG(da.is_null(), false, "Argument supplied to --doctool must be a valid directory path.");
}
#ifndef MODULE_MONO_ENABLED
@@ -2149,7 +2149,7 @@ bool Main::start() {
checked_paths.insert(path);
// Create the module documentation directory if it doesn't exist
- DirAccessRef da = DirAccess::create_for_path(path);
+ Ref<DirAccess> da = DirAccess::create_for_path(path);
err = da->make_dir_recursive(path);
ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create directory: " + path + ": " + itos(err));
@@ -2161,7 +2161,7 @@ bool Main::start() {
String index_path = doc_tool_path.plus_file("doc/classes");
// Create the main documentation directory if it doesn't exist
- DirAccessRef da = DirAccess::create_for_path(index_path);
+ Ref<DirAccess> da = DirAccess::create_for_path(index_path);
err = da->make_dir_recursive(index_path);
ERR_FAIL_COND_V_MSG(err != OK, false, "Error: Can't create index directory: " + index_path + ": " + itos(err));
@@ -2501,11 +2501,11 @@ bool Main::start() {
int sep = local_game_path.rfind("/");
if (sep == -1) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
local_game_path = da->get_current_dir().plus_file(local_game_path);
} else {
- DirAccessRef da = DirAccess::open(local_game_path.substr(0, sep));
- if (da) {
+ Ref<DirAccess> da = DirAccess::open(local_game_path.substr(0, sep));
+ if (da.is_valid()) {
local_game_path = da->get_current_dir().plus_file(
local_game_path.substr(sep + 1, local_game_path.length()));
}
diff --git a/modules/bmp/image_loader_bmp.cpp b/modules/bmp/image_loader_bmp.cpp
index ad2c7d6a3e..8813c3827a 100644
--- a/modules/bmp/image_loader_bmp.cpp
+++ b/modules/bmp/image_loader_bmp.cpp
@@ -200,8 +200,7 @@ Error ImageLoaderBMP::convert_to_image(Ref<Image> p_image,
return err;
}
-Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
- bool p_force_linear, float p_scale) {
+Error ImageLoaderBMP::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
bmp_header_s bmp_header;
Error err = ERR_INVALID_DATA;
@@ -241,7 +240,6 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
case BI_CMYKRLE8:
case BI_CMYKRLE4: {
// Stop parsing.
- f->close();
ERR_FAIL_V_MSG(ERR_UNAVAILABLE,
vformat("Compressed BMP files are not supported: %s", f->get_path()));
} break;
@@ -283,7 +281,6 @@ Error ImageLoaderBMP::load_image(Ref<Image> p_image, FileAccess *f,
err = convert_to_image(p_image, bmp_buffer_r,
bmp_color_table_r, color_table_size, bmp_header);
}
- f->close();
}
}
return err;
@@ -294,12 +291,14 @@ void ImageLoaderBMP::get_recognized_extensions(List<String> *p_extensions) const
}
static Ref<Image> _bmp_mem_loader_func(const uint8_t *p_bmp, int p_size) {
- FileAccessMemory memfile;
- Error open_memfile_error = memfile.open_custom(p_bmp, p_size);
+ Ref<FileAccessMemory> memfile;
+ memfile.instantiate();
+ Error open_memfile_error = memfile->open_custom(p_bmp, p_size);
ERR_FAIL_COND_V_MSG(open_memfile_error, Ref<Image>(), "Could not create memfile for BMP image buffer.");
+
Ref<Image> img;
img.instantiate();
- Error load_error = ImageLoaderBMP().load_image(img, &memfile, false, 1.0f);
+ Error load_error = ImageLoaderBMP().load_image(img, memfile, false, 1.0f);
ERR_FAIL_COND_V_MSG(load_error, Ref<Image>(), "Failed to load BMP image.");
return img;
}
diff --git a/modules/bmp/image_loader_bmp.h b/modules/bmp/image_loader_bmp.h
index 9c9a16a9f5..63dee0a969 100644
--- a/modules/bmp/image_loader_bmp.h
+++ b/modules/bmp/image_loader_bmp.h
@@ -83,8 +83,7 @@ protected:
const bmp_header_s &p_header);
public:
- virtual Error load_image(Ref<Image> p_image, FileAccess *f,
- bool p_force_linear, float p_scale);
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderBMP();
};
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 7bfe849106..58e5e31f46 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -100,12 +100,12 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path,
}
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
+ if (f.is_null()) {
return RES();
}
- FileAccessRef fref(f);
+ Ref<FileAccess> fref(f);
if (r_error) {
*r_error = ERR_FILE_CORRUPT;
}
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 6c7d5cc3e1..59254fc3ad 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1030,7 +1030,7 @@ Error GDScript::load_byte_code(const String &p_path) {
Error GDScript::load_source_code(const String &p_path) {
Vector<uint8_t> sourcef;
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
ERR_FAIL_COND_V(err, err);
}
@@ -1039,8 +1039,6 @@ Error GDScript::load_source_code(const String &p_path) {
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
uint64_t r = f->get_buffer(w, len);
- f->close();
- memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
w[len] = 0;
@@ -2099,7 +2097,7 @@ bool GDScriptLanguage::handles_global_class_type(const String &p_type) const {
String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const {
Vector<uint8_t> sourcef;
Error err;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
return String();
}
@@ -2133,8 +2131,8 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
} else {
Vector<StringName> extend_classes = subclass->extends;
- FileAccessRef subfile = FileAccess::open(subclass->extends_path, FileAccess::READ);
- if (!subfile) {
+ Ref<FileAccess> subfile = FileAccess::open(subclass->extends_path, FileAccess::READ);
+ if (subfile.is_null()) {
break;
}
String subsource = subfile->get_as_utf8_string();
@@ -2331,8 +2329,8 @@ String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) con
}
void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
- FileAccessRef file = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_MSG(!file, "Cannot open file '" + p_path + "'.");
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'.");
String source = file->get_as_utf8_string();
if (source.is_empty()) {
@@ -2355,18 +2353,17 @@ Error ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resou
String source = sqscr->get_source_code();
- Error err;
- FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ {
+ Error err;
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'.");
+ ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'.");
- file->store_string(source);
- if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
- memdelete(file);
- return ERR_CANT_CREATE;
+ file->store_string(source);
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
}
- file->close();
- memdelete(file);
if (ScriptServer::is_reload_scripts_on_save_enabled()) {
GDScriptLanguage::get_singleton()->reload_tool_script(p_resource, false);
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 000d36d2e6..a7e25f5aab 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -468,7 +468,7 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia
append(GDScriptFunction::OPCODE_TYPE_ADJUST_BASIS, 1);
break;
case Variant::TRANSFORM3D:
- append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM, 1);
+ append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM3D, 1);
break;
case Variant::COLOR:
append(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR, 1);
diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp
index 6ada7d36f5..8c198345c2 100644
--- a/modules/gdscript/gdscript_cache.cpp
+++ b/modules/gdscript/gdscript_cache.cpp
@@ -145,7 +145,7 @@ Ref<GDScriptParserRef> GDScriptCache::get_parser(const String &p_path, GDScriptP
String GDScriptCache::get_source_code(const String &p_path) {
Vector<uint8_t> source_file;
Error err;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
ERR_FAIL_COND_V(err, "");
}
@@ -153,7 +153,6 @@ String GDScriptCache::get_source_code(const String &p_path) {
uint64_t len = f->get_length();
source_file.resize(len + 1);
uint64_t r = f->get_buffer(source_file.ptrw(), len);
- f->close();
ERR_FAIL_COND_V(r != len, "");
source_file.write[len] = 0;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 0959ffb9b8..0138147fcc 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -35,6 +35,7 @@
#include "gdscript_cache.h"
#include "gdscript_utility_functions.h"
+#include "core/config/engine.h"
#include "core/config/project_settings.h"
bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
@@ -575,7 +576,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
// May be static built-in method call.
if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) {
gen->write_call_builtin_type_static(result, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments);
- } else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") && ClassDB::class_exists(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
+ } else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") &&
+ ClassDB::class_exists(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
// It's a static native method call.
gen->write_call_native_static(result, static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name, subscript->attribute->name, arguments);
} else {
diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp
index e5fbbfa0c1..74090d0aa9 100644
--- a/modules/gdscript/gdscript_disassembler.cpp
+++ b/modules/gdscript/gdscript_disassembler.cpp
@@ -990,7 +990,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
DISASSEMBLE_TYPE_ADJUST(QUATERNION);
DISASSEMBLE_TYPE_ADJUST(AABB);
DISASSEMBLE_TYPE_ADJUST(BASIS);
- DISASSEMBLE_TYPE_ADJUST(TRANSFORM);
+ DISASSEMBLE_TYPE_ADJUST(TRANSFORM3D);
DISASSEMBLE_TYPE_ADJUST(COLOR);
DISASSEMBLE_TYPE_ADJUST(STRING_NAME);
DISASSEMBLE_TYPE_ADJUST(NODE_PATH);
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index c4ce3324c4..718df7a0a6 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -777,7 +777,22 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
}
}
+static void _find_built_in_variants(Map<String, ScriptLanguage::CodeCompletionOption> &r_result, bool exclude_nil = false) {
+ for (int i = 0; i < Variant::VARIANT_MAX; i++) {
+ if (!exclude_nil && Variant::Type(i) == Variant::Type::NIL) {
+ ScriptLanguage::CodeCompletionOption option("null", ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+ r_result.insert(option.display, option);
+ } else {
+ ScriptLanguage::CodeCompletionOption option(Variant::get_type_name(Variant::Type(i)), ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+ r_result.insert(option.display, option);
+ }
+ }
+}
+
static void _list_available_types(bool p_inherit_only, GDScriptParser::CompletionContext &p_context, Map<String, ScriptLanguage::CodeCompletionOption> &r_result) {
+ // Built-in Variant Types
+ _find_built_in_variants(r_result, true);
+
List<StringName> native_types;
ClassDB::get_class_list(&native_types);
for (const StringName &E : native_types) {
@@ -1153,17 +1168,7 @@ static void _find_identifiers(GDScriptParser::CompletionContext &p_context, bool
return;
}
- static const char *_type_names[Variant::VARIANT_MAX] = {
- "null", "bool", "int", "float", "String", "StringName", "Vector2", "Vector2i", "Rect2", "Rect2i", "Vector3", "Vector3i", "Transform2D", "Plane", "Quaternion", "AABB", "Basis", "Transform3D",
- "Color", "NodePath", "RID", "Signal", "Callable", "Object", "Dictionary", "Array", "PackedByteArray", "PackedInt32Array", "PackedInt64Array", "PackedFloat32Array", "PackedFloat64Array", "PackedStringArray",
- "PackedVector2Array", "PackedVector3Array", "PackedColorArray"
- };
- static_assert((sizeof(_type_names) / sizeof(*_type_names)) == Variant::VARIANT_MAX, "Completion for builtin types is incomplete");
-
- for (int i = 0; i < Variant::VARIANT_MAX; i++) {
- ScriptLanguage::CodeCompletionOption option(_type_names[i], ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
- r_result.insert(option.display, option);
- }
+ _find_built_in_variants(r_result);
static const char *_keywords[] = {
"false", "PI", "TAU", "INF", "NAN", "self", "true", "breakpoint", "tool", "super",
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index a7ad2b65fd..d07a167ca2 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -365,7 +365,7 @@ public:
OPCODE_TYPE_ADJUST_QUATERNION,
OPCODE_TYPE_ADJUST_AABB,
OPCODE_TYPE_ADJUST_BASIS,
- OPCODE_TYPE_ADJUST_TRANSFORM,
+ OPCODE_TYPE_ADJUST_TRANSFORM3D,
OPCODE_TYPE_ADJUST_COLOR,
OPCODE_TYPE_ADJUST_STRING_NAME,
OPCODE_TYPE_ADJUST_NODE_PATH,
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index 152f548f4e..2afb850c32 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -372,7 +372,7 @@ void (*type_init_function_table[])(Variant *) = {
&&OPCODE_TYPE_ADJUST_QUATERNION, \
&&OPCODE_TYPE_ADJUST_AABB, \
&&OPCODE_TYPE_ADJUST_BASIS, \
- &&OPCODE_TYPE_ADJUST_TRANSFORM, \
+ &&OPCODE_TYPE_ADJUST_TRANSFORM3D, \
&&OPCODE_TYPE_ADJUST_COLOR, \
&&OPCODE_TYPE_ADJUST_STRING_NAME, \
&&OPCODE_TYPE_ADJUST_NODE_PATH, \
@@ -3263,7 +3263,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_TYPE_ADJUST(QUATERNION, Quaternion);
OPCODE_TYPE_ADJUST(AABB, AABB);
OPCODE_TYPE_ADJUST(BASIS, Basis);
- OPCODE_TYPE_ADJUST(TRANSFORM, Transform3D);
+ OPCODE_TYPE_ADJUST(TRANSFORM3D, Transform3D);
OPCODE_TYPE_ADJUST(COLOR, Color);
OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 17886181d5..4c4e810370 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -108,7 +108,7 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) {
document_links.clear();
GDScriptTokenizer tokenizer;
- FileAccessRef fs = FileAccess::create(FileAccess::ACCESS_RESOURCES);
+ Ref<FileAccess> fs = FileAccess::create(FileAccess::ACCESS_RESOURCES);
tokenizer.set_source_code(p_code);
while (true) {
GDScriptTokenizer::Token token = tokenizer.scan();
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index d5ef8fed74..c42bd58aeb 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -424,10 +424,6 @@ GDScriptTextDocument::GDScriptTextDocument() {
file_checker = FileAccess::create(FileAccess::ACCESS_RESOURCES);
}
-GDScriptTextDocument::~GDScriptTextDocument() {
- memdelete(file_checker);
-}
-
void GDScriptTextDocument::sync_script_content(const String &p_path, const String &p_content) {
String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_path);
GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content);
diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h
index a0e584e525..9732765f34 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 = nullptr;
+ Ref<FileAccess> file_checker;
void didOpen(const Variant &p_param);
void didClose(const Variant &p_param);
@@ -75,7 +75,6 @@ public:
void initialize();
GDScriptTextDocument();
- virtual ~GDScriptTextDocument();
};
#endif
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 1bf0b40842..229c322f26 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -221,7 +221,7 @@ void GDScriptWorkspace::reload_all_workspace_scripts() {
void GDScriptWorkspace::list_script_files(const String &p_root_dir, List<String> &r_files) {
Error err;
- DirAccessRef dir = DirAccess::open(p_root_dir, &err);
+ Ref<DirAccess> dir = DirAccess::open(p_root_dir, &err);
if (OK == err) {
dir->list_dir_begin();
String file_name = dir->get_next();
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index 16c143f7d9..e78517a708 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -229,7 +229,7 @@ bool GDScriptTestRunner::generate_outputs() {
bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) {
Error err = OK;
- DirAccessRef dir(DirAccess::open(p_dir, &err));
+ Ref<DirAccess> dir(DirAccess::open(p_dir, &err));
if (err != OK) {
return false;
@@ -254,7 +254,7 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) {
#ifndef DEBUG_ENABLED
// On release builds, skip tests marked as debug only.
Error open_err = OK;
- FileAccessRef script_file(FileAccess::open(current_dir.plus_file(next), FileAccess::READ, &open_err));
+ Ref<FileAccess> script_file(FileAccess::open(current_dir.plus_file(next), FileAccess::READ, &open_err));
if (open_err != OK) {
ERR_PRINT(vformat(R"(Couldn't open test file "%s".)", next));
next = dir->get_next();
@@ -286,7 +286,7 @@ bool GDScriptTestRunner::make_tests_for_dir(const String &p_dir) {
bool GDScriptTestRunner::make_tests() {
Error err = OK;
- DirAccessRef dir(DirAccess::open(source_dir, &err));
+ Ref<DirAccess> dir(DirAccess::open(source_dir, &err));
ERR_FAIL_COND_V_MSG(err != OK, false, "Could not open specified test directory.");
@@ -611,7 +611,7 @@ bool GDScriptTest::generate_output() {
}
Error err = OK;
- FileAccessRef out_file = FileAccess::open(output_file, FileAccess::WRITE, &err);
+ Ref<FileAccess> out_file = FileAccess::open(output_file, FileAccess::WRITE, &err);
if (err != OK) {
return false;
}
@@ -620,7 +620,6 @@ bool GDScriptTest::generate_output() {
output += "\n"; // Make sure to insert newline for CI static checks.
out_file->store_string(output);
- out_file->close();
return true;
}
diff --git a/modules/gdscript/tests/test_gdscript.cpp b/modules/gdscript/tests/test_gdscript.cpp
index 4255030b4e..d8f60d5e9b 100644
--- a/modules/gdscript/tests/test_gdscript.cpp
+++ b/modules/gdscript/tests/test_gdscript.cpp
@@ -204,8 +204,8 @@ void test(TestType p_type) {
return;
}
- FileAccessRef fa = FileAccess::open(test, FileAccess::READ);
- ERR_FAIL_COND_MSG(!fa, "Could not open file: " + test);
+ Ref<FileAccess> fa = FileAccess::open(test, FileAccess::READ);
+ ERR_FAIL_COND_MSG(fa.is_null(), "Could not open file: " + test);
// Initialize the language for the test routine.
init_language(fa->get_path_absolute().get_base_dir());
diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp
index cdb22b7d19..173d5131cf 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -62,10 +62,11 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_
List<String> *r_missing_deps, Error *r_err) {
// Get global paths for source and sink.
- const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path);
+ // Escape paths to be valid Python strings to embed in the script.
+ const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path).c_escape();
const String sink = ProjectSettings::get_singleton()->get_imported_files_path().plus_file(
vformat("%s-%s.gltf", p_path.get_file().get_basename(), p_path.md5_text()));
- const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink);
+ const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink).c_escape();
// Handle configuration options.
@@ -237,13 +238,12 @@ Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_
return gltf->generate_scene(state, p_bake_fps);
}
-Ref<Animation> EditorSceneFormatImporterBlend::import_animation(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps) {
- return Ref<Animation>();
-}
-
-Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, const String &p_option,
+Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option,
const Map<StringName, Variant> &p_options) {
+ if (p_path.get_extension().to_lower() != "blend") {
+ return true;
+ }
+
if (p_option.begins_with("animation/")) {
if (p_option != "animation/import" && !bool(p_options["animation/import"])) {
return false;
@@ -253,6 +253,9 @@ Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_pa
}
void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) {
+ if (p_path.get_extension().to_lower() != "blend") {
+ return;
+ }
#define ADD_OPTION_BOOL(PATH, VALUE) \
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, SNAME(PATH)), VALUE));
#define ADD_OPTION_ENUM(PATH, ENUM_HINT, VALUE) \
diff --git a/modules/gltf/editor/editor_scene_importer_blend.h b/modules/gltf/editor/editor_scene_importer_blend.h
index 9a1b5f5803..0925333a28 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.h
+++ b/modules/gltf/editor/editor_scene_importer_blend.h
@@ -68,11 +68,9 @@ public:
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps) override;
virtual void get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) override;
- virtual Variant get_option_visibility(const String &p_path, const String &p_option,
+ virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option,
const Map<StringName, Variant> &p_options) override;
};
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.cpp b/modules/gltf/editor/editor_scene_importer_fbx.cpp
index 7cfd85c73a..893d2efcec 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.cpp
+++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp
@@ -53,10 +53,13 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t
List<String> *r_missing_deps, Error *r_err) {
// Get global paths for source and sink.
- const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path);
+ // Don't use `c_escape()` as it can generate broken paths. These paths will be
+ // enclosed in double quotes by OS::execute(), so we only need to escape those.
+ // `c_escape_multiline()` seems to do this (escapes `\` and `"` only).
+ const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path).c_escape_multiline();
const String sink = ProjectSettings::get_singleton()->get_imported_files_path().plus_file(
vformat("%s-%s.glb", p_path.get_file().get_basename(), p_path.md5_text()));
- const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink);
+ const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink).c_escape_multiline();
// Run fbx2gltf.
@@ -65,9 +68,9 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t
List<String> args;
args.push_back("--pbr-metallic-roughness");
args.push_back("--input");
- args.push_back(vformat("\"%s\"", source_global));
+ args.push_back(source_global);
args.push_back("--output");
- args.push_back(vformat("\"%s\"", sink_global));
+ args.push_back(sink_global);
args.push_back("--binary");
String standard_out;
@@ -102,12 +105,7 @@ Node *EditorSceneFormatImporterFBX::import_scene(const String &p_path, uint32_t
return gltf->generate_scene(state, p_bake_fps);
}
-Ref<Animation> EditorSceneFormatImporterFBX::import_animation(const String &p_path,
- uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) {
- return Ref<Animation>();
-}
-
-Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path,
+Variant EditorSceneFormatImporterFBX::get_option_visibility(const String &p_path, bool p_for_animation,
const String &p_option, const Map<StringName, Variant> &p_options) {
return true;
}
diff --git a/modules/gltf/editor/editor_scene_importer_fbx.h b/modules/gltf/editor/editor_scene_importer_fbx.h
index bb69cfaa30..84de7fd1cc 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.h
+++ b/modules/gltf/editor/editor_scene_importer_fbx.h
@@ -47,11 +47,9 @@ public:
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps) override;
virtual void get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) override;
- virtual Variant get_option_visibility(const String &p_path, const String &p_option,
+ virtual Variant get_option_visibility(const String &p_path, bool p_for_animation, const String &p_option,
const Map<StringName, Variant> &p_options) override;
};
diff --git a/modules/gltf/editor/editor_scene_importer_gltf.cpp b/modules/gltf/editor/editor_scene_importer_gltf.cpp
index 1d6a82e58a..5e7811ad2b 100644
--- a/modules/gltf/editor/editor_scene_importer_gltf.cpp
+++ b/modules/gltf/editor/editor_scene_importer_gltf.cpp
@@ -64,9 +64,4 @@ Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t
return doc->generate_scene(state, p_bake_fps);
}
-Ref<Animation> EditorSceneFormatImporterGLTF::import_animation(const String &p_path,
- uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) {
- return Ref<Animation>();
-}
-
#endif // TOOLS_ENABLED
diff --git a/modules/gltf/editor/editor_scene_importer_gltf.h b/modules/gltf/editor/editor_scene_importer_gltf.h
index 1f62ca9537..b714ada124 100644
--- a/modules/gltf/editor/editor_scene_importer_gltf.h
+++ b/modules/gltf/editor/editor_scene_importer_gltf.h
@@ -47,8 +47,6 @@ public:
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
- virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,
- const Map<StringName, Variant> &p_options, int p_bake_fps) override;
};
#endif // TOOLS_ENABLED
diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp
index ee756c6d2e..784733aba2 100644
--- a/modules/gltf/gltf_document.cpp
+++ b/modules/gltf/gltf_document.cpp
@@ -256,8 +256,8 @@ Error GLTFDocument::_serialize_scenes(Ref<GLTFState> state) {
Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
Error err;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ, &err);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
+ if (f.is_null()) {
return err;
}
@@ -278,7 +278,7 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) {
return OK;
}
-Error GLTFDocument::_parse_glb(FileAccess *f, Ref<GLTFState> state) {
+Error GLTFDocument::_parse_glb(Ref<FileAccess> f, Ref<GLTFState> state) {
ERR_FAIL_NULL_V(f, ERR_INVALID_PARAMETER);
ERR_FAIL_NULL_V(state, ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(f->get_position() != 0, ERR_FILE_CANT_READ);
@@ -696,8 +696,8 @@ Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_pat
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
String path = p_path.get_base_dir() + "/" + filename;
Error err;
- FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err);
+ if (f.is_null()) {
return err;
}
if (buffer_data.size() == 0) {
@@ -705,7 +705,6 @@ Error GLTFDocument::_encode_buffer_glb(Ref<GLTFState> state, const String &p_pat
}
f->create(FileAccess::ACCESS_RESOURCES);
f->store_buffer(buffer_data.ptr(), buffer_data.size());
- f->close();
gltf_buffer["uri"] = filename;
gltf_buffer["byteLength"] = buffer_data.size();
buffers.push_back(gltf_buffer);
@@ -729,8 +728,8 @@ Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_pa
String filename = p_path.get_basename().get_file() + itos(i) + ".bin";
String path = p_path.get_base_dir() + "/" + filename;
Error err;
- FileAccessRef f = FileAccess::open(path, FileAccess::WRITE, &err);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE, &err);
+ if (f.is_null()) {
return err;
}
if (buffer_data.size() == 0) {
@@ -738,7 +737,6 @@ Error GLTFDocument::_encode_buffer_bins(Ref<GLTFState> state, const String &p_pa
}
f->create(FileAccess::ACCESS_RESOURCES);
f->store_buffer(buffer_data.ptr(), buffer_data.size());
- f->close();
gltf_buffer["uri"] = filename;
gltf_buffer["byteLength"] = buffer_data.size();
buffers.push_back(gltf_buffer);
@@ -3021,7 +3019,7 @@ Error GLTFDocument::_serialize_images(Ref<GLTFState> state, const String &p_path
String texture_dir = "textures";
String path = p_path.get_base_dir();
String new_texture_dir = path + "/" + texture_dir;
- DirAccessRef da = DirAccess::open(path);
+ Ref<DirAccess> da = DirAccess::open(path);
if (!da->dir_exists(new_texture_dir)) {
da->make_dir(new_texture_dir);
}
@@ -3274,7 +3272,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
Dictionary mr;
{
Array arr;
- const Color c = material->get_albedo().to_linear();
+ const Color c = material->get_albedo().srgb_to_linear();
arr.push_back(c.r);
arr.push_back(c.g);
arr.push_back(c.b);
@@ -3475,7 +3473,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) {
}
if (material->get_feature(BaseMaterial3D::FEATURE_EMISSION)) {
- const Color c = material->get_emission().to_srgb();
+ const Color c = material->get_emission().linear_to_srgb();
Array arr;
arr.push_back(c.r);
arr.push_back(c.g);
@@ -3557,7 +3555,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (sgm.has("diffuseFactor")) {
const Array &arr = sgm["diffuseFactor"];
ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb();
spec_gloss->diffuse_factor = c;
material->set_albedo(spec_gloss->diffuse_factor);
}
@@ -3588,7 +3586,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (mr.has("baseColorFactor")) {
const Array &arr = mr["baseColorFactor"];
ERR_FAIL_COND_V(arr.size() != 4, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2], arr[3]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2], arr[3]).linear_to_srgb();
material->set_albedo(c);
}
@@ -3655,7 +3653,7 @@ Error GLTFDocument::_parse_materials(Ref<GLTFState> state) {
if (d.has("emissiveFactor")) {
const Array &arr = d["emissiveFactor"];
ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb();
material->set_feature(BaseMaterial3D::FEATURE_EMISSION, true);
material->set_emission(c);
@@ -3739,11 +3737,11 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re
}
for (int32_t y = 0; y < r_spec_gloss->spec_gloss_img->get_height(); y++) {
for (int32_t x = 0; x < r_spec_gloss->spec_gloss_img->get_width(); x++) {
- const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).to_linear();
+ const Color specular_pixel = r_spec_gloss->spec_gloss_img->get_pixel(x, y).srgb_to_linear();
Color specular = Color(specular_pixel.r, specular_pixel.g, specular_pixel.b);
specular *= r_spec_gloss->specular_factor;
Color diffuse = Color(1.0f, 1.0f, 1.0f);
- diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).to_linear();
+ diffuse *= r_spec_gloss->diffuse_img->get_pixel(x, y).srgb_to_linear();
float metallic = 0.0f;
Color base_color;
spec_gloss_to_metal_base_color(specular, diffuse, base_color, metallic);
@@ -3760,7 +3758,7 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re
mr.g = 1.0f - mr.g;
rm_img->set_pixel(x, y, mr);
if (r_spec_gloss->diffuse_img.is_valid()) {
- r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.to_srgb());
+ r_spec_gloss->diffuse_img->set_pixel(x, y, base_color.linear_to_srgb());
}
}
}
@@ -4628,7 +4626,7 @@ Error GLTFDocument::_parse_lights(Ref<GLTFState> state) {
if (d.has("color")) {
const Array &arr = d["color"];
ERR_FAIL_COND_V(arr.size() != 3, ERR_PARSE_ERROR);
- const Color c = Color(arr[0], arr[1], arr[2]).to_srgb();
+ const Color c = Color(arr[0], arr[1], arr[2]).linear_to_srgb();
light->color = c;
}
if (d.has("intensity")) {
@@ -6097,7 +6095,14 @@ void GLTFDocument::_import_animation(Ref<GLTFState> state, AnimationPlayer *ap,
animation->set_length(length);
- ap->add_animation(name, animation);
+ Ref<AnimationLibrary> library;
+ if (!ap->has_animation_library("")) {
+ library.instantiate();
+ ap->add_animation_library("", library);
+ } else {
+ library = ap->get_animation_library("");
+ }
+ library->add_animation(name, animation);
}
void GLTFDocument::_convert_mesh_instances(Ref<GLTFState> state) {
@@ -6588,9 +6593,9 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
}
}
-Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, FileAccess *f, int p_bake_fps) {
+Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps) {
Error err;
- if (!f) {
+ if (f.is_null()) {
return FAILED;
}
f->seek(0);
@@ -6614,7 +6619,6 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, FileAccess *f, i
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
state->json = json.get_data();
}
- f->close();
if (!state->json.has("asset")) {
return ERR_PARSE_ERROR;
@@ -6703,8 +6707,8 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
if (p_path.to_lower().ends_with("glb")) {
err = _encode_buffer_glb(state, p_path);
ERR_FAIL_COND_V(err != OK, err);
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V(!f, FAILED);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(f.is_null(), FAILED);
String json = Variant(state->json).to_json_string();
@@ -6741,18 +6745,15 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
for (uint32_t pad_i = binary_data_length; pad_i < binary_chunk_length; pad_i++) {
f->store_8(0);
}
-
- f->close();
} else {
err = _encode_buffer_bins(state, p_path);
ERR_FAIL_COND_V(err != OK, err);
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V(!f, FAILED);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(f.is_null(), FAILED);
f->create(FileAccess::ACCESS_RESOURCES);
String json = Variant(state->json).to_json_string();
f->store_string(json);
- f->close();
}
return err;
}
@@ -6927,9 +6928,10 @@ Error GLTFDocument::append_from_buffer(PackedByteArray p_bytes, String p_base_pa
ERR_FAIL_COND_V(state.is_null(), FAILED);
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
Error err = FAILED;
- state->use_named_skin_binds =
- p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
- FileAccessMemory *file_access = memnew(FileAccessMemory);
+ state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
+
+ Ref<FileAccessMemory> file_access;
+ file_access.instantiate();
file_access->open_custom(p_bytes.ptr(), p_bytes.size());
err = _parse(state, p_base_path.get_base_dir(), file_access, p_bake_fps);
ERR_FAIL_COND_V(err != OK, FAILED);
@@ -7032,7 +7034,7 @@ Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint
r_state->filename = p_path.get_file().get_basename();
r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN);
ERR_FAIL_NULL_V(f, ERR_FILE_CANT_OPEN);
String base_path = p_base_path;
diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h
index 0b7664a616..19bc507a8d 100644
--- a/modules/gltf/gltf_document.h
+++ b/modules/gltf/gltf_document.h
@@ -196,7 +196,7 @@ private:
Ref<Texture2D> _get_texture(Ref<GLTFState> state,
const GLTFTextureIndex p_texture);
Error _parse_json(const String &p_path, Ref<GLTFState> state);
- Error _parse_glb(FileAccess *f, Ref<GLTFState> state);
+ Error _parse_glb(Ref<FileAccess> f, Ref<GLTFState> state);
void _compute_node_heights(Ref<GLTFState> state);
Error _parse_buffers(Ref<GLTFState> state, const String &p_base_path);
Error _parse_buffer_views(Ref<GLTFState> state);
@@ -457,7 +457,7 @@ public:
void _convert_animation(Ref<GLTFState> state, AnimationPlayer *ap,
String p_animation_track_name);
Error _serialize(Ref<GLTFState> state, const String &p_path);
- Error _parse(Ref<GLTFState> state, String p_path, FileAccess *f, int p_bake_fps);
+ Error _parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> f, int p_bake_fps);
};
#endif // GLTF_DOCUMENT_H
diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp
index 4166f92502..b656788a10 100644
--- a/modules/gltf/register_types.cpp
+++ b/modules/gltf/register_types.cpp
@@ -60,7 +60,7 @@
static void _editor_init() {
Ref<EditorSceneFormatImporterGLTF> import_gltf;
import_gltf.instantiate();
- ResourceImporterScene::get_singleton()->add_importer(import_gltf);
+ ResourceImporterScene::add_importer(import_gltf);
// Blend to glTF importer.
@@ -72,7 +72,7 @@ static void _editor_init() {
if (blend_enabled) {
Ref<EditorSceneFormatImporterBlend> importer;
importer.instantiate();
- ResourceImporterScene::get_singleton()->add_importer(importer);
+ ResourceImporterScene::add_importer(importer);
Ref<EditorFileSystemImportFormatSupportQueryBlend> blend_import_query;
blend_import_query.instantiate();
@@ -87,7 +87,7 @@ static void _editor_init() {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,
"filesystem/import/fbx/fbx2gltf_path", PROPERTY_HINT_GLOBAL_FILE));
if (fbx_enabled) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (fbx2gltf_path.is_empty()) {
WARN_PRINT("FBX file import is enabled, but no FBX2glTF path is configured. FBX files will not be imported.");
} else if (!da->file_exists(fbx2gltf_path)) {
@@ -95,7 +95,7 @@ static void _editor_init() {
} else {
Ref<EditorSceneFormatImporterFBX> importer;
importer.instantiate();
- ResourceImporterScene::get_singleton()->add_importer(importer);
+ ResourceImporterScene::add_importer(importer);
}
}
}
diff --git a/modules/hdr/image_loader_hdr.cpp b/modules/hdr/image_loader_hdr.cpp
index 996bbfadd1..eca689e87a 100644
--- a/modules/hdr/image_loader_hdr.cpp
+++ b/modules/hdr/image_loader_hdr.cpp
@@ -33,7 +33,7 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
-Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
+Error ImageLoaderHDR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
String header = f->get_token();
ERR_FAIL_COND_V_MSG(header != "#?RADIANCE" && header != "#?RGBE", ERR_FILE_UNRECOGNIZED, "Unsupported header information in HDR: " + header + ".");
@@ -132,7 +132,7 @@ Error ImageLoaderHDR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
ptr[2] * exp / 255.0);
if (p_force_linear) {
- c = c.to_linear();
+ c = c.srgb_to_linear();
}
*(uint32_t *)ptr = c.to_rgbe9995();
diff --git a/modules/hdr/image_loader_hdr.h b/modules/hdr/image_loader_hdr.h
index 0213fdbcb2..f2d53cc206 100644
--- a/modules/hdr/image_loader_hdr.h
+++ b/modules/hdr/image_loader_hdr.h
@@ -35,7 +35,7 @@
class ImageLoaderHDR : public ImageFormatLoader {
public:
- virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderHDR();
};
diff --git a/modules/jpg/image_loader_jpegd.cpp b/modules/jpg/image_loader_jpegd.cpp
index e8c66ab9da..51358876a4 100644
--- a/modules/jpg/image_loader_jpegd.cpp
+++ b/modules/jpg/image_loader_jpegd.cpp
@@ -103,7 +103,7 @@ Error jpeg_load_image_from_buffer(Image *p_image, const uint8_t *p_buffer, int p
return OK;
}
-Error ImageLoaderJPG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
+Error ImageLoaderJPG::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
@@ -113,8 +113,6 @@ Error ImageLoaderJPG::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
f->get_buffer(&w[0], src_image_len);
- f->close();
-
Error err = jpeg_load_image_from_buffer(p_image.ptr(), w, src_image_len);
return err;
diff --git a/modules/jpg/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h
index 8e64f6fba7..de9700faec 100644
--- a/modules/jpg/image_loader_jpegd.h
+++ b/modules/jpg/image_loader_jpegd.h
@@ -35,7 +35,7 @@
class ImageLoaderJPG : public ImageFormatLoader {
public:
- virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderJPG();
};
diff --git a/modules/mbedtls/crypto_mbedtls.cpp b/modules/mbedtls/crypto_mbedtls.cpp
index ea6b6d8233..e62581ab40 100644
--- a/modules/mbedtls/crypto_mbedtls.cpp
+++ b/modules/mbedtls/crypto_mbedtls.cpp
@@ -55,14 +55,13 @@ Error CryptoKeyMbedTLS::load(String p_path, bool p_public_only) {
ERR_FAIL_COND_V_MSG(locks, ERR_ALREADY_IN_USE, "Key is in use");
PackedByteArray out;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open CryptoKeyMbedTLS file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_INVALID_PARAMETER, "Cannot open CryptoKeyMbedTLS file '" + p_path + "'.");
uint64_t flen = f->get_length();
out.resize(flen + 1);
f->get_buffer(out.ptrw(), flen);
out.write[flen] = 0; // string terminator
- memdelete(f);
int ret = 0;
if (p_public_only) {
@@ -79,8 +78,8 @@ Error CryptoKeyMbedTLS::load(String p_path, bool p_public_only) {
}
Error CryptoKeyMbedTLS::save(String p_path, bool p_public_only) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot save CryptoKeyMbedTLS file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_INVALID_PARAMETER, "Cannot save CryptoKeyMbedTLS file '" + p_path + "'.");
unsigned char w[16000];
memset(w, 0, sizeof(w));
@@ -92,14 +91,12 @@ Error CryptoKeyMbedTLS::save(String p_path, bool p_public_only) {
ret = mbedtls_pk_write_key_pem(&pkey, w, sizeof(w));
}
if (ret != 0) {
- memdelete(f);
mbedtls_platform_zeroize(w, sizeof(w)); // Zeroize anything we might have written.
ERR_FAIL_V_MSG(FAILED, "Error writing key '" + itos(ret) + "'.");
}
size_t len = strlen((char *)w);
f->store_buffer(w, len);
- memdelete(f);
mbedtls_platform_zeroize(w, sizeof(w)); // Zeroize temporary buffer.
return OK;
}
@@ -143,14 +140,13 @@ Error X509CertificateMbedTLS::load(String p_path) {
ERR_FAIL_COND_V_MSG(locks, ERR_ALREADY_IN_USE, "Certificate is in use");
PackedByteArray out;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot open X509CertificateMbedTLS file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_INVALID_PARAMETER, "Cannot open X509CertificateMbedTLS file '" + p_path + "'.");
uint64_t flen = f->get_length();
out.resize(flen + 1);
f->get_buffer(out.ptrw(), flen);
out.write[flen] = 0; // string terminator
- memdelete(f);
int ret = mbedtls_x509_crt_parse(&cert, out.ptr(), out.size());
ERR_FAIL_COND_V_MSG(ret, FAILED, "Error parsing some certificates: " + itos(ret));
@@ -167,8 +163,8 @@ Error X509CertificateMbedTLS::load_from_memory(const uint8_t *p_buffer, int p_le
}
Error X509CertificateMbedTLS::save(String p_path) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!f, ERR_INVALID_PARAMETER, "Cannot save X509CertificateMbedTLS file '" + p_path + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_INVALID_PARAMETER, "Cannot save X509CertificateMbedTLS file '" + p_path + "'.");
mbedtls_x509_crt *crt = &cert;
while (crt) {
@@ -176,14 +172,12 @@ Error X509CertificateMbedTLS::save(String p_path) {
size_t wrote = 0;
int ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT, cert.raw.p, cert.raw.len, w, sizeof(w), &wrote);
if (ret != 0 || wrote == 0) {
- memdelete(f);
ERR_FAIL_V_MSG(FAILED, "Error writing certificate '" + itos(ret) + "'.");
}
f->store_buffer(w, wrote - 1); // don't write the string terminator
crt = crt->next;
}
- memdelete(f);
return OK;
}
diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp
index 0e0da806bf..6cd710e792 100644
--- a/modules/minimp3/resource_importer_mp3.cpp
+++ b/modules/minimp3/resource_importer_mp3.cpp
@@ -75,9 +75,8 @@ Error ResourceImporterMP3::import(const String &p_source_file, const String &p_s
bool loop = p_options["loop"];
float loop_offset = p_options["loop_offset"];
- FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ);
-
- ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
+ Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
+ ERR_FAIL_COND_V(f.is_null(), ERR_CANT_OPEN);
uint64_t len = f->get_length();
@@ -87,8 +86,6 @@ Error ResourceImporterMP3::import(const String &p_source_file, const String &p_s
f->get_buffer(w, len);
- memdelete(f);
-
Ref<AudioStreamMP3> mp3_stream;
mp3_stream.instantiate();
diff --git a/modules/mono/class_db_api_json.cpp b/modules/mono/class_db_api_json.cpp
index 5884a24454..9253f105bb 100644
--- a/modules/mono/class_db_api_json.cpp
+++ b/modules/mono/class_db_api_json.cpp
@@ -238,11 +238,10 @@ void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
}
}
- FileAccessRef f = FileAccess::open(p_output_file, FileAccess::WRITE);
- ERR_FAIL_COND_MSG(!f, "Cannot open file '" + p_output_file + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_output_file, FileAccess::WRITE);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file '" + p_output_file + "'.");
JSON json;
f->store_string(json.stringify(classes_dict, "\t"));
- f->close();
print_line(String() + "ClassDB API JSON written to: " + ProjectSettings::get_singleton()->globalize_path(p_output_file));
}
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 8acd119880..02aebb3805 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -3641,20 +3641,18 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r
}
#endif
- Error err;
- FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'.");
+ {
+ Error err;
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'.");
- file->store_string(source);
+ file->store_string(source);
- if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
- memdelete(file);
- return ERR_CANT_CREATE;
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ return ERR_CANT_CREATE;
+ }
}
- file->close();
- memdelete(file);
-
#ifdef TOOLS_ENABLED
if (ScriptServer::is_reload_scripts_on_save_enabled()) {
CSharpLanguage::get_singleton()->reload_tool_script(p_resource, false);
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index d8f5b814e4..2a93c15282 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -1035,8 +1035,8 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) {
Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED);
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE);
if (!DirAccess::exists(p_proj_dir)) {
Error err = da->make_dir_recursive(p_proj_dir);
@@ -1170,8 +1170,8 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir) {
Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir) {
ERR_FAIL_COND_V(!initialized, ERR_UNCONFIGURED);
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE);
if (!DirAccess::exists(p_proj_dir)) {
Error err = da->make_dir_recursive(p_proj_dir);
@@ -1280,8 +1280,8 @@ Error BindingsGenerator::generate_cs_api(const String &p_output_dir) {
String output_dir = path::abspath(path::realpath(p_output_dir));
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(da.is_null(), ERR_CANT_CREATE);
if (!DirAccess::exists(output_dir)) {
Error err = da->make_dir_recursive(output_dir);
@@ -2255,12 +2255,10 @@ uint32_t BindingsGenerator::get_version() {
}
Error BindingsGenerator::_save_file(const String &p_path, const StringBuilder &p_content) {
- FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE);
-
- ERR_FAIL_COND_V_MSG(!file, ERR_FILE_CANT_WRITE, "Cannot open file: '" + p_path + "'.");
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(file.is_null(), ERR_FILE_CANT_WRITE, "Cannot open file: '" + p_path + "'.");
file->store_string(p_content.as_string());
- file->close();
return OK;
}
diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp
index 3a41b3f6f5..79015686c3 100644
--- a/modules/mono/editor/code_completion.cpp
+++ b/modules/mono/editor/code_completion.cpp
@@ -144,7 +144,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
}
} break;
case CompletionKind::SCENE_PATHS: {
- DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
List<String> directories;
directories.push_back(dir_access->get_current_dir());
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
index 7c2cb2e260..cb2b60fcce 100644
--- a/modules/mono/godotsharp_dirs.cpp
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -76,7 +76,7 @@ String _get_mono_user_dir() {
exe_dir = exe_dir.plus_file("../../..").simplify_path();
}
- DirAccessRef d = DirAccess::create_for_path(exe_dir);
+ Ref<DirAccess> d = DirAccess::create_for_path(exe_dir);
if (d->file_exists("._sc_") || d->file_exists("_sc_")) {
// contain yourself
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 424b74906f..e98ce8f6c1 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -643,7 +643,7 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const
// Create destination directory if needed
if (!DirAccess::exists(dst_dir)) {
- DirAccessRef da = DirAccess::create_for_path(dst_dir);
+ Ref<DirAccess> da = DirAccess::create_for_path(dst_dir);
Error err = da->make_dir_recursive(dst_dir);
if (err != OK) {
@@ -652,7 +652,7 @@ bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const
}
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String xml_file = assembly_name + ".xml";
if (da->copy(src_dir.plus_file(xml_file), dst_dir.plus_file(xml_file)) != OK) {
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
index 01a6521876..6ea3c5539e 100644
--- a/modules/mono/mono_gd/gd_mono_log.cpp
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -77,23 +77,20 @@ static String make_text(const char *log_domain, const char *log_level, const cha
}
void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *) {
- FileAccess *f = GDMonoLog::get_singleton()->log_file;
-
if (GDMonoLog::get_singleton()->log_level_id >= get_log_level_id(log_level)) {
String text = make_text(log_domain, log_level, message);
text += "\n";
- f->seek_end();
- f->store_string(text);
+ GDMonoLog::get_singleton()->log_file->seek_end();
+ GDMonoLog::get_singleton()->log_file->store_string(text);
}
if (fatal) {
String text = make_text(log_domain, log_level, message);
ERR_PRINT("Mono: FATAL ERROR '" + text + "', ABORTING! Logfile: '" + GDMonoLog::get_singleton()->log_file_path + "'.");
// Make sure to flush before aborting
- f->flush();
- f->close();
- memdelete(f);
+ GDMonoLog::get_singleton()->log_file->flush();
+ GDMonoLog::get_singleton()->log_file.unref();
abort();
}
@@ -101,8 +98,8 @@ void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level,
bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) {
if (!DirAccess::exists(p_logs_dir)) {
- DirAccessRef diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V(!diraccess, false);
+ Ref<DirAccess> diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(diraccess.is_null(), false);
Error logs_mkdir_err = diraccess->make_dir_recursive(p_logs_dir);
ERR_FAIL_COND_V_MSG(logs_mkdir_err != OK, false, "Failed to create mono logs directory.");
}
@@ -113,8 +110,8 @@ bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) {
void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) {
static const uint64_t MAX_SECS = 5 * 86400; // 5 days
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND(!da);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND(da.is_null());
Error err = da->change_dir(p_logs_dir);
ERR_FAIL_COND_MSG(err != OK, "Cannot change directory to '" + p_logs_dir + "'.");
@@ -170,7 +167,7 @@ void GDMonoLog::initialize() {
log_file_path = logs_dir.plus_file(log_file_name);
log_file = FileAccess::open(log_file_path, FileAccess::WRITE);
- if (!log_file) {
+ if (log_file.is_null()) {
ERR_PRINT("Mono: Cannot create log file at: " + log_file_path);
}
}
@@ -178,7 +175,7 @@ void GDMonoLog::initialize() {
mono_trace_set_level_string(log_level.get_data());
log_level_id = get_log_level_id(log_level.get_data());
- if (log_file) {
+ if (log_file.is_valid()) {
OS::get_singleton()->print("Mono: Log file is: '%s'\n", log_file_path.utf8().get_data());
mono_trace_set_log_handler(mono_log_callback, this);
} else {
@@ -192,11 +189,6 @@ GDMonoLog::GDMonoLog() {
GDMonoLog::~GDMonoLog() {
singleton = nullptr;
-
- if (log_file) {
- log_file->close();
- memdelete(log_file);
- }
}
#else
diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h
index 9aa67a09e2..9fc35f8e31 100644
--- a/modules/mono/mono_gd/gd_mono_log.h
+++ b/modules/mono/mono_gd/gd_mono_log.h
@@ -48,7 +48,7 @@ class GDMonoLog {
#ifdef GD_MONO_LOG_ENABLED
int log_level_id = -1;
- FileAccess *log_file = nullptr;
+ Ref<FileAccess> log_file;
String log_file_path;
bool _try_create_logs_dir(const String &p_logs_dir);
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
index dd29299330..e6975611d2 100644
--- a/modules/mono/utils/string_utils.cpp
+++ b/modules/mono/utils/string_utils.cpp
@@ -167,15 +167,13 @@ String escape_csharp_keyword(const String &p_name) {
Error read_all_file_utf8(const String &p_path, String &r_content) {
Vector<uint8_t> sourcef;
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot open file '" + p_path + "'.");
uint64_t len = f->get_length();
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
uint64_t r = f->get_buffer(w, len);
- f->close();
- memdelete(f);
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
w[len] = 0;
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 70d50999f9..217e503d82 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -226,6 +226,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
navigation_polys.push_back(np);
to_visit.clear();
to_visit.push_back(0);
+ least_cost_id = 0;
reachable_end = nullptr;
@@ -245,6 +246,8 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
}
}
+ ERR_BREAK(least_cost_id == -1);
+
// Stores the further reachable end polygon, in case our goal is not reachable.
if (is_reachable) {
float d = navigation_polys[least_cost_id].entry.distance_to(p_destination);
@@ -254,8 +257,6 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
}
}
- ERR_BREAK(least_cost_id == -1);
-
// Check if we reached the end
if (navigation_polys[least_cost_id].poly == end_poly) {
found_route = true;
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index 61c3cefc7a..9e2daf3a99 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -124,6 +124,28 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform
}
}
+void NavigationMeshGenerator::_add_mesh_array(const Array &p_array, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices) {
+ Vector<Vector3> mesh_vertices = p_array[Mesh::ARRAY_VERTEX];
+ const Vector3 *vr = mesh_vertices.ptr();
+
+ Vector<int> mesh_indices = p_array[Mesh::ARRAY_INDEX];
+ const int *ir = mesh_indices.ptr();
+
+ const int face_count = mesh_indices.size() / 3;
+ const int current_vertex_count = p_vertices.size() / 3;
+
+ for (int j = 0; j < mesh_vertices.size(); j++) {
+ _add_vertex(p_xform.xform(vr[j]), p_vertices);
+ }
+
+ for (int j = 0; j < face_count; j++) {
+ // CCW
+ p_indices.push_back(current_vertex_count + (ir[j * 3 + 0]));
+ p_indices.push_back(current_vertex_count + (ir[j * 3 + 2]));
+ p_indices.push_back(current_vertex_count + (ir[j * 3 + 1]));
+ }
+}
+
void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices) {
int face_count = p_faces.size() / 3;
int current_vertex_count = p_vertices.size() / 3;
@@ -187,43 +209,38 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
Transform3D transform = p_navmesh_transform * static_body->get_global_transform() * col_shape->get_transform();
- Ref<Mesh> mesh;
Ref<Shape3D> s = col_shape->get_shape();
BoxShape3D *box = Object::cast_to<BoxShape3D>(*s);
if (box) {
- Ref<BoxMesh> box_mesh;
- box_mesh.instantiate();
- box_mesh->set_size(box->get_size());
- mesh = box_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ BoxMesh::create_mesh_array(arr, box->get_size());
+ _add_mesh_array(arr, transform, p_vertices, p_indices);
}
CapsuleShape3D *capsule = Object::cast_to<CapsuleShape3D>(*s);
if (capsule) {
- Ref<CapsuleMesh> capsule_mesh;
- capsule_mesh.instantiate();
- capsule_mesh->set_radius(capsule->get_radius());
- capsule_mesh->set_height(capsule->get_height());
- mesh = capsule_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ CapsuleMesh::create_mesh_array(arr, capsule->get_radius(), capsule->get_height());
+ _add_mesh_array(arr, transform, p_vertices, p_indices);
}
CylinderShape3D *cylinder = Object::cast_to<CylinderShape3D>(*s);
if (cylinder) {
- Ref<CylinderMesh> cylinder_mesh;
- cylinder_mesh.instantiate();
- cylinder_mesh->set_height(cylinder->get_height());
- cylinder_mesh->set_bottom_radius(cylinder->get_radius());
- cylinder_mesh->set_top_radius(cylinder->get_radius());
- mesh = cylinder_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ CylinderMesh::create_mesh_array(arr, cylinder->get_radius(), cylinder->get_radius(), cylinder->get_height());
+ _add_mesh_array(arr, transform, p_vertices, p_indices);
}
SphereShape3D *sphere = Object::cast_to<SphereShape3D>(*s);
if (sphere) {
- Ref<SphereMesh> sphere_mesh;
- sphere_mesh.instantiate();
- sphere_mesh->set_radius(sphere->get_radius());
- sphere_mesh->set_height(sphere->get_radius() * 2.0);
- mesh = sphere_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ SphereMesh::create_mesh_array(arr, sphere->get_radius(), sphere->get_radius() * 2.0);
+ _add_mesh_array(arr, transform, p_vertices, p_indices);
}
ConcavePolygonShape3D *concave_polygon = Object::cast_to<ConcavePolygonShape3D>(*s);
@@ -254,10 +271,6 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
_add_faces(faces, transform, p_vertices, p_indices);
}
}
-
- if (mesh.is_valid()) {
- _add_mesh(mesh, transform, p_vertices, p_indices);
- }
}
}
}
@@ -284,44 +297,39 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
RID shape = shapes[i + 1];
PhysicsServer3D::ShapeType type = PhysicsServer3D::get_singleton()->shape_get_type(shape);
Variant data = PhysicsServer3D::get_singleton()->shape_get_data(shape);
- Ref<Mesh> mesh;
switch (type) {
case PhysicsServer3D::SHAPE_SPHERE: {
real_t radius = data;
- Ref<SphereMesh> sphere_mesh;
- sphere_mesh.instantiate();
- sphere_mesh->set_radius(radius);
- sphere_mesh->set_height(radius * 2.0);
- mesh = sphere_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ SphereMesh::create_mesh_array(arr, radius, radius * 2.0);
+ _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
} break;
case PhysicsServer3D::SHAPE_BOX: {
Vector3 extents = data;
- Ref<BoxMesh> box_mesh;
- box_mesh.instantiate();
- box_mesh->set_size(2.0 * extents);
- mesh = box_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ BoxMesh::create_mesh_array(arr, extents * 2.0);
+ _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
} break;
case PhysicsServer3D::SHAPE_CAPSULE: {
Dictionary dict = data;
real_t radius = dict["radius"];
real_t height = dict["height"];
- Ref<CapsuleMesh> capsule_mesh;
- capsule_mesh.instantiate();
- capsule_mesh->set_radius(radius);
- capsule_mesh->set_height(height);
- mesh = capsule_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ CapsuleMesh::create_mesh_array(arr, radius, height);
+ _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
} break;
case PhysicsServer3D::SHAPE_CYLINDER: {
Dictionary dict = data;
real_t radius = dict["radius"];
real_t height = dict["height"];
- Ref<CylinderMesh> cylinder_mesh;
- cylinder_mesh.instantiate();
- cylinder_mesh->set_height(height);
- cylinder_mesh->set_bottom_radius(radius);
- cylinder_mesh->set_top_radius(radius);
- mesh = cylinder_mesh;
+ Array arr;
+ arr.resize(RS::ARRAY_MAX);
+ CylinderMesh::create_mesh_array(arr, radius, radius, height);
+ _add_mesh_array(arr, shapes[i], p_vertices, p_indices);
} break;
case PhysicsServer3D::SHAPE_CONVEX_POLYGON: {
PackedVector3Array vertices = data;
@@ -354,10 +362,6 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
WARN_PRINT("Unsupported collision shape type.");
} break;
}
-
- if (mesh.is_valid()) {
- _add_mesh(mesh, shapes[i], p_vertices, p_indices);
- }
}
}
}
diff --git a/modules/navigation/navigation_mesh_generator.h b/modules/navigation/navigation_mesh_generator.h
index 21f7a4941b..8cc1531b53 100644
--- a/modules/navigation/navigation_mesh_generator.h
+++ b/modules/navigation/navigation_mesh_generator.h
@@ -51,6 +51,7 @@ protected:
static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_vertices);
static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
+ static void _add_mesh_array(const Array &p_array, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _add_faces(const PackedVector3Array &p_faces, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _parse_geometry(const Transform3D &p_navmesh_transform, Node *p_node, Vector<float> &p_vertices, Vector<int> &p_indices, NavigationMesh::ParsedGeometryType p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);
diff --git a/modules/noise/fastnoise_lite.cpp b/modules/noise/fastnoise_lite.cpp
index 974b5c55bb..9497fe6a7e 100644
--- a/modules/noise/fastnoise_lite.cpp
+++ b/modules/noise/fastnoise_lite.cpp
@@ -445,7 +445,7 @@ void FastNoiseLite::_bind_methods() {
ADD_GROUP("Fractal", "fractal_");
ClassDB::bind_method(D_METHOD("set_fractal_type", "type"), &FastNoiseLite::set_fractal_type);
ClassDB::bind_method(D_METHOD("get_fractal_type"), &FastNoiseLite::get_fractal_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_type", PROPERTY_HINT_ENUM, "None,FBM,Ridged,PingPong"), "set_fractal_type", "get_fractal_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "fractal_type", PROPERTY_HINT_ENUM, "None,FBM,Ridged,Ping-Pong"), "set_fractal_type", "get_fractal_type");
ClassDB::bind_method(D_METHOD("set_fractal_octaves", "octave_count"), &FastNoiseLite::set_fractal_octaves);
ClassDB::bind_method(D_METHOD("get_fractal_octaves"), &FastNoiseLite::get_fractal_octaves);
@@ -472,7 +472,7 @@ void FastNoiseLite::_bind_methods() {
ADD_GROUP("Cellular", "cellular_");
ClassDB::bind_method(D_METHOD("set_cellular_distance_function", "func"), &FastNoiseLite::set_cellular_distance_function);
ClassDB::bind_method(D_METHOD("get_cellular_distance_function"), &FastNoiseLite::get_cellular_distance_function);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_distance_function", PROPERTY_HINT_ENUM, "Euclidean,EuclideanSquared,Manhattan,Hybrid"), "set_cellular_distance_function", "get_cellular_distance_function");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_distance_function", PROPERTY_HINT_ENUM, "Euclidean,Euclidean Squared,Manhattan,Hybrid"), "set_cellular_distance_function", "get_cellular_distance_function");
ClassDB::bind_method(D_METHOD("set_cellular_jitter", "jitter"), &FastNoiseLite::set_cellular_jitter);
ClassDB::bind_method(D_METHOD("get_cellular_jitter"), &FastNoiseLite::get_cellular_jitter);
@@ -480,7 +480,7 @@ void FastNoiseLite::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_cellular_return_type", "ret"), &FastNoiseLite::set_cellular_return_type);
ClassDB::bind_method(D_METHOD("get_cellular_return_type"), &FastNoiseLite::get_cellular_return_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_return_type", PROPERTY_HINT_ENUM, "CellValue,Distance,Distance2,Distance2Add,Distance2Sub,Distance2Mul,Distance2Div"), "set_cellular_return_type", "get_cellular_return_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "cellular_return_type", PROPERTY_HINT_ENUM, "Cell Value,Distance,Distance2,Distance2Add,Distance2Sub,Distance2Mul,Distance2Div"), "set_cellular_return_type", "get_cellular_return_type");
// Domain warp.
@@ -492,7 +492,7 @@ void FastNoiseLite::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_domain_warp_type", "domain_warp_type"), &FastNoiseLite::set_domain_warp_type);
ClassDB::bind_method(D_METHOD("get_domain_warp_type"), &FastNoiseLite::get_domain_warp_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_type", PROPERTY_HINT_ENUM, "Simplex,SimplexReduced,BasicGrid"), "set_domain_warp_type", "get_domain_warp_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "domain_warp_type", PROPERTY_HINT_ENUM, "Simplex,Simplex Reduced,Basic Grid"), "set_domain_warp_type", "get_domain_warp_type");
ClassDB::bind_method(D_METHOD("set_domain_warp_amplitude", "domain_warp_amplitude"), &FastNoiseLite::set_domain_warp_amplitude);
ClassDB::bind_method(D_METHOD("get_domain_warp_amplitude"), &FastNoiseLite::get_domain_warp_amplitude);
diff --git a/modules/openxr/action_map/openxr_action_map.cpp b/modules/openxr/action_map/openxr_action_map.cpp
index 1ea1346f61..2ba33419d7 100644
--- a/modules/openxr/action_map/openxr_action_map.cpp
+++ b/modules/openxr/action_map/openxr_action_map.cpp
@@ -226,27 +226,6 @@ void OpenXRActionMap::create_default_action_sets() {
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
add_interaction_profile(profile);
- // Create our HP MR controller profile
- profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/hp/mixed_reality_controller");
- profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
- profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
- profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
- // hpmr controllers have no select button we can use
- profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
- // hpmr controllers only register click, not touch, on our a/b/x/y buttons
- profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand
- profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand
- profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
- profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
- profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
- profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
- // primary on our hpmr controller is our thumbstick
- profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
- profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
- // No secondary on our hpmr controller
- profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
- add_interaction_profile(profile);
-
// Create our Meta touch controller profile
profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/oculus/touch_controller");
profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
@@ -297,6 +276,116 @@ void OpenXRActionMap::create_default_action_sets() {
profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
add_interaction_profile(profile);
+
+ // Note, the following profiles are all part of extensions.
+ // We include these regardless of whether the extension is active.
+ // We want our action map to be as complete as possible so our game is as portable as possible.
+ // It is very possible these will in due time become core.
+
+ // Create our HP MR controller profile
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/hp/mixed_reality_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ // hpmr controllers have no select button we can use
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
+ // hpmr controllers only register click, not touch, on our a/b/x/y buttons
+ profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand
+ profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/value,/user/hand/right/input/squeeze/value");
+ // primary on our hpmr controller is our thumbstick
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ // No secondary on our hpmr controller
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our Samsung Odyssey controller profile,
+ // Note that this controller is only identified specifically on WMR, on SteamVR this is identified as a normal WMR controller.
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/samsung/odyssey_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ // Odyssey controllers have no select button we can use
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click,/user/hand/right/input/menu/click");
+ // Odyssey controller has no a/b/x/y buttons
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ // primary on our Odyssey controller is our thumbstick, no touch
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ // secondary on our Odyssey controller is our trackpad
+ profile->add_new_binding(secondary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
+ profile->add_new_binding(secondary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
+ profile->add_new_binding(secondary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our Vive Cosmos controller
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_cosmos_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
+ profile->add_new_binding(select_button, "/user/hand/left/input/system/click"); // we'll map system to select
+ profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand
+ profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ // primary on our Cosmos controller is our thumbstick
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
+ // No secondary on our cosmos controller
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our Vive Focus 3 controller
+ // Note, Vive Focus 3 currently is not yet supported as a stand alone device
+ // however HTC currently has a beta OpenXR runtime in testing we may support in the near future
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/htc/vive_focus3_controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(menu_button, "/user/hand/left/input/menu/click");
+ profile->add_new_binding(select_button, "/user/hand/left/input/system/click"); // we'll map system to select
+ profile->add_new_binding(ax_button, "/user/hand/left/input/x/click,/user/hand/right/input/a/click"); // x on left hand, a on right hand
+ profile->add_new_binding(by_button, "/user/hand/left/input/y/click,/user/hand/right/input/b/click"); // y on left hand, b on right hand
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
+ profile->add_new_binding(trigger_touch, "/user/hand/left/input/trigger/touch,/user/hand/right/input/trigger/touch");
+ profile->add_new_binding(grip, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ profile->add_new_binding(grip_click, "/user/hand/left/input/squeeze/click,/user/hand/right/input/squeeze/click");
+ // primary on our Focus 3 controller is our thumbstick
+ profile->add_new_binding(primary, "/user/hand/left/input/thumbstick,/user/hand/right/input/thumbstick");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/thumbstick/click,/user/hand/right/input/thumbstick/click");
+ profile->add_new_binding(primary_touch, "/user/hand/left/input/thumbstick/touch,/user/hand/right/input/thumbstick/touch");
+ // We only have a thumb rest
+ profile->add_new_binding(secondary_touch, "/user/hand/left/input/thumbrest/touch,/user/hand/right/input/thumbrest/touch");
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
+
+ // Create our Huawei controller
+ profile = OpenXRInteractionProfile::new_profile("/interaction_profiles/huawei/controller");
+ profile->add_new_binding(default_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(aim_pose, "/user/hand/left/input/aim/pose,/user/hand/right/input/aim/pose");
+ profile->add_new_binding(grip_pose, "/user/hand/left/input/grip/pose,/user/hand/right/input/grip/pose");
+ profile->add_new_binding(menu_button, "/user/hand/left/input/home/click,/user/hand/right/input/home/click");
+ profile->add_new_binding(trigger, "/user/hand/left/input/trigger/value,/user/hand/right/input/trigger/value");
+ profile->add_new_binding(trigger_click, "/user/hand/left/input/trigger/click,/user/hand/right/input/trigger/click");
+ // primary on our Huawei controller is our trackpad
+ profile->add_new_binding(primary, "/user/hand/left/input/trackpad,/user/hand/right/input/trackpad");
+ profile->add_new_binding(primary_click, "/user/hand/left/input/trackpad/click,/user/hand/right/input/trackpad/click");
+ profile->add_new_binding(primary_touch, "/user/hand/left/input/trackpad/touch,/user/hand/right/input/trackpad/touch");
+ profile->add_new_binding(haptic, "/user/hand/left/output/haptic,/user/hand/right/output/haptic");
+ add_interaction_profile(profile);
}
void OpenXRActionMap::create_editor_action_sets() {
diff --git a/modules/openxr/action_map/openxr_defs.cpp b/modules/openxr/action_map/openxr_defs.cpp
index 3358b03276..e10326449c 100644
--- a/modules/openxr/action_map/openxr_defs.cpp
+++ b/modules/openxr/action_map/openxr_defs.cpp
@@ -234,6 +234,150 @@ OpenXRDefs::IOPath OpenXRDefs::index_io_paths[] = {
{ "Haptic output", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/output/haptic", OpenXRAction::OPENXR_ACTION_HAPTIC },
};
+// Samsung odyssey controller
+OpenXRDefs::IOPath OpenXRDefs::odyssey_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 },
+};
+
+// Vive Cosmos controller
+OpenXRDefs::IOPath OpenXRDefs::vive_cosmos_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 },
+ { "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 },
+
+ { "Shoulder click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/right/input/shoulder/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Shoulder click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/shoulder/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 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 },
+};
+
+// Vive Focus 3 controller
+OpenXRDefs::IOPath OpenXRDefs::vive_focus3_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 },
+ { "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 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 click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Squeeze touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/squeeze/touch", 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 },
+ { "Squeeze touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/squeeze/touch", 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 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 },
+
+ { "Thumbrest touch", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/thumbrest/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 },
+};
+
+// Huawei controller
+OpenXRDefs::IOPath OpenXRDefs::huawei_controller_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 },
+
+ { "Home click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/home/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Home click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/home/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Back click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/back/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Back click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/back/click", OpenXRAction::OPENXR_ACTION_BOOL },
+
+ { "Volume up click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/volume_up/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Volume up click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/volume_up/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Volume down click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_LEFT_HAND], "/user/hand/left/input/volume_down/click", OpenXRAction::OPENXR_ACTION_BOOL },
+ { "Volume down click", &OpenXRDefs::available_top_level_paths[OpenXRDefs::OPENXR_RIGHT_HAND], "/user/hand/right/input/volume_down/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 },
+
+ { "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 },
+};
+
OpenXRDefs::InteractionProfile OpenXRDefs::available_interaction_profiles[] = {
{
"Simple controller", // display_name
@@ -271,6 +415,30 @@ OpenXRDefs::InteractionProfile OpenXRDefs::available_interaction_profiles[] = {
index_io_paths, // io_paths
sizeof(index_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
},
+ {
+ "Samsung Odyssey controller", // display_name
+ "/interaction_profiles/samsung/odyssey_controller", // openxr_path
+ odyssey_io_paths, // io_paths
+ sizeof(odyssey_io_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "Vive Cosmos controller", // display_name
+ "/interaction_profiles/htc/vive_cosmos_controller", // openxr_path
+ vive_cosmos_paths, // io_paths
+ sizeof(vive_cosmos_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "Vive Focus 3 controller", // display_name
+ "/interaction_profiles/htc/vive_focus3_controller", // openxr_path
+ vive_focus3_paths, // io_paths
+ sizeof(vive_focus3_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
+ {
+ "Huawei controller", // display_name
+ "/interaction_profiles/huawei/controller", // openxr_path
+ huawei_controller_paths, // io_paths
+ sizeof(huawei_controller_paths) / sizeof(OpenXRDefs::IOPath) // io_path_count
+ },
};
int OpenXRDefs::available_interaction_profile_count = sizeof(OpenXRDefs::available_interaction_profiles) / sizeof(OpenXRDefs::InteractionProfile);
diff --git a/modules/openxr/action_map/openxr_defs.h b/modules/openxr/action_map/openxr_defs.h
index aa3b2a8f8a..dbda4757f1 100644
--- a/modules/openxr/action_map/openxr_defs.h
+++ b/modules/openxr/action_map/openxr_defs.h
@@ -85,6 +85,10 @@ private:
static IOPath hpmr_io_paths[];
static IOPath touch_io_paths[];
static IOPath index_io_paths[];
+ static IOPath odyssey_io_paths[];
+ static IOPath vive_cosmos_paths[];
+ static IOPath vive_focus3_paths[];
+ static IOPath huawei_controller_paths[];
static InteractionProfile available_interaction_profiles[];
static int available_interaction_profile_count;
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
index 669cc694f2..24ac5494dd 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
@@ -209,6 +209,8 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
}
void OpenXRInteractionProfileEditor::_update_interaction_profile() {
+ ERR_FAIL_NULL(profile_def);
+
// out with the old...
while (main_hb->get_child_count() > 0) {
memdelete(main_hb->get_child(0));
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index 00f81731c2..f3064041b8 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -40,6 +40,7 @@
#include <openxr/openxr.h>
class OpenXRAPI;
+class OpenXRActionMap;
class OpenXRExtensionWrapper {
protected:
diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp
index 8736296f7a..1eb7635a82 100644
--- a/modules/openxr/extensions/openxr_vulkan_extension.cpp
+++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp
@@ -34,6 +34,7 @@
#include "../openxr_api.h"
#include "../openxr_util.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering_server.h"
@@ -439,7 +440,7 @@ bool OpenXRVulkanExtension::copy_render_target_to_image(RID p_from_render_target
ERR_FAIL_COND_V(p_from_render_target.is_null(), false);
ERR_FAIL_NULL_V(RendererStorageRD::base_singleton, false);
- RID source_image = RendererStorageRD::base_singleton->render_target_get_rd_texture(p_from_render_target);
+ RID source_image = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(p_from_render_target);
ERR_FAIL_COND_V(source_image.is_null(), false);
RID depth_image; // TODO implement
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 861038be33..ae3617938e 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -172,11 +172,18 @@ bool OpenXRAPI::load_supported_extensions() {
bool OpenXRAPI::is_extension_supported(const char *p_extension) const {
for (uint32_t i = 0; i < num_supported_extensions; i++) {
- if (strcmp(supported_extensions[i].extensionName, p_extension)) {
+ if (strcmp(supported_extensions[i].extensionName, p_extension) == 0) {
+#ifdef DEBUG
+ print_line("OpenXR: requested extension", p_extension, "is supported");
+#endif
return true;
}
}
+#ifdef DEBUG
+ print_line("OpenXR: requested extension", p_extension, "is not supported");
+#endif
+
return false;
}
@@ -207,6 +214,14 @@ bool OpenXRAPI::create_instance() {
}
}
+ // Add optional extensions for controllers that may be supported.
+ // Overkill to create extension classes for this.
+ requested_extensions[XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME] = &ext_hp_mixed_reality_available;
+ requested_extensions[XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME] = &ext_samsung_odyssey_available;
+ requested_extensions[XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME] = &ext_vive_cosmos_available;
+ requested_extensions[XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME] = &ext_vive_focus3_available;
+ requested_extensions[XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME] = &ext_huawei_controller_available;
+
// Check which extensions are supported
enabled_extensions.clear();
for (auto &requested_extension : requested_extensions) {
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index d641767a9b..7baf581a05 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -75,6 +75,12 @@ private:
Vector<OpenXRExtensionWrapper *> registered_extension_wrappers;
Vector<const char *> enabled_extensions;
+ bool ext_hp_mixed_reality_available = false;
+ bool ext_samsung_odyssey_available = false;
+ bool ext_vive_cosmos_available = false;
+ bool ext_vive_focus3_available = false;
+ bool ext_huawei_controller_available = false;
+
// composition layer providers
Vector<OpenXRCompositionLayerProvider *> composition_layer_providers;
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index 79ef2de929..7fe2e589b1 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -136,7 +136,7 @@ void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const
p_extensions->push_back("svg");
}
-Error ImageLoaderSVG::load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) {
+Error ImageLoaderSVG::load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, bool p_force_linear, float p_scale) {
String svg = p_fileaccess->get_as_utf8_string();
create_image_from_string(p_image, svg, p_scale, false, false);
ERR_FAIL_COND_V(p_image->is_empty(), FAILED);
diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h
index d0bd71d92d..94c17fda43 100644
--- a/modules/svg/image_loader_svg.h
+++ b/modules/svg/image_loader_svg.h
@@ -42,7 +42,7 @@ public:
void set_replace_colors(Dictionary p_replace_colors) { replace_colors = p_replace_colors; }
void create_image_from_string(Ref<Image> p_image, String p_string, float p_scale, bool p_upsample, bool p_convert_color);
- virtual Error load_image(Ref<Image> p_image, FileAccess *p_fileaccess, bool p_force_linear, float p_scale) override;
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> p_fileaccess, bool p_force_linear, float p_scale) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
};
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 0fce54a18a..4cd5dada4d 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -410,7 +410,6 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) {
}
uint64_t len = f->get_length();
PackedByteArray icu_data = f->get_buffer(len);
- f->close();
UErrorCode err = U_ZERO_ERROR;
udata_setCommonData(icu_data.ptr(), &err);
@@ -461,9 +460,8 @@ bool TextServerAdvanced::save_support_data(const String &p_filename) const {
icu_data.resize(U_ICUDATA_SIZE);
memcpy(icu_data.ptrw(), U_ICUDATA_ENTRY_POINT, U_ICUDATA_SIZE);
f->store_buffer(icu_data);
- f->close();
- return true;
+ return true;
#else
return false;
#endif
diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp
index 5060c1ab35..08ad1ef9f8 100644
--- a/modules/tga/image_loader_tga.cpp
+++ b/modules/tga/image_loader_tga.cpp
@@ -230,7 +230,7 @@ Error ImageLoaderTGA::convert_to_image(Ref<Image> p_image, const uint8_t *p_buff
return OK;
}
-Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
+Error ImageLoaderTGA::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
@@ -330,7 +330,6 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
}
}
- f->close();
return err;
}
@@ -339,12 +338,14 @@ void ImageLoaderTGA::get_recognized_extensions(List<String> *p_extensions) const
}
static Ref<Image> _tga_mem_loader_func(const uint8_t *p_tga, int p_size) {
- FileAccessMemory memfile;
- Error open_memfile_error = memfile.open_custom(p_tga, p_size);
+ Ref<FileAccessMemory> memfile;
+ memfile.instantiate();
+ Error open_memfile_error = memfile->open_custom(p_tga, p_size);
ERR_FAIL_COND_V_MSG(open_memfile_error, Ref<Image>(), "Could not create memfile for TGA image buffer.");
+
Ref<Image> img;
img.instantiate();
- Error load_error = ImageLoaderTGA().load_image(img, &memfile, false, 1.0f);
+ Error load_error = ImageLoaderTGA().load_image(img, memfile, false, 1.0f);
ERR_FAIL_COND_V_MSG(load_error, Ref<Image>(), "Failed to load TGA image.");
return img;
}
diff --git a/modules/tga/image_loader_tga.h b/modules/tga/image_loader_tga.h
index 282a2a1662..9b7cbbac77 100644
--- a/modules/tga/image_loader_tga.h
+++ b/modules/tga/image_loader_tga.h
@@ -73,7 +73,7 @@ class ImageLoaderTGA : public ImageFormatLoader {
static Error convert_to_image(Ref<Image> p_image, const uint8_t *p_buffer, const tga_header_s &p_header, const uint8_t *p_palette, const bool p_is_monochrome, size_t p_input_size);
public:
- virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderTGA();
};
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 94f60a7d9d..3f5140cc8c 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -114,7 +114,7 @@ void VideoStreamPlaybackTheora::video_write() {
}
void VideoStreamPlaybackTheora::clear() {
- if (!file) {
+ if (file.is_null()) {
return;
}
@@ -152,10 +152,7 @@ void VideoStreamPlaybackTheora::clear() {
theora_eos = false;
vorbis_eos = false;
- if (file) {
- memdelete(file);
- }
- file = nullptr;
+ file.unref();
playing = false;
};
@@ -165,11 +162,8 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) {
th_setup_info *ts = nullptr;
file_name = p_file;
- if (file) {
- memdelete(file);
- }
file = FileAccess::open(p_file, FileAccess::READ);
- ERR_FAIL_COND_MSG(!file, "Cannot open file '" + p_file + "'.");
+ ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_file + "'.");
#ifdef THEORA_USE_THREAD_STREAMING
thread_exit = false;
@@ -375,7 +369,7 @@ Ref<Texture2D> VideoStreamPlaybackTheora::get_texture() const {
}
void VideoStreamPlaybackTheora::update(float p_delta) {
- if (!file) {
+ if (file.is_null()) {
return;
}
@@ -506,9 +500,9 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
}
#ifdef THEORA_USE_THREAD_STREAMING
- if (file && thread_eof && no_theora && theora_eos && ring_buffer.data_left() == 0) {
+ if (file.is_valid() && thread_eof && no_theora && theora_eos && ring_buffer.data_left() == 0) {
#else
- if (file && /*!videobuf_ready && */ no_theora && theora_eos) {
+ if (file.is_valid() && /*!videobuf_ready && */ no_theora && theora_eos) {
#endif
//printf("video done, stopping\n");
stop();
@@ -664,10 +658,6 @@ VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() {
memdelete(thread_sem);
#endif
clear();
-
- if (file) {
- memdelete(file);
- }
};
void VideoStreamTheora::_bind_methods() {
@@ -680,8 +670,8 @@ void VideoStreamTheora::_bind_methods() {
////////////
RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
if (r_error) {
*r_error = ERR_CANT_OPEN;
}
@@ -697,8 +687,6 @@ RES ResourceFormatLoaderTheora::load(const String &p_path, const String &p_origi
*r_error = OK;
}
- f->close();
- memdelete(f);
return ogv_stream;
}
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index b61412e665..6fa7313fad 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -56,7 +56,7 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
Image::Format format = Image::Format::FORMAT_L8;
Vector<uint8_t> frame_data;
int frames_pending = 0;
- FileAccess *file = nullptr;
+ Ref<FileAccess> file;
String file_name;
int audio_frames_wrote = 0;
Point2i size;
diff --git a/modules/tinyexr/image_loader_tinyexr.cpp b/modules/tinyexr/image_loader_tinyexr.cpp
index 688707a42d..864df765ee 100644
--- a/modules/tinyexr/image_loader_tinyexr.cpp
+++ b/modules/tinyexr/image_loader_tinyexr.cpp
@@ -37,7 +37,7 @@
#include "thirdparty/tinyexr/tinyexr.h"
-Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
+Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
@@ -47,8 +47,6 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
f->get_buffer(&w[0], src_image_len);
- f->close();
-
// Re-implementation of tinyexr's LoadEXRFromMemory using Godot types to store the Image data
// and Godot's error codes.
// When debugging after updating the thirdparty library, check that we're still in sync with
@@ -232,7 +230,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
}
if (p_force_linear) {
- color = color.to_linear();
+ color = color.srgb_to_linear();
}
*row_w++ = Math::make_half_float(color.r);
@@ -263,7 +261,7 @@ Error ImageLoaderTinyEXR::load_image(Ref<Image> p_image, FileAccess *f, bool p_f
}
if (p_force_linear) {
- color = color.to_linear();
+ color = color.srgb_to_linear();
}
*row_w++ = color.r;
diff --git a/modules/tinyexr/image_loader_tinyexr.h b/modules/tinyexr/image_loader_tinyexr.h
index aba5fdb959..c147861c26 100644
--- a/modules/tinyexr/image_loader_tinyexr.h
+++ b/modules/tinyexr/image_loader_tinyexr.h
@@ -35,7 +35,7 @@
class ImageLoaderTinyEXR : public ImageFormatLoader {
public:
- virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderTinyEXR();
};
diff --git a/modules/tinyexr/image_saver_tinyexr.cpp b/modules/tinyexr/image_saver_tinyexr.cpp
index 3750994663..5fa6ace827 100644
--- a/modules/tinyexr/image_saver_tinyexr.cpp
+++ b/modules/tinyexr/image_saver_tinyexr.cpp
@@ -275,8 +275,8 @@ Error save_exr(const String &p_path, const Ref<Image> &p_img, bool p_grayscale)
print_error(String("Saving EXR failed. Error: {0}").format(varray(err)));
return ERR_FILE_CANT_WRITE;
} else {
- FileAccessRef ref = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V(!ref, ERR_FILE_CANT_WRITE);
+ Ref<FileAccess> ref = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V(ref.is_null(), ERR_FILE_CANT_WRITE);
ref->store_buffer(mem, bytes);
free(mem);
}
diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp
index a2e59c9cdf..495303d6c4 100644
--- a/modules/visual_script/editor/visual_script_editor.cpp
+++ b/modules/visual_script/editor/visual_script_editor.cpp
@@ -2727,7 +2727,7 @@ void VisualScriptEditor::_center_on_node(int p_id) {
if (gn) {
gn->set_selected(true);
- Vector2 new_scroll = gn->get_position_offset() - graph->get_size() * 0.5 + gn->get_size() * 0.5;
+ Vector2 new_scroll = gn->get_position_offset() * graph->get_zoom() - graph->get_size() * 0.5 + gn->get_size() * 0.5;
graph->set_scroll_ofs(new_scroll);
script->set_scroll(new_scroll / EDSCALE);
script->set_edited(true);
diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp
index d12e65a96a..03e145216a 100644
--- a/modules/vorbis/resource_importer_ogg_vorbis.cpp
+++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp
@@ -78,9 +78,8 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
bool loop = p_options["loop"];
float loop_offset = p_options["loop_offset"];
- FileAccess *f = FileAccess::open(p_source_file, FileAccess::READ);
-
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'.");
uint64_t len = f->get_length();
@@ -90,8 +89,6 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin
f->get_buffer(w, len);
- memdelete(f);
-
Ref<AudioStreamOGGVorbis> ogg_vorbis_stream;
ogg_vorbis_stream.instantiate();
diff --git a/modules/webp/image_loader_webp.cpp b/modules/webp/image_loader_webp.cpp
index 902e182d83..0e41f6c973 100644
--- a/modules/webp/image_loader_webp.cpp
+++ b/modules/webp/image_loader_webp.cpp
@@ -211,7 +211,7 @@ static Ref<Image> _webp_mem_loader_func(const uint8_t *p_png, int p_size) {
return img;
}
-Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale) {
+Error ImageLoaderWEBP::load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale) {
Vector<uint8_t> src_image;
uint64_t src_image_len = f->get_length();
ERR_FAIL_COND_V(src_image_len == 0, ERR_FILE_CORRUPT);
@@ -221,8 +221,6 @@ Error ImageLoaderWEBP::load_image(Ref<Image> p_image, FileAccess *f, bool p_forc
f->get_buffer(&w[0], src_image_len);
- f->close();
-
Error err = webp_load_image_from_buffer(p_image.ptr(), w, src_image_len);
return err;
diff --git a/modules/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h
index 327582ca55..1acd1459a0 100644
--- a/modules/webp/image_loader_webp.h
+++ b/modules/webp/image_loader_webp.h
@@ -35,7 +35,7 @@
class ImageLoaderWEBP : public ImageFormatLoader {
public:
- virtual Error load_image(Ref<Image> p_image, FileAccess *f, bool p_force_linear, float p_scale);
+ virtual Error load_image(Ref<Image> p_image, Ref<FileAccess> f, bool p_force_linear, float p_scale);
virtual void get_recognized_extensions(List<String> *p_extensions) const;
ImageLoaderWEBP();
};
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index ef3279aac4..46b0274de3 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -60,6 +60,13 @@
If [code]false[/code] is passed instead (default), you must call [PacketPeer] functions ([code]put_packet[/code], [code]get_packet[/code], etc.), on the [WebSocketPeer] returned via [code]get_peer(id)[/code] to communicate with the peer with given [code]id[/code] (e.g. [code]get_peer(id).get_available_packet_count[/code]).
</description>
</method>
+ <method name="set_extra_headers">
+ <return type="void" />
+ <argument index="0" name="headers" type="PackedStringArray" default="PackedStringArray()" />
+ <description>
+ Sets additional headers to be sent to clients during the HTTP handshake.
+ </description>
+ </method>
<method name="stop">
<return type="void" />
<description>
diff --git a/modules/websocket/emws_server.cpp b/modules/websocket/emws_server.cpp
index 53b4a0207d..2033098cad 100644
--- a/modules/websocket/emws_server.cpp
+++ b/modules/websocket/emws_server.cpp
@@ -33,6 +33,9 @@
#include "emws_server.h"
#include "core/os/os.h"
+void EMWSServer::set_extra_headers(const Vector<String> &p_headers) {
+}
+
Error EMWSServer::listen(int p_port, Vector<String> p_protocols, bool gd_mp_api) {
return FAILED;
}
diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h
index 0d193d423a..ae31d9dbb0 100644
--- a/modules/websocket/emws_server.h
+++ b/modules/websocket/emws_server.h
@@ -42,6 +42,7 @@ class EMWSServer : public WebSocketServer {
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override;
+ void set_extra_headers(const Vector<String> &p_headers) override;
Error listen(int p_port, Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false) override;
void stop() override;
bool is_listening() const override;
diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp
index b3f0140b80..b7851b02c4 100644
--- a/modules/websocket/websocket_server.cpp
+++ b/modules/websocket/websocket_server.cpp
@@ -42,6 +42,7 @@ WebSocketServer::~WebSocketServer() {
void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_listening"), &WebSocketServer::is_listening);
+ ClassDB::bind_method(D_METHOD("set_extra_headers", "headers"), &WebSocketServer::set_extra_headers, DEFVAL(Vector<String>()));
ClassDB::bind_method(D_METHOD("listen", "port", "protocols", "gd_mp_api"), &WebSocketServer::listen, DEFVAL(Vector<String>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("stop"), &WebSocketServer::stop);
ClassDB::bind_method(D_METHOD("has_peer", "id"), &WebSocketServer::has_peer);
diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h
index f6f3b80045..7bd80851f5 100644
--- a/modules/websocket/websocket_server.h
+++ b/modules/websocket/websocket_server.h
@@ -51,6 +51,7 @@ protected:
uint32_t handshake_timeout = 3000;
public:
+ virtual void set_extra_headers(const Vector<String> &p_headers) = 0;
virtual Error listen(int p_port, const Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false) = 0;
virtual void stop() = 0;
virtual bool is_listening() const = 0;
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index 8cd4b78ab3..b58b2e4724 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -96,7 +96,7 @@ bool WSLServer::PendingPeer::_parse_request(const Vector<String> p_protocols, St
return true;
}
-Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name) {
+Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name, const Vector<String> &p_extra_headers) {
if (OS::get_singleton()->get_ticks_msec() - time > p_timeout) {
print_verbose(vformat("WebSocket handshake timed out after %.3f seconds.", p_timeout * 0.001));
return ERR_TIMEOUT;
@@ -141,6 +141,9 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uin
if (!protocol.is_empty()) {
s += "Sec-WebSocket-Protocol: " + protocol + "\r\n";
}
+ for (int i = 0; i < p_extra_headers.size(); i++) {
+ s += p_extra_headers[i] + "\r\n";
+ }
s += "\r\n";
response = s.utf8();
has_request = true;
@@ -167,6 +170,10 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uin
return OK;
}
+void WSLServer::set_extra_headers(const Vector<String> &p_headers) {
+ _extra_headers = p_headers;
+}
+
Error WSLServer::listen(int p_port, const Vector<String> p_protocols, bool gd_mp_api) {
ERR_FAIL_COND_V(is_listening(), ERR_ALREADY_IN_USE);
@@ -199,7 +206,7 @@ void WSLServer::poll() {
for (const Ref<PendingPeer> &E : _pending) {
String resource_name;
Ref<PendingPeer> ppeer = E;
- Error err = ppeer->do_handshake(_protocols, handshake_timeout, resource_name);
+ Error err = ppeer->do_handshake(_protocols, handshake_timeout, resource_name, _extra_headers);
if (err == ERR_BUSY) {
continue;
} else if (err != OK) {
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index 6a9dd0dd2f..a920e9c665 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -62,7 +62,7 @@ private:
CharString response;
int response_sent = 0;
- Error do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name);
+ Error do_handshake(const Vector<String> p_protocols, uint64_t p_timeout, String &r_resource_name, const Vector<String> &p_extra_headers);
};
int _in_buf_size = DEF_BUF_SHIFT;
@@ -73,9 +73,11 @@ private:
List<Ref<PendingPeer>> _pending;
Ref<TCPServer> _server;
Vector<String> _protocols;
+ Vector<String> _extra_headers;
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override;
+ void set_extra_headers(const Vector<String> &p_headers) override;
Error listen(int p_port, const Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false) override;
void stop() override;
bool is_listening() const override;
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp
index 7fb4f54fca..e2b1c757d6 100644
--- a/platform/android/dir_access_jandroid.cpp
+++ b/platform/android/dir_access_jandroid.cpp
@@ -42,7 +42,7 @@ jmethodID DirAccessJAndroid::_dir_next = nullptr;
jmethodID DirAccessJAndroid::_dir_close = nullptr;
jmethodID DirAccessJAndroid::_dir_is_dir = nullptr;
-DirAccess *DirAccessJAndroid::create_fs() {
+Ref<DirAccess> DirAccessJAndroid::create_fs() {
return memnew(DirAccessJAndroid);
}
@@ -143,7 +143,7 @@ Error DirAccessJAndroid::change_dir(String p_dir) {
return OK;
}
-String DirAccessJAndroid::get_current_dir(bool p_include_drive) {
+String DirAccessJAndroid::get_current_dir(bool p_include_drive) const {
return "res://" + current_dir;
}
@@ -155,9 +155,9 @@ bool DirAccessJAndroid::file_exists(String p_file) {
sd = current_dir.plus_file(p_file);
}
- FileAccessAndroid *f = memnew(FileAccessAndroid);
+ Ref<FileAccessAndroid> f;
+ f.instantiate();
bool exists = f->file_exists(sd);
- memdelete(f);
return exists;
}
diff --git a/platform/android/dir_access_jandroid.h b/platform/android/dir_access_jandroid.h
index 4f4a984b12..3d3c9f9223 100644
--- a/platform/android/dir_access_jandroid.h
+++ b/platform/android/dir_access_jandroid.h
@@ -51,7 +51,7 @@ class DirAccessJAndroid : public DirAccess {
String current_dir;
String current;
- static DirAccess *create_fs();
+ static Ref<DirAccess> create_fs();
public:
virtual Error list_dir_begin(); ///< This starts dir listing
@@ -64,7 +64,7 @@ public:
virtual String get_drive(int p_drive);
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true); ///< return current dir location
+ virtual String get_current_dir(bool p_include_drive = true) const; ///< return current dir location
virtual bool file_exists(String p_file);
virtual bool dir_exists(String p_dir);
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 51f2885fbe..8cfa3a67b9 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -596,8 +596,8 @@ Vector<String> EditorExportPlatformAndroid::get_abis() {
/// List the gdap files in the directory specified by the p_path parameter.
Vector<String> EditorExportPlatformAndroid::list_gdap_files(const String &p_path) {
Vector<String> dir_files;
- DirAccessRef da = DirAccess::open(p_path);
- if (da) {
+ Ref<DirAccess> da = DirAccess::open(p_path);
+ if (da.is_valid()) {
da->list_dir_begin();
while (true) {
String file = da->get_next();
@@ -2008,7 +2008,7 @@ String EditorExportPlatformAndroid::get_apksigner_path() {
Error errn;
String build_tools_dir = sdk_path.plus_file("build-tools");
- DirAccessRef da = DirAccess::open(build_tools_dir, &errn);
+ Ref<DirAccess> da = DirAccess::open(build_tools_dir, &errn);
if (errn != OK) {
print_error("Unable to open Android 'build-tools' directory.");
return apksigner_path;
@@ -2125,7 +2125,7 @@ bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_pr
} else {
Error errn;
// Check for the platform-tools directory.
- DirAccessRef da = DirAccess::open(sdk_path.plus_file("platform-tools"), &errn);
+ Ref<DirAccess> da = DirAccess::open(sdk_path.plus_file("platform-tools"), &errn);
if (errn != OK) {
err += TTR("Invalid Android SDK path in Editor Settings.");
err += TTR("Missing 'platform-tools' directory!");
@@ -2143,7 +2143,7 @@ bool EditorExportPlatformAndroid::can_export(const Ref<EditorExportPreset> &p_pr
}
// Check for the build-tools directory.
- DirAccessRef build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn);
+ Ref<DirAccess> build_tools_da = DirAccess::open(sdk_path.plus_file("build-tools"), &errn);
if (errn != OK) {
err += TTR("Invalid Android SDK path in Editor Settings.");
err += TTR("Missing 'build-tools' directory!");
@@ -2422,12 +2422,12 @@ Error EditorExportPlatformAndroid::sign_apk(const Ref<EditorExportPreset> &p_pre
}
void EditorExportPlatformAndroid::_clear_assets_directory() {
- DirAccessRef da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da_res = DirAccess::create(DirAccess::ACCESS_RESOURCES);
// Clear the APK assets directory
if (da_res->dir_exists(APK_ASSETS_DIRECTORY)) {
print_verbose("Clearing APK assets directory..");
- DirAccessRef da_assets = DirAccess::open(APK_ASSETS_DIRECTORY);
+ Ref<DirAccess> da_assets = DirAccess::open(APK_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(APK_ASSETS_DIRECTORY);
}
@@ -2435,7 +2435,7 @@ void EditorExportPlatformAndroid::_clear_assets_directory() {
// Clear the AAB assets directory
if (da_res->dir_exists(AAB_ASSETS_DIRECTORY)) {
print_verbose("Clearing AAB assets directory..");
- DirAccessRef da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY);
+ Ref<DirAccess> da_assets = DirAccess::open(AAB_ASSETS_DIRECTORY);
da_assets->erase_contents_recursive();
da_res->remove(AAB_ASSETS_DIRECTORY);
}
@@ -2455,7 +2455,7 @@ void EditorExportPlatformAndroid::_remove_copied_libs() {
ERR_FAIL_COND_MSG(error, "Error parsing \"" + libs_json + "\" on line " + itos(json.get_error_line()) + ": " + json.get_error_message());
Vector<String> libs = json.get_data();
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (int i = 0; i < libs.size(); i++) {
print_verbose("Removing previously installed library " + libs[i]);
da->remove(libs[i]);
@@ -2544,14 +2544,13 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
//test that installed build version is alright
{
print_verbose("Checking build version..");
- FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open("res://android/.build_version", FileAccess::READ);
+ if (f.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Trying to build from a custom built template, but no version info for it exists. Please reinstall from the 'Project' menu."));
return ERR_UNCONFIGURED;
}
String version = f->get_line().strip_edges();
print_verbose("- build version: " + version);
- f->close();
if (version != VERSION_FULL_CONFIG) {
EditorNode::get_singleton()->show_warning(vformat(TTR("Android build version mismatch:\n Template installed: %s\n Godot Version: %s\nPlease reinstall Android build template from 'Project' menu."), version, VERSION_FULL_CONFIG));
return ERR_UNCONFIGURED;
@@ -2587,10 +2586,9 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return err;
}
if (user_data.libs.size() > 0) {
- FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
+ Ref<FileAccess> fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
JSON json;
fa->store_string(json.stringify(user_data.libs, "\t"));
- fa->close();
}
} else {
print_verbose("Saving apk expansion file..");
@@ -2770,8 +2768,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return ERR_FILE_BAD_PATH;
}
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
if (ep.step(TTR("Creating APK..."), 0)) {
return ERR_SKIP;
@@ -2785,9 +2782,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
int ret = unzGoToFirstFile(pkg);
- zlib_filefunc_def io2 = io;
- FileAccess *dst_f = nullptr;
- io2.opaque = &dst_f;
+ zlib_filefunc_def io2 = zipio_create_io();
String tmp_unaligned_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpexport-unaligned." + uitos(OS::get_singleton()->get_unix_time()) + ".apk");
@@ -2983,9 +2978,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
ret = unzGoToFirstFile(tmp_unaligned);
- io2 = io;
- dst_f = nullptr;
- io2.opaque = &dst_f;
+ io2 = zipio_create_io();
zipFile final_apk = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2);
// Take files from the unaligned APK and write them out to the aligned one
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index 430aeaf036..173bb8bcb7 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -75,8 +75,8 @@ String _get_android_orientation_label(DisplayServer::ScreenOrientation screen_or
// Utility method used to create a directory.
Error create_directory(const String &p_dir) {
if (!DirAccess::exists(p_dir)) {
- DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'.");
+ Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ ERR_FAIL_COND_V_MSG(filesystem_da.is_null(), ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'.");
Error err = filesystem_da->make_dir_recursive(p_dir);
ERR_FAIL_COND_V_MSG(err, ERR_CANT_CREATE, "Cannot create directory '" + p_dir + "'.");
}
@@ -91,10 +91,9 @@ Error store_file_at_path(const String &p_path, const Vector<uint8_t> &p_data) {
if (err != OK) {
return err;
}
- FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
+ Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
fa->store_buffer(p_data.ptr(), p_data.size());
- memdelete(fa);
return OK;
}
@@ -109,10 +108,9 @@ Error store_string_at_path(const String &p_path, const String &p_data) {
}
return err;
}
- FileAccess *fa = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
+ Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
fa->store_string(p_data);
- memdelete(fa);
return OK;
}
@@ -152,8 +150,8 @@ Error _create_project_name_strings_files(const Ref<EditorExportPreset> &p_preset
store_string_at_path("res://android/build/res/values/godot_project_name_string.xml", processed_default_xml_string);
// Searches the Gradle project res/ directory to find all supported locales
- DirAccessRef da = DirAccess::open("res://android/build/res");
- if (!da) {
+ Ref<DirAccess> da = DirAccess::open("res://android/build/res");
+ if (da.is_null()) {
if (OS::get_singleton()->is_stdout_verbose()) {
print_error("Unable to open Android resources directory.");
}
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index c84a919b6b..d7ba31e3c9 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -34,11 +34,13 @@
AAssetManager *FileAccessAndroid::asset_manager = nullptr;
-FileAccess *FileAccessAndroid::create_android() {
+Ref<FileAccess> FileAccessAndroid::create_android() {
return memnew(FileAccessAndroid);
}
Error FileAccessAndroid::_open(const String &p_path, int p_mode_flags) {
+ _close();
+
String path = fix_path(p_path).simplify_path();
if (path.begins_with("/")) {
path = path.substr(1, path.length());
@@ -58,7 +60,7 @@ Error FileAccessAndroid::_open(const String &p_path, int p_mode_flags) {
return OK;
}
-void FileAccessAndroid::close() {
+void FileAccessAndroid::_close() {
if (!a) {
return;
}
@@ -162,5 +164,5 @@ bool FileAccessAndroid::file_exists(const String &p_path) {
}
FileAccessAndroid::~FileAccessAndroid() {
- close();
+ _close();
}
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index fb612cd008..33b692da20 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -38,17 +38,18 @@
//#include <android_native_app_glue.h>
class FileAccessAndroid : public FileAccess {
- static FileAccess *create_android();
+ static Ref<FileAccess> create_android();
mutable AAsset *a = nullptr;
mutable uint64_t len = 0;
mutable uint64_t pos = 0;
mutable bool eof = false;
+ void _close();
+
public:
static AAssetManager *asset_manager;
virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
virtual bool is_open() const; ///< true when file is open
virtual void seek(uint64_t p_position); ///< seek to a given position
diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp
index c83d13c0b8..57bee59523 100644
--- a/platform/iphone/export/export_plugin.cpp
+++ b/platform/iphone/export/export_plugin.cpp
@@ -530,8 +530,8 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
String json_description = "{\"images\":[";
String sizes;
- DirAccessRef da = DirAccess::open(p_iconset_dir);
- ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
+ Ref<DirAccess> da = DirAccess::open(p_iconset_dir);
+ ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_iconset_dir + "'.");
for (uint64_t i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
IconInfo info = icon_infos[i];
@@ -588,17 +588,15 @@ Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_pr
}
json_description += "]}";
- FileAccess *json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
- ERR_FAIL_COND_V(!json_file, ERR_CANT_CREATE);
+ Ref<FileAccess> json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
+ ERR_FAIL_COND_V(json_file.is_null(), ERR_CANT_CREATE);
CharString json_utf8 = json_description.utf8();
json_file->store_buffer((const uint8_t *)json_utf8.get_data(), json_utf8.length());
- memdelete(json_file);
- FileAccess *sizes_file = FileAccess::open(p_iconset_dir + "sizes", FileAccess::WRITE);
- ERR_FAIL_COND_V(!sizes_file, ERR_CANT_CREATE);
+ Ref<FileAccess> sizes_file = FileAccess::open(p_iconset_dir + "sizes", FileAccess::WRITE);
+ ERR_FAIL_COND_V(sizes_file.is_null(), ERR_CANT_CREATE);
CharString sizes_utf8 = sizes.utf8();
sizes_file->store_buffer((const uint8_t *)sizes_utf8.get_data(), sizes_utf8.length());
- memdelete(sizes_file);
return OK;
}
@@ -672,8 +670,8 @@ Error EditorExportPlatformIOS::_export_loading_screen_file(const Ref<EditorExpor
}
Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) {
- DirAccessRef da = DirAccess::open(p_dest_dir);
- ERR_FAIL_COND_V_MSG(!da, ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'.");
+ Ref<DirAccess> da = DirAccess::open(p_dest_dir);
+ ERR_FAIL_COND_V_MSG(da.is_null(), ERR_CANT_OPEN, "Cannot open directory '" + p_dest_dir + "'.");
for (uint64_t i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
LoadingScreenInfo info = loading_screen_infos[i];
@@ -761,7 +759,7 @@ Error EditorExportPlatformIOS::_export_loading_screen_images(const Ref<EditorExp
return OK;
}
-Error EditorExportPlatformIOS::_walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata) {
+Error EditorExportPlatformIOS::_walk_dir_recursive(Ref<DirAccess> &p_da, FileHandler p_handler, void *p_userdata) {
Vector<String> dirs;
String current_dir = p_da->get_current_dir();
p_da->list_dir_begin();
@@ -964,8 +962,8 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese
Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String &p_asset, const String *p_custom_file_name, bool p_is_framework, bool p_should_embed, Vector<IOSExportAsset> &r_exported_assets) {
String binary_name = p_out_dir.get_file().get_basename();
- DirAccessRef da = DirAccess::create_for_path(p_asset);
- if (!da) {
+ Ref<DirAccess> da = DirAccess::create_for_path(p_asset);
+ if (da.is_null()) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't create directory: " + p_asset + ".");
}
bool file_exists = da->file_exists(p_asset);
@@ -1030,8 +1028,8 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
destination = p_out_dir.plus_file(asset_path);
}
- DirAccessRef filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V_MSG(!filesystem_da, ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
+ Ref<DirAccess> filesystem_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V_MSG(filesystem_da.is_null(), ERR_CANT_CREATE, "Cannot create DirAccess for path '" + p_out_dir + "'.");
if (!filesystem_da->dir_exists(destination_dir)) {
Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir);
@@ -1097,11 +1095,9 @@ Error EditorExportPlatformIOS::_copy_asset(const String &p_out_dir, const String
String info_plist = info_plist_format.replace("$name", file_name);
- FileAccess *f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(destination_dir.plus_file("Info.plist"), FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_string(info_plist);
- f->close();
- memdelete(f);
}
}
}
@@ -1411,8 +1407,8 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
}
{
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (da) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da.is_valid()) {
String current_dir = da->get_current_dir();
// remove leftovers from last export so they don't interfere
@@ -1488,12 +1484,11 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
Vector<IOSExportAsset> assets;
- DirAccessRef tmp_app_path = DirAccess::create_for_path(dest_dir);
- ERR_FAIL_COND_V(!tmp_app_path, ERR_CANT_CREATE);
+ Ref<DirAccess> tmp_app_path = DirAccess::create_for_path(dest_dir);
+ ERR_FAIL_COND_V(tmp_app_path.is_null(), ERR_CANT_CREATE);
print_line("Unzipping...");
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
if (!src_pkg_zip) {
EditorNode::add_io_error("Could not open export template (not a zip file?):\n" + src_pkg_name);
@@ -1575,15 +1570,15 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
}
/* write the file */
- FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
- if (!f) {
- ERR_PRINT("Can't write '" + file + "'.");
- unzClose(src_pkg_zip);
- return ERR_CANT_CREATE;
- };
- f->store_buffer(data.ptr(), data.size());
- f->close();
- memdelete(f);
+ {
+ Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
+ if (f.is_null()) {
+ ERR_PRINT("Can't write '" + file + "'.");
+ unzClose(src_pkg_zip);
+ return ERR_CANT_CREATE;
+ };
+ f->store_buffer(data.ptr(), data.size());
+ }
#if defined(OSX_ENABLED) || defined(X11_ENABLED)
if (is_execute) {
@@ -1614,7 +1609,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
{
String fname = dest_dir + binary_name + "/en.lproj";
tmp_app_path->make_dir_recursive(fname);
- FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
f->store_line("/* Localized versions of Info.plist keys */");
f->store_line("");
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
@@ -1629,7 +1624,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
String lang = tr->get_locale();
String fname = dest_dir + binary_name + "/" + lang + ".lproj";
tmp_app_path->make_dir_recursive(fname);
- FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
f->store_line("/* Localized versions of Info.plist keys */");
f->store_line("");
if (appnames.has(lang)) {
@@ -1683,9 +1678,8 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
String launch_image_path = dest_dir + binary_name + "/Images.xcassets/LaunchImage.launchimage/";
String splash_image_path = dest_dir + binary_name + "/Images.xcassets/SplashImage.imageset/";
- DirAccessRef launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
-
- if (!launch_screen_da) {
+ Ref<DirAccess> launch_screen_da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (launch_screen_da.is_null()) {
return ERR_CANT_CREATE;
}
@@ -1722,25 +1716,24 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
_export_additional_assets(dest_dir + binary_name, libraries, assets);
_add_assets_to_project(p_preset, project_file_data, assets);
String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj";
- FileAccess *f = FileAccess::open(project_file_name, FileAccess::WRITE);
- if (!f) {
- ERR_PRINT("Can't write '" + project_file_name + "'.");
- return ERR_CANT_CREATE;
- };
- f->store_buffer(project_file_data.ptr(), project_file_data.size());
- f->close();
- memdelete(f);
+ {
+ Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE);
+ if (f.is_null()) {
+ ERR_PRINT("Can't write '" + project_file_name + "'.");
+ return ERR_CANT_CREATE;
+ };
+ f->store_buffer(project_file_data.ptr(), project_file_data.size());
+ }
#ifdef OSX_ENABLED
{
if (ep.step("Code-signing dylibs", 2)) {
return ERR_SKIP;
}
- DirAccess *dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
- ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
+ Ref<DirAccess> dylibs_dir = DirAccess::open(dest_dir + binary_name + "/dylibs");
+ ERR_FAIL_COND_V(dylibs_dir.is_null(), ERR_CANT_OPEN);
CodesignData codesign_data(p_preset, p_debug);
err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
- memdelete(dylibs_dir);
ERR_FAIL_COND_V(err, err);
}
diff --git a/platform/iphone/export/export_plugin.h b/platform/iphone/export/export_plugin.h
index d88b387073..3831f3bff2 100644
--- a/platform/iphone/export/export_plugin.h
+++ b/platform/iphone/export/export_plugin.h
@@ -65,7 +65,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Vector<PluginConfigIOS> plugins;
typedef Error (*FileHandler)(String p_file, void *p_userdata);
- static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata);
+ static Error _walk_dir_recursive(Ref<DirAccess> &p_da, FileHandler p_handler, void *p_userdata);
static Error _codesign(String p_file, void *p_userdata);
void _blend_and_rotate(Ref<Image> &p_dst, Ref<Image> &p_src, bool p_rot);
@@ -215,8 +215,8 @@ public:
/// List the gdip files in the directory specified by the p_path parameter.
static Vector<String> list_plugin_config_files(const String &p_path, bool p_check_directories) {
Vector<String> dir_files;
- DirAccessRef da = DirAccess::open(p_path);
- if (da) {
+ Ref<DirAccess> da = DirAccess::open(p_path);
+ if (da.is_valid()) {
da->list_dir_begin();
while (true) {
String file = da->get_next();
diff --git a/platform/iphone/os_iphone.mm b/platform/iphone/os_iphone.mm
index 1d990b5625..ea1bc0ef64 100644
--- a/platform/iphone/os_iphone.mm
+++ b/platform/iphone/os_iphone.mm
@@ -259,7 +259,7 @@ Error OSIPhone::shell_open(String p_uri) {
}
void OSIPhone::set_user_data_dir(String p_dir) {
- DirAccessRef da = DirAccess::open(p_dir);
+ Ref<DirAccess> da = DirAccess::open(p_dir);
user_data_dir = da->get_current_dir();
printf("setting data dir to %s from %s\n", user_data_dir.utf8().get_data(), p_dir.utf8().get_data());
}
diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp
index 0442a1eaeb..31ce71127d 100644
--- a/platform/javascript/api/javascript_tools_editor_plugin.cpp
+++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp
@@ -64,8 +64,7 @@ void JavaScriptToolsEditorPlugin::_download_zip(Variant p_v) {
}
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
- FileAccess *src_f;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
// Name the downloaded ZIP file to contain the project name and download date for easier organization.
// Replace characters not allowed (or risky) in Windows file names with safe characters.
@@ -82,22 +81,22 @@ void JavaScriptToolsEditorPlugin::_download_zip(Variant p_v) {
const String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/";
_zip_recursive(resource_path, base_path, zip);
zipClose(zip, nullptr);
- FileAccess *f = FileAccess::open(output_path, FileAccess::READ);
- ERR_FAIL_COND_MSG(!f, "Unable to create ZIP file.");
- Vector<uint8_t> buf;
- buf.resize(f->get_length());
- f->get_buffer(buf.ptrw(), buf.size());
- godot_js_os_download_buffer(buf.ptr(), buf.size(), output_name.utf8().get_data(), "application/zip");
+ {
+ Ref<FileAccess> f = FileAccess::open(output_path, FileAccess::READ);
+ ERR_FAIL_COND_MSG(f.is_null(), "Unable to create ZIP file.");
+ Vector<uint8_t> buf;
+ buf.resize(f->get_length());
+ f->get_buffer(buf.ptrw(), buf.size());
+ godot_js_os_download_buffer(buf.ptr(), buf.size(), output_name.utf8().get_data(), "application/zip");
+ }
- f->close();
- memdelete(f);
// Remove the temporary file since it was sent to the user's native filesystem as a download.
DirAccess::remove_file_or_error(output_path);
}
void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, zipFile p_zip) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
WARN_PRINT("Unable to open file for zipping: " + p_path);
return;
}
@@ -105,8 +104,6 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z
uint64_t len = f->get_length();
data.resize(len);
f->get_buffer(data.ptrw(), len);
- f->close();
- memdelete(f);
String path = p_path.replace_first(p_base_path, "");
zipOpenNewFileInZip(p_zip,
@@ -124,7 +121,7 @@ void JavaScriptToolsEditorPlugin::_zip_file(String p_path, String p_base_path, z
}
void JavaScriptToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zipFile p_zip) {
- DirAccessRef dir = DirAccess::open(p_path);
+ Ref<DirAccess> dir = DirAccess::open(p_path);
if (!dir) {
WARN_PRINT("Unable to open directory for zipping: " + p_path);
return;
diff --git a/platform/javascript/export/export_plugin.cpp b/platform/javascript/export/export_plugin.cpp
index ef1c170625..66d93d7c49 100644
--- a/platform/javascript/export/export_plugin.cpp
+++ b/platform/javascript/export/export_plugin.cpp
@@ -33,8 +33,7 @@
#include "core/config/project_settings.h"
Error EditorExportPlatformJavaScript::_extract_template(const String &p_template, const String &p_dir, const String &p_name, bool pwa) {
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
unzFile pkg = unzOpen2(p_template.utf8().get_data(), &io);
if (!pkg) {
@@ -70,14 +69,13 @@ Error EditorExportPlatformJavaScript::_extract_template(const String &p_template
//write
String dst = p_dir.plus_file(file.replace("godot", p_name));
- FileAccess *f = FileAccess::open(dst, FileAccess::WRITE);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(dst, FileAccess::WRITE);
+ if (f.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + dst);
unzClose(pkg);
return ERR_FILE_CANT_WRITE;
}
f->store_buffer(data.ptr(), data.size());
- memdelete(f);
} while (unzGoToNextFile(pkg) == UNZ_OK);
unzClose(pkg);
@@ -85,13 +83,12 @@ Error EditorExportPlatformJavaScript::_extract_template(const String &p_template
}
Error EditorExportPlatformJavaScript::_write_or_error(const uint8_t *p_content, int p_size, String p_path) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::WRITE);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ if (f.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + p_path);
return ERR_FILE_CANT_WRITE;
}
f->store_buffer(p_content, p_size);
- memdelete(f);
return OK;
}
@@ -233,15 +230,13 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
const String sw_path = dir.plus_file(name + ".service.worker.js");
Vector<uint8_t> sw;
{
- FileAccess *f = FileAccess::open(sw_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(sw_path, FileAccess::READ);
+ if (f.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Could not read file:") + "\n" + sw_path);
return ERR_FILE_CANT_READ;
}
sw.resize(f->get_length());
f->get_buffer(sw.ptrw(), sw.size());
- memdelete(f);
- f = nullptr;
}
_replace_strings(replaces, sw);
Error err = _write_or_error(sw.ptr(), sw.size(), dir.plus_file(name + ".service.worker.js"));
@@ -252,7 +247,7 @@ Error EditorExportPlatformJavaScript::_build_pwa(const Ref<EditorExportPreset> &
// Custom offline page
const String offline_page = p_preset->get("progressive_web_app/offline_page");
if (!offline_page.is_empty()) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
const String offline_dest = dir.plus_file(name + ".offline.html");
err = da->copy(ProjectSettings::get_singleton()->globalize_path(offline_page), offline_dest);
if (err != OK) {
@@ -456,7 +451,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
}
{
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < shared_objects.size(); i++) {
String dst = base_dir.plus_file(shared_objects[i].path.get_file());
error = da->copy(shared_objects[i].path, dst);
@@ -475,32 +470,25 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
// Parse generated file sizes (pck and wasm, to help show a meaningful loading bar).
Dictionary file_sizes;
- FileAccess *f = nullptr;
- f = FileAccess::open(pck_path, FileAccess::READ);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(pck_path, FileAccess::READ);
+ if (f.is_valid()) {
file_sizes[pck_path.get_file()] = (uint64_t)f->get_length();
- memdelete(f);
- f = nullptr;
}
f = FileAccess::open(base_path + ".wasm", FileAccess::READ);
- if (f) {
+ if (f.is_valid()) {
file_sizes[base_name + ".wasm"] = (uint64_t)f->get_length();
- memdelete(f);
- f = nullptr;
}
// Read the HTML shell file (custom or from template).
const String html_path = custom_html.is_empty() ? base_path + ".html" : custom_html;
Vector<uint8_t> html;
f = FileAccess::open(html_path, FileAccess::READ);
- if (!f) {
+ if (f.is_null()) {
EditorNode::get_singleton()->show_warning(TTR("Could not read HTML shell:") + "\n" + html_path);
return ERR_FILE_CANT_READ;
}
html.resize(f->get_length());
f->get_buffer(html.ptrw(), html.size());
- memdelete(f);
- f = nullptr;
// Generate HTML file with replaced strings.
_fix_html(html, p_preset, base_name, p_debug, p_flags, shared_objects, file_sizes);
@@ -586,7 +574,7 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese
}
const String dest = EditorPaths::get_singleton()->get_cache_dir().plus_file("web");
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (!da->dir_exists(dest)) {
Error err = da->make_dir_recursive(dest);
if (err != OK) {
diff --git a/platform/javascript/export/export_server.h b/platform/javascript/export/export_server.h
index 1b908ad9b0..f77ac3d1ad 100644
--- a/platform/javascript/export/export_server.h
+++ b/platform/javascript/export/export_server.h
@@ -153,8 +153,8 @@ public:
}
const String ctype = mimes[req_ext];
- FileAccess *f = FileAccess::open(filepath, FileAccess::READ);
- ERR_FAIL_COND(!f);
+ Ref<FileAccess> f = FileAccess::open(filepath, FileAccess::READ);
+ ERR_FAIL_COND(f.is_null());
String s = "HTTP/1.1 200 OK\r\n";
s += "Connection: Close\r\n";
s += "Content-Type: " + ctype + "\r\n";
@@ -166,7 +166,6 @@ public:
CharString cs = s.utf8();
Error err = peer->put_data((const uint8_t *)cs.get_data(), cs.size() - 1);
if (err != OK) {
- memdelete(f);
ERR_FAIL();
}
@@ -178,11 +177,9 @@ public:
}
err = peer->put_data(bytes, read);
if (err != OK) {
- memdelete(f);
ERR_FAIL();
}
}
- memdelete(f);
}
void poll() {
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index db2fe274d9..7da30ac363 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -3062,7 +3062,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) {
Callable::CallError ce;
{
- List<WindowID>::Element *E = popup_list.front();
+ List<WindowID>::Element *E = popup_list.back();
if (E && Object::cast_to<InputEventKey>(*p_event)) {
// Redirect keyboard input to active popup.
if (windows.has(E->get())) {
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp
index 24906fa3fb..9f7fab6ee8 100644
--- a/platform/linuxbsd/export/export_plugin.cpp
+++ b/platform/linuxbsd/export/export_plugin.cpp
@@ -34,8 +34,8 @@
#include "editor/editor_node.h"
Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) {
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
f->store_line("#!/bin/sh");
f->store_line("echo -ne '\\033c\\033]0;" + p_app_name + "\\a'");
@@ -101,8 +101,8 @@ List<String> EditorExportPlatformLinuxBSD::get_binary_extensions(const Ref<Edito
Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) const {
// Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ_WRITE);
+ if (f.is_null()) {
return ERR_CANT_OPEN;
}
@@ -110,7 +110,6 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
{
uint32_t magic = f->get_32();
if (magic != 0x464c457f) { // 0x7F + "ELF"
- f->close();
return ERR_FILE_CORRUPT;
}
}
@@ -120,7 +119,6 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
int bits = f->get_8() * 32;
if (bits == 32 && p_embedded_size >= 0x100000000) {
- f->close();
ERR_FAIL_V_MSG(ERR_INVALID_DATA, "32-bit executables cannot have embedded data >= 4 GiB.");
}
@@ -165,7 +163,6 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
f->seek(string_data_pos);
strings = (uint8_t *)memalloc(string_data_size);
if (!strings) {
- f->close();
return ERR_OUT_OF_MEMORY;
}
f->get_buffer(strings, string_data_size);
@@ -198,7 +195,6 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
}
memfree(strings);
- f->close();
return found ? OK : ERR_FILE_CORRUPT;
}
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 86874687ad..bf142f8804 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -131,20 +131,19 @@ void OS_LinuxBSD::initialize_joypads() {
String OS_LinuxBSD::get_unique_id() const {
static String machine_id;
if (machine_id.is_empty()) {
- if (FileAccess *f = FileAccess::open("/etc/machine-id", FileAccess::READ)) {
+ Ref<FileAccess> f = FileAccess::open("/etc/machine-id", FileAccess::READ);
+ if (f.is_valid()) {
while (machine_id.is_empty() && !f->eof_reached()) {
machine_id = f->get_line().strip_edges();
}
- f->close();
- memdelete(f);
}
}
return machine_id;
}
String OS_LinuxBSD::get_processor_name() const {
- FileAccessRef f = FileAccess::open("/proc/cpuinfo", FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, "", String("Couldn't open `/proc/cpuinfo` to get the CPU model name. Returning an empty string."));
+ Ref<FileAccess> f = FileAccess::open("/proc/cpuinfo", FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), "", String("Couldn't open `/proc/cpuinfo` to get the CPU model name. Returning an empty string."));
while (!f->eof_reached()) {
const String line = f->get_line();
@@ -465,7 +464,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Create needed directories for decided trash can location.
{
- DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
Error err = dir_access->make_dir_recursive(trash_path);
// Issue an error if trash can is not created properly.
@@ -512,13 +511,14 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
String trash_info = "[Trash Info]\nPath=" + path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;
- FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\"");
- file->store_string(trash_info);
- file->close();
+ {
+ Ref<FileAccess> file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\"");
+ file->store_string(trash_info);
+ }
// Rename our resource before moving it to the trash can.
- DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
err = dir_access->rename(path, renamed_path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + path + "\" to \"" + renamed_path + "\"");
}
@@ -535,7 +535,7 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
// Issue an error if "mv" failed to move the given resource to the trash can.
if (err != OK || retval != 0) {
ERR_PRINT("move_to_trash: Could not move the resource \"" + path + "\" to the trash can \"" + trash_path + "/files\"");
- DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
err = dir_access->rename(renamed_path, path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename \"" + renamed_path + "\" back to its original name: \"" + path + "\"");
return FAILED;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 986c711fc9..d209c90d87 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -326,7 +326,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
Callable::CallError ce;
{
- List<WindowID>::Element *E = popup_list.front();
+ List<WindowID>::Element *E = popup_list.back();
if (E && Object::cast_to<InputEventKey>(*p_event)) {
// Redirect keyboard input to active popup.
if (windows.has(E->get())) {
@@ -2892,14 +2892,13 @@ void DisplayServerOSX::swap_buffers() {
void DisplayServerOSX::set_native_icon(const String &p_filename) {
_THREAD_SAFE_METHOD_
- FileAccess *f = FileAccess::open(p_filename, FileAccess::READ);
- ERR_FAIL_COND(!f);
+ Ref<FileAccess> f = FileAccess::open(p_filename, FileAccess::READ);
+ ERR_FAIL_COND(f.is_null());
Vector<uint8_t> data;
uint64_t len = f->get_length();
data.resize(len);
f->get_buffer((uint8_t *)&data.write[0], len);
- memdelete(f);
NSData *icon_data = [[NSData alloc] initWithBytes:&data.write[0] length:len];
ERR_FAIL_COND_MSG(!icon_data, "Error reading icon data.");
diff --git a/platform/osx/export/codesign.cpp b/platform/osx/export/codesign.cpp
index dab9f3eccb..fd044c00cc 100644
--- a/platform/osx/export/codesign.cpp
+++ b/platform/osx/export/codesign.cpp
@@ -49,8 +49,8 @@
/*************************************************************************/
String CodeSignCodeResources::hash_sha1_base64(const String &p_path) {
- FileAccessRef fa = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!fa, String(), vformat("CodeSign/CodeResources: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), String(), vformat("CodeSign/CodeResources: Can't open file: \"%s\".", p_path));
CryptoCore::SHA1Context ctx;
ctx.start();
@@ -68,14 +68,13 @@ String CodeSignCodeResources::hash_sha1_base64(const String &p_path) {
unsigned char hash[0x14];
ctx.finish(hash);
- fa->close();
return CryptoCore::b64_encode_str(hash, 0x14);
}
String CodeSignCodeResources::hash_sha256_base64(const String &p_path) {
- FileAccessRef fa = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!fa, String(), vformat("CodeSign/CodeResources: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), String(), vformat("CodeSign/CodeResources: Can't open file: \"%s\".", p_path));
CryptoCore::SHA256Context ctx;
ctx.start();
@@ -93,7 +92,6 @@ String CodeSignCodeResources::hash_sha256_base64(const String &p_path) {
unsigned char hash[0x20];
ctx.finish(hash);
- fa->close();
return CryptoCore::b64_encode_str(hash, 0x20);
}
@@ -211,16 +209,14 @@ bool CodeSignCodeResources::add_nested_file(const String &p_root, const String &
} \
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V(!da, false);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(da.is_null(), false);
Vector<String> files_to_add;
if (LipO::is_lipo(p_exepath)) {
String tmp_path_name = EditorPaths::get_singleton()->get_cache_dir().plus_file("_lipo");
Error err = da->make_dir_recursive(tmp_path_name);
- if (err != OK) {
- ERR_FAIL_V_MSG(false, vformat("CodeSign/CodeResources: Failed to create \"%s\" subfolder.", tmp_path_name));
- }
+ ERR_FAIL_COND_V_MSG(err != OK, false, vformat("CodeSign/CodeResources: Failed to create \"%s\" subfolder.", tmp_path_name));
LipO lip;
if (lip.open_file(p_exepath)) {
for (int i = 0; i < lip.get_arch_count(); i++) {
@@ -287,8 +283,8 @@ bool CodeSignCodeResources::add_nested_file(const String &p_root, const String &
}
bool CodeSignCodeResources::add_folder_recursive(const String &p_root, const String &p_path, const String &p_main_exe_path) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND_V(!da, false);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(da.is_null(), false);
Error err = da->change_dir(p_root.plus_file(p_path));
ERR_FAIL_COND_V(err != OK, false);
@@ -431,12 +427,11 @@ bool CodeSignCodeResources::save_to_file(const String &p_path) {
String text = pl.save_text();
ERR_FAIL_COND_V_MSG(text.is_empty(), false, "CodeSign/CodeResources: Generating resources PList failed.");
- FileAccessRef fa = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!fa, false, vformat("CodeSign/CodeResources: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("CodeSign/CodeResources: Can't open file: \"%s\".", p_path));
CharString cs = text.utf8();
fa->store_buffer((const uint8_t *)cs.ptr(), cs.length());
- fa->close();
return true;
}
@@ -809,8 +804,8 @@ int CodeSignRequirements::get_size() const {
return blob.size();
}
-void CodeSignRequirements::write_to_file(FileAccess *p_file) const {
- ERR_FAIL_COND_MSG(!p_file, "CodeSign/Requirements: Invalid file handle.");
+void CodeSignRequirements::write_to_file(Ref<FileAccess> p_file) const {
+ ERR_FAIL_COND_MSG(p_file.is_null(), "CodeSign/Requirements: Invalid file handle.");
p_file->store_buffer(blob.ptr(), blob.size());
}
@@ -863,8 +858,8 @@ int CodeSignEntitlementsText::get_size() const {
return blob.size();
}
-void CodeSignEntitlementsText::write_to_file(FileAccess *p_file) const {
- ERR_FAIL_COND_MSG(!p_file, "CodeSign/EntitlementsText: Invalid file handle.");
+void CodeSignEntitlementsText::write_to_file(Ref<FileAccess> p_file) const {
+ ERR_FAIL_COND_MSG(p_file.is_null(), "CodeSign/EntitlementsText: Invalid file handle.");
p_file->store_buffer(blob.ptr(), blob.size());
}
@@ -918,8 +913,8 @@ int CodeSignEntitlementsBinary::get_size() const {
return blob.size();
}
-void CodeSignEntitlementsBinary::write_to_file(FileAccess *p_file) const {
- ERR_FAIL_COND_MSG(!p_file, "CodeSign/EntitlementsBinary: Invalid file handle.");
+void CodeSignEntitlementsBinary::write_to_file(Ref<FileAccess> p_file) const {
+ ERR_FAIL_COND_MSG(p_file.is_null(), "CodeSign/EntitlementsBinary: Invalid file handle.");
p_file->store_buffer(blob.ptr(), blob.size());
}
@@ -1040,8 +1035,8 @@ int CodeSignCodeDirectory::get_size() const {
return blob.size();
}
-void CodeSignCodeDirectory::write_to_file(FileAccess *p_file) const {
- ERR_FAIL_COND_MSG(!p_file, "CodeSign/CodeDirectory: Invalid file handle.");
+void CodeSignCodeDirectory::write_to_file(Ref<FileAccess> p_file) const {
+ ERR_FAIL_COND_MSG(p_file.is_null(), "CodeSign/CodeDirectory: Invalid file handle.");
p_file->store_buffer(blob.ptr(), blob.size());
}
@@ -1086,8 +1081,8 @@ int CodeSignSignature::get_size() const {
return blob.size();
}
-void CodeSignSignature::write_to_file(FileAccess *p_file) const {
- ERR_FAIL_COND_MSG(!p_file, "CodeSign/Signature: Invalid file handle.");
+void CodeSignSignature::write_to_file(Ref<FileAccess> p_file) const {
+ ERR_FAIL_COND_MSG(p_file.is_null(), "CodeSign/Signature: Invalid file handle.");
p_file->store_buffer(blob.ptr(), blob.size());
}
@@ -1115,8 +1110,8 @@ int CodeSignSuperBlob::get_size() const {
return size;
}
-void CodeSignSuperBlob::write_to_file(FileAccess *p_file) const {
- ERR_FAIL_COND_MSG(!p_file, "CodeSign/SuperBlob: Invalid file handle.");
+void CodeSignSuperBlob::write_to_file(Ref<FileAccess> p_file) const {
+ ERR_FAIL_COND_MSG(p_file.is_null(), "CodeSign/SuperBlob: Invalid file handle.");
uint32_t size = get_size();
uint32_t data_offset = 12 + blobs.size() * 8;
@@ -1147,8 +1142,8 @@ void CodeSignSuperBlob::write_to_file(FileAccess *p_file) const {
PackedByteArray CodeSign::file_hash_sha1(const String &p_path) {
PackedByteArray file_hash;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, PackedByteArray(), vformat("CodeSign: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), PackedByteArray(), vformat("CodeSign: Can't open file: \"%s\".", p_path));
CryptoCore::SHA1Context ctx;
ctx.start();
@@ -1171,8 +1166,8 @@ PackedByteArray CodeSign::file_hash_sha1(const String &p_path) {
PackedByteArray CodeSign::file_hash_sha256(const String &p_path) {
PackedByteArray file_hash;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, PackedByteArray(), vformat("CodeSign: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), PackedByteArray(), vformat("CodeSign: Can't open file: \"%s\".", p_path));
CryptoCore::SHA256Context ctx;
ctx.start();
@@ -1208,8 +1203,8 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
String id;
String main_exe = p_exe_path;
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (!da) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da.is_null()) {
r_error_msg = TTR("Can't get filesystem access.");
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access.");
}
@@ -1522,8 +1517,8 @@ Error CodeSign::_codesign_file(bool p_use_hardened_runtime, bool p_force, const
}
Error CodeSign::codesign(bool p_use_hardened_runtime, bool p_force, const String &p_path, const String &p_ent_path, String &r_error_msg) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- if (!da) {
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da.is_null()) {
r_error_msg = TTR("Can't get filesystem access.");
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "CodeSign: Can't get filesystem access.");
}
diff --git a/platform/osx/export/codesign.h b/platform/osx/export/codesign.h
index e5e9be5c28..3a08c0ea86 100644
--- a/platform/osx/export/codesign.h
+++ b/platform/osx/export/codesign.h
@@ -132,7 +132,7 @@ public:
virtual int get_size() const = 0;
virtual uint32_t get_index_type() const = 0;
- virtual void write_to_file(FileAccess *p_file) const = 0;
+ virtual void write_to_file(Ref<FileAccess> p_file) const = 0;
};
/*************************************************************************/
@@ -168,7 +168,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000002; };
- virtual void write_to_file(FileAccess *p_file) const override;
+ virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
/*************************************************************************/
@@ -190,7 +190,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000005; };
- virtual void write_to_file(FileAccess *p_file) const override;
+ virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
/*************************************************************************/
@@ -212,7 +212,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000007; };
- virtual void write_to_file(FileAccess *p_file) const override;
+ virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
/*************************************************************************/
@@ -314,7 +314,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00000000; };
- virtual void write_to_file(FileAccess *p_file) const override;
+ virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
/*************************************************************************/
@@ -333,7 +333,7 @@ public:
virtual int get_size() const override;
virtual uint32_t get_index_type() const override { return 0x00010000; };
- virtual void write_to_file(FileAccess *p_file) const override;
+ virtual void write_to_file(Ref<FileAccess> p_file) const override;
};
/*************************************************************************/
@@ -347,7 +347,7 @@ public:
bool add_blob(const Ref<CodeSignBlob> &p_blob);
int get_size() const;
- void write_to_file(FileAccess *p_file) const;
+ void write_to_file(Ref<FileAccess> p_file) const;
};
/*************************************************************************/
diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp
index 682f722a85..94ef875072 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/osx/export/export_plugin.cpp
@@ -256,22 +256,23 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
String path = EditorPaths::get_singleton()->get_cache_dir().plus_file("icon.png");
ResourceSaver::save(path, it);
- FileAccess *f = FileAccess::open(path, FileAccess::READ);
- if (!f) {
- // Clean up generated file.
- DirAccess::remove_file_or_error(path);
- ERR_FAIL();
- }
+ {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
+ if (f.is_null()) {
+ // Clean up generated file.
+ DirAccess::remove_file_or_error(path);
+ ERR_FAIL();
+ }
- int ofs = data.size();
- uint64_t len = f->get_length();
- data.resize(data.size() + len + 8);
- f->get_buffer(&data.write[ofs + 8], len);
- memdelete(f);
- len += 8;
- len = BSWAP32(len);
- memcpy(&data.write[ofs], icon_infos[i].name, 4);
- encode_uint32(len, &data.write[ofs + 4]);
+ int ofs = data.size();
+ uint64_t len = f->get_length();
+ data.resize(data.size() + len + 8);
+ f->get_buffer(&data.write[ofs + 8], len);
+ len += 8;
+ len = BSWAP32(len);
+ memcpy(&data.write[ofs], icon_infos[i].name, 4);
+ encode_uint32(len, &data.write[ofs + 4]);
+ }
// Clean up generated file.
DirAccess::remove_file_or_error(path);
@@ -565,7 +566,7 @@ Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset
}
Error dir_access_error;
- DirAccessRef dir_access{ DirAccess::open(p_path, &dir_access_error) };
+ Ref<DirAccess> dir_access{ DirAccess::open(p_path, &dir_access_error) };
if (dir_access_error != OK) {
return dir_access_error;
@@ -603,7 +604,7 @@ Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset
return OK;
}
-Error EditorExportPlatformOSX::_copy_and_sign_files(DirAccessRef &dir_access, const String &p_src_path,
+Error EditorExportPlatformOSX::_copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path,
const String &p_in_app_path, bool p_sign_enabled,
const Ref<EditorExportPreset> &p_preset, const String &p_ent_path,
bool p_should_error_on_non_code_sign) {
@@ -633,7 +634,7 @@ Error EditorExportPlatformOSX::_copy_and_sign_files(DirAccessRef &dir_access, co
}
Error EditorExportPlatformOSX::_export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin,
- const String &p_app_path_name, DirAccessRef &dir_access,
+ const String &p_app_path_name, Ref<DirAccess> &dir_access,
bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset,
const String &p_ent_path) {
Error error{ OK };
@@ -683,8 +684,8 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
}
Error EditorExportPlatformOSX::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) {
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
f->store_line("#!/bin/sh");
f->store_line("echo -ne '\\033c\\033]0;" + p_app_name + "\\a'");
@@ -721,8 +722,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
return ERR_FILE_BAD_PATH;
}
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
if (ep.step(TTR("Creating app bundle"), 0)) {
return ERR_SKIP;
@@ -778,8 +778,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
Error err = OK;
- DirAccessRef tmp_app_dir = DirAccess::create_for_path(tmp_base_path_name);
- if (!tmp_app_dir) {
+ Ref<DirAccess> tmp_app_dir = DirAccess::create_for_path(tmp_base_path_name);
+ if (tmp_app_dir.is_null()) {
err = ERR_CANT_CREATE;
}
@@ -832,7 +832,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
{
String fname = tmp_app_path_name + "/Contents/Resources/en.lproj";
tmp_app_dir->make_dir_recursive(fname);
- FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
f->store_line("/* Localized versions of Info.plist keys */");
f->store_line("");
f->store_line("CFBundleDisplayName = \"" + ProjectSettings::get_singleton()->get("application/config/name").operator String() + "\";");
@@ -878,7 +878,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String lang = tr->get_locale();
String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj";
tmp_app_dir->make_dir_recursive(fname);
- FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
f->store_line("/* Localized versions of Info.plist keys */");
f->store_line("");
if (appnames.has(lang)) {
@@ -996,12 +996,10 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (!iconpath.is_empty()) {
if (iconpath.get_extension() == "icns") {
- FileAccess *icon = FileAccess::open(iconpath, FileAccess::READ);
- if (icon) {
+ Ref<FileAccess> icon = FileAccess::open(iconpath, FileAccess::READ);
+ if (icon.is_valid()) {
data.resize(icon->get_length());
icon->get_buffer(&data.write[0], icon->get_length());
- icon->close();
- memdelete(icon);
}
} else {
Ref<Image> icon;
@@ -1042,15 +1040,13 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
err = tmp_app_dir->make_dir_recursive(file.get_base_dir());
}
if (err == OK) {
- FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
- if (f) {
+ Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
+ if (f.is_valid()) {
f->store_buffer(data.ptr(), data.size());
- f->close();
if (is_execute) {
// chmod with 0755 if the file is executable.
FileAccess::set_unix_permissions(file, 0755);
}
- memdelete(f);
} else {
err = ERR_CANT_CREATE;
}
@@ -1094,8 +1090,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (sign_enabled && (ent_path.is_empty())) {
ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements");
- FileAccess *ent_f = FileAccess::open(ent_path, FileAccess::WRITE);
- if (ent_f) {
+ Ref<FileAccess> ent_f = FileAccess::open(ent_path, FileAccess::WRITE);
+ if (ent_f.is_valid()) {
ent_f->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
ent_f->store_line("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
ent_f->store_line("<plist version=\"1.0\">");
@@ -1216,16 +1212,13 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ent_f->store_line("</dict>");
ent_f->store_line("</plist>");
-
- ent_f->close();
- memdelete(ent_f);
} else {
err = ERR_CANT_CREATE;
}
if ((err == OK) && helpers.size() > 0) {
ent_f = FileAccess::open(hlp_ent_path, FileAccess::WRITE);
- if (ent_f) {
+ if (ent_f.is_valid()) {
ent_f->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
ent_f->store_line("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
ent_f->store_line("<plist version=\"1.0\">");
@@ -1236,9 +1229,6 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ent_f->store_line("<true/>");
ent_f->store_line("</dict>");
ent_f->store_line("</plist>");
-
- ent_f->close();
- memdelete(ent_f);
} else {
err = ERR_CANT_CREATE;
}
@@ -1246,7 +1236,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if ((err == OK) && helpers.size() > 0) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < helpers.size(); i++) {
String hlp_path = helpers[i];
err = da->copy(hlp_path, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file());
@@ -1273,7 +1263,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if (err == OK) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < shared_objects.size(); i++) {
String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path);
if (shared_objects[i].target.is_empty()) {
@@ -1337,8 +1327,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
OS::get_singleton()->move_to_trash(p_path);
}
- FileAccess *dst_f = nullptr;
- zlib_filefunc_def io_dst = zipio_create_io_from_file(&dst_f);
+ zlib_filefunc_def io_dst = zipio_create_io();
zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io_dst);
_zip_folder_recursive(zip, tmp_base_path_name, "", pkg_name);
@@ -1383,7 +1372,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) {
String dir = p_folder.is_empty() ? p_root_path : p_root_path.plus_file(p_folder);
- DirAccessRef da = DirAccess::open(dir);
+ Ref<DirAccess> da = DirAccess::open(dir);
da->list_dir_begin();
String f = da->get_next();
while (!f.is_empty()) {
@@ -1474,8 +1463,8 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
0);
- FileAccessRef fa = FileAccess::open(dir.plus_file(f), FileAccess::READ);
- if (!fa) {
+ Ref<FileAccess> fa = FileAccess::open(dir.plus_file(f), FileAccess::READ);
+ if (fa.is_null()) {
ERR_FAIL_MSG(vformat("Can't open file to read from path \"%s\".", dir.plus_file(f)));
}
const int bufsize = 16384;
diff --git a/platform/osx/export/export_plugin.h b/platform/osx/export/export_plugin.h
index b3edfb7f90..013e5eaa71 100644
--- a/platform/osx/export/export_plugin.h
+++ b/platform/osx/export/export_plugin.h
@@ -58,11 +58,11 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
Error _notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path);
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn = true);
Error _code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_should_error_on_non_code = true);
- Error _copy_and_sign_files(DirAccessRef &dir_access, const String &p_src_path, const String &p_in_app_path,
+ Error _copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path, const String &p_in_app_path,
bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path,
bool p_should_error_on_non_code_sign);
Error _export_osx_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name,
- DirAccessRef &dir_access, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset,
+ Ref<DirAccess> &dir_access, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset,
const String &p_ent_path);
Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
void _zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name);
diff --git a/platform/osx/export/lipo.cpp b/platform/osx/export/lipo.cpp
index 66d2ecdbcf..82baf18c52 100644
--- a/platform/osx/export/lipo.cpp
+++ b/platform/osx/export/lipo.cpp
@@ -35,8 +35,8 @@
#ifdef MODULE_REGEX_ENABLED
bool LipO::is_lipo(const String &p_path) {
- FileAccessRef fb = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!fb, false, vformat("LipO: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> fb = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(fb.is_null(), false, vformat("LipO: Can't open file: \"%s\".", p_path));
uint32_t magic = fb->get_32();
return (magic == 0xbebafeca || magic == 0xcafebabe || magic == 0xbfbafeca || magic == 0xcafebabf);
}
@@ -45,7 +45,7 @@ bool LipO::create_file(const String &p_output_path, const PackedStringArray &p_f
close();
fa = FileAccess::open(p_output_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!fa, false, vformat("LipO: Can't open file: \"%s\".", p_output_path));
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("LipO: Can't open file: \"%s\".", p_output_path));
uint64_t max_size = 0;
for (int i = 0; i < p_files.size(); i++) {
@@ -64,8 +64,8 @@ bool LipO::create_file(const String &p_output_path, const PackedStringArray &p_f
archs.push_back(arch);
- FileAccessRef fb = FileAccess::open(p_files[i], FileAccess::READ);
- if (!fb) {
+ Ref<FileAccess> fb = FileAccess::open(p_files[i], FileAccess::READ);
+ if (fb.is_null()) {
close();
ERR_FAIL_V_MSG(false, vformat("LipO: Can't open file: \"%s.\"", p_files[i]));
}
@@ -101,8 +101,8 @@ bool LipO::create_file(const String &p_output_path, const PackedStringArray &p_f
// Write files and padding.
for (int i = 0; i < archs.size(); i++) {
- FileAccessRef fb = FileAccess::open(p_files[i], FileAccess::READ);
- if (!fb) {
+ Ref<FileAccess> fb = FileAccess::open(p_files[i], FileAccess::READ);
+ if (fb.is_null()) {
close();
ERR_FAIL_V_MSG(false, vformat("LipO: Can't open file: \"%s.\"", p_files[i]));
}
@@ -123,7 +123,6 @@ bool LipO::create_file(const String &p_output_path, const PackedStringArray &p_f
if (br > 0) {
fa->store_buffer(step, br);
}
- fb->close();
}
return true;
}
@@ -132,7 +131,7 @@ bool LipO::open_file(const String &p_path) {
close();
fa = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!fa, false, vformat("LipO: Can't open file: \"%s\".", p_path));
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("LipO: Can't open file: \"%s\".", p_path));
uint32_t magic = fa->get_32();
if (magic == 0xbebafeca) {
@@ -197,16 +196,16 @@ bool LipO::open_file(const String &p_path) {
}
int LipO::get_arch_count() const {
- ERR_FAIL_COND_V_MSG(!fa, 0, "LipO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "LipO: File not opened.");
return archs.size();
}
bool LipO::extract_arch(int p_index, const String &p_path) {
- ERR_FAIL_COND_V_MSG(!fa, false, "LipO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, "LipO: File not opened.");
ERR_FAIL_INDEX_V(p_index, archs.size(), false);
- FileAccessRef fb = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V_MSG(!fb, false, vformat("LipO: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> fb = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V_MSG(fb.is_null(), false, vformat("LipO: Can't open file: \"%s\".", p_path));
fa->seek(archs[p_index].offset);
@@ -223,16 +222,10 @@ bool LipO::extract_arch(int p_index, const String &p_path) {
if (br > 0) {
fb->store_buffer(step, br);
}
- fb->close();
return true;
}
void LipO::close() {
- if (fa) {
- fa->close();
- memdelete(fa);
- fa = nullptr;
- }
archs.clear();
}
diff --git a/platform/osx/export/lipo.h b/platform/osx/export/lipo.h
index 68bbe42dd6..0e419be17e 100644
--- a/platform/osx/export/lipo.h
+++ b/platform/osx/export/lipo.h
@@ -50,7 +50,7 @@ class LipO : public RefCounted {
uint32_t align;
};
- FileAccess *fa = nullptr;
+ Ref<FileAccess> fa;
Vector<FatArch> archs;
static inline size_t PAD(size_t s, size_t a) {
diff --git a/platform/osx/export/macho.cpp b/platform/osx/export/macho.cpp
index 08f2a855b0..e6e67eff06 100644
--- a/platform/osx/export/macho.cpp
+++ b/platform/osx/export/macho.cpp
@@ -49,7 +49,7 @@ uint32_t MachO::seg_align(uint64_t p_vmaddr, uint32_t p_min, uint32_t p_max) {
}
bool MachO::alloc_signature(uint64_t p_size) {
- ERR_FAIL_COND_V_MSG(!fa, false, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, "MachO: File not opened.");
if (signature_offset != 0) {
// Nothing to do, already have signature load command.
return true;
@@ -103,15 +103,15 @@ bool MachO::alloc_signature(uint64_t p_size) {
}
bool MachO::is_macho(const String &p_path) {
- FileAccessRef fb = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!fb, false, vformat("MachO: Can't open file: \"%s\".", p_path));
+ Ref<FileAccess> fb = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(fb.is_null(), false, vformat("MachO: Can't open file: \"%s\".", p_path));
uint32_t magic = fb->get_32();
return (magic == 0xcefaedfe || magic == 0xfeedface || magic == 0xcffaedfe || magic == 0xfeedfacf);
}
bool MachO::open_file(const String &p_path) {
fa = FileAccess::open(p_path, FileAccess::READ_WRITE);
- ERR_FAIL_COND_V_MSG(!fa, false, vformat("MachO: Can't open file: \"%s\".", p_path));
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("MachO: Can't open file: \"%s\".", p_path));
uint32_t magic = fa->get_32();
MachHeader mach_header;
@@ -232,37 +232,37 @@ bool MachO::open_file(const String &p_path) {
}
uint64_t MachO::get_exe_base() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
return exe_base;
}
uint64_t MachO::get_exe_limit() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
return exe_limit;
}
int32_t MachO::get_align() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
return align;
}
uint32_t MachO::get_cputype() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
return cputype;
}
uint32_t MachO::get_cpusubtype() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
return cpusubtype;
}
uint64_t MachO::get_size() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
return fa->get_length();
}
uint64_t MachO::get_signature_offset() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
ERR_FAIL_COND_V_MSG(signature_offset == 0, 0, "MachO: No signature load command.");
fa->seek(signature_offset + 8);
@@ -274,7 +274,7 @@ uint64_t MachO::get_signature_offset() {
}
uint64_t MachO::get_code_limit() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
if (signature_offset == 0) {
return fa->get_length() + PAD(fa->get_length(), 16);
@@ -284,7 +284,7 @@ uint64_t MachO::get_code_limit() {
}
uint64_t MachO::get_signature_size() {
- ERR_FAIL_COND_V_MSG(!fa, 0, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), 0, "MachO: File not opened.");
ERR_FAIL_COND_V_MSG(signature_offset == 0, 0, "MachO: No signature load command.");
fa->seek(signature_offset + 12);
@@ -296,7 +296,7 @@ uint64_t MachO::get_signature_size() {
}
bool MachO::is_signed() {
- ERR_FAIL_COND_V_MSG(!fa, false, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, "MachO: File not opened.");
if (signature_offset == 0) {
return false;
}
@@ -325,7 +325,7 @@ bool MachO::is_signed() {
}
PackedByteArray MachO::get_cdhash_sha1() {
- ERR_FAIL_COND_V_MSG(!fa, PackedByteArray(), "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), PackedByteArray(), "MachO: File not opened.");
if (signature_offset == 0) {
return PackedByteArray();
}
@@ -372,7 +372,7 @@ PackedByteArray MachO::get_cdhash_sha1() {
}
PackedByteArray MachO::get_cdhash_sha256() {
- ERR_FAIL_COND_V_MSG(!fa, PackedByteArray(), "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), PackedByteArray(), "MachO: File not opened.");
if (signature_offset == 0) {
return PackedByteArray();
}
@@ -419,7 +419,7 @@ PackedByteArray MachO::get_cdhash_sha256() {
}
PackedByteArray MachO::get_requirements() {
- ERR_FAIL_COND_V_MSG(!fa, PackedByteArray(), "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), PackedByteArray(), "MachO: File not opened.");
if (signature_offset == 0) {
return PackedByteArray();
}
@@ -451,16 +451,16 @@ PackedByteArray MachO::get_requirements() {
return PackedByteArray();
}
-const FileAccess *MachO::get_file() const {
+const Ref<FileAccess> MachO::get_file() const {
return fa;
}
-FileAccess *MachO::get_file() {
+Ref<FileAccess> MachO::get_file() {
return fa;
}
bool MachO::set_signature_size(uint64_t p_size) {
- ERR_FAIL_COND_V_MSG(!fa, false, "MachO: File not opened.");
+ ERR_FAIL_COND_V_MSG(fa.is_null(), false, "MachO: File not opened.");
// Ensure signature load command exists.
ERR_FAIL_COND_V_MSG(link_edit_offset == 0, false, "MachO: No __LINKEDIT segment found.");
@@ -545,12 +545,4 @@ bool MachO::set_signature_size(uint64_t p_size) {
return true;
}
-MachO::~MachO() {
- if (fa) {
- fa->close();
- memdelete(fa);
- fa = nullptr;
- }
-}
-
#endif // MODULE_REGEX_ENABLED
diff --git a/platform/osx/export/macho.h b/platform/osx/export/macho.h
index e09906898b..6cfc3c44f5 100644
--- a/platform/osx/export/macho.h
+++ b/platform/osx/export/macho.h
@@ -161,7 +161,7 @@ class MachO : public RefCounted {
uint32_t reserved3;
};
- FileAccess *fa = nullptr;
+ Ref<FileAccess> fa;
bool swap = false;
uint64_t lc_limit = 0;
@@ -203,13 +203,11 @@ public:
PackedByteArray get_requirements();
- const FileAccess *get_file() const;
- FileAccess *get_file();
+ const Ref<FileAccess> get_file() const;
+ Ref<FileAccess> get_file();
uint64_t get_signature_size();
bool set_signature_size(uint64_t p_size);
-
- ~MachO();
};
#endif // MODULE_REGEX_ENABLED
diff --git a/platform/osx/export/plist.cpp b/platform/osx/export/plist.cpp
index 3580ad877d..d089233b80 100644
--- a/platform/osx/export/plist.cpp
+++ b/platform/osx/export/plist.cpp
@@ -343,8 +343,8 @@ PList::PList(const String &p_string) {
bool PList::load_file(const String &p_filename) {
root = Ref<PListNode>();
- FileAccessRef fb = FileAccess::open(p_filename, FileAccess::READ);
- if (!fb) {
+ Ref<FileAccess> fb = FileAccess::open(p_filename, FileAccess::READ);
+ if (fb.is_null()) {
return false;
}
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index afbd338832..33fee01c08 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -47,7 +47,7 @@
_FORCE_INLINE_ String OS_OSX::get_framework_executable(const String &p_path) {
// Append framework executable name, or return as is if p_path is not a framework.
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (da->dir_exists(p_path) && da->file_exists(p_path.plus_file(p_path.get_file().get_basename()))) {
return p_path.plus_file(p_path.get_file().get_basename());
} else {
diff --git a/platform/uwp/export/app_packager.cpp b/platform/uwp/export/app_packager.cpp
index e5a1e951e4..2f70c3e74c 100644
--- a/platform/uwp/export/app_packager.cpp
+++ b/platform/uwp/export/app_packager.cpp
@@ -46,7 +46,7 @@ String AppxPackager::hash_block(const uint8_t *p_block_data, size_t p_block_len)
}
void AppxPackager::make_block_map(const String &p_path) {
- FileAccess *tmp_file = FileAccess::open(p_path, FileAccess::WRITE);
+ Ref<FileAccess> tmp_file = FileAccess::open(p_path, FileAccess::WRITE);
tmp_file->store_string("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
tmp_file->store_string("<BlockMap xmlns=\"http://schemas.microsoft.com/appx/2010/blockmap\" HashMethod=\"http://www.w3.org/2001/04/xmlenc#sha256\">");
@@ -69,9 +69,6 @@ void AppxPackager::make_block_map(const String &p_path) {
}
tmp_file->store_string("</BlockMap>");
-
- tmp_file->close();
- memdelete(tmp_file);
}
String AppxPackager::content_type(String p_extension) {
@@ -89,7 +86,7 @@ String AppxPackager::content_type(String p_extension) {
}
void AppxPackager::make_content_types(const String &p_path) {
- FileAccess *tmp_file = FileAccess::open(p_path, FileAccess::WRITE);
+ Ref<FileAccess> tmp_file = FileAccess::open(p_path, FileAccess::WRITE);
tmp_file->store_string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
tmp_file->store_string("<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">");
@@ -118,9 +115,6 @@ void AppxPackager::make_content_types(const String &p_path) {
tmp_file->store_string("<Override PartName=\"/AppxMetadata/CodeIntegrity.cat\" ContentType=\"application/vnd.ms-pkiseccat\" />");
tmp_file->store_string("</Types>");
-
- tmp_file->close();
- memdelete(tmp_file);
}
Vector<uint8_t> AppxPackager::make_file_header(FileMeta p_file_meta) {
@@ -285,7 +279,7 @@ Vector<uint8_t> AppxPackager::make_end_of_central_record() {
return buf;
}
-void AppxPackager::init(FileAccess *p_fa) {
+void AppxPackager::init(Ref<FileAccess> p_fa) {
package = p_fa;
central_dir_offset = 0;
end_of_central_dir_offset = 0;
@@ -308,7 +302,6 @@ Error AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t
// Data for compression
z_stream strm;
- FileAccess *strm_f = nullptr;
Vector<uint8_t> strm_in;
strm_in.resize(BLOCK_SIZE);
Vector<uint8_t> strm_out;
@@ -316,7 +309,7 @@ Error AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t
if (p_compress) {
strm.zalloc = zipio_alloc;
strm.zfree = zipio_free;
- strm.opaque = &strm_f;
+ strm.opaque = Z_NULL;
strm_out.resize(BLOCK_SIZE + 8);
@@ -418,16 +411,15 @@ void AppxPackager::finish() {
const String &tmp_blockmap_file_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpblockmap.xml");
make_block_map(tmp_blockmap_file_path);
- FileAccess *blockmap_file = FileAccess::open(tmp_blockmap_file_path, FileAccess::READ);
- Vector<uint8_t> blockmap_buffer;
- blockmap_buffer.resize(blockmap_file->get_length());
-
- blockmap_file->get_buffer(blockmap_buffer.ptrw(), blockmap_buffer.size());
+ {
+ Ref<FileAccess> blockmap_file = FileAccess::open(tmp_blockmap_file_path, FileAccess::READ);
+ Vector<uint8_t> blockmap_buffer;
+ blockmap_buffer.resize(blockmap_file->get_length());
- add_file("AppxBlockMap.xml", blockmap_buffer.ptr(), blockmap_buffer.size(), -1, -1, true);
+ blockmap_file->get_buffer(blockmap_buffer.ptrw(), blockmap_buffer.size());
- blockmap_file->close();
- memdelete(blockmap_file);
+ add_file("AppxBlockMap.xml", blockmap_buffer.ptr(), blockmap_buffer.size(), -1, -1, true);
+ }
// Add content types
@@ -436,16 +428,15 @@ void AppxPackager::finish() {
const String &tmp_content_types_file_path = EditorPaths::get_singleton()->get_cache_dir().plus_file("tmpcontenttypes.xml");
make_content_types(tmp_content_types_file_path);
- FileAccess *types_file = FileAccess::open(tmp_content_types_file_path, FileAccess::READ);
- Vector<uint8_t> types_buffer;
- types_buffer.resize(types_file->get_length());
-
- types_file->get_buffer(types_buffer.ptrw(), types_buffer.size());
+ {
+ Ref<FileAccess> types_file = FileAccess::open(tmp_content_types_file_path, FileAccess::READ);
+ Vector<uint8_t> types_buffer;
+ types_buffer.resize(types_file->get_length());
- add_file("[Content_Types].xml", types_buffer.ptr(), types_buffer.size(), -1, -1, true);
+ types_file->get_buffer(types_buffer.ptrw(), types_buffer.size());
- types_file->close();
- memdelete(types_file);
+ add_file("[Content_Types].xml", types_buffer.ptr(), types_buffer.size(), -1, -1, true);
+ }
// Cleanup generated files.
DirAccess::remove_file_or_error(tmp_blockmap_file_path);
@@ -466,9 +457,7 @@ void AppxPackager::finish() {
Vector<uint8_t> end_record = make_end_of_central_record();
package->store_buffer(end_record.ptr(), end_record.size());
- package->close();
- memdelete(package);
- package = nullptr;
+ package.unref();
}
AppxPackager::AppxPackager() {}
diff --git a/platform/uwp/export/app_packager.h b/platform/uwp/export/app_packager.h
index da118449c7..a32b78bf04 100644
--- a/platform/uwp/export/app_packager.h
+++ b/platform/uwp/export/app_packager.h
@@ -87,7 +87,7 @@ class AppxPackager {
};
String progress_task;
- FileAccess *package = nullptr;
+ Ref<FileAccess> package;
Set<String> mime_types;
@@ -138,7 +138,7 @@ class AppxPackager {
public:
void set_progress_task(String p_task) { progress_task = p_task; }
- void init(FileAccess *p_fa);
+ void init(Ref<FileAccess> p_fa);
Error add_file(String p_file_name, const uint8_t *p_buffer, size_t p_len, int p_file_no, int p_total_files, bool p_compress = false);
void finish();
diff --git a/platform/uwp/export/export_plugin.cpp b/platform/uwp/export/export_plugin.cpp
index 375e860f5a..7e06bf01e3 100644
--- a/platform/uwp/export/export_plugin.cpp
+++ b/platform/uwp/export/export_plugin.cpp
@@ -295,14 +295,13 @@ Error EditorExportPlatformUWP::export_project(const Ref<EditorExportPreset> &p_p
Error err = OK;
- FileAccess *fa_pack = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> fa_pack = FileAccess::open(p_path, FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_CREATE, "Cannot create file '" + p_path + "'.");
AppxPackager packager;
packager.init(fa_pack);
- FileAccess *src_f = nullptr;
- zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
+ zlib_filefunc_def io = zipio_create_io();
if (ep.step("Creating package...", 0)) {
return ERR_SKIP;
diff --git a/platform/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h
index e2a4314ef5..ceb6d613b3 100644
--- a/platform/uwp/export/export_plugin.h
+++ b/platform/uwp/export/export_plugin.h
@@ -346,21 +346,21 @@ class EditorExportPlatformUWP : public EditorExportPlatform {
ERR_FAIL_V_MSG(data, err_string);
}
- FileAccess *f = FileAccess::open(tmp_path, FileAccess::READ, &err);
+ {
+ Ref<FileAccess> f = FileAccess::open(tmp_path, FileAccess::READ, &err);
+
+ if (err != OK) {
+ String err_string = "Couldn't open temp logo file.";
+ // Cleanup generated file.
+ DirAccess::remove_file_or_error(tmp_path);
+ EditorNode::add_io_error(err_string);
+ ERR_FAIL_V_MSG(data, err_string);
+ }
- if (err != OK) {
- String err_string = "Couldn't open temp logo file.";
- // Cleanup generated file.
- DirAccess::remove_file_or_error(tmp_path);
- EditorNode::add_io_error(err_string);
- ERR_FAIL_V_MSG(data, err_string);
+ data.resize(f->get_length());
+ f->get_buffer(data.ptrw(), data.size());
}
- data.resize(f->get_length());
- f->get_buffer(data.ptrw(), data.size());
-
- f->close();
- memdelete(f);
DirAccess::remove_file_or_error(tmp_path);
return data;
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index a8acffb0db..31bad0f053 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -1765,8 +1765,8 @@ void DisplayServerWindows::swap_buffers() {
void DisplayServerWindows::set_native_icon(const String &p_filename) {
_THREAD_SAFE_METHOD_
- FileAccess *f = FileAccess::open(p_filename, FileAccess::READ);
- ERR_FAIL_COND_MSG(!f, "Cannot open file with icon '" + p_filename + "'.");
+ Ref<FileAccess> f = FileAccess::open(p_filename, FileAccess::READ);
+ ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file with icon '" + p_filename + "'.");
ICONDIR *icon_dir = (ICONDIR *)memalloc(sizeof(ICONDIR));
int pos = 0;
@@ -1852,7 +1852,6 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) {
err = GetLastError();
ERR_FAIL_COND_MSG(err, "Error setting ICON_BIG: " + format_error_message(err) + ".");
- memdelete(f);
memdelete(icon_dir);
}
@@ -2004,7 +2003,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
Callable::CallError ce;
{
- List<WindowID>::Element *E = popup_list.front();
+ List<WindowID>::Element *E = popup_list.back();
if (E && Object::cast_to<InputEventKey>(*p_event)) {
// Redirect keyboard input to active popup.
if (windows.has(E->get())) {
diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp
index e627253739..917a0af90b 100644
--- a/platform/windows/export/export_plugin.cpp
+++ b/platform/windows/export/export_plugin.cpp
@@ -42,8 +42,8 @@ Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPres
}
Error EditorExportPlatformWindows::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) {
- FileAccessRef f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V(!f, ERR_CANT_CREATE);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
+ ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
f->store_line("@echo off");
f->store_line("title \"" + p_app_name + "\"");
@@ -359,7 +359,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
}
#ifndef WINDOWS_ENABLED
- DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
+ Ref<DirAccess> tmp_dir = DirAccess::create_for_path(p_path.get_base_dir());
err = tmp_dir->remove(p_path);
ERR_FAIL_COND_V(err != OK, err);
@@ -417,8 +417,8 @@ bool EditorExportPlatformWindows::can_export(const Ref<EditorExportPreset> &p_pr
Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) const {
// Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ_WRITE);
+ if (f.is_null()) {
return ERR_CANT_OPEN;
}
@@ -430,7 +430,6 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6
f->seek(pe_pos);
uint32_t magic = f->get_32();
if (magic != 0x00004550) {
- f->close();
return ERR_FILE_CORRUPT;
}
}
@@ -480,7 +479,5 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6
}
}
- f->close();
-
return found ? OK : ERR_FILE_CORRUPT;
}
diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp
index 4eace17cc0..1f0c9acef5 100644
--- a/scene/3d/camera_3d.cpp
+++ b/scene/3d/camera_3d.cpp
@@ -509,7 +509,7 @@ void Camera3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "projection", PROPERTY_HINT_ENUM, "Perspective,Orthogonal,Frustum"), "set_projection", "get_projection");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "set_current", "is_current");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fov", PROPERTY_HINT_RANGE, "1,179,0.1,degrees"), "set_fov", "get_fov");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.1,16384,0.01"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size", PROPERTY_HINT_RANGE, "0.001,16384,0.001"), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frustum_offset"), "set_frustum_offset", "get_frustum_offset");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp"), "set_near", "get_near");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp"), "set_far", "get_far");
@@ -557,7 +557,7 @@ void Camera3D::set_fov(real_t p_fov) {
}
void Camera3D::set_size(real_t p_size) {
- ERR_FAIL_COND(p_size < 0.1 || p_size > 16384);
+ ERR_FAIL_COND(p_size < 0.001 || p_size > 16384);
size = p_size;
_update_camera_mode();
}
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 191a04b6a0..8b457b683d 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -884,7 +884,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
Light3D *light = lights_found[i].light;
Transform3D xf = lights_found[i].xform;
- Color linear_color = light->get_color().to_linear();
+ Color linear_color = light->get_color().srgb_to_linear();
if (Object::cast_to<DirectionalLight3D>(light)) {
DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), linear_color, l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE));
@@ -1101,7 +1101,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
//#define DEBUG_SIMPLICES_AS_OBJ_FILE
#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE
{
- FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open("res://bsp.obj", FileAccess::WRITE);
for (uint32_t i = 0; i < bsp_simplices.size(); i++) {
f->store_line("o Simplex" + itos(i));
for (int j = 0; j < 4; j++) {
@@ -1118,7 +1118,6 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2]));
}
}
- f->close();
}
#endif
@@ -1150,7 +1149,7 @@ LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_pa
}
//#define DEBUG_BSP_TREE
#ifdef DEBUG_BSP_TREE
- FileAccessRef f = FileAccess::open("res://bsp.txt", FileAccess::WRITE);
+ Ref<FileAccess> f = FileAccess::open("res://bsp.txt", FileAccess::WRITE);
for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under));
}
diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp
index 62cc7c143b..bbc977647e 100644
--- a/scene/3d/node_3d.cpp
+++ b/scene/3d/node_3d.cpp
@@ -181,15 +181,6 @@ void Node3D::_notification(int p_what) {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint() && get_tree()->is_node_being_edited(this)) {
get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
- if (!data.gizmos_disabled) {
- for (int i = 0; i < data.gizmos.size(); i++) {
- data.gizmos.write[i]->create();
- if (is_visible_in_tree()) {
- data.gizmos.write[i]->redraw();
- }
- data.gizmos.write[i]->transform();
- }
- }
}
#endif
} break;
@@ -427,6 +418,7 @@ void Node3D::update_gizmos() {
}
if (data.gizmos.is_empty()) {
+ get_tree()->call_group_flags(0, SceneStringNames::get_singleton()->_spatial_editor_group, SceneStringNames::get_singleton()->_request_gizmo, this);
return;
}
if (data.gizmos_dirty) {
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 1ab2e2419e..6949e3681c 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -83,8 +83,31 @@ bool AnimationPlayer::_set(const StringName &p_name, const Variant &p_value) {
set_current_animation(p_value);
} else if (name.begins_with("anims/")) {
+ // Backwards compatibility with 3.x, add them to "default" library.
String which = name.get_slicec('/', 1);
- add_animation(which, p_value);
+
+ Ref<Animation> anim = p_value;
+ Ref<AnimationLibrary> al;
+ if (!has_animation_library(StringName())) {
+ al.instantiate();
+ add_animation_library(StringName(), al);
+ } else {
+ al = get_animation_library(StringName());
+ }
+ al->add_animation(which, anim);
+
+ } else if (name.begins_with("libraries")) {
+ Dictionary d = p_value;
+ while (animation_libraries.size()) {
+ remove_animation_library(animation_libraries[0].name);
+ }
+ List<Variant> keys;
+ d.get_key_list(&keys);
+ for (const Variant &K : keys) {
+ StringName lib_name = K;
+ Ref<AnimationLibrary> lib = d[lib_name];
+ add_animation_library(lib_name, lib);
+ }
} else if (name.begins_with("next/")) {
String which = name.get_slicec('/', 1);
@@ -117,9 +140,13 @@ bool AnimationPlayer::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = get_current_animation();
- } else if (name.begins_with("anims/")) {
- String which = name.get_slicec('/', 1);
- r_ret = get_animation(which);
+ } else if (name.begins_with("libraries")) {
+ Dictionary d;
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ d[animation_libraries[i].name] = animation_libraries[i].library;
+ }
+
+ r_ret = d;
} else if (name.begins_with("next/")) {
String which = name.get_slicec('/', 1);
@@ -173,8 +200,9 @@ void AnimationPlayer::_validate_property(PropertyInfo &property) const {
void AnimationPlayer::_get_property_list(List<PropertyInfo> *p_list) const {
List<PropertyInfo> anim_names;
+ anim_names.push_back(PropertyInfo(Variant::DICTIONARY, "libraries"));
+
for (const KeyValue<StringName, AnimationData> &E : animation_set) {
- anim_names.push_back(PropertyInfo(Variant::OBJECT, "anims/" + String(E.key), PROPERTY_HINT_RESOURCE_TYPE, "Animation", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL | PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE));
if (E.value.next != StringName()) {
anim_names.push_back(PropertyInfo(Variant::STRING, "next/" + String(E.key), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL));
}
@@ -1155,71 +1183,106 @@ void AnimationPlayer::_animation_process(double p_delta) {
}
}
-Error AnimationPlayer::add_animation(const StringName &p_name, const Ref<Animation> &p_animation) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_V_MSG(String(p_name).contains("/") || String(p_name).contains(":") || String(p_name).contains(",") || String(p_name).contains("["), ERR_INVALID_PARAMETER, "Invalid animation name: " + String(p_name) + ".");
-#endif
+void AnimationPlayer::_animation_set_cache_update() {
+ // Relatively fast function to update all animations.
- ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER);
+ animation_set_update_pass++;
+ bool clear_cache_needed = false;
- if (animation_set.has(p_name)) {
- _unref_anim(animation_set[p_name].animation);
- animation_set[p_name].animation = p_animation;
- clear_caches();
- } else {
- AnimationData ad;
- ad.animation = p_animation;
- ad.name = p_name;
- animation_set[p_name] = ad;
- }
+ // Update changed and add otherwise
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) {
+ StringName key = animation_libraries[i].name == StringName() ? K.key : StringName(String(animation_libraries[i].name) + "/" + String(K.key));
+ if (!animation_set.has(key)) {
+ AnimationData ad;
+ ad.animation = K.value;
+ ad.animation_library = animation_libraries[i].name;
+ ad.name = key;
+ ad.last_update = animation_set_update_pass;
+ animation_set.insert(ad.name, ad);
+ } else {
+ AnimationData &ad = animation_set[key];
+ if (ad.last_update != animation_set_update_pass) {
+ // Was not updated, update. If the animation is duplicated, the second one will be ignored.
+ if (ad.animation != K.value || ad.animation_library != animation_libraries[i].name) {
+ // Animation changed, update and clear caches.
+ clear_cache_needed = true;
+ ad.animation = K.value;
+ ad.animation_library = animation_libraries[i].name;
+ }
- _ref_anim(p_animation);
- notify_property_list_changed();
- return OK;
-}
+ ad.last_update = animation_set_update_pass;
+ }
+ }
+ }
+ }
-void AnimationPlayer::remove_animation(const StringName &p_name) {
- ERR_FAIL_COND(!animation_set.has(p_name));
+ // Check removed
+ List<StringName> to_erase;
+ for (const KeyValue<StringName, AnimationData> &E : animation_set) {
+ if (E.value.last_update != animation_set_update_pass) {
+ // Was not updated, must be erased
+ to_erase.push_back(E.key);
+ clear_cache_needed = true;
+ }
+ }
- stop();
- _unref_anim(animation_set[p_name].animation);
- animation_set.erase(p_name);
+ while (to_erase.size()) {
+ animation_set.erase(to_erase.front()->get());
+ to_erase.pop_front();
+ }
- clear_caches();
- notify_property_list_changed();
+ if (clear_cache_needed) {
+ // If something was modified or removed, caches need to be cleared
+ clear_caches();
+ }
}
-void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) {
- Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), varray(), CONNECT_REFERENCE_COUNTED);
-}
+void AnimationPlayer::_animation_added(const StringName &p_name, const StringName &p_library) {
+ _animation_set_cache_update();
-void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) {
- Ref<Animation>(p_anim)->disconnect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed));
+ update_configuration_warnings();
}
-void AnimationPlayer::rename_animation(const StringName &p_name, const StringName &p_new_name) {
- ERR_FAIL_COND(!animation_set.has(p_name));
- ERR_FAIL_COND(String(p_new_name).contains("/") || String(p_new_name).contains(":"));
- ERR_FAIL_COND(animation_set.has(p_new_name));
+void AnimationPlayer::_animation_removed(const StringName &p_name, const StringName &p_library) {
+ StringName name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name));
- stop();
- AnimationData ad = animation_set[p_name];
- ad.name = p_new_name;
- animation_set.erase(p_name);
- animation_set[p_new_name] = ad;
+ if (!animation_set.has(name)) {
+ return; // No need to update because not the one from the library being used.
+ }
+ _animation_set_cache_update();
+
+ // Erase blends if needed
+ List<BlendKey> to_erase;
+ for (const KeyValue<BlendKey, float> &E : blend_times) {
+ BlendKey bk = E.key;
+ if (bk.from == name || bk.to == name) {
+ to_erase.push_back(bk);
+ }
+ }
+
+ while (to_erase.size()) {
+ blend_times.erase(to_erase.front()->get());
+ to_erase.pop_front();
+ }
+
+ update_configuration_warnings();
+}
+void AnimationPlayer::_rename_animation(const StringName &p_from_name, const StringName &p_to_name) {
+ // Rename autoplay or blends if needed.
List<BlendKey> to_erase;
Map<BlendKey, float> to_insert;
for (const KeyValue<BlendKey, float> &E : blend_times) {
BlendKey bk = E.key;
BlendKey new_bk = bk;
bool erase = false;
- if (bk.from == p_name) {
- new_bk.from = p_new_name;
+ if (bk.from == p_from_name) {
+ new_bk.from = p_to_name;
erase = true;
}
- if (bk.to == p_name) {
- new_bk.to = p_new_name;
+ if (bk.to == p_from_name) {
+ new_bk.to = p_to_name;
erase = true;
}
@@ -1239,12 +1302,184 @@ void AnimationPlayer::rename_animation(const StringName &p_name, const StringNam
to_insert.erase(to_insert.front());
}
- if (autoplay == p_name) {
- autoplay = p_new_name;
+ if (autoplay == p_from_name) {
+ autoplay = p_to_name;
}
+}
+
+void AnimationPlayer::_animation_renamed(const StringName &p_name, const StringName &p_to_name, const StringName &p_library) {
+ StringName from_name = p_library == StringName() ? p_name : StringName(String(p_library) + "/" + String(p_name));
+ StringName to_name = p_library == StringName() ? p_to_name : StringName(String(p_library) + "/" + String(p_to_name));
+
+ if (!animation_set.has(from_name)) {
+ return; // No need to update because not the one from the library being used.
+ }
+ _animation_set_cache_update();
+
+ _rename_animation(from_name, to_name);
+ update_configuration_warnings();
+}
+
+Error AnimationPlayer::add_animation_library(const StringName &p_name, const Ref<AnimationLibrary> &p_animation_library) {
+ ERR_FAIL_COND_V(p_animation_library.is_null(), ERR_INVALID_PARAMETER);
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_V_MSG(String(p_name).contains("/") || String(p_name).contains(":") || String(p_name).contains(",") || String(p_name).contains("["), ERR_INVALID_PARAMETER, "Invalid animation name: " + String(p_name) + ".");
+#endif
+
+ int insert_pos = 0;
+
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ ERR_FAIL_COND_V_MSG(animation_libraries[i].name == p_name, ERR_ALREADY_EXISTS, "Can't add animation library twice with name: " + String(p_name));
+ ERR_FAIL_COND_V_MSG(animation_libraries[i].library == p_animation_library, ERR_ALREADY_EXISTS, "Can't add animation library twice (adding as '" + p_name.operator String() + "', exists as '" + animation_libraries[i].name.operator String() + "'.");
+
+ if (animation_libraries[i].name.operator String() >= p_name.operator String()) {
+ break;
+ }
+
+ insert_pos++;
+ }
+
+ AnimationLibraryData ald;
+ ald.name = p_name;
+ ald.library = p_animation_library;
+
+ animation_libraries.insert(insert_pos, ald);
+
+ ald.library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name));
+ ald.library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_name));
+ ald.library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_name));
+
+ _animation_set_cache_update();
+
+ notify_property_list_changed();
+
+ update_configuration_warnings();
+ return OK;
+}
+
+void AnimationPlayer::remove_animation_library(const StringName &p_name) {
+ int at_pos = -1;
+
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ if (animation_libraries[i].name == p_name) {
+ at_pos = i;
+ break;
+ }
+ }
+
+ ERR_FAIL_COND(at_pos == -1);
+
+ animation_libraries[at_pos].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added));
+ animation_libraries[at_pos].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added));
+ animation_libraries[at_pos].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed));
+
+ stop();
+
+ for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[at_pos].library->animations) {
+ _unref_anim(K.value);
+ }
+
+ animation_libraries.remove_at(at_pos);
+ _animation_set_cache_update();
- clear_caches();
notify_property_list_changed();
+ update_configuration_warnings();
+}
+
+void AnimationPlayer::_ref_anim(const Ref<Animation> &p_anim) {
+ Ref<Animation>(p_anim)->connect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed), varray(), CONNECT_REFERENCE_COUNTED);
+}
+
+void AnimationPlayer::_unref_anim(const Ref<Animation> &p_anim) {
+ Ref<Animation>(p_anim)->disconnect(SceneStringNames::get_singleton()->tracks_changed, callable_mp(this, &AnimationPlayer::_animation_changed));
+}
+
+void AnimationPlayer::rename_animation_library(const StringName &p_name, const StringName &p_new_name) {
+ if (p_name == p_new_name) {
+ return;
+ }
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_MSG(String(p_new_name).contains("/") || String(p_new_name).contains(":") || String(p_new_name).contains(",") || String(p_new_name).contains("["), "Invalid animation library name: " + String(p_new_name) + ".");
+#endif
+
+ bool found = false;
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ ERR_FAIL_COND_MSG(animation_libraries[i].name == p_new_name, "Can't rename animation library to another existing name: " + String(p_new_name));
+ if (animation_libraries[i].name == p_name) {
+ found = true;
+ animation_libraries[i].name = p_new_name;
+ // rename connections
+ animation_libraries[i].library->disconnect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added));
+ animation_libraries[i].library->disconnect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added));
+ animation_libraries[i].library->disconnect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed));
+
+ animation_libraries[i].library->connect(SNAME("animation_added"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_removed"), callable_mp(this, &AnimationPlayer::_animation_added), varray(p_new_name));
+ animation_libraries[i].library->connect(SNAME("animation_renamed"), callable_mp(this, &AnimationPlayer::_animation_renamed), varray(p_new_name));
+
+ for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) {
+ StringName old_name = p_name == StringName() ? K.key : StringName(String(p_name) + "/" + String(K.key));
+ StringName new_name = p_new_name == StringName() ? K.key : StringName(String(p_new_name) + "/" + String(K.key));
+ _rename_animation(old_name, new_name);
+ }
+ }
+ }
+
+ ERR_FAIL_COND(!found);
+
+ stop();
+
+ animation_libraries.sort(); // Must keep alphabetical order.
+
+ _animation_set_cache_update(); // Update cache.
+
+ notify_property_list_changed();
+}
+
+bool AnimationPlayer::has_animation_library(const StringName &p_name) const {
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ if (animation_libraries[i].name == p_name) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Ref<AnimationLibrary> AnimationPlayer::get_animation_library(const StringName &p_name) const {
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ if (animation_libraries[i].name == p_name) {
+ return animation_libraries[i].library;
+ }
+ }
+ ERR_FAIL_V(Ref<AnimationLibrary>());
+}
+
+TypedArray<StringName> AnimationPlayer::_get_animation_library_list() const {
+ TypedArray<StringName> ret;
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ ret.push_back(animation_libraries[i].name);
+ }
+ return ret;
+}
+
+void AnimationPlayer::get_animation_library_list(List<StringName> *p_libraries) const {
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ p_libraries->push_back(animation_libraries[i].name);
+ }
+}
+
+TypedArray<String> AnimationPlayer::get_configuration_warnings() const {
+ TypedArray<String> warnings = Node::get_configuration_warnings();
+
+ for (uint32_t i = 0; i < animation_libraries.size(); i++) {
+ for (const KeyValue<StringName, Ref<Animation>> &K : animation_libraries[i].library->animations) {
+ if (animation_set.has(K.key) && animation_set[K.key].animation_library != animation_libraries[i].name) {
+ warnings.push_back(vformat(RTR("Animation '%s' in library '%s' is unused because another animation with the same name exists in library '%s'."), K.key, animation_libraries[i].name, animation_set[K.key].animation_library));
+ }
+ }
+ }
+ return warnings;
}
bool AnimationPlayer::has_animation(const StringName &p_name) const {
@@ -1585,7 +1820,16 @@ StringName AnimationPlayer::find_animation(const Ref<Animation> &p_animation) co
}
}
- return "";
+ return StringName();
+}
+
+StringName AnimationPlayer::find_animation_library(const Ref<Animation> &p_animation) const {
+ for (const KeyValue<StringName, AnimationData> &E : animation_set) {
+ if (E.value.animation == p_animation) {
+ return E.value.animation_library;
+ }
+ }
+ return StringName();
}
void AnimationPlayer::set_autoplay(const String &p_name) {
@@ -1764,7 +2008,10 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
AnimationPlayer *aux_player = memnew(AnimationPlayer);
EditorNode::get_singleton()->add_child(aux_player);
- aux_player->add_animation(SceneStringNames::get_singleton()->RESET, reset_anim);
+ Ref<AnimationLibrary> al;
+ al.instantiate();
+ al->add_animation(SceneStringNames::get_singleton()->RESET, reset_anim);
+ aux_player->add_animation_library("default", al);
aux_player->set_assigned_animation(SceneStringNames::get_singleton()->RESET);
// Forcing the use of the original root because the scene where original player belongs may be not the active one
Node *root = get_node(get_root());
@@ -1792,9 +2039,13 @@ bool AnimationPlayer::can_apply_reset() const {
#endif // TOOLS_ENABLED
void AnimationPlayer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_animation", "name", "animation"), &AnimationPlayer::add_animation);
- ClassDB::bind_method(D_METHOD("remove_animation", "name"), &AnimationPlayer::remove_animation);
- ClassDB::bind_method(D_METHOD("rename_animation", "name", "newname"), &AnimationPlayer::rename_animation);
+ ClassDB::bind_method(D_METHOD("add_animation_library", "name", "library"), &AnimationPlayer::add_animation_library);
+ ClassDB::bind_method(D_METHOD("remove_animation_library", "name"), &AnimationPlayer::remove_animation_library);
+ ClassDB::bind_method(D_METHOD("rename_animation_library", "name", "newname"), &AnimationPlayer::rename_animation_library);
+ ClassDB::bind_method(D_METHOD("has_animation_library", "name"), &AnimationPlayer::has_animation_library);
+ ClassDB::bind_method(D_METHOD("get_animation_library", "name"), &AnimationPlayer::get_animation_library);
+ ClassDB::bind_method(D_METHOD("get_animation_library_list"), &AnimationPlayer::_get_animation_library_list);
+
ClassDB::bind_method(D_METHOD("has_animation", "name"), &AnimationPlayer::has_animation);
ClassDB::bind_method(D_METHOD("get_animation", "name"), &AnimationPlayer::get_animation);
ClassDB::bind_method(D_METHOD("get_animation_list"), &AnimationPlayer::_get_animation_list);
@@ -1838,6 +2089,7 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_root"), &AnimationPlayer::get_root);
ClassDB::bind_method(D_METHOD("find_animation", "animation"), &AnimationPlayer::find_animation);
+ ClassDB::bind_method(D_METHOD("find_animation_library", "animation"), &AnimationPlayer::find_animation_library);
ClassDB::bind_method(D_METHOD("clear_caches"), &AnimationPlayer::clear_caches);
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index a68f6b9d5b..1d450175ad 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -36,6 +36,7 @@
#include "scene/3d/node_3d.h"
#include "scene/3d/skeleton_3d.h"
#include "scene/resources/animation.h"
+#include "scene/resources/animation_library.h"
#ifdef TOOLS_ENABLED
class AnimatedValuesBackup : public RefCounted {
@@ -184,9 +185,20 @@ private:
StringName next;
Vector<TrackNodeCache *> node_cache;
Ref<Animation> animation;
+ StringName animation_library;
+ uint64_t last_update = 0;
};
Map<StringName, AnimationData> animation_set;
+
+ struct AnimationLibraryData {
+ StringName name;
+ Ref<AnimationLibrary> library;
+ bool operator<(const AnimationLibraryData &p_data) const { return name.operator String() < p_data.name.operator String(); }
+ };
+
+ LocalVector<AnimationLibraryData> animation_libraries;
+
struct BlendKey {
StringName from;
StringName to;
@@ -261,6 +273,15 @@ private:
bool playing = false;
+ uint64_t animation_set_update_pass = 1;
+ void _animation_set_cache_update();
+ void _animation_added(const StringName &p_name, const StringName &p_library);
+ void _animation_removed(const StringName &p_name, const StringName &p_library);
+ void _animation_renamed(const StringName &p_name, const StringName &p_to_name, const StringName &p_library);
+ void _rename_animation(const StringName &p_from_name, const StringName &p_to_name);
+
+ TypedArray<StringName> _get_animation_library_list() const;
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -272,13 +293,18 @@ protected:
public:
StringName find_animation(const Ref<Animation> &p_animation) const;
+ StringName find_animation_library(const Ref<Animation> &p_animation) const;
+
+ Error add_animation_library(const StringName &p_name, const Ref<AnimationLibrary> &p_animation_library);
+ void remove_animation_library(const StringName &p_name);
+ void rename_animation_library(const StringName &p_name, const StringName &p_new_name);
+ Ref<AnimationLibrary> get_animation_library(const StringName &p_name) const;
+ void get_animation_library_list(List<StringName> *p_animations) const;
+ bool has_animation_library(const StringName &p_name) const;
- Error add_animation(const StringName &p_name, const Ref<Animation> &p_animation);
- void remove_animation(const StringName &p_name);
- void rename_animation(const StringName &p_name, const StringName &p_new_name);
- bool has_animation(const StringName &p_name) const;
Ref<Animation> get_animation(const StringName &p_name) const;
void get_animation_list(List<StringName> *p_animations) const;
+ bool has_animation(const StringName &p_name) const;
void set_blend_time(const StringName &p_animation1, const StringName &p_animation2, float p_time);
float get_blend_time(const StringName &p_animation1, const StringName &p_animation2) const;
@@ -340,6 +366,8 @@ public:
bool can_apply_reset() const;
#endif
+ TypedArray<String> get_configuration_warnings() const override;
+
AnimationPlayer();
~AnimationPlayer();
};
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index 64c71697a5..0996eb9f9f 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -540,6 +540,11 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
List<StringName> sname;
player->get_animation_list(&sname);
+ Ref<Animation> reset_anim;
+ bool has_reset_anim = player->has_animation("RESET");
+ if (has_reset_anim) {
+ reset_anim = player->get_animation("RESET");
+ }
for (const StringName &E : sname) {
Ref<Animation> anim = player->get_animation(E);
for (int i = 0; i < anim->get_track_count(); i++) {
@@ -593,6 +598,12 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track = track_value;
+ if (has_reset_anim) {
+ int rt = reset_anim->find_track(path, track_type);
+ if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
+ track_value->init_value = reset_anim->track_get_key_value(rt, 0);
+ }
+ }
} break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
@@ -612,16 +623,17 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track_xform->skeleton = nullptr;
track_xform->bone_idx = -1;
+ bool has_rest = false;
if (path.get_subname_count() == 1 && Object::cast_to<Skeleton3D>(node_3d)) {
Skeleton3D *sk = Object::cast_to<Skeleton3D>(node_3d);
track_xform->skeleton = sk;
int bone_idx = sk->find_bone(path.get_subname(0));
if (bone_idx != -1) {
+ has_rest = true;
track_xform->bone_idx = bone_idx;
Transform3D rest = sk->get_bone_rest(bone_idx);
track_xform->init_loc = rest.origin;
- track_xform->ref_rot = rest.basis.get_rotation_quaternion();
- track_xform->init_rot = track_xform->ref_rot.log();
+ track_xform->init_rot = rest.basis.get_rotation_quaternion();
track_xform->init_scale = rest.basis.get_scale();
}
}
@@ -645,6 +657,25 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
}
}
+ // For non Skeleton3D bone animation.
+ if (has_reset_anim && !has_rest) {
+ int rt = reset_anim->find_track(path, track_type);
+ if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
+ switch (track_type) {
+ case Animation::TYPE_POSITION_3D: {
+ track_xform->init_loc = reset_anim->track_get_key_value(rt, 0);
+ } break;
+ case Animation::TYPE_ROTATION_3D: {
+ track_xform->init_rot = reset_anim->track_get_key_value(rt, 0);
+ } break;
+ case Animation::TYPE_SCALE_3D: {
+ track_xform->init_scale = reset_anim->track_get_key_value(rt, 0);
+ } break;
+ default: {
+ }
+ }
+ }
+ }
#endif // _3D_DISABLED
} break;
case Animation::TYPE_BLEND_SHAPE: {
@@ -675,6 +706,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track_bshape->object = mesh_3d;
track_bshape->object_id = mesh_3d->get_instance_id();
track = track_bshape;
+
+ if (has_reset_anim) {
+ int rt = reset_anim->find_track(path, track_type);
+ if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
+ track_bshape->init_value = reset_anim->track_get_key_value(rt, 0);
+ }
+ }
#endif
} break;
case Animation::TYPE_METHOD: {
@@ -704,6 +742,13 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
track_bezier->object_id = track_bezier->object->get_instance_id();
track = track_bezier;
+
+ if (has_reset_anim) {
+ int rt = reset_anim->find_track(path, track_type);
+ if (rt >= 0 && reset_anim->track_get_key_count(rt) > 0) {
+ track_bezier->init_value = reset_anim->track_get_key_value(rt, 0);
+ }
+ }
} break;
case Animation::TYPE_AUDIO: {
TrackCacheAudio *track_audio = memnew(TrackCacheAudio);
@@ -950,13 +995,13 @@ void AnimationTree::_process_graph(double p_delta) {
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = t->init_loc;
- t->rot = t->init_rot;
- t->scale = t->init_scale;
- }
if (track->root_motion) {
+ if (t->process_pass != process_pass) {
+ t->process_pass = process_pass;
+ t->loc = Vector3(0, 0, 0);
+ t->rot = Quaternion(0, 0, 0, 0);
+ t->scale = Vector3(0, 0, 0);
+ }
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
@@ -1026,6 +1071,12 @@ void AnimationTree::_process_graph(double p_delta) {
prev_time = !backward ? 0 : (double)a->get_length();
} else {
+ if (t->process_pass != process_pass) {
+ t->process_pass = process_pass;
+ t->loc = t->init_loc;
+ t->rot = t->init_rot;
+ t->scale = t->init_scale;
+ }
Vector3 loc;
Error err = a->position_track_interpolate(i, time, &loc);
@@ -1040,13 +1091,13 @@ void AnimationTree::_process_graph(double p_delta) {
case Animation::TYPE_ROTATION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = t->init_loc;
- t->rot = t->init_rot;
- t->scale = t->init_scale;
- }
if (track->root_motion) {
+ if (t->process_pass != process_pass) {
+ t->process_pass = process_pass;
+ t->loc = Vector3(0, 0, 0);
+ t->rot = Quaternion(0, 0, 0, 0);
+ t->scale = Vector3(0, 0, 0);
+ }
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
@@ -1091,7 +1142,7 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]);
- t->rot += (rot[1].log() - rot[0].log()) * blend;
+ t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = 0;
}
} else {
@@ -1101,7 +1152,7 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
a->rotation_track_interpolate(i, 0, &rot[1]);
- t->rot += (rot[1].log() - rot[0].log()) * blend;
+ t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = 0;
}
}
@@ -1112,10 +1163,16 @@ void AnimationTree::_process_graph(double p_delta) {
}
a->rotation_track_interpolate(i, time, &rot[1]);
- t->rot += (rot[1].log() - rot[0].log()) * blend;
+ t->rot = (t->rot * Quaternion().slerp(rot[0].inverse() * rot[1], blend)).normalized();
prev_time = !backward ? 0 : (double)a->get_length();
} else {
+ if (t->process_pass != process_pass) {
+ t->process_pass = process_pass;
+ t->loc = t->init_loc;
+ t->rot = t->init_rot;
+ t->scale = t->init_scale;
+ }
Quaternion rot;
Error err = a->rotation_track_interpolate(i, time, &rot);
@@ -1123,23 +1180,20 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
- if (signbit(rot.dot(t->ref_rot))) {
- rot = -rot;
- }
- t->rot += (rot.log() - t->init_rot) * blend;
+ t->rot = (t->rot * Quaternion().slerp(t->init_rot.inverse() * rot, blend)).normalized();
}
#endif // _3D_DISABLED
} break;
case Animation::TYPE_SCALE_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
- if (t->process_pass != process_pass) {
- t->process_pass = process_pass;
- t->loc = t->init_loc;
- t->rot = t->init_rot;
- t->scale = t->init_scale;
- }
if (track->root_motion) {
+ if (t->process_pass != process_pass) {
+ t->process_pass = process_pass;
+ t->loc = Vector3(0, 0, 0);
+ t->rot = Quaternion(0, 0, 0, 0);
+ t->scale = Vector3(0, 0, 0);
+ }
double prev_time = time - delta;
if (!backward) {
if (prev_time < 0) {
@@ -1209,6 +1263,12 @@ void AnimationTree::_process_graph(double p_delta) {
prev_time = !backward ? 0 : (double)a->get_length();
} else {
+ if (t->process_pass != process_pass) {
+ t->process_pass = process_pass;
+ t->loc = t->init_loc;
+ t->rot = t->init_rot;
+ t->scale = t->init_scale;
+ }
Vector3 scale;
Error err = a->scale_track_interpolate(i, time, &scale);
@@ -1226,7 +1286,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
- t->value = 0;
+ t->value = t->init_value;
}
float value;
@@ -1238,7 +1298,7 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
- t->value += value * blend;
+ t->value += (value - t->init_value) * blend;
#endif // _3D_DISABLED
} break;
case Animation::TYPE_VALUE: {
@@ -1256,10 +1316,14 @@ void AnimationTree::_process_graph(double p_delta) {
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
- t->value = value;
- t->value.zero();
+ if (!t->init_value) {
+ t->init_value = value;
+ t->init_value.zero();
+ }
+ t->value = t->init_value;
}
+ Variant::sub(value, t->init_value, value);
Variant::blend(t->value, value, blend, t->value);
} else {
if (blend < CMP_EPSILON) {
@@ -1303,10 +1367,10 @@ void AnimationTree::_process_graph(double p_delta) {
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
- t->value = 0;
+ t->value = t->init_value;
}
- t->value += bezier * blend;
+ t->value += (bezier - t->init_value) * blend;
} break;
case Animation::TYPE_AUDIO: {
if (blend < CMP_EPSILON) {
@@ -1516,12 +1580,11 @@ void AnimationTree::_process_graph(double p_delta) {
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
- t->rot = t->rot.exp();
if (t->root_motion) {
Transform3D xform;
xform.origin = t->loc;
- xform.basis.set_quaternion_scale(t->rot, t->scale);
+ xform.basis.set_quaternion_scale(t->rot, Vector3(1, 1, 1) + t->scale);
root_motion_transform = xform;
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 3ccb6be073..e61a297b04 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -198,8 +198,7 @@ private:
bool rot_used = false;
bool scale_used = false;
Vector3 init_loc = Vector3(0, 0, 0);
- Quaternion ref_rot = Quaternion(0, 0, 0, 1);
- Quaternion init_rot = Quaternion(0, 0, 0, 0);
+ Quaternion init_rot = Quaternion(0, 0, 0, 1);
Vector3 init_scale = Vector3(1, 1, 1);
Vector3 loc;
Quaternion rot;
@@ -212,12 +211,14 @@ private:
struct TrackCacheBlendShape : public TrackCache {
MeshInstance3D *mesh_3d = nullptr;
+ float init_value = 0;
float value = 0;
int shape_index = -1;
TrackCacheBlendShape() { type = Animation::TYPE_BLEND_SHAPE; }
};
struct TrackCacheValue : public TrackCache {
+ Variant init_value;
Variant value;
Vector<StringName> subpath;
TrackCacheValue() { type = Animation::TYPE_VALUE; }
@@ -228,6 +229,7 @@ private:
};
struct TrackCacheBezier : public TrackCache {
+ real_t init_value = 0.0;
real_t value = 0.0;
Vector<StringName> subpath;
TrackCacheBezier() {
diff --git a/scene/gui/aspect_ratio_container.cpp b/scene/gui/aspect_ratio_container.cpp
index b59eda465e..75f19ac452 100644
--- a/scene/gui/aspect_ratio_container.cpp
+++ b/scene/gui/aspect_ratio_container.cpp
@@ -172,7 +172,7 @@ void AspectRatioContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_alignment_vertical", "alignment_vertical"), &AspectRatioContainer::set_alignment_vertical);
ClassDB::bind_method(D_METHOD("get_alignment_vertical"), &AspectRatioContainer::get_alignment_vertical);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio"), "set_ratio", "get_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio", PROPERTY_HINT_RANGE, "0.001,10.0,0.0001,or_greater"), "set_ratio", "get_ratio");
ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Width Controls Height,Height Controls Width,Fit,Cover"), "set_stretch_mode", "get_stretch_mode");
ADD_GROUP("Alignment", "alignment_");
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 5e74658470..c953dbf4c3 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -798,7 +798,6 @@ void FileDialog::set_access(Access p_access) {
if (access == p_access) {
return;
}
- memdelete(dir_access);
switch (p_access) {
case ACCESS_FILESYSTEM: {
dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
@@ -1091,5 +1090,4 @@ FileDialog::~FileDialog() {
if (unregister_func) {
unregister_func(this);
}
- memdelete(dir_access);
}
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index b41a08c6c7..2e326d2949 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -82,7 +82,7 @@ private:
OptionButton *filter = nullptr;
AcceptDialog *mkdirerr = nullptr;
AcceptDialog *exterr = nullptr;
- DirAccess *dir_access = nullptr;
+ Ref<DirAccess> dir_access;
ConfirmationDialog *confirm_save = nullptr;
Label *message = nullptr;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 1394b4192f..8b7e0f22b9 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -696,7 +696,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
int type = gn->get_connection_output_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_output_hotzone(gn, j, mpos, port_size)) {
+ if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_output_hotzone(gn, j, mpos, port_size)) {
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -708,7 +708,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
int type = gn->get_connection_input_type(j);
- if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_input_hotzone(gn, j, mpos, port_size)) {
+ if ((type == connecting_type || valid_connection_types.has(ConnType(connecting_type, type))) && is_in_input_hotzone(gn, j, mpos, port_size)) {
connecting_target = true;
connecting_to = pos;
connecting_target_to = gn->get_name();
@@ -1568,26 +1568,17 @@ void GraphEdit::_update_zoom_label() {
}
void GraphEdit::add_valid_connection_type(int p_type, int p_with_type) {
- ConnType ct;
- ct.type_a = p_type;
- ct.type_b = p_with_type;
-
+ ConnType ct(p_type, p_with_type);
valid_connection_types.insert(ct);
}
void GraphEdit::remove_valid_connection_type(int p_type, int p_with_type) {
- ConnType ct;
- ct.type_a = p_type;
- ct.type_b = p_with_type;
-
+ ConnType ct(p_type, p_with_type);
valid_connection_types.erase(ct);
}
bool GraphEdit::is_valid_connection_type(int p_type, int p_with_type) const {
- ConnType ct;
- ct.type_a = p_type;
- ct.type_b = p_with_type;
-
+ ConnType ct(p_type, p_with_type);
return valid_connection_types.has(ct);
}
@@ -1646,6 +1637,7 @@ float GraphEdit::get_minimap_opacity() const {
void GraphEdit::set_minimap_enabled(bool p_enable) {
minimap_button->set_pressed(p_enable);
+ _minimap_toggled();
minimap->update();
}
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index ef0ac75cb4..51fb26b459 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -393,7 +393,6 @@ void GraphNode::_notification(int p_what) {
w -= close->get_width();
}
- title_buf->set_width(w);
title_buf->draw(get_canvas_item(), Point2(sb->get_margin(SIDE_LEFT) + title_h_offset, -title_buf->get_size().y + title_offset), title_color);
if (show_close) {
Vector2 cpos = Point2(w + sb->get_margin(SIDE_LEFT) + close_h_offset, -close->get_height() + close_offset);
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 3c1f4bb93b..35bceea606 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -50,6 +50,9 @@ void GridContainer::_notification(int p_what) {
if (!c || !c->is_visible_in_tree()) {
continue;
}
+ if (c->is_set_as_top_level()) {
+ continue;
+ }
int row = valid_controls_index / columns;
int col = valid_controls_index % columns;
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 1e8a149e11..307696c44a 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -203,16 +203,18 @@ void OptionButton::pressed() {
}
void OptionButton::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id) {
+ bool first_selectable = !has_selectable_items();
popup->add_icon_radio_check_item(p_icon, p_label, p_id);
- if (popup->get_item_count() == 1) {
- select(0);
+ if (first_selectable) {
+ select(get_item_count() - 1);
}
}
void OptionButton::add_item(const String &p_label, int p_id) {
+ bool first_selectable = !has_selectable_items();
popup->add_radio_check_item(p_label, p_id);
- if (popup->get_item_count() == 1) {
- select(0);
+ if (first_selectable) {
+ select(get_item_count() - 1);
}
}
@@ -280,6 +282,9 @@ bool OptionButton::is_item_disabled(int p_idx) const {
return popup->is_item_disabled(p_idx);
}
+bool OptionButton::is_item_separator(int p_idx) const {
+ return popup->is_item_separator(p_idx);
+}
void OptionButton::set_item_count(int p_count) {
ERR_FAIL_COND(p_count < 0);
@@ -299,12 +304,37 @@ void OptionButton::set_item_count(int p_count) {
notify_property_list_changed();
}
+bool OptionButton::has_selectable_items() const {
+ for (int i = 0; i < get_item_count(); i++) {
+ if (!is_item_disabled(i) && !is_item_separator(i)) {
+ return true;
+ }
+ }
+ return false;
+}
+int OptionButton::get_selectable_item(bool p_from_last) const {
+ if (!p_from_last) {
+ for (int i = 0; i < get_item_count(); i++) {
+ if (!is_item_disabled(i) && !is_item_separator(i)) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = get_item_count() - 1; i >= 0; i++) {
+ if (!is_item_disabled(i) && !is_item_separator(i)) {
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
int OptionButton::get_item_count() const {
return popup->get_item_count();
}
-void OptionButton::add_separator() {
- popup->add_separator();
+void OptionButton::add_separator(const String &p_text) {
+ popup->add_separator(p_text);
}
void OptionButton::clear() {
@@ -407,7 +437,8 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata);
ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &OptionButton::get_item_tooltip);
ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled);
- ClassDB::bind_method(D_METHOD("add_separator"), &OptionButton::add_separator);
+ ClassDB::bind_method(D_METHOD("is_item_separator", "idx"), &OptionButton::is_item_separator);
+ ClassDB::bind_method(D_METHOD("add_separator", "text"), &OptionButton::add_separator, DEFVAL(String()));
ClassDB::bind_method(D_METHOD("clear"), &OptionButton::clear);
ClassDB::bind_method(D_METHOD("select", "idx"), &OptionButton::select);
ClassDB::bind_method(D_METHOD("get_selected"), &OptionButton::get_selected);
@@ -420,6 +451,8 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_count", "count"), &OptionButton::set_item_count);
ClassDB::bind_method(D_METHOD("get_item_count"), &OptionButton::get_item_count);
+ ClassDB::bind_method(D_METHOD("has_selectable_items"), &OptionButton::has_selectable_items);
+ ClassDB::bind_method(D_METHOD("get_selectable_item", "from_last"), &OptionButton::get_selectable_item, DEFVAL(false));
// "selected" property must come after "item_count", otherwise GH-10213 occurs.
ADD_ARRAY_COUNT("Items", "item_count", "set_item_count", "get_item_count", "popup/item_");
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index 921b76c52a..7896132626 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -77,12 +77,16 @@ public:
int get_item_index(int p_id) const;
Variant get_item_metadata(int p_idx) const;
bool is_item_disabled(int p_idx) const;
+ bool is_item_separator(int p_idx) const;
String get_item_tooltip(int p_idx) const;
+ bool has_selectable_items() const;
+ int get_selectable_item(bool p_from_last = false) const;
+
void set_item_count(int p_count);
int get_item_count() const;
- void add_separator();
+ void add_separator(const String &p_text = "");
void clear();
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 9fc1fb072c..ab496d058c 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -169,7 +169,7 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
return -1;
}
-void PopupMenu::_activate_submenu(int p_over) {
+void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
Node *n = get_node(items[p_over].submenu);
ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[p_over].submenu + ".");
Popup *submenu_popup = Object::cast_to<Popup>(n);
@@ -213,8 +213,10 @@ void PopupMenu::_activate_submenu(int p_over) {
return;
}
+ submenu_pum->activated_by_keyboard = p_by_keyboard;
+
// If not triggered by the mouse, start the popup with its first item selected.
- if (submenu_pum->get_item_count() > 0 && Input::get_singleton()->is_action_just_pressed("ui_accept")) {
+ if (submenu_pum->get_item_count() > 0 && p_by_keyboard) {
submenu_pum->set_current_index(0);
}
@@ -323,14 +325,14 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
set_input_as_handled();
}
} else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
- if (mouse_over >= 0 && mouse_over < items.size() && !!items[mouse_over].separator && items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
- _activate_submenu(mouse_over);
+ if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && !items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
+ _activate_submenu(mouse_over, true);
set_input_as_handled();
}
} else if (p_event->is_action("ui_accept") && p_event->is_pressed()) {
if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {
if (!items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
- _activate_submenu(mouse_over);
+ _activate_submenu(mouse_over, true);
} else {
activate_item(mouse_over);
}
@@ -396,6 +398,11 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) {
+ if (m->get_velocity().is_equal_approx(Vector2())) {
+ return;
+ }
+ activated_by_keyboard = false;
+
for (const Rect2 &E : autohide_areas) {
if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E.has_point(m->get_position())) {
_close_pressed();
@@ -557,10 +564,8 @@ void PopupMenu::_draw_items() {
// Separator
item_ofs.x += items[i].h_ofs;
if (items[i].separator) {
- int sep_h = separator->get_center_size().height + separator->get_minimum_size().height;
- int sep_ofs = Math::floor((h - sep_h) / 2.0);
if (!text.is_empty() || !items[i].icon.is_null()) {
- int content_size = items[i].text_buf->get_size().width;
+ int content_size = items[i].text_buf->get_size().width + hseparation * 2;
if (!items[i].icon.is_null()) {
content_size += icon_size.width + hseparation;
}
@@ -569,12 +574,18 @@ void PopupMenu::_draw_items() {
int content_left = content_center - content_size / 2;
int content_right = content_center + content_size / 2;
if (content_left > item_ofs.x) {
+ int sep_h = labeled_separator_left->get_center_size().height + labeled_separator_left->get_minimum_size().height;
+ int sep_ofs = Math::floor((h - sep_h) / 2.0);
labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(MAX(0, content_left - item_ofs.x), sep_h)));
}
if (content_right < display_width) {
+ int sep_h = labeled_separator_right->get_center_size().height + labeled_separator_right->get_minimum_size().height;
+ int sep_ofs = Math::floor((h - sep_h) / 2.0);
labeled_separator_right->draw(ci, Rect2(Point2(content_right, item_ofs.y + sep_ofs), Size2(MAX(0, display_width - content_right), sep_h)));
}
} else {
+ int sep_h = separator->get_center_size().height + separator->get_minimum_size().height;
+ int sep_ofs = Math::floor((h - sep_h) / 2.0);
separator->draw(ci, Rect2(item_ofs + Point2(0, sep_ofs), Size2(display_width, sep_h)));
}
}
@@ -624,23 +635,28 @@ void PopupMenu::_draw_items() {
}
}
- // Text
Color font_outline_color = get_theme_color(SNAME("font_outline_color"));
int outline_size = get_theme_constant(SNAME("outline_size"));
+
+ // Text
if (items[i].separator) {
+ Color font_separator_outline_color = get_theme_color(SNAME("font_separator_outline_color"));
+ int separator_outline_size = get_theme_constant(SNAME("separator_outline_size"));
+
if (!text.is_empty()) {
Vector2 text_pos = Point2(separator_ofs, item_ofs.y + Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
if (!rtl && !items[i].icon.is_null()) {
text_pos.x += icon_size.width + hseparation;
}
- if (outline_size > 0 && font_outline_color.a > 0) {
- items[i].text_buf->draw_outline(ci, text_pos, outline_size, font_outline_color);
+ if (separator_outline_size > 0 && font_separator_outline_color.a > 0) {
+ items[i].text_buf->draw_outline(ci, text_pos, separator_outline_size, font_separator_outline_color);
}
items[i].text_buf->draw(ci, text_pos, font_separator_color);
}
} else {
item_ofs.x += icon_ofs + check_ofs;
+
if (rtl) {
Vector2 text_pos = Size2(control->get_size().width - items[i].text_buf->get_size().width - item_ofs.x, item_ofs.y) + Point2(0, Math::floor((h - items[i].text_buf->get_size().y) / 2.0));
if (outline_size > 0 && font_outline_color.a > 0) {
@@ -687,7 +703,7 @@ void PopupMenu::_draw_background() {
void PopupMenu::_minimum_lifetime_timeout() {
close_allowed = true;
// If the mouse still isn't in this popup after timer expires, close.
- if (!get_visible_rect().has_point(get_mouse_position())) {
+ if (!activated_by_keyboard && !get_visible_rect().has_point(get_mouse_position())) {
_close_pressed();
}
}
@@ -713,8 +729,8 @@ void PopupMenu::_shape_item(int p_item) {
if (items.write[p_item].dirty) {
items.write[p_item].text_buf->clear();
- Ref<Font> font = get_theme_font(SNAME("font"));
- int font_size = get_theme_font_size(SNAME("font_size"));
+ Ref<Font> font = get_theme_font(items[p_item].separator ? SNAME("font_separator") : SNAME("font"));
+ int font_size = get_theme_font_size(items[p_item].separator ? SNAME("font_separator_size") : SNAME("font_size"));
if (items[p_item].text_direction == Control::TEXT_DIRECTION_INHERITED) {
items.write[p_item].text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
@@ -772,7 +788,7 @@ void PopupMenu::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PROCESS: {
// Only used when using operating system windows.
- if (!is_embedded() && autohide_areas.size()) {
+ if (!activated_by_keyboard && !is_embedded() && autohide_areas.size()) {
Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
mouse_pos -= get_position();
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index 518ba14dae..98d76875cb 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -87,6 +87,7 @@ class PopupMenu : public Popup {
};
bool close_allowed = false;
+ bool activated_by_keyboard = false;
Timer *minimum_lifetime_timer = nullptr;
Timer *submenu_timer = nullptr;
@@ -107,7 +108,7 @@ class PopupMenu : public Popup {
void _shape_item(int p_item);
virtual void gui_input(const Ref<InputEvent> &p_event);
- void _activate_submenu(int p_over);
+ void _activate_submenu(int p_over, bool p_by_keyboard = false);
void _submenu_timeout();
uint64_t popup_time_msec = 0;
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 981766e5eb..ec13399f82 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -30,6 +30,7 @@
#include "rich_text_label.h"
+#include "core/input/input_map.h"
#include "core/math/math_defs.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -1868,6 +1869,13 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
vscroll->set_value(vscroll->get_value() + vscroll->get_page() * b->get_factor() * 0.5 / 8);
}
}
+ if (b->get_button_index() == MouseButton::RIGHT && context_menu_enabled) {
+ _generate_context_menu();
+ menu->set_position(get_screen_position() + b->get_position());
+ menu->reset_size();
+ menu->popup();
+ grab_focus();
+ }
}
Ref<InputEventPanGesture> pan_gesture = p_event;
@@ -1909,8 +1917,24 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
vscroll->set_value(vscroll->get_max());
handled = true;
}
- if (k->is_action("ui_copy")) {
- selection_copy();
+ if (is_shortcut_keys_enabled()) {
+ if (k->is_action("ui_text_select_all")) {
+ select_all();
+ handled = true;
+ }
+ if (k->is_action("ui_copy")) {
+ selection_copy();
+ handled = true;
+ }
+ }
+ if (k->is_action("ui_menu", true)) {
+ if (context_menu_enabled) {
+ _generate_context_menu();
+ menu->set_position(get_screen_position());
+ menu->reset_size();
+ menu->popup();
+ menu->grab_focus();
+ }
handled = true;
}
@@ -4171,6 +4195,32 @@ String RichTextLabel::_get_line_text(ItemFrame *p_frame, int p_line, Selection p
return text;
}
+void RichTextLabel::set_context_menu_enabled(bool p_enabled) {
+ context_menu_enabled = p_enabled;
+}
+
+bool RichTextLabel::is_context_menu_enabled() const {
+ return context_menu_enabled;
+}
+
+void RichTextLabel::set_shortcut_keys_enabled(bool p_enabled) {
+ shortcut_keys_enabled = p_enabled;
+}
+
+bool RichTextLabel::is_shortcut_keys_enabled() const {
+ return shortcut_keys_enabled;
+}
+
+// Context menu.
+PopupMenu *RichTextLabel::get_menu() const {
+ const_cast<RichTextLabel *>(this)->_generate_context_menu();
+ return menu;
+}
+
+bool RichTextLabel::is_menu_visible() const {
+ return menu && menu->is_visible();
+}
+
String RichTextLabel::get_selected_text() const {
if (!selection.active || !selection.enabled) {
return "";
@@ -4196,6 +4246,53 @@ void RichTextLabel::selection_copy() {
}
}
+void RichTextLabel::select_all() {
+ if (!selection.enabled) {
+ return;
+ }
+
+ Item *it = main;
+ Item *from_item = nullptr;
+ Item *to_item = nullptr;
+
+ while (it) {
+ if (it->type != ITEM_FRAME) {
+ if (!from_item) {
+ from_item = it;
+ } else {
+ to_item = it;
+ }
+ }
+ it = _get_next_item(it, true);
+ }
+ if (!from_item || !to_item) {
+ return;
+ }
+
+ ItemFrame *from_frame = nullptr;
+ int from_line = 0;
+ _find_frame(from_item, &from_frame, &from_line);
+ if (!from_frame) {
+ return;
+ }
+ ItemFrame *to_frame = nullptr;
+ int to_line = 0;
+ _find_frame(to_item, &to_frame, &to_line);
+ if (!to_frame) {
+ return;
+ }
+ selection.from_line = from_line;
+ selection.from_frame = from_frame;
+ selection.from_char = 0;
+ selection.from_item = from_item;
+ selection.to_line = to_line;
+ selection.to_frame = to_frame;
+ selection.to_char = to_frame->lines[to_line].char_count;
+ selection.to_item = to_item;
+ selection.active = true;
+ update();
+}
+
bool RichTextLabel::is_selection_enabled() const {
return selection.enabled;
}
@@ -4485,12 +4582,19 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_selection_enabled", "enabled"), &RichTextLabel::set_selection_enabled);
ClassDB::bind_method(D_METHOD("is_selection_enabled"), &RichTextLabel::is_selection_enabled);
+ ClassDB::bind_method(D_METHOD("set_context_menu_enabled", "enabled"), &RichTextLabel::set_context_menu_enabled);
+ ClassDB::bind_method(D_METHOD("is_context_menu_enabled"), &RichTextLabel::is_context_menu_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enabled"), &RichTextLabel::set_shortcut_keys_enabled);
+ ClassDB::bind_method(D_METHOD("is_shortcut_keys_enabled"), &RichTextLabel::is_shortcut_keys_enabled);
+
ClassDB::bind_method(D_METHOD("set_deselect_on_focus_loss_enabled", "enable"), &RichTextLabel::set_deselect_on_focus_loss_enabled);
ClassDB::bind_method(D_METHOD("is_deselect_on_focus_loss_enabled"), &RichTextLabel::is_deselect_on_focus_loss_enabled);
ClassDB::bind_method(D_METHOD("get_selection_from"), &RichTextLabel::get_selection_from);
ClassDB::bind_method(D_METHOD("get_selection_to"), &RichTextLabel::get_selection_to);
+ ClassDB::bind_method(D_METHOD("select_all"), &RichTextLabel::select_all);
ClassDB::bind_method(D_METHOD("get_selected_text"), &RichTextLabel::get_selected_text);
ClassDB::bind_method(D_METHOD("deselect"), &RichTextLabel::deselect);
@@ -4533,6 +4637,9 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_effects"), &RichTextLabel::get_effects);
ClassDB::bind_method(D_METHOD("install_effect", "effect"), &RichTextLabel::install_effect);
+ ClassDB::bind_method(D_METHOD("get_menu"), &RichTextLabel::get_menu);
+ ClassDB::bind_method(D_METHOD("is_menu_visible"), &RichTextLabel::is_menu_visible);
+
// Note: set "bbcode_enabled" first, to avoid unnecessary "text" resets.
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode");
@@ -4554,6 +4661,9 @@ void RichTextLabel::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled");
+
ADD_GROUP("Locale", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
@@ -4733,6 +4843,59 @@ Size2 RichTextLabel::get_minimum_size() const {
return size;
}
+// Context menu.
+void RichTextLabel::_generate_context_menu() {
+ if (!menu) {
+ menu = memnew(PopupMenu);
+ add_child(menu, false, INTERNAL_MODE_FRONT);
+
+ menu->connect("id_pressed", callable_mp(this, &RichTextLabel::_menu_option));
+ }
+
+ // Reorganize context menu.
+ menu->clear();
+ if (selection.enabled) {
+ menu->add_item(RTR("Copy"), MENU_COPY, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_copy") : Key::NONE);
+ menu->add_item(RTR("Select All"), MENU_SELECT_ALL, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_text_select_all") : Key::NONE);
+ }
+}
+
+Key RichTextLabel::_get_menu_action_accelerator(const String &p_action) {
+ const List<Ref<InputEvent>> *events = InputMap::get_singleton()->action_get_events(p_action);
+ if (!events) {
+ return Key::NONE;
+ }
+
+ // Use first event in the list for the accelerator.
+ const List<Ref<InputEvent>>::Element *first_event = events->front();
+ if (!first_event) {
+ return Key::NONE;
+ }
+
+ const Ref<InputEventKey> event = first_event->get();
+ if (event.is_null()) {
+ return Key::NONE;
+ }
+
+ // Use physical keycode if non-zero
+ if (event->get_physical_keycode() != Key::NONE) {
+ return event->get_physical_keycode_with_modifiers();
+ } else {
+ return event->get_keycode_with_modifiers();
+ }
+}
+
+void RichTextLabel::_menu_option(int p_option) {
+ switch (p_option) {
+ case MENU_COPY: {
+ selection_copy();
+ } break;
+ case MENU_SELECT_ALL: {
+ select_all();
+ } break;
+ }
+}
+
void RichTextLabel::_draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item *it_from, Item *it_to, int start, int end, int fbg_flag) {
Vector2i fbg_index = Vector2i(end, start);
Color last_color = Color(0, 0, 0, 0);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index b710413987..856dd52b6e 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -32,6 +32,7 @@
#define RICH_TEXT_LABEL_H
#include "rich_text_effect.h"
+#include "scene/gui/popup_menu.h"
#include "scene/gui/scroll_bar.h"
#include "scene/resources/text_paragraph.h"
@@ -91,6 +92,11 @@ public:
VC_GLYPHS_RTL,
};
+ enum MenuItems {
+ MENU_COPY,
+ MENU_SELECT_ALL,
+ };
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -420,6 +426,15 @@ private:
Selection selection;
bool deselect_on_focus_loss_enabled = true;
+ bool context_menu_enabled = false;
+ bool shortcut_keys_enabled = true;
+
+ // Context menu.
+ PopupMenu *menu = nullptr;
+ void _generate_context_menu();
+ Key _get_menu_action_accelerator(const String &p_action);
+ void _menu_option(int p_option);
+
int visible_characters = -1;
float percent_visible = 1.0;
VisibleCharactersBehavior visible_chars_behavior = VC_CHARS_BEFORE_SHAPING;
@@ -555,6 +570,12 @@ public:
void set_tab_size(int p_spaces);
int get_tab_size() const;
+ void set_context_menu_enabled(bool p_enabled);
+ bool is_context_menu_enabled() const;
+
+ void set_shortcut_keys_enabled(bool p_enabled);
+ bool is_shortcut_keys_enabled() const;
+
void set_fit_content_height(bool p_enabled);
bool is_fit_content_height_enabled() const;
@@ -584,11 +605,16 @@ public:
int get_selection_from() const;
int get_selection_to() const;
String get_selected_text() const;
+ void select_all();
void selection_copy();
void set_deselect_on_focus_loss_enabled(const bool p_enabled);
bool is_deselect_on_focus_loss_enabled() const;
void deselect();
+ // Context menu.
+ PopupMenu *get_menu() const;
+ bool is_menu_visible() const;
+
void parse_bbcode(const String &p_bbcode);
void append_text(const String &p_bbcode);
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 86969e3ef4..ff23e44cb7 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1944,44 +1944,45 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
- // SELECT ALL, SELECT WORD UNDER CARET, CUT, COPY, PASTE.
-
- if (k->is_action("ui_text_select_all", true)) {
- select_all();
- accept_event();
- return;
- }
- if (k->is_action("ui_text_select_word_under_caret", true)) {
- select_word_under_caret();
- accept_event();
- return;
- }
- if (k->is_action("ui_cut", true)) {
- cut();
- accept_event();
- return;
- }
- if (k->is_action("ui_copy", true)) {
- copy();
- accept_event();
- return;
- }
- if (k->is_action("ui_paste", true)) {
- paste();
- accept_event();
- return;
- }
+ if (is_shortcut_keys_enabled()) {
+ // SELECT ALL, SELECT WORD UNDER CARET, CUT, COPY, PASTE.
+ if (k->is_action("ui_text_select_all", true)) {
+ select_all();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_text_select_word_under_caret", true)) {
+ select_word_under_caret();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_cut", true)) {
+ cut();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_copy", true)) {
+ copy();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_paste", true)) {
+ paste();
+ accept_event();
+ return;
+ }
- // UNDO/REDO.
- if (k->is_action("ui_undo", true)) {
- undo();
- accept_event();
- return;
- }
- if (k->is_action("ui_redo", true)) {
- redo();
- accept_event();
- return;
+ // UNDO/REDO.
+ if (k->is_action("ui_undo", true)) {
+ undo();
+ accept_event();
+ return;
+ }
+ if (k->is_action("ui_redo", true)) {
+ redo();
+ accept_event();
+ return;
+ }
}
// MISC.
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index ccd24ed2cf..3c8ea4d6df 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -101,6 +101,7 @@ void TreeItem::_change_tree(Tree *p_tree) {
if (tree->popup_edited_item == this) {
tree->popup_edited_item = nullptr;
+ tree->popup_pressing_edited_item = nullptr;
tree->pressing_for_editor = false;
}
@@ -2088,7 +2089,6 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
if (!p_item->collapsed) { /* if not collapsed, check the children */
-
TreeItem *c = p_item->first_child;
int base_ofs = children_pos.y - cache.offset.y + p_draw_ofs.y;
@@ -2096,82 +2096,97 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
int prev_hl_ofs = base_ofs;
while (c) {
+ int child_h = -1;
if (htotal >= 0) {
- int child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c);
+ child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c);
+ }
- // Draw relationship lines.
- if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root)) {
- int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
- int parent_ofs = p_pos.x + cache.item_margin;
- Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
+ // Draw relationship lines.
+ if (cache.draw_relationship_lines > 0 && (!hide_root || c->parent != root)) {
+ int root_ofs = children_pos.x + ((p_item->disable_folding || hide_folding) ? cache.hseparation : cache.item_margin);
+ int parent_ofs = p_pos.x + cache.item_margin;
+ Point2i root_pos = Point2i(root_ofs, children_pos.y + label_h / 2) - cache.offset + p_draw_ofs;
- if (c->get_first_child() != nullptr) {
- root_pos -= Point2i(cache.arrow->get_width(), 0);
- }
+ if (c->get_first_child() != nullptr) {
+ root_pos -= Point2i(cache.arrow->get_width(), 0);
+ }
- float line_width = cache.relationship_line_width * Math::round(cache.base_scale);
- float parent_line_width = cache.parent_hl_line_width * Math::round(cache.base_scale);
- float children_line_width = cache.children_hl_line_width * Math::round(cache.base_scale);
+ float line_width = cache.relationship_line_width * Math::round(cache.base_scale);
+ float parent_line_width = cache.parent_hl_line_width * Math::round(cache.base_scale);
+ float children_line_width = cache.children_hl_line_width * Math::round(cache.base_scale);
- Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
+ Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs;
- int more_prev_ofs = 0;
+ int more_prev_ofs = 0;
- if (root_pos.y + line_width >= 0) {
- if (rtl) {
- root_pos.x = get_size().width - root_pos.x;
- parent_pos.x = get_size().width - parent_pos.x;
- }
+ if (root_pos.y + line_width >= 0) {
+ if (rtl) {
+ root_pos.x = get_size().width - root_pos.x;
+ parent_pos.x = get_size().width - parent_pos.x;
+ }
- // Order of parts on this bend: the horizontal line first, then the vertical line.
- if (_is_branch_selected(c)) {
- // If this item or one of its children is selected, we draw the line using parent highlight style.
+ // Order of parts on this bend: the horizontal line first, then the vertical line.
+ if (_is_branch_selected(c)) {
+ // If this item or one of its children is selected, we draw the line using parent highlight style.
+ if (htotal >= 0) {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.parent_hl_line_color, parent_line_width);
+ }
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+
+ more_prev_ofs = cache.parent_hl_line_margin;
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else if (p_item->is_selected(0)) {
+ // If parent item is selected (but this item is not), we draw the line using children highlight style.
+ // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
+ if (_is_sibling_branch_selected(c)) {
+ if (htotal >= 0) {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
+ }
RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
- more_prev_ofs = cache.parent_hl_line_margin;
prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
- } else if (p_item->is_selected(0)) {
- // If parent item is selected (but this item is not), we draw the line using children highlight style.
- // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
- if (_is_sibling_branch_selected(c)) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(parent_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
-
- prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
- } else {
+ } else {
+ if (htotal >= 0) {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(children_line_width / 2), root_pos.y), cache.children_hl_line_color, children_line_width);
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), cache.children_hl_line_color, children_line_width);
}
- } else {
- // If nothing of the above is true, we draw the line using normal style.
- // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
- if (_is_sibling_branch_selected(c)) {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(children_line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(children_line_width / 2)), cache.children_hl_line_color, children_line_width);
+ }
+ } else {
+ // If nothing of the above is true, we draw the line using normal style.
+ // Siblings of the selected branch can be drawn with a slight offset and their vertical line must appear as highlighted.
+ if (_is_sibling_branch_selected(c)) {
+ if (htotal >= 0) {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + cache.parent_hl_line_margin, root_pos.y), cache.relationship_line_color, line_width);
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
+ }
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(parent_line_width / 2)), Point2i(parent_pos.x, prev_hl_ofs), cache.parent_hl_line_color, parent_line_width);
- prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
- } else {
+ prev_hl_ofs = root_pos.y + Math::floor(parent_line_width / 2);
+ } else {
+ if (htotal >= 0) {
RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x + Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width);
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), cache.relationship_line_color, line_width);
}
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y + Math::floor(line_width / 2)), Point2i(parent_pos.x, prev_ofs + Math::floor(line_width / 2)), cache.relationship_line_color, line_width);
}
}
-
- prev_ofs = root_pos.y + more_prev_ofs;
}
- if (child_h < 0) {
- if (cache.draw_relationship_lines == 0) {
- return -1; // break, stop drawing, no need to anymore
- }
+ prev_ofs = root_pos.y + more_prev_ofs;
+ }
- htotal = -1;
- children_pos.y = cache.offset.y + p_draw_size.height;
- } else {
- htotal += child_h;
- children_pos.y += child_h;
+ if (child_h < 0) {
+ if (htotal == -1) {
+ break; // Last loop done, stop.
+ }
+
+ if (cache.draw_relationship_lines == 0) {
+ return -1; // No need to draw anymore, full stop.
}
+
+ htotal = -1;
+ children_pos.y = cache.offset.y + p_draw_size.height;
+ } else {
+ htotal += child_h;
+ children_pos.y += child_h;
}
c = c->next;
@@ -2670,8 +2685,8 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, int
}
click_handled = true;
- popup_edited_item = p_item;
- popup_edited_item_col = col;
+ popup_pressing_edited_item = p_item;
+ popup_pressing_edited_item_column = col;
pressing_item_rect = Rect2(get_global_position() + Point2i(col_ofs, _get_title_button_height() + y_ofs) - cache.offset, Size2(col_width, item_h));
pressing_for_editor_text = editor_text;
@@ -3206,10 +3221,16 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
update();
}
- if (pressing_for_editor && popup_edited_item && (popup_edited_item->get_cell_mode(popup_edited_item_col) == TreeItem::CELL_MODE_RANGE)) {
- //range drag
+ if (pressing_for_editor && popup_pressing_edited_item && (popup_pressing_edited_item->get_cell_mode(popup_pressing_edited_item_column) == TreeItem::CELL_MODE_RANGE)) {
+ /* This needs to happen now, because the popup can be closed when pressing another item, and must remain the popup edited item until it actually closes */
+ popup_edited_item = popup_pressing_edited_item;
+ popup_edited_item_col = popup_pressing_edited_item_column;
+
+ popup_pressing_edited_item = nullptr;
+ popup_pressing_edited_item_column = -1;
if (!range_drag_enabled) {
+ //range drag
Vector2 cpos = mm->get_position();
if (rtl) {
cpos.x = get_size().width - cpos.x;
@@ -3994,6 +4015,7 @@ void Tree::clear() {
selected_item = nullptr;
edited_item = nullptr;
popup_edited_item = nullptr;
+ popup_pressing_edited_item = nullptr;
update();
};
@@ -4309,12 +4331,16 @@ int Tree::get_pressed_button() const {
return pressed_button;
}
-Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column) const {
+Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column, int p_button) const {
ERR_FAIL_NULL_V(p_item, Rect2());
ERR_FAIL_COND_V(p_item->tree != this, Rect2());
if (p_column != -1) {
ERR_FAIL_INDEX_V(p_column, columns.size(), Rect2());
}
+ if (p_button != -1) {
+ ERR_FAIL_COND_V(p_column == -1, Rect2()); // pass a column if you want to pass a button
+ ERR_FAIL_INDEX_V(p_button, p_item->cells[p_column].buttons.size(), Rect2());
+ }
int ofs = get_item_offset(p_item);
int height = compute_item_height(p_item);
@@ -4332,6 +4358,19 @@ Rect2 Tree::get_item_rect(TreeItem *p_item, int p_column) const {
}
r.position.x = accum;
r.size.x = get_column_width(p_column);
+ if (p_button != -1) {
+ const TreeItem::Cell &c = p_item->cells[p_column];
+ Vector2 ofst = Vector2(r.position.x + r.size.x, r.position.y);
+ for (int j = c.buttons.size() - 1; j >= 0; j--) {
+ Ref<Texture2D> b = c.buttons[j].texture;
+ Size2 size = b->get_size() + cache.button_pressed->get_minimum_size();
+ ofst.x -= size.x;
+
+ if (j == p_button) {
+ return Rect2(ofst, size);
+ }
+ }
+ }
}
return r;
@@ -4870,7 +4909,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited_column"), &Tree::get_edited_column);
ClassDB::bind_method(D_METHOD("edit_selected"), &Tree::edit_selected);
ClassDB::bind_method(D_METHOD("get_custom_popup_rect"), &Tree::get_custom_popup_rect);
- ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column"), &Tree::get_item_rect, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column", "button_index"), &Tree::get_item_rect, DEFVAL(-1), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_item_at_position", "position"), &Tree::get_item_at_position);
ClassDB::bind_method(D_METHOD("get_column_at_position", "position"), &Tree::get_column_at_position);
ClassDB::bind_method(D_METHOD("get_drop_section_at_position", "position"), &Tree::get_drop_section_at_position);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 74ad4f94b8..b704495444 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -379,6 +379,9 @@ private:
TreeItem *selected_item = nullptr;
TreeItem *edited_item = nullptr;
+ TreeItem *popup_pressing_edited_item = nullptr; // Candidate.
+ int popup_pressing_edited_item_column = -1;
+
TreeItem *drop_mode_over = nullptr;
int drop_mode_section = 0;
@@ -673,7 +676,7 @@ public:
Rect2 get_custom_popup_rect() const;
int get_item_offset(TreeItem *p_item) const;
- Rect2 get_item_rect(TreeItem *p_item, int p_column = -1) const;
+ Rect2 get_item_rect(TreeItem *p_item, int p_column = -1, int p_button = -1) const;
bool edit_selected();
bool is_editing();
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 15d36d8230..708359f106 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -463,10 +463,10 @@ void CanvasItem::draw_dashed_line(const Point2 &p_from, const Point2 &p_to, cons
RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, off, p_to, p_color, p_width);
}
-void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width) {
+void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width, bool p_antialiased) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
- RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width, p_antialiased);
}
void CanvasItem::draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width, bool p_antialiased) {
@@ -883,10 +883,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent);
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
- ClassDB::bind_method(D_METHOD("_set_on_top", "on_top"), &CanvasItem::_set_on_top);
- ClassDB::bind_method(D_METHOD("_is_on_top"), &CanvasItem::_is_on_top);
-
- ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width"), &CanvasItem::draw_line, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash"), &CanvasItem::draw_dashed_line, DEFVAL(1.0), DEFVAL(2.0));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));
@@ -959,7 +956,6 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "self_modulate"), "set_self_modulate", "get_self_modulate");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_behind_parent"), "set_draw_behind_parent", "is_draw_behind_parent_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_on_top", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_on_top", "_is_on_top"); //compatibility
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_children"), "set_clip_children", "is_clipping_children");
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index dbc833aa5b..ad64f1ab5e 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -120,9 +120,6 @@ private:
void _notify_transform(CanvasItem *p_node);
- void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
- bool _is_on_top() const { return !is_draw_behind_parent_enabled(); }
-
static CanvasItem *current_item_drawn;
friend class Viewport;
void _update_texture_repeat_changed(bool p_propagate);
@@ -218,7 +215,7 @@ public:
/* DRAWING API */
void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, real_t p_dash = 2.0);
- void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0);
+ void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0, bool p_antialiased = false);
void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 2d5814c954..34b0e19d31 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -197,10 +197,7 @@ void HTTPRequest::cancel_request() {
thread.wait_to_finish();
}
- if (file) {
- memdelete(file);
- file = nullptr;
- }
+ file.unref();
client->close();
body.clear();
got_response = false;
@@ -365,7 +362,7 @@ bool HTTPRequest::_update_connection() {
if (!download_to_file.is_empty()) {
file = FileAccess::open(download_to_file, FileAccess::WRITE);
- if (!file) {
+ if (file.is_null()) {
call_deferred(SNAME("_request_done"), RESULT_DOWNLOAD_FILE_CANT_OPEN, response_code, response_headers, PackedByteArray());
return true;
}
@@ -381,7 +378,7 @@ bool HTTPRequest::_update_connection() {
if (chunk.size()) {
downloaded.add(chunk.size());
- if (file) {
+ if (file.is_valid()) {
const uint8_t *r = chunk.ptr();
file->store_buffer(r, chunk.size());
if (file->get_error() != OK) {
@@ -642,9 +639,3 @@ HTTPRequest::HTTPRequest() {
timer->connect("timeout", callable_mp(this, &HTTPRequest::_timeout));
add_child(timer);
}
-
-HTTPRequest::~HTTPRequest() {
- if (file) {
- memdelete(file);
- }
-}
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 8b3441f7d7..49b4b1b30c 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -84,7 +84,7 @@ private:
String download_to_file;
- FileAccess *file = nullptr;
+ Ref<FileAccess> file;
int body_len = -1;
SafeNumeric<int> downloaded;
@@ -158,7 +158,6 @@ public:
void set_https_proxy(const String &p_host, int p_port);
HTTPRequest();
- ~HTTPRequest();
};
VARIANT_ENUM_CAST(HTTPRequest::Result);
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index d005633bb5..151239c9e7 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1262,7 +1262,7 @@ void SceneTree::add_idle_callback(IdleCallback p_callback) {
void SceneTree::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
if (p_function == "change_scene") {
- DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_RESOURCES);
List<String> directories;
directories.push_back(dir_access->get_current_dir());
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index e20287c875..b78f07b6d0 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3726,7 +3726,6 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
#endif // _3D_DISABLED
@@ -3744,7 +3743,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
#ifndef _3D_DISABLED
ADD_GROUP("Scaling 3D", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Disabled (Slowest),Bilinear (Fastest),FSR (Fast)"), "set_scaling_3d_mode", "get_scaling_3d_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scaling_3d_mode", PROPERTY_HINT_ENUM, "Bilinear (Fastest),FSR 1.0 (Fast)"), "set_scaling_3d_mode", "get_scaling_3d_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scaling_3d_scale", PROPERTY_HINT_RANGE, "0.25,2.0,0.01"), "set_scaling_3d_scale", "get_scaling_3d_scale");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_mipmap_bias", PROPERTY_HINT_RANGE, "-2,2,0.1"), "set_fsr_mipmap_bias", "get_fsr_mipmap_bias");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness");
@@ -3754,6 +3753,9 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
ADD_GROUP("Audio Listener", "audio_listener_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
+#ifndef _3D_DISABLED
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
+#endif
ADD_GROUP("Physics", "physics_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking");
ADD_GROUP("GUI", "gui_");
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 2faa107fb4..8b1a4680d2 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -981,7 +981,7 @@ void Window::_window_input_text(const String &p_text) {
}
void Window::_window_drop_files(const Vector<String> &p_files) {
- emit_signal(SNAME("files_dropped"), p_files, current_screen);
+ emit_signal(SNAME("files_dropped"), p_files);
}
Viewport *Window::get_parent_viewport() const {
@@ -1066,11 +1066,9 @@ void Window::popup_centered(const Size2i &p_minsize) {
}
Rect2i popup_rect;
- if (p_minsize == Size2i()) {
- popup_rect.size = _get_contents_minimum_size();
- } else {
- popup_rect.size = p_minsize;
- }
+ Size2 contents_minsize = _get_contents_minimum_size();
+ popup_rect.size.x = MAX(p_minsize.x, contents_minsize.x);
+ popup_rect.size.y = MAX(p_minsize.y, contents_minsize.y);
popup_rect.position = parent_rect.position + (parent_rect.size - popup_rect.size) / 2;
popup(popup_rect);
@@ -1079,6 +1077,7 @@ void Window::popup_centered(const Size2i &p_minsize) {
void Window::popup_centered_ratio(float p_ratio) {
ERR_FAIL_COND(!is_inside_tree());
ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
+ ERR_FAIL_COND_MSG(p_ratio <= 0.0 || p_ratio > 1.0, "Ratio must be between 0.0 and 1.0!");
Rect2 parent_rect;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 321f633c1f..a2ab9c1f67 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -139,6 +139,7 @@
#include "scene/multiplayer/scene_cache_interface.h"
#include "scene/multiplayer/scene_replication_interface.h"
#include "scene/multiplayer/scene_rpc_interface.h"
+#include "scene/resources/animation_library.h"
#include "scene/resources/audio_stream_sample.h"
#include "scene/resources/bit_map.h"
#include "scene/resources/box_shape_3d.h"
@@ -836,6 +837,7 @@ void register_scene_types() {
GDREGISTER_CLASS(CompressedTexture2DArray);
GDREGISTER_CLASS(Animation);
+ GDREGISTER_CLASS(AnimationLibrary);
GDREGISTER_CLASS(FontData);
GDREGISTER_CLASS(Font);
GDREGISTER_CLASS(Curve);
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 0ddf164c79..e045a379d2 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -3828,7 +3828,7 @@ void Animation::_bind_methods() {
ClassDB::bind_method(D_METHOD("compress", "page_size", "fps", "split_tolerance"), &Animation::compress, DEFVAL(8192), DEFVAL(120), DEFVAL(4.0));
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "length", PROPERTY_HINT_RANGE, "0.001,99999,0.001"), "set_length", "get_length");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode"), "set_loop_mode", "get_loop_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Ping-Pong"), "set_loop_mode", "get_loop_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001"), "set_step", "get_step");
ADD_SIGNAL(MethodInfo("tracks_changed"));
diff --git a/scene/resources/animation_library.cpp b/scene/resources/animation_library.cpp
new file mode 100644
index 0000000000..229d9ab218
--- /dev/null
+++ b/scene/resources/animation_library.cpp
@@ -0,0 +1,134 @@
+/*************************************************************************/
+/* animation_library.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 "animation_library.h"
+
+Error AnimationLibrary::add_animation(const StringName &p_name, const Ref<Animation> &p_animation) {
+ ERR_FAIL_COND_V_MSG(String(p_name).contains("/") || String(p_name).contains(":") || String(p_name).contains(",") || String(p_name).contains("["), ERR_INVALID_PARAMETER, "Invalid animation name: " + String(p_name) + ".");
+ ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER);
+
+ if (animations.has(p_name)) {
+ animations.erase(p_name);
+ emit_signal(SNAME("animation_removed"), p_name);
+ }
+
+ animations.insert(p_name, p_animation);
+ emit_signal(SNAME("animation_added"), p_name);
+ notify_property_list_changed();
+ return OK;
+}
+
+void AnimationLibrary::remove_animation(const StringName &p_name) {
+ ERR_FAIL_COND(!animations.has(p_name));
+
+ animations.erase(p_name);
+ emit_signal(SNAME("animation_removed"), p_name);
+ notify_property_list_changed();
+}
+
+void AnimationLibrary::rename_animation(const StringName &p_name, const StringName &p_new_name) {
+ ERR_FAIL_COND(!animations.has(p_name));
+ ERR_FAIL_COND_MSG(String(p_new_name).contains("/") || String(p_new_name).contains(":") || String(p_new_name).contains(",") || String(p_new_name).contains("["), "Invalid animation name: " + String(p_new_name) + ".");
+ ERR_FAIL_COND(animations.has(p_new_name));
+
+ animations.insert(p_new_name, animations[p_name]);
+ animations.erase(p_name);
+ emit_signal(SNAME("animation_renamed"), p_name, p_new_name);
+}
+
+bool AnimationLibrary::has_animation(const StringName &p_name) const {
+ return animations.has(p_name);
+}
+
+Ref<Animation> AnimationLibrary::get_animation(const StringName &p_name) const {
+ ERR_FAIL_COND_V(!animations.has(p_name), Ref<Animation>());
+
+ return animations[p_name];
+}
+
+TypedArray<StringName> AnimationLibrary::_get_animation_list() const {
+ TypedArray<StringName> ret;
+ List<StringName> names;
+ get_animation_list(&names);
+ for (const StringName &K : names) {
+ ret.push_back(K);
+ }
+ return ret;
+}
+
+void AnimationLibrary::get_animation_list(List<StringName> *p_animations) const {
+ List<StringName> anims;
+
+ for (const KeyValue<StringName, Ref<Animation>> &E : animations) {
+ anims.push_back(E.key);
+ }
+
+ anims.sort_custom<StringName::AlphCompare>();
+
+ for (const StringName &E : anims) {
+ p_animations->push_back(E);
+ }
+}
+
+void AnimationLibrary::_set_data(const Dictionary &p_data) {
+ animations.clear();
+ List<Variant> keys;
+ p_data.get_key_list(&keys);
+ for (const Variant &K : keys) {
+ add_animation(K, p_data[K]);
+ }
+}
+
+Dictionary AnimationLibrary::_get_data() const {
+ Dictionary ret;
+ for (const KeyValue<StringName, Ref<Animation>> &K : animations) {
+ ret[K.key] = K.value;
+ }
+ return ret;
+}
+
+void AnimationLibrary::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_animation", "name", "animation"), &AnimationLibrary::add_animation);
+ ClassDB::bind_method(D_METHOD("remove_animation", "name"), &AnimationLibrary::remove_animation);
+ ClassDB::bind_method(D_METHOD("rename_animation", "name", "newname"), &AnimationLibrary::rename_animation);
+ ClassDB::bind_method(D_METHOD("has_animation", "name"), &AnimationLibrary::has_animation);
+ ClassDB::bind_method(D_METHOD("get_animation", "name"), &AnimationLibrary::get_animation);
+ ClassDB::bind_method(D_METHOD("get_animation_list"), &AnimationLibrary::_get_animation_list);
+
+ ClassDB::bind_method(D_METHOD("_set_data", "data"), &AnimationLibrary::_set_data);
+ ClassDB::bind_method(D_METHOD("_get_data"), &AnimationLibrary::_get_data);
+
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "_set_data", "_get_data");
+ ADD_SIGNAL(MethodInfo("animation_added", PropertyInfo(Variant::OBJECT, "name", PROPERTY_HINT_RESOURCE_TYPE, "Animation")));
+ ADD_SIGNAL(MethodInfo("animation_removed", PropertyInfo(Variant::OBJECT, "name", PROPERTY_HINT_RESOURCE_TYPE, "Animation")));
+ ADD_SIGNAL(MethodInfo("animation_renamed", PropertyInfo(Variant::OBJECT, "name", PROPERTY_HINT_RESOURCE_TYPE, "Animation"), PropertyInfo(Variant::OBJECT, "to_name", PROPERTY_HINT_RESOURCE_TYPE, "Animation")));
+}
+AnimationLibrary::AnimationLibrary() {
+}
diff --git a/servers/rendering/storage/canvas_texture_storage.h b/scene/resources/animation_library.h
index ad4c67f649..69ac5a97d2 100644
--- a/servers/rendering/storage/canvas_texture_storage.h
+++ b/scene/resources/animation_library.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* canvas_texture_storage.h */
+/* animation_library.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,24 +28,35 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CANVAS_TEXTURE_STORAGE_H
-#define CANVAS_TEXTURE_STORAGE_H
+#ifndef ANIMATION_LIBRARY_H
+#define ANIMATION_LIBRARY_H
-#include "servers/rendering_server.h"
+#include "core/variant/typed_array.h"
+#include "scene/resources/animation.h"
-class RendererCanvasTextureStorage {
-public:
- virtual ~RendererCanvasTextureStorage(){};
+class AnimationLibrary : public Resource {
+ GDCLASS(AnimationLibrary, Resource)
+
+ void _set_data(const Dictionary &p_data);
+ Dictionary _get_data() const;
+
+ TypedArray<StringName> _get_animation_list() const;
- virtual RID canvas_texture_allocate() = 0;
- virtual void canvas_texture_initialize(RID p_rid) = 0;
- virtual void canvas_texture_free(RID p_rid) = 0;
+ friend class AnimationPlayer; //for faster access
+ Map<StringName, Ref<Animation>> animations;
- virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0;
- virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
+protected:
+ static void _bind_methods();
+
+public:
+ Error add_animation(const StringName &p_name, const Ref<Animation> &p_animation);
+ void remove_animation(const StringName &p_name);
+ void rename_animation(const StringName &p_name, const StringName &p_new_name);
+ bool has_animation(const StringName &p_name) const;
+ Ref<Animation> get_animation(const StringName &p_name) const;
+ void get_animation_list(List<StringName> *p_animations) const;
- virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0;
- virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0;
+ AnimationLibrary();
};
-#endif // !CANVAS_TEXTURE_STORAGE_H
+#endif // ANIMATIONLIBRARY_H
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index 56786ac4b1..30c222bdff 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -556,9 +556,9 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
file_path += ".wav";
}
- FileAccessRef file = FileAccess::open(file_path, FileAccess::WRITE); //Overrides existing file if present
+ Ref<FileAccess> file = FileAccess::open(file_path, FileAccess::WRITE); //Overrides existing file if present
- ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
+ ERR_FAIL_COND_V(file.is_null(), ERR_FILE_CANT_WRITE);
// Create WAV Header
file->store_string("RIFF"); //ChunkID
@@ -596,8 +596,6 @@ Error AudioStreamSample::save_to_wav(const String &p_path) {
break;
}
- file->close();
-
return OK;
}
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index 667399ee75..c416a03f38 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -82,7 +82,7 @@ void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) {
if (is_collision_outline_enabled()) {
RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
// Draw the last segment as it's not drawn by `canvas_item_add_polyline()`.
- RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color);
+ RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color, 1.0, true);
}
}
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index eb71401a3a..69b8355497 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -649,11 +649,13 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("unchecked", "PopupMenu", icons["unchecked"]);
theme->set_icon("radio_checked", "PopupMenu", icons["radio_checked"]);
theme->set_icon("radio_unchecked", "PopupMenu", icons["radio_unchecked"]);
- theme->set_icon("submenu", "PopupMenu", icons["arrow_right"]);
- theme->set_icon("submenu_mirrored", "PopupMenu", icons["arrow_left"]);
+ theme->set_icon("submenu", "PopupMenu", icons["popup_menu_arrow_right"]);
+ theme->set_icon("submenu_mirrored", "PopupMenu", icons["popup_menu_arrow_left"]);
theme->set_font("font", "PopupMenu", Ref<Font>());
+ theme->set_font("font_separator", "PopupMenu", Ref<Font>());
theme->set_font_size("font_size", "PopupMenu", -1);
+ theme->set_font_size("font_separator_size", "PopupMenu", -1);
theme->set_color("font_color", "PopupMenu", control_font_color);
theme->set_color("font_accelerator_color", "PopupMenu", Color(0.7, 0.7, 0.7, 0.8));
@@ -661,10 +663,12 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_hover_color", "PopupMenu", control_font_color);
theme->set_color("font_separator_color", "PopupMenu", control_font_color);
theme->set_color("font_outline_color", "PopupMenu", Color(1, 1, 1));
+ theme->set_color("font_separator_outline_color", "PopupMenu", Color(1, 1, 1));
theme->set_constant("hseparation", "PopupMenu", 4 * scale);
theme->set_constant("vseparation", "PopupMenu", 4 * scale);
theme->set_constant("outline_size", "PopupMenu", 0);
+ theme->set_constant("separator_outline_size", "PopupMenu", 0);
theme->set_constant("item_start_padding", "PopupMenu", 2 * scale);
theme->set_constant("item_end_padding", "PopupMenu", 2 * scale);
diff --git a/scene/resources/default_theme/popup_menu_arrow_left.svg b/scene/resources/default_theme/popup_menu_arrow_left.svg
new file mode 100644
index 0000000000..8fae265a3b
--- /dev/null
+++ b/scene/resources/default_theme/popup_menu_arrow_left.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" height="16" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 8 16" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m5.4999793 11-3-3 3-3" fill="none" stroke="#b2b2b2" stroke-opacity=".45" stroke-width="2"/></svg>
diff --git a/scene/resources/default_theme/popup_menu_arrow_right.svg b/scene/resources/default_theme/popup_menu_arrow_right.svg
new file mode 100644
index 0000000000..03f05fc46e
--- /dev/null
+++ b/scene/resources/default_theme/popup_menu_arrow_right.svg
@@ -0,0 +1 @@
+<svg clip-rule="evenodd" fill-rule="evenodd" height="16" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 8 16" width="8" xmlns="http://www.w3.org/2000/svg"><path d="m2.5000207 11 3-3-3-3" fill="none" stroke="#b2b2b2" stroke-opacity=".45" stroke-width="2"/></svg>
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index 78698835fc..d92d34437e 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -189,6 +189,7 @@ void Environment::_update_ambient_light() {
void Environment::set_tonemapper(ToneMapper p_tone_mapper) {
tone_mapper = p_tone_mapper;
_update_tonemap();
+ notify_property_list_changed();
}
Environment::ToneMapper Environment::get_tonemapper() const {
@@ -1049,6 +1050,10 @@ void Environment::_validate_property(PropertyInfo &property) const {
}
}
+ if (property.name == "tonemap_white" && tone_mapper == TONE_MAPPER_LINEAR) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+
if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) {
property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL;
}
@@ -1081,6 +1086,7 @@ void Environment::_validate_property(PropertyInfo &property) const {
"auto_exposure_",
"ssr_",
"ssao_",
+ "ssil_",
"sdfgi_",
"glow_",
"adjustment_",
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 6e6ee7d3ac..efbe9c93f7 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -740,8 +740,8 @@ Error FontData::load_bitmap_font(const String &p_path) {
hinting = TextServer::HINTING_NONE;
oversampling = 1.0f;
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_CREATE, vformat(RTR("Cannot open font from file: %s."), p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, vformat(RTR("Cannot open font from file: %s."), p_path));
int base_size = 16;
int height = 0;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 781e219f1f..40edc5f198 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -270,6 +270,10 @@ PrimitiveMesh::~PrimitiveMesh() {
*/
void CapsuleMesh::_create_mesh_array(Array &p_arr) const {
+ create_mesh_array(p_arr, radius, height, radial_segments, rings);
+}
+
+void CapsuleMesh::create_mesh_array(Array &p_arr, const float radius, const float height, const int radial_segments, const int rings) {
int i, j, prevrow, thisrow, point;
float x, y, z, u, v, w;
float onethird = 1.0 / 3.0;
@@ -481,6 +485,10 @@ CapsuleMesh::CapsuleMesh() {}
*/
void BoxMesh::_create_mesh_array(Array &p_arr) const {
+ BoxMesh::create_mesh_array(p_arr, size, subdivide_w, subdivide_h, subdivide_d);
+}
+
+void BoxMesh::create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w, int subdivide_h, int subdivide_d) {
int i, j, prevrow, thisrow, point;
float x, y, z;
float onethird = 1.0 / 3.0;
@@ -732,6 +740,10 @@ BoxMesh::BoxMesh() {}
*/
void CylinderMesh::_create_mesh_array(Array &p_arr) const {
+ create_mesh_array(p_arr, top_radius, bottom_radius, height, radial_segments, rings);
+}
+
+void CylinderMesh::create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments, int rings) {
int i, j, prevrow, thisrow, point;
float x, y, z, u, v, radius;
@@ -1431,6 +1443,10 @@ Vector3 QuadMesh::get_center_offset() const {
*/
void SphereMesh::_create_mesh_array(Array &p_arr) const {
+ create_mesh_array(p_arr, radius, height, radial_segments, rings, is_hemisphere);
+}
+
+void SphereMesh::create_mesh_array(Array &p_arr, float radius, float height, int radial_segments, int rings, bool is_hemisphere) {
int i, j, prevrow, thisrow, point;
float x, y, z;
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index eef5eb3f7d..8cd05c1740 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -117,6 +117,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const override;
public:
+ static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8);
+
void set_radius(const float p_radius);
float get_radius() const;
@@ -149,6 +151,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const override;
public:
+ static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0);
+
void set_size(const Vector3 &p_size);
Vector3 get_size() const;
@@ -183,6 +187,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const override;
public:
+ static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4);
+
void set_top_radius(const float p_radius);
float get_top_radius() const;
@@ -314,6 +320,8 @@ protected:
virtual void _create_mesh_array(Array &p_arr) const override;
public:
+ static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false);
+
void set_radius(const float p_radius);
float get_radius() const;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index ed19b362eb..4b0456681b 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -738,11 +738,7 @@ void ResourceLoaderText::set_translation_remapped(bool p_remapped) {
ResourceLoaderText::ResourceLoaderText() {}
-ResourceLoaderText::~ResourceLoaderText() {
- memdelete(f);
-}
-
-void ResourceLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types) {
+void ResourceLoaderText::get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types) {
open(p_f);
ignore_resource_parsing = true;
ERR_FAIL_COND(error != OK);
@@ -798,13 +794,13 @@ void ResourceLoaderText::get_dependencies(FileAccess *p_f, List<String> *p_depen
}
}
-Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map) {
+Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const Map<String, String> &p_map) {
open(p_f, true);
ERR_FAIL_COND_V(error != OK, error);
ignore_resource_parsing = true;
//FileAccess
- FileAccess *fw = nullptr;
+ Ref<FileAccess> fw;
String base_path = local_path.get_base_dir();
@@ -814,23 +810,20 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
Error err = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &rp);
if (err != OK) {
- if (fw) {
- memdelete(fw);
- }
error = ERR_FILE_CORRUPT;
ERR_FAIL_V(error);
}
if (next_tag.name != "ext_resource") {
//nothing was done
- if (!fw) {
+ if (fw.is_null()) {
return OK;
}
break;
} else {
- if (!fw) {
+ if (fw.is_null()) {
fw = FileAccess::open(p_path + ".depren", FileAccess::WRITE);
if (is_scene) {
fw->store_line("[gd_scene load_steps=" + itos(resources_total) + " format=" + itos(FORMAT_VERSION) + "]\n");
@@ -840,7 +833,6 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
}
if (!next_tag.fields.has("path") || !next_tag.fields.has("id") || !next_tag.fields.has("type")) {
- memdelete(fw);
error = ERR_FILE_CORRUPT;
ERR_FAIL_V(error);
}
@@ -898,24 +890,22 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
fw->store_8(c);
c = f->get_8();
}
- f->close();
+ f.unref();
bool all_ok = fw->get_error() == OK;
- memdelete(fw);
-
if (!all_ok) {
return ERR_CANT_CREATE;
}
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(p_path);
da->rename(p_path + ".depren", p_path);
return OK;
}
-void ResourceLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) {
+void ResourceLoaderText::open(Ref<FileAccess> p_f, bool p_skip_first_tag) {
error = OK;
lines = 1;
@@ -992,23 +982,23 @@ void ResourceLoaderText::open(FileAccess *p_f, bool p_skip_first_tag) {
rp.userdata = this;
}
-static void bs_save_unicode_string(FileAccess *f, const String &p_string, bool p_bit_on_len = false) {
+static void bs_save_unicode_string(Ref<FileAccess> p_f, const String &p_string, bool p_bit_on_len = false) {
CharString utf8 = p_string.utf8();
if (p_bit_on_len) {
- f->store_32((utf8.length() + 1) | 0x80000000);
+ p_f->store_32((utf8.length() + 1) | 0x80000000);
} else {
- f->store_32(utf8.length() + 1);
+ p_f->store_32(utf8.length() + 1);
}
- f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
+ p_f->store_buffer((const uint8_t *)utf8.get_data(), utf8.length() + 1);
}
-Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path) {
+Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_path) {
if (error) {
return error;
}
- FileAccessRef wf = FileAccess::open(p_path, FileAccess::WRITE);
- if (!wf) {
+ Ref<FileAccess> wf = FileAccess::open(p_path, FileAccess::WRITE);
+ if (wf.is_null()) {
return ERR_CANT_OPEN;
}
@@ -1023,7 +1013,7 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
static const int save_format_version = 3; //use format version 3 for saving
wf->store_32(save_format_version);
- bs_save_unicode_string(wf.f, is_scene ? "PackedScene" : resource_type);
+ bs_save_unicode_string(wf, is_scene ? "PackedScene" : resource_type);
wf->store_64(0); //offset to import metadata, this is no longer used
wf->store_32(ResourceFormatSaverBinaryInstance::FORMAT_FLAG_NAMED_SCENE_IDS | ResourceFormatSaverBinaryInstance::FORMAT_FLAG_UIDS);
@@ -1078,8 +1068,8 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
uid = ResourceUID::get_singleton()->text_to_id(uidt);
}
- bs_save_unicode_string(wf.f, type);
- bs_save_unicode_string(wf.f, path);
+ bs_save_unicode_string(wf, type);
+ bs_save_unicode_string(wf, path);
wf->store_64(uid);
int lindex = dummy_read.external_resources.size();
@@ -1108,146 +1098,145 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
wf->store_32(0); //zero sub resources, still parsing them
String temp_file = p_path + ".temp";
- FileAccessRef wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
- if (!wf2) {
- return ERR_CANT_OPEN;
- }
-
Vector<uint64_t> local_offsets;
Vector<uint64_t> local_pointers_pos;
+ {
+ Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
+ if (wf2.is_null()) {
+ return ERR_CANT_OPEN;
+ }
- while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
- String type;
- int id = -1;
- bool main_res;
+ while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
+ String type;
+ int id = -1;
+ bool main_res;
- if (next_tag.name == "sub_resource") {
- if (!next_tag.fields.has("type")) {
- error = ERR_FILE_CORRUPT;
- error_text = "Missing 'type' in external resource tag";
- _printerr();
- return error;
- }
+ if (next_tag.name == "sub_resource") {
+ if (!next_tag.fields.has("type")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'type' in external resource tag";
+ _printerr();
+ return error;
+ }
- if (!next_tag.fields.has("id")) {
- error = ERR_FILE_CORRUPT;
- error_text = "Missing 'id' in external resource tag";
- _printerr();
- return error;
+ if (!next_tag.fields.has("id")) {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Missing 'id' in external resource tag";
+ _printerr();
+ return error;
+ }
+
+ type = next_tag.fields["type"];
+ id = next_tag.fields["id"];
+ main_res = false;
+ } else {
+ type = res_type;
+ id = 0; //used for last anyway
+ main_res = true;
}
- type = next_tag.fields["type"];
- id = next_tag.fields["id"];
- main_res = false;
- } else {
- type = res_type;
- id = 0; //used for last anyway
- main_res = true;
- }
+ local_offsets.push_back(wf2->get_position());
- local_offsets.push_back(wf2->get_position());
+ bs_save_unicode_string(wf, "local://" + itos(id));
+ local_pointers_pos.push_back(wf->get_position());
+ wf->store_64(0); //temp local offset
- bs_save_unicode_string(wf, "local://" + itos(id));
- local_pointers_pos.push_back(wf->get_position());
- wf->store_64(0); //temp local offset
+ bs_save_unicode_string(wf2, type);
+ uint64_t propcount_ofs = wf2->get_position();
+ wf2->store_32(0);
- bs_save_unicode_string(wf2, type);
- uint64_t propcount_ofs = wf2->get_position();
- wf2->store_32(0);
+ int prop_count = 0;
- int prop_count = 0;
+ while (true) {
+ String assign;
+ Variant value;
- while (true) {
- String assign;
- Variant value;
+ error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
- error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp);
+ if (error) {
+ if (main_res && error == ERR_FILE_EOF) {
+ next_tag.name = ""; //exit
+ break;
+ }
- if (error) {
- if (main_res && error == ERR_FILE_EOF) {
- next_tag.name = ""; //exit
- break;
+ _printerr();
+ return error;
}
- _printerr();
- return error;
+ if (!assign.is_empty()) {
+ Map<StringName, int> empty_string_map; //unused
+ bs_save_unicode_string(wf2, assign, true);
+ ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
+ prop_count++;
+
+ } else if (!next_tag.name.is_empty()) {
+ error = OK;
+ break;
+ } else {
+ error = ERR_FILE_CORRUPT;
+ error_text = "Premature end of file while parsing [sub_resource]";
+ _printerr();
+ return error;
+ }
}
- if (!assign.is_empty()) {
- Map<StringName, int> empty_string_map; //unused
- bs_save_unicode_string(wf2, assign, true);
- ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
- prop_count++;
+ wf2->seek(propcount_ofs);
+ wf2->store_32(prop_count);
+ wf2->seek_end();
+ }
- } else if (!next_tag.name.is_empty()) {
- error = OK;
- break;
- } else {
- error = ERR_FILE_CORRUPT;
- error_text = "Premature end of file while parsing [sub_resource]";
+ if (next_tag.name == "node") {
+ //this is a node, must save one more!
+
+ if (!is_scene) {
+ error_text += "found the 'node' tag on a resource file!";
_printerr();
+ error = ERR_FILE_CORRUPT;
return error;
}
- }
-
- wf2->seek(propcount_ofs);
- wf2->store_32(prop_count);
- wf2->seek_end();
- }
- if (next_tag.name == "node") {
- //this is a node, must save one more!
+ Ref<PackedScene> packed_scene = _parse_node_tag(rp);
- if (!is_scene) {
- error_text += "found the 'node' tag on a resource file!";
- _printerr();
- error = ERR_FILE_CORRUPT;
- return error;
- }
+ if (!packed_scene.is_valid()) {
+ return error;
+ }
- Ref<PackedScene> packed_scene = _parse_node_tag(rp);
+ error = OK;
+ //get it here
+ List<PropertyInfo> props;
+ packed_scene->get_property_list(&props);
- if (!packed_scene.is_valid()) {
- return error;
- }
+ bs_save_unicode_string(wf, "local://0");
+ local_pointers_pos.push_back(wf->get_position());
+ wf->store_64(0); //temp local offset
- error = OK;
- //get it here
- List<PropertyInfo> props;
- packed_scene->get_property_list(&props);
+ local_offsets.push_back(wf2->get_position());
+ bs_save_unicode_string(wf2, "PackedScene");
+ uint64_t propcount_ofs = wf2->get_position();
+ wf2->store_32(0);
- bs_save_unicode_string(wf, "local://0");
- local_pointers_pos.push_back(wf->get_position());
- wf->store_64(0); //temp local offset
+ int prop_count = 0;
- local_offsets.push_back(wf2->get_position());
- bs_save_unicode_string(wf2, "PackedScene");
- uint64_t propcount_ofs = wf2->get_position();
- wf2->store_32(0);
+ for (const PropertyInfo &E : props) {
+ if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
+ continue;
+ }
- int prop_count = 0;
+ String name = E.name;
+ Variant value = packed_scene->get(name);
- for (const PropertyInfo &E : props) {
- if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
- continue;
+ Map<StringName, int> empty_string_map; //unused
+ bs_save_unicode_string(wf2, name, true);
+ ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
+ prop_count++;
}
- String name = E.name;
- Variant value = packed_scene->get(name);
-
- Map<StringName, int> empty_string_map; //unused
- bs_save_unicode_string(wf2, name, true);
- ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map);
- prop_count++;
+ wf2->seek(propcount_ofs);
+ wf2->store_32(prop_count);
+ wf2->seek_end();
}
-
- wf2->seek(propcount_ofs);
- wf2->store_32(prop_count);
- wf2->seek_end();
}
- wf2->close();
-
uint64_t offset_from = wf->get_position();
wf->seek(sub_res_count_pos); //plus one because the saved one
wf->store_32(local_offsets.size());
@@ -1262,18 +1251,16 @@ Error ResourceLoaderText::save_as_binary(FileAccess *p_f, const String &p_path)
Vector<uint8_t> data = FileAccess::get_file_as_array(temp_file);
wf->store_buffer(data.ptr(), data.size());
{
- DirAccessRef dar = DirAccess::open(temp_file.get_base_dir());
+ Ref<DirAccess> dar = DirAccess::open(temp_file.get_base_dir());
dar->remove(temp_file);
}
wf->store_buffer((const uint8_t *)"RSRC", 4); //magic at end
- wf->close();
-
return OK;
}
-String ResourceLoaderText::recognize(FileAccess *p_f) {
+String ResourceLoaderText::recognize(Ref<FileAccess> p_f) {
error = OK;
lines = 1;
@@ -1317,7 +1304,7 @@ String ResourceLoaderText::recognize(FileAccess *p_f) {
return tag.fields["type"];
}
-ResourceUID::ID ResourceLoaderText::get_uid(FileAccess *p_f) {
+ResourceUID::ID ResourceLoaderText::get_uid(Ref<FileAccess> p_f) {
error = OK;
lines = 1;
@@ -1352,7 +1339,7 @@ RES ResourceFormatLoaderText::load(const String &p_path, const String &p_origina
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, RES(), "Cannot open file '" + p_path + "'.");
@@ -1407,8 +1394,8 @@ String ResourceFormatLoaderText::get_resource_type(const String &p_path) const {
// ...for anything else must test...
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
return ""; //could not read
}
@@ -1426,8 +1413,8 @@ ResourceUID::ID ResourceFormatLoaderText::get_resource_uid(const String &p_path)
return ResourceUID::INVALID_ID;
}
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
return ResourceUID::INVALID_ID; //could not read
}
@@ -1438,8 +1425,8 @@ ResourceUID::ID ResourceFormatLoaderText::get_resource_uid(const String &p_path)
}
void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
ERR_FAIL();
}
@@ -1450,8 +1437,8 @@ void ResourceFormatLoaderText::get_dependencies(const String &p_path, List<Strin
}
Error ResourceFormatLoaderText::rename_dependencies(const String &p_path, const Map<String, String> &p_map) {
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ if (f.is_null()) {
ERR_FAIL_V(ERR_CANT_OPEN);
}
@@ -1465,7 +1452,7 @@ ResourceFormatLoaderText *ResourceFormatLoaderText::singleton = nullptr;
Error ResourceFormatLoaderText::convert_file_to_binary(const String &p_src_path, const String &p_dst_path) {
Error err;
- FileAccess *f = FileAccess::open(p_src_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_src_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err != OK, ERR_CANT_OPEN, "Cannot open file '" + p_src_path + "'.");
@@ -1603,9 +1590,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
}
Error err;
- f = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err, ERR_CANT_OPEN, "Cannot save file '" + p_path + "'.");
- FileAccessRef _fref(f);
+ Ref<FileAccess> _fref(f);
local_path = ProjectSettings::get_singleton()->localize_path(p_path);
@@ -1942,12 +1929,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
}
if (f->get_error() != OK && f->get_error() != ERR_FILE_EOF) {
- f->close();
return ERR_CANT_CREATE;
}
- f->close();
-
return OK;
}
diff --git a/scene/resources/resource_format_text.h b/scene/resources/resource_format_text.h
index 00919165b8..c6543e616d 100644
--- a/scene/resources/resource_format_text.h
+++ b/scene/resources/resource_format_text.h
@@ -43,7 +43,7 @@ class ResourceLoaderText {
String res_path;
String error_text;
- FileAccess *f = nullptr;
+ Ref<FileAccess> f;
VariantParser::StreamFile stream;
@@ -120,15 +120,14 @@ public:
int get_stage_count() const;
void set_translation_remapped(bool p_remapped);
- void open(FileAccess *p_f, bool p_skip_first_tag = false);
- String recognize(FileAccess *p_f);
- ResourceUID::ID get_uid(FileAccess *p_f);
- void get_dependencies(FileAccess *p_f, List<String> *p_dependencies, bool p_add_types);
- Error rename_dependencies(FileAccess *p_f, const String &p_path, const Map<String, String> &p_map);
+ void open(Ref<FileAccess> p_f, bool p_skip_first_tag = false);
+ String recognize(Ref<FileAccess> p_f);
+ ResourceUID::ID get_uid(Ref<FileAccess> p_f);
+ void get_dependencies(Ref<FileAccess> p_f, List<String> *p_dependencies, bool p_add_types);
+ Error rename_dependencies(Ref<FileAccess> p_f, const String &p_path, const Map<String, String> &p_map);
- Error save_as_binary(FileAccess *p_f, const String &p_path);
+ Error save_as_binary(Ref<FileAccess> p_f, const String &p_path);
ResourceLoaderText();
- ~ResourceLoaderText();
};
class ResourceFormatLoaderText : public ResourceFormatLoader {
@@ -157,7 +156,6 @@ class ResourceFormatSaverTextInstance {
bool relative_paths = false;
bool bundle_resources = false;
bool skip_editor = false;
- FileAccess *f = nullptr;
struct NonPersistentKey { //for resource properties generated on the fly
RES base;
diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp
index ce7fcb199d..25a9278e66 100644
--- a/scene/resources/shader.cpp
+++ b/scene/resources/shader.cpp
@@ -217,17 +217,14 @@ Error ResourceFormatSaverShader::save(const String &p_path, const RES &p_resourc
String source = shader->get_code();
Error err;
- FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);
ERR_FAIL_COND_V_MSG(err, err, "Cannot save shader '" + p_path + "'.");
file->store_string(source);
if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
- memdelete(file);
return ERR_CANT_CREATE;
}
- file->close();
- memdelete(file);
return OK;
}
diff --git a/scene/resources/text_file.cpp b/scene/resources/text_file.cpp
index cbfee754e2..96a47c37c4 100644
--- a/scene/resources/text_file.cpp
+++ b/scene/resources/text_file.cpp
@@ -51,7 +51,7 @@ void TextFile::reload_from_file() {
Error TextFile::load_text(const String &p_path) {
Vector<uint8_t> sourcef;
Error err;
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V_MSG(err, err, "Cannot open TextFile '" + p_path + "'.");
@@ -59,8 +59,7 @@ Error TextFile::load_text(const String &p_path) {
sourcef.resize(len + 1);
uint8_t *w = sourcef.ptrw();
uint64_t r = f->get_buffer(w, len);
- f->close();
- memdelete(f);
+
ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
w[len] = 0;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 44da90de30..4c20e07976 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -646,7 +646,7 @@ PortableCompressedTexture2D::~PortableCompressedTexture2D() {
//////////////////////////////////////////
-Ref<Image> CompressedTexture2D::load_image_from_file(FileAccess *f, int p_size_limit) {
+Ref<Image> CompressedTexture2D::load_image_from_file(Ref<FileAccess> f, int p_size_limit) {
uint32_t data_format = f->get_32();
uint32_t w = f->get_16();
uint32_t h = f->get_16();
@@ -821,20 +821,18 @@ Error CompressedTexture2D::_load_data(const String &p_path, int &r_width, int &r
ERR_FAIL_COND_V(image.is_null(), ERR_INVALID_PARAMETER);
- FileAccess *f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path));
uint8_t header[4];
f->get_buffer(header, 4);
if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != '2') {
- memdelete(f);
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is corrupt (Bad header).");
}
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
- memdelete(f);
ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
r_width = f->get_32();
@@ -867,8 +865,6 @@ Error CompressedTexture2D::_load_data(const String &p_path, int &r_width, int &r
image = load_image_from_file(f, p_size_limit);
- memdelete(f);
-
if (image.is_null() || image->is_empty()) {
return ERR_CANT_OPEN;
}
@@ -1272,8 +1268,8 @@ Image::Format CompressedTexture3D::get_format() const {
}
Error CompressedTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &r_data, Image::Format &r_format, int &r_width, int &r_height, int &r_depth, bool &r_mipmaps) {
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path));
uint8_t header[4];
f->get_buffer(header, 4);
@@ -3092,8 +3088,8 @@ Image::Format CompressedTextureLayered::get_format() const {
Error CompressedTextureLayered::_load_data(const String &p_path, Vector<Ref<Image>> &images, int &mipmap_limit, int p_size_limit) {
ERR_FAIL_COND_V(images.size() != 0, ERR_INVALID_PARAMETER);
- FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path));
+ Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, vformat("Unable to open file: %s.", p_path));
uint8_t header[4];
f->get_buffer(header, 4);
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index 7e194fd21d..525e3ff979 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -253,7 +253,7 @@ protected:
void _validate_property(PropertyInfo &property) const override;
public:
- static Ref<Image> load_image_from_file(FileAccess *p_file, int p_size_limit);
+ static Ref<Image> load_image_from_file(Ref<FileAccess> p_file, int p_size_limit);
typedef void (*TextureFormatRequestCallback)(const Ref<CompressedTexture2D> &);
typedef void (*TextureFormatRoughnessRequestCallback)(const Ref<CompressedTexture2D> &, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel);
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index ee196673a3..0fef416680 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -193,7 +193,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer2D::agent_is_map_changed);
ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer2D::free);
+ ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
}
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index d18777869a..46192772f6 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -72,7 +72,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer3D::agent_is_map_changed);
ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer3D::free);
+ ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active);
ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process);
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
index f7bd7d0d18..6cad45ea6d 100644
--- a/servers/rendering/dummy/rasterizer_dummy.h
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -37,10 +37,10 @@
#include "servers/rendering/dummy/rasterizer_canvas_dummy.h"
#include "servers/rendering/dummy/rasterizer_scene_dummy.h"
#include "servers/rendering/dummy/rasterizer_storage_dummy.h"
-#include "servers/rendering/dummy/storage/canvas_texture_storage.h"
-#include "servers/rendering/dummy/storage/decal_atlas_storage.h"
+#include "servers/rendering/dummy/storage/light_storage.h"
#include "servers/rendering/dummy/storage/material_storage.h"
#include "servers/rendering/dummy/storage/mesh_storage.h"
+#include "servers/rendering/dummy/storage/particles_storage.h"
#include "servers/rendering/dummy/storage/texture_storage.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
@@ -52,20 +52,20 @@ private:
protected:
RasterizerCanvasDummy canvas;
- RendererDummy::CanvasTextureStorage canvas_texture_storage;
+ RendererDummy::LightStorage light_storage;
RendererDummy::MaterialStorage material_storage;
RendererDummy::MeshStorage mesh_storage;
+ RendererDummy::ParticlesStorage particles_storage;
RendererDummy::TextureStorage texture_storage;
- RendererDummy::DecalAtlasStorage decal_atlas_storage;
RasterizerStorageDummy storage;
RasterizerSceneDummy scene;
public:
- RendererCanvasTextureStorage *get_canvas_texture_storage() override { return &canvas_texture_storage; };
+ RendererLightStorage *get_light_storage() override { return &light_storage; };
RendererMaterialStorage *get_material_storage() override { return &material_storage; };
RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
+ RendererParticlesStorage *get_particles_storage() override { return &particles_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; }
RendererCanvasRender *get_canvas() override { return &canvas; }
RendererSceneRender *get_scene() override { return &scene; }
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h
index ea69d2f9a6..ac6085cdec 100644
--- a/servers/rendering/dummy/rasterizer_storage_dummy.h
+++ b/servers/rendering/dummy/rasterizer_storage_dummy.h
@@ -36,76 +36,6 @@
class RasterizerStorageDummy : public RendererStorage {
public:
- /* Light API */
-
- RID directional_light_allocate() override { return RID(); }
- void directional_light_initialize(RID p_rid) override {}
- RID omni_light_allocate() override { return RID(); }
- void omni_light_initialize(RID p_rid) override {}
- RID spot_light_allocate() override { return RID(); }
- void spot_light_initialize(RID p_rid) override {}
- RID reflection_probe_allocate() override { return RID(); }
- void reflection_probe_initialize(RID p_rid) override {}
-
- void light_set_color(RID p_light, const Color &p_color) override {}
- void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
- void light_set_shadow(RID p_light, bool p_enabled) override {}
- void light_set_projector(RID p_light, RID p_texture) override {}
- void light_set_negative(RID p_light, bool p_enable) override {}
- void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
- void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
- void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
- void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
- void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
-
- void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
-
- void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
- void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
- bool light_directional_get_blend_splits(RID p_light) const override { return false; }
- void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override {}
- RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; }
-
- RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
- RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
-
- bool light_has_shadow(RID p_light) const override { return false; }
- bool light_has_projector(RID p_light) const override { return false; }
-
- RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
- AABB light_get_aabb(RID p_light) const override { return AABB(); }
- float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
- Color light_get_color(RID p_light) override { return Color(); }
- RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
- uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
- uint64_t light_get_version(RID p_light) const override { return 0; }
-
- /* PROBE API */
-
- void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
- void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
- void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
- void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
- void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
- void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
- void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
- void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
- void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
- void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
- 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; }
- uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
- Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
- Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
- float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
- bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
-
void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
/* VOXEL GI API */
@@ -149,105 +79,10 @@ public:
uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; }
- /* LIGHTMAP CAPTURE */
- RID lightmap_allocate() override { return RID(); }
- void lightmap_initialize(RID p_rid) override {}
- void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
- void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
- void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
- void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
- PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
- PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
- PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
- PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
- AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
- void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
- bool lightmap_is_interior(RID p_lightmap) const override { return false; }
- void lightmap_set_probe_capture_update_speed(float p_speed) override {}
- float lightmap_get_probe_capture_update_speed() const override { return 0; }
-
/* OCCLUDER */
void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
- /* PARTICLES */
-
- RID particles_allocate() override { return RID(); }
- void particles_initialize(RID p_rid) override {}
- void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {}
- void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
- void particles_set_emitting(RID p_particles, bool p_emitting) override {}
- void particles_set_amount(RID p_particles, int p_amount) override {}
- void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
- void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
- void particles_set_pre_process_time(RID p_particles, double p_time) override {}
- void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
- void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
- void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
- void particles_set_speed_scale(RID p_particles, double p_scale) override {}
- void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
- void particles_set_process_material(RID p_particles, RID p_material) override {}
- RID particles_get_process_material(RID p_particles) const override { return RID(); }
- void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
- void particles_set_interpolate(RID p_particles, bool p_enable) override {}
- void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
- void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
- void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
- void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
-
- void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
-
- void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
- void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
-
- void particles_restart(RID p_particles) override {}
-
- void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
-
- void particles_set_draw_passes(RID p_particles, int p_count) override {}
- void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
-
- void particles_request_process(RID p_particles) override {}
- AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
- AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
-
- void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
-
- bool particles_get_emitting(RID p_particles) override { return false; }
- int particles_get_draw_passes(RID p_particles) const override { return 0; }
- RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
-
- void particles_add_collision(RID p_particles, RID p_instance) override {}
- void particles_remove_collision(RID p_particles, RID p_instance) override {}
-
- void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
-
- void update_particles() override {}
-
- /* PARTICLES COLLISION */
-
- RID particles_collision_allocate() override { return RID(); }
- void particles_collision_initialize(RID p_rid) override {}
- void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
- void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
- void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {}
- void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
- void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {}
- void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {}
- void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {}
- void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
- void particles_collision_height_field_update(RID p_particles_collision) override {}
- void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
- AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
- bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
- RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
-
- RID particles_collision_instance_create(RID p_collision) override { return RID(); }
- void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
- void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
-
- bool particles_is_inactive(RID p_particles) const override { return false; }
-
/* FOG VOLUMES */
RID fog_volume_allocate() override { return RID(); }
@@ -268,26 +103,7 @@ public:
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
- /* RENDER TARGET */
-
- RID render_target_create() override { return RID(); }
- void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
- void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
- RID render_target_get_texture(RID p_render_target) override { return RID(); }
- void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
- void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
- bool render_target_was_used(RID p_render_target) override { return false; }
- void render_target_set_as_unused(RID p_render_target) override {}
-
- void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
- bool render_target_is_clear_requested(RID p_render_target) override { return false; }
- Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
- void render_target_disable_clear_request(RID p_render_target) override {}
- void render_target_do_clear_request(RID p_render_target) override {}
-
- void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
- Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
- void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
+ /* STORAGE */
RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
bool free(RID p_rid) override {
diff --git a/servers/rendering/dummy/storage/canvas_texture_storage.h b/servers/rendering/dummy/storage/canvas_texture_storage.h
deleted file mode 100644
index daa3ac5e42..0000000000
--- a/servers/rendering/dummy/storage/canvas_texture_storage.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*************************************************************************/
-/* canvas_texture_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 CANVAS_TEXTURE_STORAGE_DUMMY_H
-#define CANVAS_TEXTURE_STORAGE_DUMMY_H
-
-#include "servers/rendering/storage/canvas_texture_storage.h"
-
-namespace RendererDummy {
-
-class CanvasTextureStorage : public RendererCanvasTextureStorage {
-public:
- virtual RID canvas_texture_allocate() override { return RID(); };
- virtual void canvas_texture_initialize(RID p_rid) override{};
- virtual void canvas_texture_free(RID p_rid) override{};
-
- virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{};
- virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{};
-
- virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{};
- virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{};
-};
-
-} // namespace RendererDummy
-
-#endif // !CANVAS_TEXTURE_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/decal_atlas_storage.h b/servers/rendering/dummy/storage/decal_atlas_storage.h
deleted file mode 100644
index 04ddfaca6d..0000000000
--- a/servers/rendering/dummy/storage/decal_atlas_storage.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*************************************************************************/
-/* decal_atlas_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 DECAL_ATLAS_STORAGE_DUMMY_H
-#define DECAL_ATLAS_STORAGE_DUMMY_H
-
-#include "servers/rendering/storage/decal_atlas_storage.h"
-
-namespace RendererDummy {
-
-class DecalAtlasStorage : public RendererDecalAtlasStorage {
-public:
- virtual RID decal_allocate() override { return RID(); }
- virtual void decal_initialize(RID p_rid) override {}
- virtual void decal_free(RID p_rid) override{};
-
- virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
- virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
- virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {}
- virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
- virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
- virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
- virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
- virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
- virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {}
-
- virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
-
- virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
- virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
-};
-
-} // namespace RendererDummy
-
-#endif // !DECAL_ATLAS_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
new file mode 100644
index 0000000000..b0100a5fe7
--- /dev/null
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -0,0 +1,135 @@
+/*************************************************************************/
+/* light_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 LIGHT_STORAGE_DUMMY_H
+#define LIGHT_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/light_storage.h"
+
+namespace RendererDummy {
+
+class LightStorage : public RendererLightStorage {
+public:
+ /* Light API */
+
+ virtual RID directional_light_allocate() override { return RID(); }
+ virtual void directional_light_initialize(RID p_rid) override {}
+ virtual RID omni_light_allocate() override { return RID(); }
+ virtual void omni_light_initialize(RID p_rid) override {}
+ virtual RID spot_light_allocate() override { return RID(); }
+ virtual void spot_light_initialize(RID p_rid) override {}
+
+ virtual void light_free(RID p_rid) override {}
+
+ virtual void light_set_color(RID p_light, const Color &p_color) override {}
+ virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override {}
+ virtual void light_set_shadow(RID p_light, bool p_enabled) override {}
+ virtual void light_set_projector(RID p_light, RID p_texture) override {}
+ virtual void light_set_negative(RID p_light, bool p_enable) override {}
+ virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override {}
+ virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override {}
+ virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override {}
+ virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override {}
+ virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
+
+ virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override {}
+
+ virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override {}
+ virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override {}
+ virtual bool light_directional_get_blend_splits(RID p_light) const override { return false; }
+ virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override {}
+ virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override { return RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; }
+
+ virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; }
+ virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
+
+ virtual bool light_has_shadow(RID p_light) const override { return false; }
+ virtual bool light_has_projector(RID p_light) const override { return false; }
+
+ virtual RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
+ virtual AABB light_get_aabb(RID p_light) const override { return AABB(); }
+ virtual float light_get_param(RID p_light, RS::LightParam p_param) override { return 0.0; }
+ virtual Color light_get_color(RID p_light) override { return Color(); }
+ virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override { return RS::LIGHT_BAKE_DISABLED; }
+ virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
+ virtual uint64_t light_get_version(RID p_light) const override { return 0; }
+
+ /* PROBE API */
+ virtual RID reflection_probe_allocate() override { return RID(); }
+ virtual void reflection_probe_initialize(RID p_rid) override {}
+ virtual void reflection_probe_free(RID p_rid) override {}
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override {}
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override {}
+ virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override {}
+ virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override {}
+ virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override {}
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override {}
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override {}
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override {}
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override {}
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override {}
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override {}
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override {}
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override {}
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
+ virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
+
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
+ virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const override { return Vector3(); }
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override { return Vector3(); }
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
+
+ /* LIGHTMAP CAPTURE */
+ virtual RID lightmap_allocate() override { return RID(); }
+ virtual void lightmap_initialize(RID p_rid) override {}
+ virtual void lightmap_free(RID p_rid) override {}
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override {}
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
+ virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override { return PackedInt32Array(); }
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const override { return AABB(); }
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override {}
+ virtual bool lightmap_is_interior(RID p_lightmap) const override { return false; }
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed) override {}
+ virtual float lightmap_get_probe_capture_update_speed() const override { return 0; }
+};
+
+} // namespace RendererDummy
+
+#endif // !LIGHT_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
new file mode 100644
index 0000000000..f614b41c4c
--- /dev/null
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -0,0 +1,126 @@
+/*************************************************************************/
+/* particles_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 PARTICLES_STORAGE_DUMMY_H
+#define PARTICLES_STORAGE_DUMMY_H
+
+#include "servers/rendering/storage/particles_storage.h"
+
+namespace RendererDummy {
+
+class ParticlesStorage : public RendererParticlesStorage {
+public:
+ /* PARTICLES */
+
+ virtual RID particles_allocate() override { return RID(); }
+ virtual void particles_initialize(RID p_rid) override {}
+ virtual void particles_free(RID p_rid) override {}
+
+ virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override {}
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
+ virtual void particles_set_emitting(RID p_particles, bool p_emitting) override {}
+ virtual void particles_set_amount(RID p_particles, int p_amount) override {}
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
+ virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) override {}
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override {}
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override {}
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override {}
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) override {}
+ virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override {}
+ virtual void particles_set_process_material(RID p_particles, RID p_material) override {}
+ virtual RID particles_get_process_material(RID p_particles) const override { return RID(); }
+ virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override {}
+ virtual void particles_set_interpolate(RID p_particles, bool p_enable) override {}
+ virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override {}
+ virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override {}
+ virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override {}
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override {}
+
+ virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override {}
+
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override {}
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override {}
+
+ virtual void particles_restart(RID p_particles) override {}
+
+ virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override {}
+
+ virtual void particles_set_draw_passes(RID p_particles, int p_count) override {}
+ virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override {}
+
+ virtual void particles_request_process(RID p_particles) override {}
+ virtual AABB particles_get_current_aabb(RID p_particles) override { return AABB(); }
+ virtual AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
+
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
+
+ virtual bool particles_get_emitting(RID p_particles) override { return false; }
+ virtual int particles_get_draw_passes(RID p_particles) const override { return 0; }
+ virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override { return RID(); }
+
+ virtual void particles_add_collision(RID p_particles, RID p_instance) override {}
+ virtual void particles_remove_collision(RID p_particles, RID p_instance) override {}
+
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override {}
+
+ virtual void update_particles() override {}
+
+ /* PARTICLES COLLISION */
+
+ virtual RID particles_collision_allocate() override { return RID(); }
+ virtual void particles_collision_initialize(RID p_rid) override {}
+ virtual void particles_collision_free(RID p_rid) override {}
+
+ virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override {}
+ virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override {}
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override {}
+ virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override {}
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override {}
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override {}
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override {}
+ virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override {}
+ virtual void particles_collision_height_field_update(RID p_particles_collision) override {}
+ virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override {}
+ virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override { return AABB(); }
+ virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override { return false; }
+ virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override { return RID(); }
+
+ virtual RID particles_collision_instance_create(RID p_collision) override { return RID(); }
+ virtual void particles_collision_instance_free(RID p_rid) override {}
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override {}
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override {}
+
+ virtual bool particles_is_inactive(RID p_particles) const override { return false; }
+};
+
+} // namespace RendererDummy
+
+#endif // !PARTICLES_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index d40a1842a4..534b9f07d8 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -52,6 +52,20 @@ public:
virtual bool can_create_resources_async() const override { return false; }
+ /* Canvas Texture API */
+
+ virtual RID canvas_texture_allocate() override { return RID(); };
+ virtual void canvas_texture_initialize(RID p_rid) override{};
+ virtual void canvas_texture_free(RID p_rid) override{};
+
+ virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override{};
+ virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override{};
+
+ virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override{};
+ virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override{};
+
+ /* Texture API */
+
DummyTexture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
@@ -109,6 +123,48 @@ public:
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) override{};
virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); };
+
+ /* DECAL API */
+ virtual RID decal_allocate() override { return RID(); }
+ virtual void decal_initialize(RID p_rid) override {}
+ virtual void decal_free(RID p_rid) override{};
+
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override {}
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override {}
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy) override {}
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override {}
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override {}
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override {}
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override {}
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override {}
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade) override {}
+
+ virtual AABB decal_get_aabb(RID p_decal) const override { return AABB(); }
+
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+
+ /* RENDER TARGET */
+
+ virtual RID render_target_create() override { return RID(); }
+ virtual void render_target_free(RID p_rid) override {}
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
+ virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
+ virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override {}
+ virtual bool render_target_was_used(RID p_render_target) override { return false; }
+ virtual void render_target_set_as_unused(RID p_render_target) override {}
+
+ virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
+ virtual bool render_target_is_clear_requested(RID p_render_target) override { return false; }
+ virtual Color render_target_get_clear_request_color(RID p_render_target) override { return Color(); }
+ virtual void render_target_disable_clear_request(RID p_render_target) override {}
+ virtual void render_target_do_clear_request(RID p_render_target) override {}
+
+ virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
+ virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
+ virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
};
} // namespace RendererDummy
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index f38d800aa7..f4d09ded64 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -34,7 +34,7 @@
#include "renderer_viewport.h"
#include "rendering_server_default.h"
#include "rendering_server_globals.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
+#include "servers/rendering/storage/texture_storage.h"
static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
@@ -552,27 +552,188 @@ void RendererCanvasCull::canvas_item_set_update_when_visible(RID p_item, bool p_
canvas_item->update_when_visible = p_update;
}
-void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) {
+void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width, bool p_antialiased) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
Item::CommandPrimitive *line = canvas_item->alloc_command<Item::CommandPrimitive>();
ERR_FAIL_COND(!line);
+
+ Vector2 diff = (p_from - p_to);
+ Vector2 dir = diff.orthogonal().normalized();
+ Vector2 t = dir * p_width * 0.5;
+
+ Vector2 begin_left;
+ Vector2 begin_right;
+ Vector2 end_left;
+ Vector2 end_right;
+
if (p_width > 1.001) {
- Vector2 t = (p_from - p_to).orthogonal().normalized() * p_width * 0.5;
- line->points[0] = p_from + t;
- line->points[1] = p_from - t;
- line->points[2] = p_to - t;
- line->points[3] = p_to + t;
+ begin_left = p_from + t;
+ begin_right = p_from - t;
+ end_left = p_to + t;
+ end_right = p_to - t;
+
+ line->points[0] = begin_left;
+ line->points[1] = begin_right;
+ line->points[2] = end_right;
+ line->points[3] = end_left;
line->point_count = 4;
} else {
- line->point_count = 2;
+ begin_left = p_from;
+ begin_right = p_from;
+ end_left = p_to;
+ end_right = p_to;
+
line->points[0] = p_from;
line->points[1] = p_to;
+ line->point_count = 2;
}
for (uint32_t i = 0; i < line->point_count; i++) {
line->colors[i] = p_color;
}
+
+ if (p_antialiased) {
+ float border_size = 2.0;
+ if (p_width < border_size) {
+ border_size = p_width;
+ }
+ Vector2 dir2 = diff.normalized();
+
+ Vector2 border = dir * border_size;
+ Vector2 border2 = dir2 * border_size;
+
+ Color transparent = Color(p_color.r, p_color.g, p_color.b, 0.0);
+
+ {
+ Item::CommandPrimitive *left_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!left_border);
+
+ left_border->points[0] = begin_left;
+ left_border->points[1] = begin_left + border;
+ left_border->points[2] = end_left + border;
+ left_border->points[3] = end_left;
+
+ left_border->colors[0] = p_color;
+ left_border->colors[1] = transparent;
+ left_border->colors[2] = transparent;
+ left_border->colors[3] = p_color;
+
+ left_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *right_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!right_border);
+
+ right_border->points[0] = begin_right;
+ right_border->points[1] = begin_right - border;
+ right_border->points[2] = end_right - border;
+ right_border->points[3] = end_right;
+
+ right_border->colors[0] = p_color;
+ right_border->colors[1] = transparent;
+ right_border->colors[2] = transparent;
+ right_border->colors[3] = p_color;
+
+ right_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!top_border);
+
+ top_border->points[0] = begin_left;
+ top_border->points[1] = begin_left + border2;
+ top_border->points[2] = begin_right + border2;
+ top_border->points[3] = begin_right;
+
+ top_border->colors[0] = p_color;
+ top_border->colors[1] = transparent;
+ top_border->colors[2] = transparent;
+ top_border->colors[3] = p_color;
+
+ top_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_border = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!bottom_border);
+
+ bottom_border->points[0] = end_left;
+ bottom_border->points[1] = end_left - border2;
+ bottom_border->points[2] = end_right - border2;
+ bottom_border->points[3] = end_right;
+
+ bottom_border->colors[0] = p_color;
+ bottom_border->colors[1] = transparent;
+ bottom_border->colors[2] = transparent;
+ bottom_border->colors[3] = p_color;
+
+ bottom_border->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!top_left_corner);
+
+ top_left_corner->points[0] = begin_left;
+ top_left_corner->points[1] = begin_left + border2;
+ top_left_corner->points[2] = begin_left + border + border2;
+ top_left_corner->points[3] = begin_left + border;
+
+ top_left_corner->colors[0] = p_color;
+ top_left_corner->colors[1] = transparent;
+ top_left_corner->colors[2] = transparent;
+ top_left_corner->colors[3] = transparent;
+
+ top_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *top_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!top_right_corner);
+
+ top_right_corner->points[0] = begin_right;
+ top_right_corner->points[1] = begin_right + border2;
+ top_right_corner->points[2] = begin_right - border + border2;
+ top_right_corner->points[3] = begin_right - border;
+
+ top_right_corner->colors[0] = p_color;
+ top_right_corner->colors[1] = transparent;
+ top_right_corner->colors[2] = transparent;
+ top_right_corner->colors[3] = transparent;
+
+ top_right_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_left_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!bottom_left_corner);
+
+ bottom_left_corner->points[0] = end_left;
+ bottom_left_corner->points[1] = end_left - border2;
+ bottom_left_corner->points[2] = end_left + border - border2;
+ bottom_left_corner->points[3] = end_left + border;
+
+ bottom_left_corner->colors[0] = p_color;
+ bottom_left_corner->colors[1] = transparent;
+ bottom_left_corner->colors[2] = transparent;
+ bottom_left_corner->colors[3] = transparent;
+
+ bottom_left_corner->point_count = 4;
+ }
+ {
+ Item::CommandPrimitive *bottom_right_corner = canvas_item->alloc_command<Item::CommandPrimitive>();
+ ERR_FAIL_COND(!bottom_right_corner);
+
+ bottom_right_corner->points[0] = end_right;
+ bottom_right_corner->points[1] = end_right - border2;
+ bottom_right_corner->points[2] = end_right - border - border2;
+ bottom_right_corner->points[3] = end_right - border;
+
+ bottom_right_corner->colors[0] = p_color;
+ bottom_right_corner->colors[1] = transparent;
+ bottom_right_corner->colors[2] = transparent;
+ bottom_right_corner->colors[3] = transparent;
+
+ bottom_right_corner->point_count = 4;
+ }
+ }
}
void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
@@ -602,42 +763,119 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_ptr = colors.ptrw();
if (p_antialiased) {
+ float border_size = 2.0;
+ if (p_width < border_size) {
+ border_size = p_width;
+ }
Color color2 = Color(1, 1, 1, 0);
- PackedColorArray colors_top;
- PackedVector2Array points_top;
+ PackedColorArray colors_begin;
+ PackedVector2Array points_begin;
+
+ colors_begin.resize(4);
+ points_begin.resize(4);
+
+ PackedColorArray colors_begin_left_corner;
+ PackedVector2Array points_begin_left_corner;
+
+ colors_begin_left_corner.resize(4);
+ points_begin_left_corner.resize(4);
+
+ PackedColorArray colors_begin_right_corner;
+ PackedVector2Array points_begin_right_corner;
+
+ colors_begin_right_corner.resize(4);
+ points_begin_right_corner.resize(4);
+
+ PackedColorArray colors_end;
+ PackedVector2Array points_end;
+
+ colors_end.resize(4);
+ points_end.resize(4);
+
+ PackedColorArray colors_end_left_corner;
+ PackedVector2Array points_end_left_corner;
+
+ colors_end_left_corner.resize(4);
+ points_end_left_corner.resize(4);
+
+ PackedColorArray colors_end_right_corner;
+ PackedVector2Array points_end_right_corner;
+
+ colors_end_right_corner.resize(4);
+ points_end_right_corner.resize(4);
- colors_top.resize(pc2);
- points_top.resize(pc2);
+ PackedColorArray colors_left;
+ PackedVector2Array points_left;
- PackedColorArray colors_bottom;
- PackedVector2Array points_bottom;
+ colors_left.resize(pc2);
+ points_left.resize(pc2);
- colors_bottom.resize(pc2);
- points_bottom.resize(pc2);
+ PackedColorArray colors_right;
+ PackedVector2Array points_right;
- Item::CommandPolygon *pline_top = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_COND(!pline_top);
+ colors_right.resize(pc2);
+ points_right.resize(pc2);
- Item::CommandPolygon *pline_bottom = canvas_item->alloc_command<Item::CommandPolygon>();
- ERR_FAIL_COND(!pline_bottom);
+ Item::CommandPolygon *pline_begin = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_begin);
- //make three trianglestrip's for drawing the antialiased line...
+ Item::CommandPolygon *pline_begin_left_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_begin_left_corner);
- Vector2 *points_top_ptr = points_top.ptrw();
- Vector2 *points_bottom_ptr = points_bottom.ptrw();
+ Item::CommandPolygon *pline_begin_right_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_begin_right_corner);
- Color *colors_top_ptr = colors_top.ptrw();
- Color *colors_bottom_ptr = colors_bottom.ptrw();
+ Item::CommandPolygon *pline_end = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_end);
+
+ Item::CommandPolygon *pline_end_left_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_end_left_corner);
+
+ Item::CommandPolygon *pline_end_right_corner = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_end_right_corner);
+
+ Item::CommandPolygon *pline_left = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_left);
+
+ Item::CommandPolygon *pline_right = canvas_item->alloc_command<Item::CommandPolygon>();
+ ERR_FAIL_COND(!pline_right);
+
+ // Makes nine triangle strips for drawing the antialiased line.
+
+ Vector2 *points_begin_ptr = points_begin.ptrw();
+ Vector2 *points_begin_left_corner_ptr = points_begin_left_corner.ptrw();
+ Vector2 *points_begin_right_corner_ptr = points_begin_right_corner.ptrw();
+ Vector2 *points_end_ptr = points_end.ptrw();
+ Vector2 *points_end_left_corner_ptr = points_end_left_corner.ptrw();
+ Vector2 *points_end_right_corner_ptr = points_end_right_corner.ptrw();
+ Vector2 *points_left_ptr = points_left.ptrw();
+ Vector2 *points_right_ptr = points_right.ptrw();
+
+ Color *colors_begin_ptr = colors_begin.ptrw();
+ Color *colors_begin_left_corner_ptr = colors_begin_left_corner.ptrw();
+ Color *colors_begin_right_corner_ptr = colors_begin_right_corner.ptrw();
+ Color *colors_end_ptr = colors_end.ptrw();
+ Color *colors_end_left_corner_ptr = colors_end_left_corner.ptrw();
+ Color *colors_end_right_corner_ptr = colors_end_right_corner.ptrw();
+ Color *colors_left_ptr = colors_left.ptrw();
+ Color *colors_right_ptr = colors_right.ptrw();
for (int i = 0, j = 0; i < pc; i++, j += 2) {
+ bool is_begin = i == 0;
+ bool is_end = i == pc - 1;
+
Vector2 t;
- if (i == pc - 1) {
+ Vector2 end_border;
+ Vector2 begin_border;
+ if (is_end) {
t = prev_t;
+ end_border = (p_points[i] - p_points[i - 1]).normalized() * border_size;
} else {
t = (p_points[i + 1] - p_points[i]).normalized().orthogonal();
- if (i == 0) {
+ if (is_begin) {
prev_t = t;
+ begin_border = (p_points[i] - p_points[i + 1]).normalized() * border_size;
}
}
@@ -645,17 +883,17 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Vector2 dir = (t + prev_t).normalized();
Vector2 tangent = dir * p_width * 0.5;
- Vector2 border = dir * 2.0;
+ Vector2 border = dir * border_size;
Vector2 pos = p_points[i];
points_ptr[j] = pos + tangent;
points_ptr[j2] = pos - tangent;
- points_top_ptr[j] = pos + tangent + border;
- points_top_ptr[j2] = pos + tangent;
+ points_left_ptr[j] = pos + tangent + border;
+ points_left_ptr[j2] = pos + tangent;
- points_bottom_ptr[j] = pos - tangent;
- points_bottom_ptr[j2] = pos - tangent - border;
+ points_right_ptr[j] = pos - tangent;
+ points_right_ptr[j2] = pos - tangent - border;
if (i < p_colors.size()) {
color = p_colors[i];
@@ -665,22 +903,104 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
colors_ptr[j] = color;
colors_ptr[j2] = color;
- colors_top_ptr[j] = color2;
- colors_top_ptr[j2] = color;
+ colors_left_ptr[j] = color2;
+ colors_left_ptr[j2] = color;
+
+ colors_right_ptr[j] = color;
+ colors_right_ptr[j2] = color2;
+
+ if (is_begin) {
+ points_begin_ptr[0] = pos + tangent + begin_border;
+ points_begin_ptr[1] = pos - tangent + begin_border;
+ points_begin_ptr[2] = pos + tangent;
+ points_begin_ptr[3] = pos - tangent;
+
+ colors_begin_ptr[0] = color2;
+ colors_begin_ptr[1] = color2;
+ colors_begin_ptr[2] = color;
+ colors_begin_ptr[3] = color;
+
+ points_begin_left_corner_ptr[0] = pos - tangent - border;
+ points_begin_left_corner_ptr[1] = pos - tangent + begin_border - border;
+ points_begin_left_corner_ptr[2] = pos - tangent;
+ points_begin_left_corner_ptr[3] = pos - tangent + begin_border;
+
+ colors_begin_left_corner_ptr[0] = color2;
+ colors_begin_left_corner_ptr[1] = color2;
+ colors_begin_left_corner_ptr[2] = color;
+ colors_begin_left_corner_ptr[3] = color2;
+
+ points_begin_right_corner_ptr[0] = pos + tangent + begin_border;
+ points_begin_right_corner_ptr[1] = pos + tangent + begin_border + border;
+ points_begin_right_corner_ptr[2] = pos + tangent;
+ points_begin_right_corner_ptr[3] = pos + tangent + border;
+
+ colors_begin_right_corner_ptr[0] = color2;
+ colors_begin_right_corner_ptr[1] = color2;
+ colors_begin_right_corner_ptr[2] = color;
+ colors_begin_right_corner_ptr[3] = color2;
+ }
- colors_bottom_ptr[j] = color;
- colors_bottom_ptr[j2] = color2;
+ if (is_end) {
+ points_end_ptr[0] = pos + tangent + end_border;
+ points_end_ptr[1] = pos - tangent + end_border;
+ points_end_ptr[2] = pos + tangent;
+ points_end_ptr[3] = pos - tangent;
+
+ colors_end_ptr[0] = color2;
+ colors_end_ptr[1] = color2;
+ colors_end_ptr[2] = color;
+ colors_end_ptr[3] = color;
+
+ points_end_left_corner_ptr[0] = pos - tangent - border;
+ points_end_left_corner_ptr[1] = pos - tangent + end_border - border;
+ points_end_left_corner_ptr[2] = pos - tangent;
+ points_end_left_corner_ptr[3] = pos - tangent + end_border;
+
+ colors_end_left_corner_ptr[0] = color2;
+ colors_end_left_corner_ptr[1] = color2;
+ colors_end_left_corner_ptr[2] = color;
+ colors_end_left_corner_ptr[3] = color2;
+
+ points_end_right_corner_ptr[0] = pos + tangent + end_border;
+ points_end_right_corner_ptr[1] = pos + tangent + end_border + border;
+ points_end_right_corner_ptr[2] = pos + tangent;
+ points_end_right_corner_ptr[3] = pos + tangent + border;
+
+ colors_end_right_corner_ptr[0] = color2;
+ colors_end_right_corner_ptr[1] = color2;
+ colors_end_right_corner_ptr[2] = color;
+ colors_end_right_corner_ptr[3] = color2;
+ }
prev_t = t;
}
- pline_top->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
- pline_top->polygon.create(indices, points_top, colors_top);
+ pline_begin->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_begin->polygon.create(indices, points_begin, colors_begin);
+
+ pline_begin_left_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_begin_left_corner->polygon.create(indices, points_begin_left_corner, colors_begin_left_corner);
+
+ pline_begin_right_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_begin_right_corner->polygon.create(indices, points_begin_right_corner, colors_begin_right_corner);
+
+ pline_end->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_end->polygon.create(indices, points_end, colors_end);
+
+ pline_end_left_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_end_left_corner->polygon.create(indices, points_end_left_corner, colors_end_left_corner);
+
+ pline_end_right_corner->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_end_right_corner->polygon.create(indices, points_end_right_corner, colors_end_right_corner);
+
+ pline_left->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_left->polygon.create(indices, points_left, colors_left);
- pline_bottom->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
- pline_bottom->polygon.create(indices, points_bottom, colors_bottom);
+ pline_right->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
+ pline_right->polygon.create(indices, points_right, colors_right);
} else {
- //make a trianglestrip for drawing the line...
+ // Makes a single triangle strip for drawing the line.
for (int i = 0, j = 0; i < pc; i++, j += 2) {
Vector2 t;
@@ -1018,7 +1338,7 @@ void RendererCanvasCull::canvas_item_add_particles(RID p_item, RID p_particles,
part->texture = p_texture;
//take the chance and request processing for them, at least once until they become visible again
- RSG::storage->particles_request_process(p_particles);
+ RSG::particles_storage->particles_request_process(p_particles);
}
void RendererCanvasCull::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) {
@@ -1531,26 +1851,26 @@ void RendererCanvasCull::canvas_set_shadow_texture_size(int p_size) {
}
RID RendererCanvasCull::canvas_texture_allocate() {
- return RSG::canvas_texture_storage->canvas_texture_allocate();
+ return RSG::texture_storage->canvas_texture_allocate();
}
void RendererCanvasCull::canvas_texture_initialize(RID p_rid) {
- RSG::canvas_texture_storage->canvas_texture_initialize(p_rid);
+ RSG::texture_storage->canvas_texture_initialize(p_rid);
}
void RendererCanvasCull::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
- RSG::canvas_texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture);
+ RSG::texture_storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture);
}
void RendererCanvasCull::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) {
- RSG::canvas_texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess);
+ RSG::texture_storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess);
}
void RendererCanvasCull::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
- RSG::canvas_texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter);
+ RSG::texture_storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter);
}
void RendererCanvasCull::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
- RSG::canvas_texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat);
+ RSG::texture_storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat);
}
void RendererCanvasCull::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) {
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 94bae30ae0..637245502d 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -215,7 +215,7 @@ public:
void canvas_item_set_update_when_visible(RID p_item, bool p_update);
- void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0);
+ void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 46ca3b0da8..59cc3b7a92 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -32,6 +32,7 @@
#define RENDERINGSERVERCANVASRENDER_H
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
#include "servers/rendering/renderer_storage.h"
class RendererCanvasRender {
@@ -419,7 +420,7 @@ public:
case Item::Command::TYPE_PARTICLES: {
const Item::CommandParticles *particles_cmd = static_cast<const Item::CommandParticles *>(c);
if (particles_cmd->particles.is_valid()) {
- AABB aabb = RendererStorage::base_singleton->particles_get_aabb(particles_cmd->particles);
+ AABB aabb = RendererRD::ParticlesStorage::get_singleton()->particles_get_aabb(particles_cmd->particles);
r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y);
}
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index 74eff4bb40..9466148a31 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -34,10 +34,10 @@
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_storage.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/material_storage.h"
#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/particles_storage.h"
#include "servers/rendering/storage/texture_storage.h"
#include "servers/rendering_server.h"
@@ -75,11 +75,11 @@ protected:
public:
static RendererCompositor *create();
- virtual RendererCanvasTextureStorage *get_canvas_texture_storage() = 0;
+ virtual RendererLightStorage *get_light_storage() = 0;
virtual RendererMaterialStorage *get_material_storage() = 0;
virtual RendererMeshStorage *get_mesh_storage() = 0;
+ virtual RendererParticlesStorage *get_particles_storage() = 0;
virtual RendererTextureStorage *get_texture_storage() = 0;
- virtual RendererDecalAtlasStorage *get_decal_atlas_storage() = 0;
virtual RendererStorage *get_storage() = 0;
virtual RendererCanvasRender *get_canvas() = 0;
virtual RendererSceneRender *get_scene() = 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 e24d020a14..93baa9a96f 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -30,8 +30,10 @@
#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/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_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"
@@ -783,7 +785,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
//ambient
if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
@@ -793,7 +795,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
} else {
float energy = environment_get_ambient_light_energy(p_render_data->environment);
Color color = environment_get_ambient_light_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
scene_state.ubo.ambient_light_color_energy[2] = color.b * energy;
@@ -829,7 +831,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
- Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
+ Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
@@ -839,12 +841,12 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
} else {
- if (p_render_data->reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
scene_state.ubo.use_ambient_light = false;
} else {
scene_state.ubo.use_ambient_light = true;
Color clear_color = p_default_bg_color;
- clear_color = clear_color.to_linear();
+ clear_color = clear_color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
@@ -1230,7 +1232,7 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
scene_state.lightmap_ids[i] = p_lightmaps[i];
- scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap);
+ scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
scene_state.lightmaps_used++;
}
@@ -1338,7 +1340,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
color_only_framebuffer = color_framebuffer;
depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
env = nullptr;
}
@@ -1391,7 +1393,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_COLOR: {
@@ -1401,7 +1403,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.b *= bg_energy;
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_SKY: {
@@ -1520,7 +1522,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
Vector<Color> c;
{
- Color cc = clear_color.to_linear();
+ Color cc = clear_color.srgb_to_linear();
if (using_separate_specular) {
cc.a = 0; //subsurf scatter must be 0
}
@@ -2025,14 +2027,17 @@ void RenderForwardClustered::_base_uniforms_changed() {
}
void RenderForwardClustered::_update_render_base_uniform_set() {
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version()) || base_uniform_set_updated) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version()) || base_uniform_set_updated) {
base_uniform_set_updated = false;
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
- lightmap_texture_array_version = storage->lightmap_array_get_version();
+ lightmap_texture_array_version = light_storage->lightmap_array_get_version();
Vector<RD::Uniform> uniforms;
@@ -2040,18 +2045,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
Vector<RID> ids;
ids.resize(12);
RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
@@ -2073,19 +2078,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (decals_get_filter()) {
case RS::DECAL_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -2100,19 +2105,19 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID sampler;
switch (light_projectors_get_filter()) {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -2167,7 +2172,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
u.append_id(decal_atlas);
uniforms.push_back(u);
}
@@ -2175,7 +2180,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb();
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_srgb();
u.append_id(decal_atlas);
uniforms.push_back(u);
}
@@ -2209,6 +2214,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RenderBufferDataForwardClustered *rb = nullptr;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
@@ -2273,7 +2279,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
}
u.append_id(texture);
uniforms.push_back(u);
@@ -2285,7 +2291,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
u.append_id(directional_shadow_get_texture());
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
@@ -2298,7 +2304,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
- RID texture = storage->lightmap_get_texture(base);
+ RID texture = light_storage->lightmap_get_texture(base);
RID rd_texture = texture_storage->texture_get_rd_texture(texture);
u.append_id(rd_texture);
} else {
@@ -2342,7 +2348,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2499,7 +2505,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2509,7 +2515,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2662,7 +2668,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
SceneShaderForwardClustered::MaterialData *material_shadow = nullptr;
void *surface_shadow = nullptr;
- if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
+ if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
@@ -2780,6 +2786,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();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2836,10 +2843,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
} break;
#endif
case RS::INSTANCE_PARTICLES: {
- int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+ int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);
for (int j = 0; j < draw_passes; j++) {
- RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+ RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
if (!mesh.is_valid()) {
continue;
}
@@ -2855,7 +2862,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
}
}
- ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
+ ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
} break;
@@ -2892,10 +2899,10 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
//for particles, stride is the trail size
ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT);
- if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+ if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {
store_transform = false;
}
- ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = particles_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 (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
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 2acce8bab7..2dfc4f426e 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
@@ -55,7 +55,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
int blend_mode = BLEND_MODE_MIX;
int depth_testi = DEPTH_TEST_ENABLED;
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
- int cull = CULL_BACK;
+ int cull_modei = CULL_BACK;
uses_point_size = false;
uses_alpha = false;
@@ -101,9 +101,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
- actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull, CULL_DISABLED);
- actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull, CULL_FRONT);
- actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull, CULL_BACK);
+ actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
+ actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
+ actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
actions.render_mode_flags["unshaded"] = &unshaded;
actions.render_mode_flags["wireframe"] = &wireframe;
@@ -145,6 +145,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
+ cull_mode = Cull(cull_modei);
#if 0
print_line("**compiling shader:");
@@ -258,7 +259,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
};
- RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull];
+ RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull_mode];
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
@@ -293,16 +294,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
raster_state.cull_mode = cull_mode_rd;
raster_state.wireframe = wireframe;
- RD::PipelineColorBlendState blend_state;
- RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
- RD::PipelineMultisampleState multisample_state;
-
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;
}
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
+ RD::PipelineMultisampleState multisample_state;
+
int shader_flags = 0;
if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) {
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
@@ -338,6 +339,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
}
} else {
+ RD::PipelineColorBlendState blend_state;
+ RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
+ RD::PipelineMultisampleState multisample_state;
+
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) {
@@ -824,6 +829,9 @@ void SceneShaderForwardClustered::set_default_specialization_constants(const Vec
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
}
+ for (int k = 0; k < PIPELINE_COLOR_PASS_FLAG_COUNT; k++) {
+ E->self()->color_pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
+ }
}
}
}
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 1b7709bedb..6185fa7413 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
@@ -171,6 +171,7 @@ public:
bool uses_time;
bool writes_modelview_or_projection;
bool uses_world_coordinates;
+ Cull cull_mode;
uint64_t last_pass = 0;
uint32_t index = 0;
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 156d535447..ade2b976c8 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -30,8 +30,10 @@
#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/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/rendering_server_default.h"
@@ -350,7 +352,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
}
u.append_id(texture);
uniforms.push_back(u);
@@ -362,7 +364,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
u.append_id(directional_shadow_get_texture());
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
@@ -377,7 +379,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
- RID texture = storage->lightmap_get_texture(base);
+ RID texture = RendererRD::LightStorage::get_singleton()->lightmap_get_texture(base);
RID rd_texture = texture_storage->texture_get_rd_texture(texture);
u.append_id(rd_texture);
} else {
@@ -425,7 +427,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -465,7 +467,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
scene_state.lightmap_ids[i] = p_lightmaps[i];
- scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap);
+ scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
scene_state.lightmaps_used++;
}
@@ -553,7 +555,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
env = nullptr;
}
@@ -596,7 +598,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
*/
} break;
@@ -608,7 +610,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
- RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear()));
+ RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
*/
} break;
@@ -723,10 +725,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
{
// regular forward for now
Vector<Color> c;
- c.push_back(clear_color.to_linear()); // our render buffer
+ c.push_back(clear_color.srgb_to_linear()); // our render buffer
if (render_buffer) {
if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- c.push_back(clear_color.to_linear()); // our resolve buffer
+ c.push_back(clear_color.srgb_to_linear()); // our resolve buffer
}
if (using_subpass_post_process) {
c.push_back(Color()); // our 2D buffer we're copying into
@@ -1137,14 +1139,17 @@ void RenderForwardMobile::_base_uniforms_changed() {
}
void RenderForwardMobile::_update_render_base_uniform_set() {
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != storage->lightmap_array_get_version())) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version())) {
if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
// This is all loaded into set 0
- lightmap_texture_array_version = storage->lightmap_array_get_version();
+ lightmap_texture_array_version = light_storage->lightmap_array_get_version();
Vector<RD::Uniform> uniforms;
@@ -1152,18 +1157,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
Vector<RID> ids;
ids.resize(12);
RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
@@ -1185,19 +1190,19 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RID sampler;
switch (decals_get_filter()) {
case RS::DECAL_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -1212,19 +1217,19 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RID sampler;
switch (light_projectors_get_filter()) {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
- sampler = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
}
@@ -1279,7 +1284,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
u.append_id(decal_atlas);
uniforms.push_back(u);
}
@@ -1287,7 +1292,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 12;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_srgb();
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_srgb();
u.append_id(decal_atlas);
uniforms.push_back(u);
}
@@ -1616,7 +1621,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
//ambient
if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
@@ -1626,7 +1631,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
} else {
float energy = environment_get_ambient_light_energy(p_render_data->environment);
Color color = environment_get_ambient_light_color(p_render_data->environment);
- color = color.to_linear();
+ color = color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
scene_state.ubo.ambient_light_color_energy[2] = color.b * energy;
@@ -1657,7 +1662,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
- Color fog_color = environment_get_fog_light_color(p_render_data->environment).to_linear();
+ Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
@@ -1667,12 +1672,12 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
} else {
- if (p_render_data->reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
scene_state.ubo.use_ambient_light = false;
} else {
scene_state.ubo.use_ambient_light = true;
Color clear_color = p_default_bg_color;
- clear_color = clear_color.to_linear();
+ clear_color = clear_color.srgb_to_linear();
scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
@@ -2449,6 +2454,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();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
if (ginstance->data->dirty_dependencies) {
@@ -2505,10 +2511,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
} break;
#endif
case RS::INSTANCE_PARTICLES: {
- int draw_passes = storage->particles_get_draw_passes(ginstance->data->base);
+ int draw_passes = particles_storage->particles_get_draw_passes(ginstance->data->base);
for (int j = 0; j < draw_passes; j++) {
- RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
+ RID mesh = particles_storage->particles_get_draw_pass_mesh(ginstance->data->base, j);
if (!mesh.is_valid()) {
continue;
}
@@ -2524,7 +2530,7 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
}
}
- ginstance->instance_count = storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
+ ginstance->instance_count = particles_storage->particles_get_amount(ginstance->data->base, ginstance->trail_steps);
} break;
@@ -2563,10 +2569,10 @@ void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry
//for particles, stride is the trail size
ginstance->base_flags |= (ginstance->trail_steps << INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT);
- if (!storage->particles_is_using_local_coords(ginstance->data->base)) {
+ if (!particles_storage->particles_is_using_local_coords(ginstance->data->base)) {
store_transform = false;
}
- ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ ginstance->transforms_uniform_set = particles_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 (mesh_storage->skeleton_is_valid(ginstance->data->skeleton)) {
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 5b5a39c215..fce798e3df 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -35,9 +35,8 @@
#include "core/math/math_defs.h"
#include "core/math/math_funcs.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/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
@@ -364,7 +363,7 @@ void RendererCanvasRenderRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RI
bool use_normal;
bool use_specular;
- bool success = RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
+ bool success = RendererRD::TextureStorage::get_singleton()->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular);
//something odd happened
if (!success) {
_bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size);
@@ -401,7 +400,9 @@ 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::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
RS::CanvasItemTextureFilter current_filter = default_filter;
RS::CanvasItemTextureRepeat current_repeat = default_repeat;
@@ -780,24 +781,24 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
} else if (c->type == Item::Command::TYPE_PARTICLES) {
const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c);
- ERR_BREAK(storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
- storage->particles_request_process(pt->particles);
+ ERR_BREAK(particles_storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D);
+ particles_storage->particles_request_process(pt->particles);
- if (storage->particles_is_inactive(pt->particles)) {
+ if (particles_storage->particles_is_inactive(pt->particles)) {
break;
}
RenderingServerDefault::redraw_request(); // active particles means redraw request
bool local_coords = true;
- int dpc = storage->particles_get_draw_passes(pt->particles);
+ int dpc = particles_storage->particles_get_draw_passes(pt->particles);
if (dpc == 0) {
break; //nothing to draw
}
uint32_t divisor = 1;
- instance_count = storage->particles_get_amount(pt->particles, divisor);
+ instance_count = particles_storage->particles_get_amount(pt->particles, divisor);
- RID uniform_set = storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
+ RID uniform_set = particles_storage->particles_get_instance_buffer_uniform_set(pt->particles, 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 |= divisor;
@@ -806,10 +807,10 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS;
push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA;
- mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
+ mesh = particles_storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored
texture = pt->texture;
- if (storage->particles_has_collision(pt->particles) && storage->render_target_is_sdf_enabled(p_render_target)) {
+ if (particles_storage->particles_has_collision(pt->particles) && texture_storage->render_target_is_sdf_enabled(p_render_target)) {
//pass collision information
Transform2D xform;
if (local_coords) {
@@ -818,19 +819,19 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
xform = p_canvas_transform_inverse;
}
- RID sdf_texture = storage->render_target_get_sdf_texture(p_render_target);
+ RID sdf_texture = texture_storage->render_target_get_sdf_texture(p_render_target);
Rect2 to_screen;
{
- Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_render_target);
+ Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_render_target);
to_screen.size = Vector2(1.0 / sdf_rect.size.width, 1.0 / sdf_rect.size.height);
to_screen.position = -sdf_rect.position * to_screen.size;
}
- storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, true, xform, to_screen, sdf_texture);
} else {
- storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
+ particles_storage->particles_set_canvas_sdf_collision(pt->particles, false, Transform2D(), Rect2(), RID());
}
}
@@ -931,6 +932,9 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, bool p_backbuffer) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
//re create canvas state
Vector<RD::Uniform> uniforms;
@@ -954,7 +958,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 3;
- u.append_id(RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture());
+ u.append_id(RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture());
uniforms.push_back(u);
}
@@ -980,9 +984,9 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
u.binding = 6;
RID screen;
if (p_backbuffer) {
- screen = storage->render_target_get_rd_texture(p_to_render_target);
+ screen = texture_storage->render_target_get_rd_texture(p_to_render_target);
} else {
- screen = storage->render_target_get_rd_backbuffer(p_to_render_target);
+ screen = texture_storage->render_target_get_rd_backbuffer(p_to_render_target);
if (screen.is_null()) { //unallocated backbuffer
screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
}
@@ -995,7 +999,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 7;
- RID sdf = storage->render_target_get_sdf_texture(p_to_render_target);
+ RID sdf = texture_storage->render_target_get_sdf_texture(p_to_render_target);
u.append_id(sdf);
uniforms.push_back(u);
}
@@ -1005,18 +1009,18 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
Vector<RID> ids;
ids.resize(12);
RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 8, ids);
@@ -1033,9 +1037,9 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, BASE_UNIFORM_SET);
if (p_backbuffer) {
- storage->render_target_set_backbuffer_uniform_set(p_to_render_target, uniform_set);
+ texture_storage->render_target_set_backbuffer_uniform_set(p_to_render_target, uniform_set);
} else {
- storage->render_target_set_framebuffer_uniform_set(p_to_render_target, uniform_set);
+ texture_storage->render_target_set_framebuffer_uniform_set(p_to_render_target, uniform_set);
}
return uniform_set;
@@ -1043,6 +1047,8 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
Item *current_clip = nullptr;
Transform2D canvas_transform_inverse = p_canvas_transform_inverse;
@@ -1053,21 +1059,21 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
Vector<Color> clear_colors;
if (p_to_backbuffer) {
- framebuffer = storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
- fb_uniform_set = storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
+ framebuffer = texture_storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target);
+ fb_uniform_set = texture_storage->render_target_get_backbuffer_uniform_set(p_to_render_target);
} else {
- framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target);
+ framebuffer = texture_storage->render_target_get_rd_framebuffer(p_to_render_target);
- if (storage->render_target_is_clear_requested(p_to_render_target)) {
+ if (texture_storage->render_target_is_clear_requested(p_to_render_target)) {
clear = true;
- clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target));
- storage->render_target_disable_clear_request(p_to_render_target);
+ clear_colors.push_back(texture_storage->render_target_get_clear_request_color(p_to_render_target));
+ texture_storage->render_target_disable_clear_request(p_to_render_target);
}
#ifndef _MSC_VER
#warning TODO obtain from framebuffer format eventually when this is implemented
#endif
- fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
+ fb_uniform_set = texture_storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
}
if (fb_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fb_uniform_set)) {
@@ -1136,6 +1142,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::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
@@ -1264,7 +1271,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
}
if (clight->texture.is_valid()) {
- Rect2 atlas_rect = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture_rect(clight->texture);
+ Rect2 atlas_rect = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture_rect(clight->texture);
state.light_uniforms[index].atlas_rect[0] = atlas_rect.position.x;
state.light_uniforms[index].atlas_rect[1] = atlas_rect.position.y;
state.light_uniforms[index].atlas_rect[2] = atlas_rect.size.width;
@@ -1294,7 +1301,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
//update canvas state uniform buffer
State::Buffer state_buffer;
- Size2i ssize = storage->render_target_get_size(p_to_render_target);
+ Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
@@ -1313,7 +1320,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
state_buffer.canvas_modulate[2] = p_modulate.b;
state_buffer.canvas_modulate[3] = p_modulate.a;
- Size2 render_target_size = storage->render_target_get_size(p_to_render_target);
+ Size2 render_target_size = texture_storage->render_target_get_size(p_to_render_target);
state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x;
state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y;
@@ -1330,7 +1337,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
state_buffer.screen_to_sdf[0] = 1.0 / state_buffer.sdf_to_screen[0];
state_buffer.screen_to_sdf[1] = 1.0 / state_buffer.sdf_to_screen[1];
- Rect2 sdf_rect = storage->render_target_get_sdf_rect(p_to_render_target);
+ Rect2 sdf_rect = texture_storage->render_target_get_sdf_rect(p_to_render_target);
Rect2 sdf_tex_rect(sdf_rect.position / canvas_scale, sdf_rect.size / canvas_scale);
state_buffer.sdf_to_tex[0] = 1.0 / sdf_tex_rect.size.width;
@@ -1420,9 +1427,9 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
- storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
} else {
- storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0));
+ texture_storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0));
}
backbuffer_copy = false;
@@ -1442,7 +1449,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
item_count = 0;
if (ci->canvas_group->blur_mipmaps) {
- storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
+ texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache);
}
canvas_group_owner = nullptr;
@@ -1457,7 +1464,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
backbuffer_copy = false;
material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
@@ -1490,7 +1497,7 @@ RID RendererCanvasRenderRD::light_create() {
}
void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
- RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
CanvasLight *cl = canvas_light_owner.get_or_null(p_rid);
ERR_FAIL_COND(!cl);
@@ -1498,12 +1505,12 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
return;
}
if (cl->texture.is_valid()) {
- decal_atlas_storage->texture_remove_from_decal_atlas(cl->texture);
+ texture_storage->texture_remove_from_decal_atlas(cl->texture);
}
cl->texture = p_texture;
if (cl->texture.is_valid()) {
- decal_atlas_storage->texture_add_to_decal_atlas(cl->texture);
+ texture_storage->texture_add_to_decal_atlas(cl->texture);
}
}
@@ -1703,8 +1710,10 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
}
void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) {
- RID fb = storage->render_target_get_sdf_framebuffer(p_render_target);
- Rect2i rect = storage->render_target_get_sdf_rect(p_render_target);
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+ RID fb = texture_storage->render_target_get_sdf_framebuffer(p_render_target);
+ Rect2i rect = texture_storage->render_target_get_sdf_rect(p_render_target);
Transform2D to_sdf;
to_sdf.elements[0] *= rect.size.width;
@@ -1761,7 +1770,7 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
RD::get_singleton()->draw_list_end();
- storage->render_target_sdf_process(p_render_target); //done rendering, process it
+ texture_storage->render_target_sdf_process(p_render_target); //done rendering, process it
}
RID RendererCanvasRenderRD::occluder_polygon_create() {
@@ -2258,7 +2267,7 @@ void RendererCanvasRenderRD::update() {
}
RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
- RendererRD::CanvasTextureStorage *canvas_texture_storage = RendererRD::CanvasTextureStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
@@ -2590,8 +2599,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET);
}
- default_canvas_texture = canvas_texture_storage->canvas_texture_allocate();
- canvas_texture_storage->canvas_texture_initialize(default_canvas_texture);
+ default_canvas_texture = texture_storage->canvas_texture_allocate();
+ texture_storage->canvas_texture_initialize(default_canvas_texture);
state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
@@ -2712,6 +2721,6 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
}
RD::get_singleton()->free(state.shadow_texture);
- RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
+ RendererRD::TextureStorage::get_singleton()->canvas_texture_free(default_canvas_texture);
//pipelines don't need freeing, they are all gone after shaders are gone
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 5b7c63b508..fd56de845f 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -44,7 +44,7 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
}
for (int i = 0; i < p_amount; i++) {
- RID texture = storage->render_target_get_texture(p_render_targets[i].render_target);
+ RID texture = texture_storage->render_target_get_texture(p_render_targets[i].render_target);
ERR_CONTINUE(texture.is_null());
RID rd_texture = texture_storage->texture_get_rd_texture(texture);
ERR_CONTINUE(rd_texture.is_null());
@@ -155,11 +155,11 @@ void RendererCompositorRD::finalize() {
memdelete(scene);
memdelete(canvas);
memdelete(storage);
- memdelete(decal_atlas_storage);
+ memdelete(particles_storage);
+ memdelete(light_storage);
memdelete(mesh_storage);
memdelete(material_storage);
memdelete(texture_storage);
- memdelete(canvas_texture_storage);
//only need to erase these, the rest are erased by cascade
blit.shader.version_free(blit.shader_version);
@@ -253,8 +253,8 @@ RendererCompositorRD::RendererCompositorRD() {
if (shader_cache_dir.is_empty()) {
shader_cache_dir = "user://";
}
- DirAccessRef da = DirAccess::open(shader_cache_dir);
- if (!da) {
+ Ref<DirAccess> da = DirAccess::open(shader_cache_dir);
+ if (da.is_null()) {
ERR_PRINT("Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir);
} else {
Error err = da->change_dir("shader_cache");
@@ -288,11 +288,11 @@ RendererCompositorRD::RendererCompositorRD() {
singleton = this;
time = 0;
- canvas_texture_storage = memnew(RendererRD::CanvasTextureStorage);
texture_storage = memnew(RendererRD::TextureStorage);
- decal_atlas_storage = memnew(RendererRD::DecalAtlasStorage);
material_storage = memnew(RendererRD::MaterialStorage);
mesh_storage = memnew(RendererRD::MeshStorage);
+ light_storage = memnew(RendererRD::LightStorage);
+ particles_storage = memnew(RendererRD::ParticlesStorage);
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 542cff0159..768e9e0947 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -39,10 +39,10 @@
#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/blit.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/light_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/particles_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
@@ -50,11 +50,11 @@ class RendererCompositorRD : public RendererCompositor {
protected:
UniformSetCacheRD *uniform_set_cache = nullptr;
RendererCanvasRenderRD *canvas = nullptr;
- RendererRD::CanvasTextureStorage *canvas_texture_storage;
+ RendererRD::LightStorage *light_storage;
RendererRD::MaterialStorage *material_storage;
RendererRD::MeshStorage *mesh_storage;
+ RendererRD::ParticlesStorage *particles_storage;
RendererRD::TextureStorage *texture_storage;
- RendererRD::DecalAtlasStorage *decal_atlas_storage;
RendererStorageRD *storage = nullptr;
RendererSceneRenderRD *scene = nullptr;
@@ -98,10 +98,10 @@ protected:
static uint64_t frame;
public:
- RendererCanvasTextureStorage *get_canvas_texture_storage() { return canvas_texture_storage; }
- RendererDecalAtlasStorage *get_decal_atlas_storage() { return decal_atlas_storage; }
+ RendererLightStorage *get_light_storage() { return light_storage; };
RendererMaterialStorage *get_material_storage() { return material_storage; };
RendererMeshStorage *get_mesh_storage() { return mesh_storage; };
+ RendererParticlesStorage *get_particles_storage() { return particles_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.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
index 75202d5abb..d8b7d5384e 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
@@ -32,6 +32,8 @@
#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
@@ -41,6 +43,8 @@ const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFF
void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
storage = p_gi->storage;
gi = p_gi;
num_cascades = p_env->sdfgi_cascades;
@@ -387,7 +391,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
{
@@ -669,7 +673,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 6;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -921,7 +925,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
if (p_env->background == RS::ENV_BG_CLEAR_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = storage->get_default_clear_color().to_linear();
+ Color c = storage->get_default_clear_color().srgb_to_linear();
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
@@ -949,7 +953,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 1;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -1110,6 +1114,7 @@ void RendererSceneGIRD::SDFGI::update_cascades() {
void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -1176,7 +1181,7 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
RD::Uniform u;
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
{
@@ -1245,11 +1250,13 @@ void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, cons
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1);
RD::get_singleton()->compute_list_end();
- Size2 rtsize = storage->render_target_get_size(p_render_target);
- storage->get_effects()->copy_to_fb_rect(p_texture, storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
+ Size2 rtsize = texture_storage->render_target_get_size(p_render_target);
+ storage->get_effects()->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
}
void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
SDFGIShader::DebugProbesPushConstant push_constant;
for (int i = 0; i < 4; i++) {
@@ -1296,7 +1303,7 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
{
@@ -1458,7 +1465,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j));
ERR_CONTINUE(!li);
- if (storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+ if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
continue;
}
@@ -1468,14 +1475,14 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
lights[idx].direction[0] = dir.x;
lights[idx].direction[1] = dir.y;
lights[idx].direction[2] = dir.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
+ Color color = RSG::light_storage->light_get_color(li->light);
+ color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
lights[idx].type = RS::LIGHT_DIRECTIONAL;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
+ lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
idx++;
}
@@ -1492,7 +1499,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]);
ERR_CONTINUE(!li);
- uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+ uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
if (i > max_sdfgi_cascade) {
continue;
}
@@ -1513,18 +1520,18 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
lights[idx].position[0] = pos.x;
lights[idx].position[1] = pos.y;
lights[idx].position[2] = pos.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
+ Color color = RSG::light_storage->light_get_color(li->light);
+ color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
- lights[idx].type = storage->light_get_type(li->light);
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
- lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ lights[idx].type = RSG::light_storage->light_get_type(li->light);
+ lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
+ lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -1928,7 +1935,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]);
ERR_CONTINUE(!li);
- uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light);
+ uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
if (p_cascade_indices[i] > max_sdfgi_cascade) {
continue;
}
@@ -1937,7 +1944,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
continue;
}
- lights[idx].type = storage->light_get_type(li->light);
+ lights[idx].type = RSG::light_storage->light_get_type(li->light);
Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z);
if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {
@@ -1952,17 +1959,17 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
lights[idx].position[0] = pos.x;
lights[idx].position[1] = pos.y;
lights[idx].position[2] = pos.z;
- Color color = storage->light_get_color(li->light);
- color = color.to_linear();
+ Color color = RSG::light_storage->light_get_color(li->light);
+ color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
- lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = storage->light_has_shadow(li->light);
- lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- lights[idx].inv_spot_attenuation = 1.0f / storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
+ lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -2019,6 +2026,8 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
// VoxelGIInstance
void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
uint32_t data_version = storage->voxel_gi_get_data_version(probe);
// (RE)CREATE IF NEEDED
@@ -2111,7 +2120,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 10;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -2265,7 +2274,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 10;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
{
@@ -2334,7 +2343,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 10;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -2387,22 +2396,22 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RID light_instance = p_light_instances[i];
RID light = p_scene_render->light_instance_get_base_light(light_instance);
- l.type = storage->light_get_type(light);
- if (l.type == RS::LIGHT_DIRECTIONAL && storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+ l.type = RSG::light_storage->light_get_type(light);
+ if (l.type == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
light_count--;
continue;
}
- l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
- l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
- Color color = storage->light_get_color(light).to_linear();
+ l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
+ l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ l.radius = to_cell.basis.xform(Vector3(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
+ Color color = RSG::light_storage->light_get_color(light).srgb_to_linear();
l.color[0] = color.r;
l.color[1] = color.g;
l.color[2] = color.b;
- l.cos_spot_angle = Math::cos(Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- l.inv_spot_attenuation = 1.0f / storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance);
@@ -2417,7 +2426,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
l.direction[1] = dir.y;
l.direction[2] = dir.z;
- l.has_shadow = storage->light_has_shadow(light);
+ l.has_shadow = RSG::light_storage->light_has_shadow(light);
}
RD::get_singleton()->buffer_update(gi->voxel_gi_lights_uniform, 0, sizeof(VoxelGILight) * light_count, gi->voxel_gi_lights);
@@ -2722,6 +2731,8 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
}
void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
if (mipmaps.size() == 0) {
return;
}
@@ -2770,7 +2781,7 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 3;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -2811,6 +2822,7 @@ RendererSceneGIRD::~RendererSceneGIRD() {
void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
storage = p_storage;
@@ -2936,7 +2948,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 1;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
@@ -3129,6 +3141,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RD::get_singleton()->draw_command_begin_label("GI Render");
@@ -3254,14 +3267,14 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 6;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 7;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
index ed60bc4362..122644498b 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
@@ -45,7 +45,6 @@
#include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index ac7ac692ce..bdbc228bde 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -33,7 +33,6 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "renderer_compositor_rd.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/rendering_server_default.h"
@@ -517,7 +516,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
ambient_color_sky_mix = env->ambient_sky_contribution;
const float ambient_energy = env->ambient_light_energy;
ambient_color = env->ambient_light;
- ambient_color = ambient_color.to_linear();
+ ambient_color = ambient_color.srgb_to_linear();
ambient_color.r *= ambient_energy;
ambient_color.g *= ambient_energy;
ambient_color.b *= ambient_energy;
@@ -536,7 +535,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
} else {
const float bg_energy = env->bg_energy;
Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color);
- panorama_color = panorama_color.to_linear();
+ panorama_color = panorama_color.srgb_to_linear();
panorama_color.r *= bg_energy;
panorama_color.g *= bg_energy;
panorama_color.b *= bg_energy;
@@ -690,7 +689,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instanc
return true;
}
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
return true;
}
@@ -714,12 +713,12 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
RD::get_singleton()->draw_command_begin_label("Reflection probe render");
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
}
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
// Invalidate reflection atlas, need to regenerate
RD::get_singleton()->free(atlas->reflection);
atlas->reflection = RID();
@@ -736,7 +735,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
if (atlas->reflection.is_null()) {
int mipmaps = MIN(sky.roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
- mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
+ mipmaps = RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
{
//reflection atlas was unused, create:
RD::TextureFormat tf;
@@ -760,7 +759,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc
}
atlas->reflections.resize(atlas->count);
for (int i = 0; i < atlas->count; i++) {
- atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
+ atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
for (int j = 0; j < 6; j++) {
atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
}
@@ -828,7 +827,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins
return false;
}
- if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+ if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
// Using real time reflections, all roughness is done in one step
atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(storage, false);
rpi->rendering = false;
@@ -1346,7 +1345,7 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance);
ERR_FAIL_COND_V(!light_instance, 0);
- switch (storage->light_directional_get_shadow_mode(light_instance->light)) {
+ switch (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light)) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
break; //none
case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
@@ -1408,7 +1407,7 @@ RID RendererSceneRenderRD::light_instance_create(RID p_light) {
light_instance->self = li;
light_instance->light = p_light;
- light_instance->light_type = storage->light_get_type(p_light);
+ light_instance->light_type = RSG::light_storage->light_get_type(p_light);
if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
light_instance->forward_id = _allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT);
}
@@ -2557,7 +2556,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
tonemap.view_count = p_render_data->view_count;
- storage->get_effects()->tonemapper(rb->internal_texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+ storage->get_effects()->tonemapper(rb->internal_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
RD::get_singleton()->draw_command_end_label();
}
@@ -2570,7 +2569,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RD::get_singleton()->draw_command_end_label();
}
- storage->render_target_disable_clear_request(rb->render_target);
+ texture_storage->render_target_disable_clear_request(rb->render_target);
}
void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
@@ -2647,7 +2646,8 @@ void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- storage->render_target_disable_clear_request(rb->render_target);
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ texture_storage->render_target_disable_clear_request(rb->render_target);
}
void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
@@ -2665,64 +2665,64 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
}
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) {
if (directional_shadow_get_texture().is_valid()) {
RID shadow_atlas_texture = directional_shadow_get_texture();
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DECAL_ATLAS) {
- RID decal_atlas = RendererRD::DecalAtlasStorage::get_singleton()->decal_atlas_get_texture();
+ RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
if (decal_atlas.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(decal_atlas, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
+ effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
if (rb->luminance.current.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
+ effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
RID ambient_texture = rb->ambient_buffer;
RID reflection_texture = rb->reflection_buffer;
- effects->copy_to_fb_rect(ambient_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
+ effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) {
if (p_occlusion_buffer.is_valid()) {
- Size2 rtsize = storage->render_target_get_size(rb->render_target);
- effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
+ Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
}
}
}
@@ -2943,6 +2943,9 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
}
void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
if (!_render_buffers_can_be_storage()) {
@@ -2952,7 +2955,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
if (p_width != p_internal_width) {
float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
- storage->sampler_rd_configure_custom(fsr_mipmap_bias);
+ material_storage->sampler_rd_configure_custom(fsr_mipmap_bias);
update_uniform_sets();
}
@@ -3040,11 +3043,11 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
}
- RID target_texture = storage->render_target_get_rd_texture(rb->render_target);
+ RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count);
if (is_clustered_enabled()) {
- rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
+ rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
}
}
@@ -3189,6 +3192,7 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
}
void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
cluster.reflection_count = 0;
for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
@@ -3223,30 +3227,30 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
Cluster::ReflectionData &reflection_ubo = cluster.reflections[i];
- Vector3 extents = storage->reflection_probe_get_extents(base_probe);
+ Vector3 extents = light_storage->reflection_probe_get_extents(base_probe);
- rpi->cull_mask = storage->reflection_probe_get_cull_mask(base_probe);
+ rpi->cull_mask = light_storage->reflection_probe_get_cull_mask(base_probe);
reflection_ubo.box_extents[0] = extents.x;
reflection_ubo.box_extents[1] = extents.y;
reflection_ubo.box_extents[2] = extents.z;
reflection_ubo.index = rpi->atlas_index;
- Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe);
+ Vector3 origin_offset = light_storage->reflection_probe_get_origin_offset(base_probe);
reflection_ubo.box_offset[0] = origin_offset.x;
reflection_ubo.box_offset[1] = origin_offset.y;
reflection_ubo.box_offset[2] = origin_offset.z;
- reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
+ reflection_ubo.mask = light_storage->reflection_probe_get_cull_mask(base_probe);
- reflection_ubo.intensity = storage->reflection_probe_get_intensity(base_probe);
- reflection_ubo.ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
+ reflection_ubo.intensity = light_storage->reflection_probe_get_intensity(base_probe);
+ reflection_ubo.ambient_mode = light_storage->reflection_probe_get_ambient_mode(base_probe);
- reflection_ubo.exterior = !storage->reflection_probe_is_interior(base_probe);
- reflection_ubo.box_project = storage->reflection_probe_is_box_projection(base_probe);
+ reflection_ubo.exterior = !light_storage->reflection_probe_is_interior(base_probe);
+ reflection_ubo.box_project = light_storage->reflection_probe_is_box_projection(base_probe);
- Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear();
- float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe);
+ Color ambient_linear = light_storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear();
+ float interior_ambient_energy = light_storage->reflection_probe_get_ambient_color_energy(base_probe);
reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
@@ -3268,7 +3272,8 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
}
void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
- RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
Transform3D inverse_transform = p_camera_transform.affine_inverse();
@@ -3291,10 +3296,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
ERR_CONTINUE(base.is_null());
- RS::LightType type = storage->light_get_type(base);
+ RS::LightType type = light_storage->light_get_type(base);
switch (type) {
case RS::LIGHT_DIRECTIONAL: {
- if (r_directional_light_count >= cluster.max_directional_lights || storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+ if (r_directional_light_count >= cluster.max_directional_lights || light_storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
continue;
}
@@ -3308,19 +3313,19 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.direction[1] = direction.y;
light_data.direction[2] = direction.z;
- float sign = storage->light_is_negative(base) ? -1 : 1;
+ float sign = light_storage->light_is_negative(base) ? -1 : 1;
- light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
+ light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
- Color linear_col = storage->light_get_color(base).to_linear();
+ Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
light_data.color[0] = linear_col.r;
light_data.color[1] = linear_col.g;
light_data.color[2] = linear_col.b;
- light_data.specular = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
- light_data.mask = storage->light_get_cull_mask(base);
+ light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
+ light_data.mask = light_storage->light_get_cull_mask(base);
- float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
@@ -3328,15 +3333,15 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
}
- light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base);
+ light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base);
- float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
if (angular_diameter > 0.0) {
// I know tan(0) is 0, but let's not risk it with numerical precision.
// technically this will keep expanding until reaching the sun, but all we care
// is expand until we reach the radius of the near plane (there can't be more occluders than that)
angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
- if (storage->light_has_shadow(base)) {
+ if (light_storage->light_has_shadow(base)) {
r_directional_light_soft_shadows = true;
}
} else {
@@ -3344,10 +3349,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
if (light_data.shadow_enabled) {
- RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base);
+ RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base);
int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
- light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && storage->light_directional_get_blend_splits(base);
+ light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base);
for (int j = 0; j < 4; j++) {
Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
CameraMatrix matrix = li->shadow_transform[j].camera;
@@ -3363,9 +3368,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
light_data.shadow_split_offsets[j] = split;
float bias_scale = li->shadow_transform[j].bias_scale;
- light_data.shadow_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
- light_data.shadow_normal_bias[j] = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
- light_data.shadow_transmittance_bias[j] = storage->light_get_transmittance_bias(base) * bias_scale;
+ light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
+ light_data.shadow_normal_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
+ light_data.shadow_transmittance_bias[j] = light_storage->light_get_transmittance_bias(base) * bias_scale;
light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin;
RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
@@ -3392,14 +3397,14 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
- float fade_start = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
+ float fade_start = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
light_data.fade_to = -light_data.shadow_split_offsets[3];
- light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+ light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
- light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+ light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
light_data.softshadow_angle = angular_diameter;
- light_data.bake_mode = storage->light_get_bake_mode(base);
+ light_data.bake_mode = light_storage->light_get_bake_mode(base);
if (angular_diameter <= 0.0) {
light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
@@ -3415,9 +3420,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
const real_t distance = camera_plane.distance_to(li->transform.origin);
- if (storage->light_is_distance_fade_enabled(li->light)) {
- const float fade_begin = storage->light_get_distance_fade_begin(li->light);
- const float fade_length = storage->light_get_distance_fade_length(li->light);
+ if (light_storage->light_is_distance_fade_enabled(li->light)) {
+ const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+ const float fade_length = light_storage->light_get_distance_fade_length(li->light);
if (distance > fade_begin) {
if (distance > fade_begin + fade_length) {
@@ -3438,9 +3443,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
const real_t distance = camera_plane.distance_to(li->transform.origin);
- if (storage->light_is_distance_fade_enabled(li->light)) {
- const float fade_begin = storage->light_get_distance_fade_begin(li->light);
- const float fade_length = storage->light_get_distance_fade_length(li->light);
+ if (light_storage->light_is_distance_fade_enabled(li->light)) {
+ const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+ const float fade_length = light_storage->light_get_distance_fade_length(li->light);
if (distance > fade_begin) {
if (distance > fade_begin + fade_length) {
@@ -3490,10 +3495,10 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
Transform3D light_transform = li->transform;
- float sign = storage->light_is_negative(base) ? -1 : 1;
- Color linear_col = storage->light_get_color(base).to_linear();
+ float sign = light_storage->light_is_negative(base) ? -1 : 1;
+ Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
- light_data.attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
+ light_data.attenuation = light_storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
// Reuse fade begin, fade length and distance for shadow LOD determination later.
float fade_begin = 0.0;
@@ -3501,9 +3506,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
real_t distance = 0.0;
float fade = 1.0;
- if (storage->light_is_distance_fade_enabled(li->light)) {
- fade_begin = storage->light_get_distance_fade_begin(li->light);
- fade_length = storage->light_get_distance_fade_length(li->light);
+ if (light_storage->light_is_distance_fade_enabled(li->light)) {
+ fade_begin = light_storage->light_get_distance_fade_begin(li->light);
+ fade_length = light_storage->light_get_distance_fade_length(li->light);
distance = camera_plane.distance_to(li->transform.origin);
if (distance > fade_begin) {
@@ -3512,15 +3517,15 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
- float energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
+ float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
light_data.color[0] = linear_col.r * energy;
light_data.color[1] = linear_col.g * energy;
light_data.color[2] = linear_col.b * energy;
- light_data.specular_amount = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
- light_data.bake_mode = storage->light_get_bake_mode(base);
+ light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
+ light_data.bake_mode = light_storage->light_get_bake_mode(base);
- float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
+ float radius = MAX(0.001, light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
light_data.inv_radius = 1.0 / radius;
Vector3 pos = inverse_transform.xform(light_transform.origin);
@@ -3535,25 +3540,25 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.direction[1] = direction.y;
light_data.direction[2] = direction.z;
- float size = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
light_data.size = size;
- light_data.inv_spot_attenuation = 1.0f / storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
- float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle));
- light_data.mask = storage->light_get_cull_mask(base);
+ light_data.mask = light_storage->light_get_cull_mask(base);
light_data.atlas_rect[0] = 0;
light_data.atlas_rect[1] = 0;
light_data.atlas_rect[2] = 0;
light_data.atlas_rect[3] = 0;
- RID projector = storage->light_get_projector(base);
+ RID projector = light_storage->light_get_projector(base);
if (projector.is_valid()) {
- Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(projector);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(projector);
if (type == RS::LIGHT_SPOT) {
light_data.projector_rect[0] = rect.position.x;
@@ -3576,8 +3581,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self);
bool in_shadow_range = true;
- if (needs_shadow && storage->light_is_distance_fade_enabled(li->light)) {
- if (distance > storage->light_get_distance_fade_shadow(li->light)) {
+ if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
+ if (distance > light_storage->light_get_distance_fade_shadow(li->light)) {
// Out of range, don't draw shadows to improve performance.
in_shadow_range = false;
}
@@ -3589,15 +3594,15 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.shadow_enabled = true;
float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
- light_data.shadow_normal_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
+ light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
if (type == RS::LIGHT_SPOT) {
- light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
+ light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
} else { //omni
- light_data.shadow_bias = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
+ light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
}
- light_data.transmittance_bias = storage->light_get_transmittance_bias(base);
+ light_data.transmittance_bias = light_storage->light_get_transmittance_bias(base);
Vector2i omni_offset;
Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas, omni_offset);
@@ -3607,8 +3612,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.atlas_rect[2] = rect.size.width;
light_data.atlas_rect[3] = rect.size.height;
- light_data.soft_shadow_scale = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
- light_data.shadow_volumetric_fog_fade = 1.0 / storage->light_get_shadow_volumetric_fog_fade(base);
+ light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
+ light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
if (type == RS::LIGHT_OMNI) {
Transform3D proj = (inverse_transform * light_transform).inverse();
@@ -3645,7 +3650,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
light_data.shadow_enabled = false;
}
- li->cull_mask = storage->light_get_cull_mask(base);
+ li->cull_mask = light_storage->light_get_cull_mask(base);
if (current_cluster_builder != nullptr) {
current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
@@ -3669,7 +3674,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
- RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
Transform3D uv_xform;
uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
@@ -3694,9 +3699,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
- if (decal_atlas_storage->decal_is_distance_fade_enabled(decal)) {
- float fade_begin = decal_atlas_storage->decal_get_distance_fade_begin(decal);
- float fade_length = decal_atlas_storage->decal_get_distance_fade_length(decal);
+ if (texture_storage->decal_is_distance_fade_enabled(decal)) {
+ float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
+ float fade_length = texture_storage->decal_get_distance_fade_length(decal);
if (distance > fade_begin) {
if (distance > fade_begin + fade_length) {
@@ -3724,15 +3729,15 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
_map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i);
}
- di->cull_mask = decal_atlas_storage->decal_get_cull_mask(decal);
+ di->cull_mask = texture_storage->decal_get_cull_mask(decal);
Transform3D xform = di->transform;
float fade = 1.0;
- if (decal_atlas_storage->decal_is_distance_fade_enabled(decal)) {
+ if (texture_storage->decal_is_distance_fade_enabled(decal)) {
real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
- float fade_begin = decal_atlas_storage->decal_get_distance_fade_begin(decal);
- float fade_length = decal_atlas_storage->decal_get_distance_fade_length(decal);
+ float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
+ float fade_length = texture_storage->decal_get_distance_fade_length(decal);
if (distance > fade_begin) {
fade = 1.0 - (distance - fade_begin) / fade_length;
@@ -3741,7 +3746,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
Cluster::DecalData &dd = cluster.decals[i];
- Vector3 decal_extents = decal_atlas_storage->decal_get_extents(decal);
+ Vector3 decal_extents = texture_storage->decal_get_extents(decal);
Transform3D scale_xform;
scale_xform.basis.scale(decal_extents);
@@ -3754,12 +3759,12 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.normal[0] = normal.x;
dd.normal[1] = normal.y;
dd.normal[2] = normal.z;
- dd.normal_fade = decal_atlas_storage->decal_get_normal_fade(decal);
+ dd.normal_fade = texture_storage->decal_get_normal_fade(decal);
- RID albedo_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
- RID emission_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
+ RID albedo_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
+ RID emission_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
if (albedo_tex.is_valid()) {
- Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(albedo_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(albedo_tex);
dd.albedo_rect[0] = rect.position.x;
dd.albedo_rect[1] = rect.position.y;
dd.albedo_rect[2] = rect.size.x;
@@ -3774,10 +3779,10 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.albedo_rect[3] = 0;
}
- RID normal_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
+ RID normal_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
if (normal_tex.is_valid()) {
- Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(normal_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(normal_tex);
dd.normal_rect[0] = rect.position.x;
dd.normal_rect[1] = rect.position.y;
dd.normal_rect[2] = rect.size.x;
@@ -3792,9 +3797,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.normal_rect[3] = 0;
}
- RID orm_tex = decal_atlas_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
+ RID orm_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
if (orm_tex.is_valid()) {
- Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(orm_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(orm_tex);
dd.orm_rect[0] = rect.position.x;
dd.orm_rect[1] = rect.position.y;
dd.orm_rect[2] = rect.size.x;
@@ -3807,7 +3812,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
}
if (emission_tex.is_valid()) {
- Rect2 rect = decal_atlas_storage->decal_atlas_get_texture_rect(emission_tex);
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(emission_tex);
dd.emission_rect[0] = rect.position.x;
dd.emission_rect[1] = rect.position.y;
dd.emission_rect[2] = rect.size.x;
@@ -3819,16 +3824,16 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
dd.emission_rect[3] = 0;
}
- Color modulate = decal_atlas_storage->decal_get_modulate(decal);
+ Color modulate = texture_storage->decal_get_modulate(decal);
dd.modulate[0] = modulate.r;
dd.modulate[1] = modulate.g;
dd.modulate[2] = modulate.b;
dd.modulate[3] = modulate.a * fade;
- dd.emission_energy = decal_atlas_storage->decal_get_emission_energy(decal) * fade;
- dd.albedo_mix = decal_atlas_storage->decal_get_albedo_mix(decal);
- dd.mask = decal_atlas_storage->decal_get_cull_mask(decal);
- dd.upper_fade = decal_atlas_storage->decal_get_upper_fade(decal);
- dd.lower_fade = decal_atlas_storage->decal_get_lower_fade(decal);
+ dd.emission_energy = texture_storage->decal_get_emission_energy(decal) * fade;
+ dd.albedo_mix = texture_storage->decal_get_albedo_mix(decal);
+ dd.mask = texture_storage->decal_get_cull_mask(decal);
+ dd.upper_fade = texture_storage->decal_get_upper_fade(decal);
+ dd.lower_fade = texture_storage->decal_get_lower_fade(decal);
if (current_cluster_builder != nullptr) {
current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);
@@ -4438,7 +4443,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 7;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4500,7 +4505,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
u.binding = 13;
- u.append_id(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
uniforms.push_back(u);
copy_uniforms.push_back(u);
}
@@ -4641,7 +4646,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.fog_frustum_end = fog_end;
- Color ambient_color = env->ambient_light.to_linear();
+ Color ambient_color = env->ambient_light.srgb_to_linear();
params.ambient_color[0] = ambient_color.r;
params.ambient_color[1] = ambient_color.g;
params.ambient_color[2] = ambient_color.b;
@@ -4653,13 +4658,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.directional_light_count = p_directional_light_count;
- Color emission = env->volumetric_fog_emission.to_linear();
+ Color emission = env->volumetric_fog_emission.srgb_to_linear();
params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy;
params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy;
params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy;
params.base_density = env->volumetric_fog_density;
- Color base_scattering = env->volumetric_fog_scattering.to_linear();
+ Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear();
params.base_scattering[0] = base_scattering.r;
params.base_scattering[1] = base_scattering.g;
params.base_scattering[2] = base_scattering.b;
@@ -4809,6 +4814,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) {
// Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
if (p_render_data->render_buffers.is_valid() && p_use_gi) {
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
@@ -4828,9 +4834,9 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
for (int i = 0; i < render_state.render_shadow_count; i++) {
LightInstance *li = light_instance_owner.get_or_null(render_state.render_shadows[i].light);
- if (storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
+ if (light_storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
render_state.directional_shadows.push_back(i);
- } else if (storage->light_get_type(li->light) == RS::LIGHT_OMNI && storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ } else if (light_storage->light_get_type(li->light) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
render_state.cube_shadows.push_back(i);
} else {
render_state.shadows.push_back(i);
@@ -4940,7 +4946,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
bool using_shadows = true;
if (p_render_data->reflection_probe.is_valid()) {
- if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (!RSG::light_storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
using_shadows = false;
}
} else {
@@ -4974,6 +4980,8 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
// getting this here now so we can direct call a bunch of things more easily
RenderBuffers *rb = nullptr;
if (p_render_buffers.is_valid()) {
@@ -5052,7 +5060,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
Color clear_color;
if (p_render_buffers.is_valid()) {
- clear_color = storage->render_target_get_clear_request_color(rb->render_target);
+ clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target);
} else {
clear_color = storage->get_default_clear_color();
}
@@ -5171,7 +5179,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
CameraMatrix light_projection;
Transform3D light_transform;
- if (storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
+ if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
//set pssm stuff
if (light_instance->last_scene_shadow_pass != scene_pass) {
light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
@@ -5179,13 +5187,13 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
light_instance->last_scene_shadow_pass = scene_pass;
}
- use_pancake = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
+ use_pancake = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
light_projection = light_instance->shadow_transform[p_pass].camera;
light_transform = light_instance->shadow_transform[p_pass].transform;
atlas_rect = light_instance->directional_rect;
- if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+ if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
atlas_rect.size.width /= 2;
atlas_rect.size.height /= 2;
@@ -5196,7 +5204,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
} else if (p_pass == 3) {
atlas_rect.position += atlas_rect.size;
}
- } else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+ } else if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
atlas_rect.size.height /= 2;
if (p_pass == 0) {
@@ -5210,7 +5218,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
- zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
+ zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
render_fb = directional_shadow.fb;
render_texture = RID();
@@ -5244,13 +5252,13 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
atlas_rect.size.width = shadow_size;
atlas_rect.size.height = shadow_size;
- zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
+ zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
- if (storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
+ if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
bool wrap = (shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision == 0;
dual_paraboloid_offset = wrap ? Vector2i(1 - shadow_atlas->quadrants[quadrant].subdivision, 1) : Vector2i(1, 0);
- if (storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ if (RSG::light_storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2);
render_fb = cubemap->side_fb[p_pass];
@@ -5285,7 +5293,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
flip_y = true;
}
- } else if (storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
+ } else if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
light_projection = light_instance->shadow_transform[0].camera;
light_transform = light_instance->shadow_transform[0].transform;
@@ -5324,8 +5332,10 @@ void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform,
}
void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
- ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));
- Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
+ RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
+
+ ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider));
+ Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
CameraMatrix cm;
cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
@@ -5335,7 +5345,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
Transform3D cam_xform;
cam_xform.set_look_at(cam_pos, cam_pos - p_transform.basis.get_axis(Vector3::AXIS_Y), -p_transform.basis.get_axis(Vector3::AXIS_Z).normalized());
- RID fb = storage->particles_collision_get_heightfield_framebuffer(p_collider);
+ RID fb = particles_storage->particles_collision_get_heightfield_framebuffer(p_collider);
_render_particle_collider_heightfield(fb, cam_xform, cm, p_instances);
}
@@ -5741,18 +5751,18 @@ void fog() {
Vector<RID> ids;
ids.resize(12);
RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
uniforms.push_back(u);
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
index 061aa8b4aa..db7a5250b6 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
@@ -927,18 +927,18 @@ void sky() {
Vector<RID> ids;
ids.resize(12);
RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 0, ids);
@@ -1086,6 +1086,7 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
}
void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
@@ -1181,8 +1182,8 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
ERR_CONTINUE(base.is_null());
- RS::LightType type = storage->light_get_type(base);
- if (type == RS::LIGHT_DIRECTIONAL && storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) {
+ RS::LightType type = light_storage->light_get_type(base);
+ if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) {
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count];
Transform3D light_transform = li->transform;
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
@@ -1191,17 +1192,17 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_light_data.direction[1] = world_direction.y;
sky_light_data.direction[2] = world_direction.z;
- float sign = storage->light_is_negative(base) ? -1 : 1;
- sky_light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
+ float sign = light_storage->light_is_negative(base) ? -1 : 1;
+ sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
- Color linear_col = storage->light_get_color(base).to_linear();
+ Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
sky_light_data.color[0] = linear_col.r;
sky_light_data.color[1] = linear_col.g;
sky_light_data.color[2] = linear_col.b;
sky_light_data.enabled = true;
- float angular_diameter = storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
+ float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
if (angular_diameter > 0.0) {
// I know tan(0) is 0, but let's not risk it with numerical precision.
// technically this will keep expanding until reaching the sun, but all we care
@@ -1286,7 +1287,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
sky_scene_state.ubo.fog_enabled = p_env->fog_enabled;
sky_scene_state.ubo.fog_density = p_env->fog_density;
sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective;
- Color fog_color = p_env->fog_light_color.to_linear();
+ Color fog_color = p_env->fog_light_color.srgb_to_linear();
float fog_energy = p_env->fog_light_energy;
sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
index 72f98a4690..fa9f87abbe 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
@@ -35,1770 +35,13 @@
#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/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/particles_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"
-/* CANVAS TEXTURE */
-
-void RendererStorageRD::sampler_rd_configure_custom(float p_mipmap_bias) {
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- RD::SamplerState sampler_state;
- switch (i) {
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.lod_bias = p_mipmap_bias;
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
-
- } break;
- default: {
- }
- }
- switch (j) {
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- } break;
- default: {
- }
- }
-
- if (custom_rd_samplers[i][j].is_valid()) {
- RD::get_singleton()->free(custom_rd_samplers[i][j]);
- }
-
- custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
- }
- }
-}
-
-/* PARTICLES */
-
-RID RendererStorageRD::particles_allocate() {
- return particles_owner.allocate_rid();
-}
-void RendererStorageRD::particles_initialize(RID p_rid) {
- particles_owner.initialize_rid(p_rid, Particles());
-}
-
-void RendererStorageRD::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- if (particles->mode == p_mode) {
- return;
- }
-
- _particles_free_data(particles);
-
- particles->mode = p_mode;
-}
-
-void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->emitting = p_emitting;
-}
-
-bool RendererStorageRD::particles_get_emitting(RID p_particles) {
- ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, false);
-
- return particles->emitting;
-}
-
-void RendererStorageRD::_particles_free_data(Particles *particles) {
- if (particles->particle_buffer.is_valid()) {
- RD::get_singleton()->free(particles->particle_buffer);
- particles->particle_buffer = RID();
- RD::get_singleton()->free(particles->particle_instance_buffer);
- particles->particle_instance_buffer = RID();
- }
-
- particles->userdata_count = 0;
-
- if (particles->frame_params_buffer.is_valid()) {
- RD::get_singleton()->free(particles->frame_params_buffer);
- particles->frame_params_buffer = RID();
- }
- particles->particles_transforms_buffer_uniform_set = RID();
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->trail_bind_pose_uniform_set)) {
- RD::get_singleton()->free(particles->trail_bind_pose_uniform_set);
- }
- particles->trail_bind_pose_uniform_set = RID();
-
- if (particles->trail_bind_pose_buffer.is_valid()) {
- RD::get_singleton()->free(particles->trail_bind_pose_buffer);
- particles->trail_bind_pose_buffer = RID();
- }
- if (RD::get_singleton()->uniform_set_is_valid(particles->collision_textures_uniform_set)) {
- RD::get_singleton()->free(particles->collision_textures_uniform_set);
- }
- particles->collision_textures_uniform_set = RID();
-
- if (particles->particles_sort_buffer.is_valid()) {
- RD::get_singleton()->free(particles->particles_sort_buffer);
- particles->particles_sort_buffer = RID();
- particles->particles_sort_uniform_set = RID();
- }
-
- if (particles->emission_buffer != nullptr) {
- particles->emission_buffer = nullptr;
- particles->emission_buffer_data.clear();
- RD::get_singleton()->free(particles->emission_storage_buffer);
- particles->emission_storage_buffer = RID();
- }
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
- //will need to be re-created
- RD::get_singleton()->free(particles->particles_material_uniform_set);
- }
- particles->particles_material_uniform_set = RID();
-}
-
-void RendererStorageRD::particles_set_amount(RID p_particles, int p_amount) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- if (particles->amount == p_amount) {
- return;
- }
-
- _particles_free_data(particles);
-
- particles->amount = p_amount;
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_lifetime(RID p_particles, double p_lifetime) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->lifetime = p_lifetime;
-}
-
-void RendererStorageRD::particles_set_one_shot(RID p_particles, bool p_one_shot) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->one_shot = p_one_shot;
-}
-
-void RendererStorageRD::particles_set_pre_process_time(RID p_particles, double p_time) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->pre_process_time = p_time;
-}
-void RendererStorageRD::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->explosiveness = p_ratio;
-}
-void RendererStorageRD::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->randomness = p_ratio;
-}
-
-void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->custom_aabb = p_aabb;
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_set_speed_scale(RID p_particles, double p_scale) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->speed_scale = p_scale;
-}
-void RendererStorageRD::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->use_local_coords = p_enable;
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_fixed_fps(RID p_particles, int p_fps) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->fixed_fps = p_fps;
-
- _particles_free_data(particles);
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_interpolate(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->interpolate = p_enable;
-}
-
-void RendererStorageRD::particles_set_fractional_delta(RID p_particles, bool p_enable) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->fractional_delta = p_enable;
-}
-
-void RendererStorageRD::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(p_length < 0.1);
- p_length = MIN(10.0, p_length);
-
- particles->trails_enabled = p_enable;
- particles->trail_length = p_length;
-
- _particles_free_data(particles);
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) {
- _particles_free_data(particles);
-
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- }
- particles->trail_bind_poses = p_bind_poses;
- particles->trail_bind_poses_dirty = true;
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES);
-}
-
-void RendererStorageRD::particles_set_collision_base_size(RID p_particles, real_t p_size) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->collision_base_size = p_size;
-}
-
-void RendererStorageRD::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->transform_align = p_transform_align;
-}
-
-void RendererStorageRD::particles_set_process_material(RID p_particles, RID p_material) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->process_material = p_material;
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
-}
-
-RID RendererStorageRD::particles_get_process_material(RID p_particles) const {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RID());
-
- return particles->process_material;
-}
-
-void RendererStorageRD::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->draw_order = p_order;
-}
-
-void RendererStorageRD::particles_set_draw_passes(RID p_particles, int p_passes) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->draw_passes.resize(p_passes);
-}
-
-void RendererStorageRD::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
- particles->draw_passes.write[p_pass] = p_mesh;
-}
-
-void RendererStorageRD::particles_restart(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->restart_request = true;
-}
-
-void RendererStorageRD::_particles_allocate_emission_buffer(Particles *particles) {
- ERR_FAIL_COND(particles->emission_buffer != nullptr);
-
- particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4);
- memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size());
- particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw());
- particles->emission_buffer->particle_max = particles->amount;
-
- particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data);
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
- //will need to be re-created
- RD::get_singleton()->free(particles->particles_material_uniform_set);
- particles->particles_material_uniform_set = RID();
- }
-}
-
-void RendererStorageRD::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(p_particles == p_subemitter_particles);
-
- particles->sub_emitter = p_subemitter_particles;
-
- if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
- RD::get_singleton()->free(particles->particles_material_uniform_set);
- particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting
- }
-}
-
-void RendererStorageRD::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND(particles->amount == 0);
-
- if (particles->emitting) {
- particles->clear = true;
- particles->emitting = false;
- }
-
- if (particles->emission_buffer == nullptr) {
- _particles_allocate_emission_buffer(particles);
- }
-
- if (particles->inactive) {
- //in case it was inactive, make active again
- particles->inactive = false;
- particles->inactive_time = 0;
- }
-
- int32_t idx = particles->emission_buffer->particle_count;
- if (idx < particles->emission_buffer->particle_max) {
- store_transform(p_transform, particles->emission_buffer->data[idx].xform);
-
- particles->emission_buffer->data[idx].velocity[0] = p_velocity.x;
- particles->emission_buffer->data[idx].velocity[1] = p_velocity.y;
- particles->emission_buffer->data[idx].velocity[2] = p_velocity.z;
-
- particles->emission_buffer->data[idx].custom[0] = p_custom.r;
- particles->emission_buffer->data[idx].custom[1] = p_custom.g;
- particles->emission_buffer->data[idx].custom[2] = p_custom.b;
- particles->emission_buffer->data[idx].custom[3] = p_custom.a;
-
- particles->emission_buffer->data[idx].color[0] = p_color.r;
- particles->emission_buffer->data[idx].color[1] = p_color.g;
- particles->emission_buffer->data[idx].color[2] = p_color.b;
- particles->emission_buffer->data[idx].color[3] = p_color.a;
-
- particles->emission_buffer->data[idx].flags = p_emit_flags;
- particles->emission_buffer->particle_count++;
- }
-}
-
-void RendererStorageRD::particles_request_process(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- if (!particles->dirty) {
- particles->dirty = true;
- particles->update_list = particle_update_list;
- particle_update_list = particles;
- }
-}
-
-AABB RendererStorageRD::particles_get_current_aabb(RID p_particles) {
- if (RSG::threaded) {
- WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
- }
-
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, AABB());
-
- int total_amount = particles->amount;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- total_amount *= particles->trail_bind_poses.size();
- }
-
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer);
- ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB());
-
- Transform3D inv = particles->emission_transform.affine_inverse();
-
- AABB aabb;
- if (buffer.size()) {
- bool first = true;
-
- const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
- uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count;
-
- for (int i = 0; i < total_amount; i++) {
- const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i];
- if (particle_data.active) {
- Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]);
- if (!particles->use_local_coords) {
- pos = inv.xform(pos);
- }
- if (first) {
- aabb.position = pos;
- first = false;
- } else {
- aabb.expand_to(pos);
- }
- }
- }
- }
-
- float longest_axis_size = 0;
- for (int i = 0; i < particles->draw_passes.size(); i++) {
- if (particles->draw_passes[i].is_valid()) {
- 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);
- }
- }
-
- aabb.grow_by(longest_axis_size);
-
- return aabb;
-}
-
-AABB RendererStorageRD::particles_get_aabb(RID p_particles) const {
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, AABB());
-
- return particles->custom_aabb;
-}
-
-void RendererStorageRD::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- particles->emission_transform = p_transform;
-}
-
-int RendererStorageRD::particles_get_draw_passes(RID p_particles) const {
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, 0);
-
- return particles->draw_passes.size();
-}
-
-RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RID());
- ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
-
- return particles->draw_passes[p_pass];
-}
-
-void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->collisions.insert(p_particles_collision_instance);
-}
-
-void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->collisions.erase(p_particles_collision_instance);
-}
-
-void RendererStorageRD::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
- particles->has_sdf_collision = p_enable;
- particles->sdf_collision_transform = p_xform;
- particles->sdf_collision_to_screen = p_to_screen;
- particles->sdf_collision_texture = p_texture;
-}
-
-void RendererStorageRD::_particles_process(Particles *p_particles, double p_delta) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
- if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(p_particles->frame_params_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 1;
- u.append_id(p_particles->particle_buffer);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- if (p_particles->emission_storage_buffer.is_valid()) {
- u.append_id(p_particles->emission_storage_buffer);
- } else {
- u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 3;
- Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
- if (sub_emitter) {
- if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer
- _particles_allocate_emission_buffer(sub_emitter);
- }
- u.append_id(sub_emitter->emission_storage_buffer);
- } else {
- u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
- }
- uniforms.push_back(u);
- }
-
- p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
- }
-
- double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
-
- //move back history (if there is any)
- for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
- p_particles->frame_history[i] = p_particles->frame_history[i - 1];
- }
- //update current frame
- ParticlesFrameParams &frame_params = p_particles->frame_history[0];
-
- if (p_particles->clear) {
- p_particles->cycle_number = 0;
- p_particles->random_seed = Math::rand();
- } else if (new_phase < p_particles->phase) {
- if (p_particles->one_shot) {
- p_particles->emitting = false;
- }
- p_particles->cycle_number++;
- }
-
- frame_params.emitting = p_particles->emitting;
- frame_params.system_phase = new_phase;
- frame_params.prev_system_phase = p_particles->phase;
-
- p_particles->phase = new_phase;
-
- frame_params.time = RendererCompositorRD::singleton->get_total_time();
- frame_params.delta = p_delta * p_particles->speed_scale;
- frame_params.random_seed = p_particles->random_seed;
- frame_params.explosiveness = p_particles->explosiveness;
- frame_params.randomness = p_particles->randomness;
-
- if (p_particles->use_local_coords) {
- store_transform(Transform3D(), frame_params.emission_transform);
- } else {
- store_transform(p_particles->emission_transform, frame_params.emission_transform);
- }
-
- frame_params.cycle = p_particles->cycle_number;
- frame_params.frame = p_particles->frame_counter++;
- frame_params.pad0 = 0;
- frame_params.pad1 = 0;
- frame_params.pad2 = 0;
-
- { //collision and attractors
-
- frame_params.collider_count = 0;
- frame_params.attractor_count = 0;
- frame_params.particle_size = p_particles->collision_base_size;
-
- RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
- RID collision_heightmap_texture;
-
- Transform3D to_particles;
- if (p_particles->use_local_coords) {
- to_particles = p_particles->emission_transform.affine_inverse();
- }
-
- if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) {
- //2D collision
-
- Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
- Transform2D revert = xform.affine_inverse();
- frame_params.collider_count = 1;
- frame_params.colliders[0].transform[0] = xform.elements[0][0];
- frame_params.colliders[0].transform[1] = xform.elements[0][1];
- frame_params.colliders[0].transform[2] = 0;
- frame_params.colliders[0].transform[3] = xform.elements[2][0];
-
- frame_params.colliders[0].transform[4] = xform.elements[1][0];
- frame_params.colliders[0].transform[5] = xform.elements[1][1];
- frame_params.colliders[0].transform[6] = 0;
- frame_params.colliders[0].transform[7] = xform.elements[2][1];
-
- frame_params.colliders[0].transform[8] = revert.elements[0][0];
- frame_params.colliders[0].transform[9] = revert.elements[0][1];
- frame_params.colliders[0].transform[10] = 0;
- frame_params.colliders[0].transform[11] = revert.elements[2][0];
-
- frame_params.colliders[0].transform[12] = revert.elements[1][0];
- frame_params.colliders[0].transform[13] = revert.elements[1][1];
- frame_params.colliders[0].transform[14] = 0;
- frame_params.colliders[0].transform[15] = revert.elements[2][1];
-
- frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
- frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
- frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
- frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
- frame_params.colliders[0].texture_index = 0;
- frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
-
- collision_heightmap_texture = p_particles->sdf_collision_texture;
-
- //replace in all other history frames where used because parameters are no longer valid if screen moves
- for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) {
- if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
- p_particles->frame_history[i].colliders[0] = frame_params.colliders[0];
- }
- }
- }
-
- uint32_t collision_3d_textures_used = 0;
- for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get());
- if (!pci || !pci->active) {
- continue;
- }
- ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
- ERR_CONTINUE(!pc);
-
- Transform3D to_collider = pci->transform;
- if (p_particles->use_local_coords) {
- to_collider = to_particles * to_collider;
- }
- Vector3 scale = to_collider.basis.get_scale();
- to_collider.basis.orthonormalize();
-
- if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
- //attractor
- if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) {
- continue;
- }
-
- ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
-
- store_transform(to_collider, attr.transform);
- attr.strength = pc->attractor_strength;
- attr.attenuation = pc->attractor_attenuation;
- attr.directionality = pc->attractor_directionality;
-
- switch (pc->type) {
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: {
- attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE;
- float radius = pc->radius;
- radius *= (scale.x + scale.y + scale.z) / 3.0;
- attr.extents[0] = radius;
- attr.extents[1] = radius;
- attr.extents[2] = radius;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: {
- attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX;
- Vector3 extents = pc->extents * scale;
- attr.extents[0] = extents.x;
- attr.extents[1] = extents.y;
- attr.extents[2] = extents.z;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
- if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
- continue;
- }
- attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_VECTOR_FIELD;
- Vector3 extents = pc->extents * scale;
- attr.extents[0] = extents.x;
- attr.extents[1] = extents.y;
- attr.extents[2] = extents.z;
- attr.texture_index = collision_3d_textures_used;
-
- collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
- collision_3d_textures_used++;
- } break;
- default: {
- }
- }
-
- frame_params.attractor_count++;
- } else {
- //collider
- if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) {
- continue;
- }
-
- ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
-
- store_transform(to_collider, col.transform);
- switch (pc->type) {
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
- col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
- float radius = pc->radius;
- radius *= (scale.x + scale.y + scale.z) / 3.0;
- col.extents[0] = radius;
- col.extents[1] = radius;
- col.extents[2] = radius;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: {
- col.type = ParticlesFrameParams::COLLISION_TYPE_BOX;
- Vector3 extents = pc->extents * scale;
- col.extents[0] = extents.x;
- col.extents[1] = extents.y;
- col.extents[2] = extents.z;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
- if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
- continue;
- }
- col.type = ParticlesFrameParams::COLLISION_TYPE_SDF;
- Vector3 extents = pc->extents * scale;
- col.extents[0] = extents.x;
- col.extents[1] = extents.y;
- col.extents[2] = extents.z;
- col.texture_index = collision_3d_textures_used;
- col.scale = (scale.x + scale.y + scale.z) * 0.333333333333; //non uniform scale non supported
-
- collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
- collision_3d_textures_used++;
- } break;
- case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
- if (collision_heightmap_texture != RID()) { //already taken
- continue;
- }
-
- col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD;
- Vector3 extents = pc->extents * scale;
- col.extents[0] = extents.x;
- col.extents[1] = extents.y;
- col.extents[2] = extents.z;
- collision_heightmap_texture = pc->heightfield_texture;
- } break;
- default: {
- }
- }
-
- frame_params.collider_count++;
- }
- }
-
- bool different = false;
- if (collision_3d_textures_used == p_particles->collision_3d_textures_used) {
- for (int i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
- if (p_particles->collision_3d_textures[i] != collision_3d_textures[i]) {
- different = true;
- break;
- }
- }
- }
-
- if (collision_heightmap_texture != p_particles->collision_heightmap_texture) {
- different = true;
- }
-
- bool uniform_set_valid = RD::get_singleton()->uniform_set_is_valid(p_particles->collision_textures_uniform_set);
-
- if (different || !uniform_set_valid) {
- if (uniform_set_valid) {
- RD::get_singleton()->free(p_particles->collision_textures_uniform_set);
- }
-
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
- for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
- RID rd_tex;
- if (i < collision_3d_textures_used) {
- RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]);
- if (t && t->type == RendererRD::Texture::TYPE_3D) {
- rd_tex = t->rd_texture;
- }
- }
-
- if (rd_tex == RID()) {
- rd_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- }
- u.append_id(rd_tex);
- }
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- if (collision_heightmap_texture.is_valid()) {
- u.append_id(collision_heightmap_texture);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
- }
- uniforms.push_back(u);
- }
- p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2);
- }
- }
-
- ParticlesShader::PushConstant push_constant;
-
- int process_amount = p_particles->amount;
-
- if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
- process_amount *= p_particles->trail_bind_poses.size();
- }
- push_constant.clear = p_particles->clear;
- push_constant.total_particles = p_particles->amount;
- push_constant.lifetime = p_particles->lifetime;
- push_constant.trail_size = p_particles->trail_params.size();
- push_constant.use_fractional_delta = p_particles->fractional_delta;
- push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit);
- push_constant.trail_pass = false;
-
- p_particles->force_sub_emit = false; //reset
-
- Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
-
- if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) {
- // print_line("updating subemitter buffer");
- int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 };
- RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero);
- push_constant.can_emit = true;
-
- if (sub_emitter->emitting) {
- sub_emitter->emitting = false;
- sub_emitter->clear = true; //will need to clear if it was emitting, sorry
- }
- //make sure the sub emitter processes particles too
- sub_emitter->inactive = false;
- sub_emitter->inactive_time = 0;
-
- sub_emitter->force_sub_emit = true;
-
- } else {
- push_constant.can_emit = false;
- }
-
- if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) {
- RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer);
- p_particles->emission_buffer->particle_count = 0;
- }
-
- p_particles->clear = false;
-
- if (p_particles->trail_params.size() > 1) {
- //fill the trail params
- for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) {
- uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size();
- p_particles->trail_params[i] = p_particles->frame_history[src_idx];
- }
- } else {
- p_particles->trail_params[0] = p_particles->frame_history[0];
- }
-
- RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
-
- ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, RendererRD::SHADER_TYPE_PARTICLES));
- if (!m) {
- m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES));
- }
-
- ERR_FAIL_COND(!m);
-
- p_particles->has_collision_cache = m->shader_data->uses_collision;
-
- //todo should maybe compute all particle systems together?
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2);
-
- if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
-
- if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
- //trails requires two passes in order to catch particle starts
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount / p_particles->trail_bind_poses.size(), 1, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- push_constant.trail_pass = true;
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount - p_particles->amount, 1, 1);
- } else {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount, 1, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND(!particles);
-
- if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
- return;
- }
-
- if (particles->particle_buffer.is_null()) {
- return; //particles have not processed yet
- }
-
- bool do_sort = particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH;
-
- //copy to sort buffer
- if (do_sort && particles->particles_sort_buffer == RID()) {
- uint32_t size = particles->amount;
- if (size & 1) {
- size++; //make multiple of 16
- }
- size *= sizeof(float) * 2;
- particles->particles_sort_buffer = RD::get_singleton()->storage_buffer_create(size);
-
- {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(particles->particles_sort_buffer);
- uniforms.push_back(u);
- }
-
- particles->particles_sort_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, ParticlesShader::COPY_MODE_FILL_SORT_BUFFER), 1);
- }
- }
-
- ParticlesShader::CopyPushConstant copy_push_constant;
-
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- int fixed_fps = 60.0;
- if (particles->fixed_fps > 0) {
- fixed_fps = particles->fixed_fps;
- }
-
- copy_push_constant.trail_size = particles->trail_bind_poses.size();
- copy_push_constant.trail_total = particles->frame_history.size();
- copy_push_constant.frame_delta = 1.0 / fixed_fps;
- } else {
- copy_push_constant.trail_size = 1;
- copy_push_constant.trail_total = 1;
- copy_push_constant.frame_delta = 0.0;
- }
-
- copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
- copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
- copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
-
- copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
- copy_push_constant.total_particles = particles->amount;
- copy_push_constant.copy_mode_2d = false;
-
- Vector3 axis = -p_axis; // cameras look to z negative
-
- if (particles->use_local_coords) {
- axis = particles->emission_transform.basis.xform_inv(axis).normalized();
- }
-
- copy_push_constant.sort_direction[0] = axis.x;
- copy_push_constant.sort_direction[1] = axis.y;
- copy_push_constant.sort_direction[2] = axis.z;
-
- copy_push_constant.align_up[0] = p_up_axis.x;
- copy_push_constant.align_up[1] = p_up_axis.y;
- copy_push_constant.align_up[2] = p_up_axis.z;
-
- copy_push_constant.align_mode = particles->transform_align;
-
- if (do_sort) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
-
- RD::get_singleton()->compute_list_end();
- effects->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
- }
-
- copy_push_constant.total_particles *= copy_push_constant.total_particles;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
- copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX;
- copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
- if (do_sort) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, copy_push_constant.total_particles, 1, 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RendererStorageRD::_particles_update_buffers(Particles *particles) {
- uint32_t userdata_count = 0;
-
- const RendererRD::Material *material = RendererRD::MaterialStorage::get_singleton()->get_material(particles->process_material);
- if (material && material->shader && material->shader->data) {
- const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
- userdata_count = shader_data->userdata_count;
- }
-
- if (userdata_count != particles->userdata_count) {
- // Mismatch userdata, re-create buffers.
- _particles_free_data(particles);
- }
-
- if (particles->amount > 0 && particles->particle_buffer.is_null()) {
- int total_amount = particles->amount;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- total_amount *= particles->trail_bind_poses.size();
- }
-
- uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
-
- particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount);
-
- particles->userdata_count = userdata_count;
-
- particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount);
- //needs to clear it
-
- {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 1;
- u.append_id(particles->particle_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(particles->particle_instance_buffer);
- uniforms.push_back(u);
- }
-
- particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0);
- }
- }
-}
-void RendererStorageRD::update_particles() {
- while (particle_update_list) {
- //use transform feedback to process particles
-
- Particles *particles = particle_update_list;
-
- //take and remove
- particle_update_list = particles->update_list;
- particles->update_list = nullptr;
- particles->dirty = false;
-
- _particles_update_buffers(particles);
-
- if (particles->restart_request) {
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- particles->restart_request = false;
- }
-
- if (particles->inactive && !particles->emitting) {
- //go next
- continue;
- }
-
- if (particles->emitting) {
- if (particles->inactive) {
- //restart system from scratch
- particles->prev_ticks = 0;
- particles->phase = 0;
- particles->prev_phase = 0;
- particles->clear = true;
- }
- particles->inactive = false;
- particles->inactive_time = 0;
- } else {
- particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time();
- if (particles->inactive_time > particles->lifetime * 1.2) {
- particles->inactive = true;
- continue;
- }
- }
-
-#ifndef _MSC_VER
-#warning Should use display refresh rate for all this
-#endif
-
- float screen_hz = 60;
-
- int fixed_fps = 0;
- if (particles->fixed_fps > 0) {
- fixed_fps = particles->fixed_fps;
- } else if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- fixed_fps = screen_hz;
- }
- {
- //update trails
- int history_size = 1;
- int trail_steps = 1;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- history_size = MAX(1, int(particles->trail_length * fixed_fps));
- trail_steps = particles->trail_bind_poses.size();
- }
-
- if (uint32_t(history_size) != particles->frame_history.size()) {
- particles->frame_history.resize(history_size);
- memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size);
- }
-
- if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) {
- particles->trail_params.resize(trail_steps);
- if (particles->frame_params_buffer.is_valid()) {
- RD::get_singleton()->free(particles->frame_params_buffer);
- }
- particles->frame_params_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticlesFrameParams) * trail_steps);
- }
-
- if (particles->trail_bind_poses.size() > 1 && particles->trail_bind_pose_buffer.is_null()) {
- particles->trail_bind_pose_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 16 * particles->trail_bind_poses.size());
- particles->trail_bind_poses_dirty = true;
- }
-
- if (particles->trail_bind_pose_uniform_set.is_null()) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- if (particles->trail_bind_pose_buffer.is_valid()) {
- u.append_id(particles->trail_bind_pose_buffer);
- } else {
- u.append_id(RendererRD::MeshStorage::get_singleton()->get_default_rd_storage_buffer());
- }
- uniforms.push_back(u);
- }
-
- particles->trail_bind_pose_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 2);
- }
-
- if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses_dirty) {
- if (particles_shader.pose_update_buffer.size() < uint32_t(particles->trail_bind_poses.size()) * 16) {
- particles_shader.pose_update_buffer.resize(particles->trail_bind_poses.size() * 16);
- }
-
- for (int i = 0; i < particles->trail_bind_poses.size(); i++) {
- store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
- }
-
- RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr());
- }
- }
-
- bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
-
- if (particles->clear && particles->pre_process_time > 0.0) {
- double frame_time;
- if (fixed_fps > 0) {
- frame_time = 1.0 / fixed_fps;
- } else {
- frame_time = 1.0 / 30.0;
- }
-
- double todo = particles->pre_process_time;
-
- while (todo >= 0) {
- _particles_process(particles, frame_time);
- todo -= frame_time;
- }
- }
-
- if (fixed_fps > 0) {
- double frame_time;
- double decr;
- if (zero_time_scale) {
- frame_time = 0.0;
- decr = 1.0 / fixed_fps;
- } else {
- frame_time = 1.0 / fixed_fps;
- decr = frame_time;
- }
- double delta = RendererCompositorRD::singleton->get_frame_delta_time();
- if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
- delta = 0.1;
- } else if (delta <= 0.0) { //unlikely but..
- delta = 0.001;
- }
- double todo = particles->frame_remainder + delta;
-
- while (todo >= frame_time) {
- _particles_process(particles, frame_time);
- todo -= decr;
- }
-
- particles->frame_remainder = todo;
-
- } else {
- if (zero_time_scale) {
- _particles_process(particles, 0.0);
- } else {
- _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time());
- }
- }
-
- //copy particles to instance buffer
-
- if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
- //does not need view dependent operation, do copy here
- ParticlesShader::CopyPushConstant copy_push_constant;
-
- int total_amount = particles->amount;
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- total_amount *= particles->trail_bind_poses.size();
- }
-
- // Affect 2D only.
- if (particles->use_local_coords) {
- // In local mode, particle positions are calculated locally (relative to the node position)
- // and they're also drawn locally.
- // It works as expected, so we just pass an identity transform.
- store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
- } else {
- // In global mode, particle positions are calculated globally (relative to the canvas origin)
- // but they're drawn locally.
- // So, we need to pass the inverse of the emission transform to bring the
- // particles to local coordinates before drawing.
- Transform3D inv = particles->emission_transform.affine_inverse();
- store_transform(inv, copy_push_constant.inv_emission_transform);
- }
-
- copy_push_constant.total_particles = total_amount;
- copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
- copy_push_constant.align_mode = particles->transform_align;
- copy_push_constant.align_up[0] = 0;
- copy_push_constant.align_up[1] = 0;
- copy_push_constant.align_up[2] = 0;
-
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- copy_push_constant.trail_size = particles->trail_bind_poses.size();
- copy_push_constant.trail_total = particles->frame_history.size();
- copy_push_constant.frame_delta = 1.0 / fixed_fps;
- } else {
- copy_push_constant.trail_size = 1;
- copy_push_constant.trail_total = 1;
- copy_push_constant.frame_delta = 0.0;
- }
-
- copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
- copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
- copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, total_amount, 1, 1);
-
- RD::get_singleton()->compute_list_end();
- }
-
- particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
- }
-}
-
-bool RendererStorageRD::particles_is_inactive(RID p_particles) const {
- ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
- const Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, false);
- return !particles->emitting && particles->inactive;
-}
-
-/* SKY SHADER */
-
-void RendererStorageRD::ParticlesShaderData::set_code(const String &p_code) {
- //compile
-
- code = p_code;
- valid = false;
- ubo_size = 0;
- uniforms.clear();
- uses_collision = false;
-
- if (code.is_empty()) {
- return; //just invalid, but no error
- }
-
- ShaderCompiler::GeneratedCode gen_code;
- ShaderCompiler::IdentifierActions actions;
- actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE;
- actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE;
-
- /*
- uses_time = false;
-
- actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
- actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
-
- actions.usage_flag_pointers["TIME"] = &uses_time;
-*/
-
- actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
-
- userdata_count = 0;
- for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
- userdatas_used[i] = false;
- actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i];
- }
-
- actions.uniforms = &uniforms;
-
- Error err = base_singleton->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
- ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
-
- if (version.is_null()) {
- version = base_singleton->particles_shader.shader.version_create();
- }
-
- for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
- if (userdatas_used[i]) {
- userdata_count++;
- }
- }
-
- base_singleton->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
- ERR_FAIL_COND(!base_singleton->particles_shader.shader.version_is_valid(version));
-
- ubo_size = gen_code.uniform_total_size;
- ubo_offsets = gen_code.uniform_offsets;
- texture_uniforms = gen_code.texture_uniforms;
-
- //update pipelines
-
- pipeline = RD::get_singleton()->compute_pipeline_create(base_singleton->particles_shader.shader.version_get_shader(version, 0));
-
- valid = true;
-}
-
-void RendererStorageRD::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
- if (!p_texture.is_valid()) {
- if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
- default_texture_params[p_name].erase(p_index);
-
- if (default_texture_params[p_name].is_empty()) {
- default_texture_params.erase(p_name);
- }
- }
- } else {
- if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
- }
- default_texture_params[p_name][p_index] = p_texture;
- }
-}
-
-void RendererStorageRD::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- if (E.value.texture_order >= 0) {
- order[E.value.texture_order + 100000] = E.key;
- } else {
- order[E.value.order] = E.key;
- }
- }
-
- for (const KeyValue<int, StringName> &E : order) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
- pi.name = E.value;
- p_param_list->push_back(pi);
- }
-}
-
-void RendererStorageRD::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- RendererMaterialStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E.value);
- p.info.name = E.key; //supply name
- p.index = E.value.instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
- p_param_list->push_back(p);
- }
-}
-
-bool RendererStorageRD::ParticlesShaderData::is_param_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
-bool RendererStorageRD::ParticlesShaderData::is_animated() const {
- return false;
-}
-
-bool RendererStorageRD::ParticlesShaderData::casts_shadows() const {
- return false;
-}
-
-Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const {
- if (uniforms.has(p_parameter)) {
- ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
- Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
- }
- return Variant();
-}
-
-RS::ShaderNativeSourceCode RendererStorageRD::ParticlesShaderData::get_native_source_code() const {
- return base_singleton->particles_shader.shader.version_get_native_source_code(version);
-}
-
-RendererStorageRD::ParticlesShaderData::ParticlesShaderData() {
- valid = false;
-}
-
-RendererStorageRD::ParticlesShaderData::~ParticlesShaderData() {
- //pipeline variants will clear themselves if shader is gone
- if (version.is_valid()) {
- base_singleton->particles_shader.shader.version_free(version);
- }
-}
-
-RendererRD::ShaderData *RendererStorageRD::_create_particles_shader_func() {
- ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
- return shader_data;
-}
-
-bool RendererStorageRD::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, base_singleton->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
-}
-
-RendererStorageRD::ParticlesMaterialData::~ParticlesMaterialData() {
- free_parameters_uniform_set(uniform_set);
-}
-
-RendererRD::MaterialData *RendererStorageRD::_create_particles_material_func(ParticlesShaderData *p_shader) {
- ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
- material_data->shader_data = p_shader;
- //update will happen later anyway so do nothing.
- return material_data;
-}
-////////
-
-/* PARTICLES COLLISION API */
-
-RID RendererStorageRD::particles_collision_allocate() {
- return particles_collision_owner.allocate_rid();
-}
-void RendererStorageRD::particles_collision_initialize(RID p_rid) {
- particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
-}
-
-RID RendererStorageRD::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND_V(!particles_collision, RID());
- ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID());
-
- if (particles_collision->heightfield_texture == RID()) {
- //create
- int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 };
- Size2i size;
- if (particles_collision->extents.x > particles_collision->extents.z) {
- size.x = resolutions[particles_collision->heightfield_resolution];
- size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x);
- } else {
- size.y = resolutions[particles_collision->heightfield_resolution];
- size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y);
- }
-
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_D32_SFLOAT;
- tf.width = size.x;
- tf.height = size.y;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
-
- particles_collision->heightfield_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- Vector<RID> fb_tex;
- fb_tex.push_back(particles_collision->heightfield_texture);
- particles_collision->heightfield_fb = RD::get_singleton()->framebuffer_create(fb_tex);
- particles_collision->heightfield_fb_size = size;
- }
-
- return particles_collision->heightfield_fb;
-}
-
-void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- if (p_type == particles_collision->type) {
- return;
- }
-
- if (particles_collision->heightfield_texture.is_valid()) {
- RD::get_singleton()->free(particles_collision->heightfield_texture);
- particles_collision->heightfield_texture = RID();
- }
- particles_collision->type = p_type;
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
- particles_collision->cull_mask = p_cull_mask;
-}
-
-void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->radius = p_radius;
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->extents = p_extents;
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->attractor_strength = p_strength;
-}
-
-void RendererStorageRD::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->attractor_directionality = p_directionality;
-}
-
-void RendererStorageRD::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->attractor_attenuation = p_curve;
-}
-
-void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
-
- particles_collision->field_texture = p_texture;
-}
-
-void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
- particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND(!particles_collision);
- ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
-
- if (particles_collision->heightfield_resolution == p_resolution) {
- return;
- }
-
- particles_collision->heightfield_resolution = p_resolution;
-
- if (particles_collision->heightfield_texture.is_valid()) {
- RD::get_singleton()->free(particles_collision->heightfield_texture);
- particles_collision->heightfield_texture = RID();
- }
-}
-
-AABB RendererStorageRD::particles_collision_get_aabb(RID p_particles_collision) const {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND_V(!particles_collision, AABB());
-
- switch (particles_collision->type) {
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT:
- case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
- AABB aabb;
- aabb.position = -Vector3(1, 1, 1) * particles_collision->radius;
- aabb.size = Vector3(2, 2, 2) * particles_collision->radius;
- return aabb;
- }
- default: {
- AABB aabb;
- aabb.position = -particles_collision->extents;
- aabb.size = particles_collision->extents * 2;
- return aabb;
- }
- }
-
- return AABB();
-}
-
-Vector3 RendererStorageRD::particles_collision_get_extents(RID p_particles_collision) const {
- const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND_V(!particles_collision, Vector3());
- return particles_collision->extents;
-}
-
-bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_collision) const {
- const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
- ERR_FAIL_COND_V(!particles_collision, false);
- return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
-}
-
-RID RendererStorageRD::particles_collision_instance_create(RID p_collision) {
- ParticlesCollisionInstance pci;
- pci.collision = p_collision;
- return particles_collision_instance_owner.make_rid(pci);
-}
-void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
- ERR_FAIL_COND(!pci);
- pci->transform = p_transform;
-}
-void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
- ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
- ERR_FAIL_COND(!pci);
- pci->active = p_active;
-}
-
/* FOG VOLUMES */
RID RendererStorageRD::fog_volume_allocate() {
@@ -1928,520 +171,7 @@ void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, b
}
}
-/* LIGHT */
-
-void RendererStorageRD::_light_initialize(RID p_light, RS::LightType p_type) {
- Light light;
- light.type = p_type;
-
- light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;
- light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
- light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
- light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
- light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
- light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;
- light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
- light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;
- light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
- light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
- light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
- light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
- light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
- light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
- light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
- light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
- light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
- light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
- light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
-
- light_owner.initialize_rid(p_light, light);
-}
-
-RID RendererStorageRD::directional_light_allocate() {
- return light_owner.allocate_rid();
-}
-void RendererStorageRD::directional_light_initialize(RID p_light) {
- _light_initialize(p_light, RS::LIGHT_DIRECTIONAL);
-}
-
-RID RendererStorageRD::omni_light_allocate() {
- return light_owner.allocate_rid();
-}
-void RendererStorageRD::omni_light_initialize(RID p_light) {
- _light_initialize(p_light, RS::LIGHT_OMNI);
-}
-
-RID RendererStorageRD::spot_light_allocate() {
- return light_owner.allocate_rid();
-}
-void RendererStorageRD::spot_light_initialize(RID p_light) {
- _light_initialize(p_light, RS::LIGHT_SPOT);
-}
-
-void RendererStorageRD::light_set_color(RID p_light, const Color &p_color) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->color = p_color;
-}
-
-void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
- ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
-
- if (light->param[p_param] == p_value) {
- return;
- }
-
- switch (p_param) {
- case RS::LIGHT_PARAM_RANGE:
- case RS::LIGHT_PARAM_SPOT_ANGLE:
- case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
- case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
- case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
- case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
- case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
- case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
- case RS::LIGHT_PARAM_SHADOW_BIAS: {
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
- } break;
- case RS::LIGHT_PARAM_SIZE: {
- if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
- //changing from no size to size and the opposite
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
- }
- } break;
- default: {
- }
- }
-
- light->param[p_param] = p_value;
-}
-
-void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
- light->shadow = p_enabled;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
- RendererRD::DecalAtlasStorage *decal_atlas_storage = RendererRD::DecalAtlasStorage::get_singleton();
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- if (light->projector == p_texture) {
- return;
- }
-
- if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
- decal_atlas_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
- }
-
- light->projector = p_texture;
-
- if (light->type != RS::LIGHT_DIRECTIONAL) {
- if (light->projector.is_valid()) {
- decal_atlas_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
- }
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
- }
-}
-
-void RendererStorageRD::light_set_negative(RID p_light, bool p_enable) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->negative = p_enable;
-}
-
-void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->cull_mask = p_mask;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->distance_fade = p_enabled;
- light->distance_fade_begin = p_begin;
- light->distance_fade_shadow = p_shadow;
- light->distance_fade_length = p_length;
-}
-
-void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->reverse_cull = p_enabled;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->bake_mode = p_bake_mode;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->max_sdfgi_cascade = p_cascade;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->omni_shadow_mode = p_mode;
-
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
-
- return light->omni_shadow_mode;
-}
-
-void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_shadow_mode = p_mode;
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_blend_splits = p_enable;
- light->version++;
- light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
-}
-
-bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, false);
-
- return light->directional_blend_splits;
-}
-
-void RendererStorageRD::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
- Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light);
-
- light->directional_sky_mode = p_mode;
-}
-
-RS::LightDirectionalSkyMode RendererStorageRD::light_directional_get_sky_mode(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY);
-
- return light->directional_sky_mode;
-}
-
-RS::LightDirectionalShadowMode RendererStorageRD::light_directional_get_shadow_mode(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
-
- return light->directional_shadow_mode;
-}
-
-uint32_t RendererStorageRD::light_get_max_sdfgi_cascade(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->max_sdfgi_cascade;
-}
-
-RS::LightBakeMode RendererStorageRD::light_get_bake_mode(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED);
-
- return light->bake_mode;
-}
-
-uint64_t RendererStorageRD::light_get_version(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->version;
-}
-
-AABB RendererStorageRD::light_get_aabb(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, AABB());
-
- switch (light->type) {
- case RS::LIGHT_SPOT: {
- float len = light->param[RS::LIGHT_PARAM_RANGE];
- float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
- return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
- };
- case RS::LIGHT_OMNI: {
- float r = light->param[RS::LIGHT_PARAM_RANGE];
- return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
- };
- case RS::LIGHT_DIRECTIONAL: {
- return AABB();
- };
- }
-
- ERR_FAIL_V(AABB());
-}
-
-/* REFLECTION PROBE */
-
-RID RendererStorageRD::reflection_probe_allocate() {
- return reflection_probe_owner.allocate_rid();
-}
-void RendererStorageRD::reflection_probe_initialize(RID p_reflection_probe) {
- reflection_probe_owner.initialize_rid(p_reflection_probe, ReflectionProbe());
-}
-
-void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->update_mode = p_mode;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->intensity = p_intensity;
-}
-
-void RendererStorageRD::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->ambient_mode = p_mode;
-}
-
-void RendererStorageRD::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->ambient_color = p_color;
-}
-
-void RendererStorageRD::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->ambient_color_energy = p_energy;
-}
-
-void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->max_distance = p_distance;
-
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- if (reflection_probe->extents == p_extents) {
- return;
- }
- reflection_probe->extents = p_extents;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->origin_offset = p_offset;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->interior = p_enable;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->box_projection = p_enable;
-}
-
-void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->enable_shadows = p_enable;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->cull_mask = p_layers;
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
- ERR_FAIL_COND(p_resolution < 32);
-
- reflection_probe->resolution = p_resolution;
-}
-
-void RendererStorageRD::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
- ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND(!reflection_probe);
-
- reflection_probe->mesh_lod_threshold = p_ratio;
-
- reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);
-}
-
-AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, AABB());
-
- AABB aabb;
- aabb.position = -reflection_probe->extents;
- aabb.size = reflection_probe->extents * 2.0;
-
- return aabb;
-}
-
-RS::ReflectionProbeUpdateMode RendererStorageRD::reflection_probe_get_update_mode(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS);
-
- return reflection_probe->update_mode;
-}
-
-uint32_t RendererStorageRD::reflection_probe_get_cull_mask(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->cull_mask;
-}
-
-Vector3 RendererStorageRD::reflection_probe_get_extents(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Vector3());
-
- return reflection_probe->extents;
-}
-
-Vector3 RendererStorageRD::reflection_probe_get_origin_offset(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Vector3());
-
- return reflection_probe->origin_offset;
-}
-
-bool RendererStorageRD::reflection_probe_renders_shadows(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, false);
-
- return reflection_probe->enable_shadows;
-}
-
-float RendererStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->max_distance;
-}
-
-float RendererStorageRD::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->mesh_lod_threshold;
-}
-
-int RendererStorageRD::reflection_probe_get_resolution(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->resolution;
-}
-
-float RendererStorageRD::reflection_probe_get_intensity(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->intensity;
-}
-
-bool RendererStorageRD::reflection_probe_is_interior(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, false);
-
- return reflection_probe->interior;
-}
-
-bool RendererStorageRD::reflection_probe_is_box_projection(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, false);
-
- return reflection_probe->box_projection;
-}
-
-RS::ReflectionProbeAmbientMode RendererStorageRD::reflection_probe_get_ambient_mode(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED);
- return reflection_probe->ambient_mode;
-}
-
-Color RendererStorageRD::reflection_probe_get_ambient_color(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, Color());
-
- return reflection_probe->ambient_color;
-}
-float RendererStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) const {
- const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
- ERR_FAIL_COND_V(!reflection_probe, 0);
-
- return reflection_probe->ambient_color_energy;
-}
+/* VOXEL GI */
RID RendererStorageRD::voxel_gi_allocate() {
return voxel_gi_owner.allocate_rid();
@@ -2771,876 +501,7 @@ RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
return voxel_gi->sdf_texture;
}
-/* LIGHTMAP API */
-
-RID RendererStorageRD::lightmap_allocate() {
- return lightmap_owner.allocate_rid();
-}
-
-void RendererStorageRD::lightmap_initialize(RID p_lightmap) {
- lightmap_owner.initialize_rid(p_lightmap, Lightmap());
-}
-
-void RendererStorageRD::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
-
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
-
- lightmap_array_version++;
-
- //erase lightmap users
- if (lm->light_texture.is_valid()) {
- RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture);
- if (t) {
- t->lightmap_users.erase(p_lightmap);
- }
- }
-
- RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light);
- lm->light_texture = p_light;
- lm->uses_spherical_harmonics = p_uses_spherical_haromics;
-
- RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
- if (!t) {
- if (using_lightmap_array) {
- if (lm->array_index >= 0) {
- lightmap_textures.write[lm->array_index] = default_2d_array;
- lm->array_index = -1;
- }
- }
-
- return;
- }
-
- t->lightmap_users.insert(p_lightmap);
-
- if (using_lightmap_array) {
- if (lm->array_index < 0) {
- //not in array, try to put in array
- for (int i = 0; i < lightmap_textures.size(); i++) {
- if (lightmap_textures[i] == default_2d_array) {
- lm->array_index = i;
- break;
- }
- }
- }
- ERR_FAIL_COND_MSG(lm->array_index < 0, "Maximum amount of lightmaps in use (" + itos(lightmap_textures.size()) + ") has been exceeded, lightmap will nod display properly.");
-
- lightmap_textures.write[lm->array_index] = t->rd_texture;
- }
-}
-
-void RendererStorageRD::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
- lm->bounds = p_bounds;
-}
-
-void RendererStorageRD::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
- lm->interior = p_interior;
-}
-
-void RendererStorageRD::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
-
- if (p_points.size()) {
- ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size());
- ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
- ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
- }
-
- lm->points = p_points;
- lm->bsp_tree = p_bsp_tree;
- lm->point_sh = p_point_sh;
- lm->tetrahedra = p_tetrahedra;
-}
-
-PackedVector3Array RendererStorageRD::lightmap_get_probe_capture_points(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedVector3Array());
-
- return lm->points;
-}
-
-PackedColorArray RendererStorageRD::lightmap_get_probe_capture_sh(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedColorArray());
- return lm->point_sh;
-}
-
-PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedInt32Array());
- return lm->tetrahedra;
-}
-
-PackedInt32Array RendererStorageRD::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, PackedInt32Array());
- return lm->bsp_tree;
-}
-
-void RendererStorageRD::lightmap_set_probe_capture_update_speed(float p_speed) {
- lightmap_probe_capture_update_speed = p_speed;
-}
-
-void RendererStorageRD::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
- Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!lm);
-
- for (int i = 0; i < 9; i++) {
- r_sh[i] = Color(0, 0, 0, 0);
- }
-
- if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) {
- return;
- }
-
- static_assert(sizeof(Lightmap::BSP) == 24);
-
- const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr();
- int32_t node = 0;
- while (node >= 0) {
- if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node);
-#endif
-
- node = bsp[node].over;
- } else {
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node);
-#endif
- node = bsp[node].under;
- }
- }
-
- if (node == Lightmap::BSP::EMPTY_LEAF) {
- return; //nothing could be done
- }
-
- node = ABS(node) - 1;
-
- uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
- Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };
- const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };
- Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
-
- for (int i = 0; i < 4; i++) {
- float c = CLAMP(barycentric[i], 0.0, 1.0);
- for (int j = 0; j < 9; j++) {
- r_sh[j] += sh_colors[i][j] * c;
- }
- }
-}
-
-bool RendererStorageRD::lightmap_is_interior(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, false);
- return lm->interior;
-}
-
-AABB RendererStorageRD::lightmap_get_aabb(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, AABB());
- return lm->bounds;
-}
-
-/* RENDER TARGET API */
-
-void RendererStorageRD::_clear_render_target(RenderTarget *rt) {
- //free in reverse dependency order
- if (rt->framebuffer.is_valid()) {
- RD::get_singleton()->free(rt->framebuffer);
- rt->framebuffer_uniform_set = RID(); //chain deleted
- }
-
- if (rt->color.is_valid()) {
- RD::get_singleton()->free(rt->color);
- }
-
- if (rt->backbuffer.is_valid()) {
- RD::get_singleton()->free(rt->backbuffer);
- rt->backbuffer = RID();
- rt->backbuffer_mipmaps.clear();
- rt->backbuffer_uniform_set = RID(); //chain deleted
- }
-
- _render_target_clear_sdf(rt);
-
- rt->framebuffer = RID();
- rt->color = RID();
-}
-
-void RendererStorageRD::_update_render_target(RenderTarget *rt) {
- if (rt->texture.is_null()) {
- //create a placeholder until updated
- rt->texture = RendererRD::TextureStorage::get_singleton()->texture_allocate();
- RendererRD::TextureStorage::get_singleton()->texture_2d_placeholder_initialize(rt->texture);
- RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture);
- tex->is_render_target = true;
- }
-
- _clear_render_target(rt);
-
- if (rt->size.width == 0 || rt->size.height == 0) {
- return;
- }
- //until we implement support for HDR monitors (and render target is attached to screen), this is enough.
- rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
-
- RD::TextureFormat rd_format;
- RD::TextureView rd_view;
- { //attempt register
- rd_format.format = rt->color_format;
- rd_format.width = rt->size.width;
- rd_format.height = rt->size.height;
- rd_format.depth = 1;
- rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
- rd_format.mipmaps = 1;
- if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
- rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- } else {
- rd_format.texture_type = RD::TEXTURE_TYPE_2D;
- }
- rd_format.samples = RD::TEXTURE_SAMPLES_1;
- rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
- rd_format.shareable_formats.push_back(rt->color_format);
- rd_format.shareable_formats.push_back(rt->color_format_srgb);
- }
-
- rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
- ERR_FAIL_COND(rt->color.is_null());
-
- Vector<RID> fb_textures;
- fb_textures.push_back(rt->color);
- rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
- if (rt->framebuffer.is_null()) {
- _clear_render_target(rt);
- ERR_FAIL_COND(rt->framebuffer.is_null());
- }
-
- { //update texture
-
- RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture);
-
- //free existing textures
- if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
- RD::get_singleton()->free(tex->rd_texture);
- }
- if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
- RD::get_singleton()->free(tex->rd_texture_srgb);
- }
-
- tex->rd_texture = RID();
- tex->rd_texture_srgb = RID();
-
- //create shared textures to the color buffer,
- //so transparent can be supported
- RD::TextureView view;
- view.format_override = rt->color_format;
- if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
- view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
- }
- tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
- if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
- view.format_override = rt->color_format_srgb;
- tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
- }
- tex->rd_view = view;
- tex->width = rt->size.width;
- tex->height = rt->size.height;
- tex->width_2d = rt->size.width;
- tex->height_2d = rt->size.height;
- tex->rd_format = rt->color_format;
- tex->rd_format_srgb = rt->color_format_srgb;
- tex->format = rt->image_format;
-
- Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
- for (int i = 0; i < proxies.size(); i++) {
- RendererRD::TextureStorage::get_singleton()->texture_proxy_update(proxies[i], rt->texture);
- }
- }
-}
-
-void RendererStorageRD::_create_render_target_backbuffer(RenderTarget *rt) {
- ERR_FAIL_COND(rt->backbuffer.is_valid());
-
- uint32_t mipmaps_required = Image::get_image_required_mipmaps(rt->size.width, rt->size.height, Image::FORMAT_RGBA8);
- RD::TextureFormat tf;
- tf.format = rt->color_format;
- tf.width = rt->size.width;
- tf.height = rt->size.height;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- tf.mipmaps = mipmaps_required;
-
- rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rt->backbuffer, "Render Target Back Buffer");
- rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
- RD::get_singleton()->set_resource_name(rt->backbuffer_mipmap0, "Back Buffer slice mipmap 0");
-
- {
- Vector<RID> fb_tex;
- fb_tex.push_back(rt->backbuffer_mipmap0);
- rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex);
- }
-
- if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) {
- //the new one will require the backbuffer.
- RD::get_singleton()->free(rt->framebuffer_uniform_set);
- rt->framebuffer_uniform_set = RID();
- }
- //create mipmaps
- for (uint32_t i = 1; i < mipmaps_required; i++) {
- RID mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
- RD::get_singleton()->set_resource_name(mipmap, "Back Buffer slice mip: " + itos(i));
-
- rt->backbuffer_mipmaps.push_back(mipmap);
- }
-}
-
-RID RendererStorageRD::render_target_create() {
- RenderTarget render_target;
-
- render_target.was_used = false;
- render_target.clear_requested = false;
-
- for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
- render_target.flags[i] = false;
- }
- _update_render_target(&render_target);
- return render_target_owner.make_rid(render_target);
-}
-
-void RendererStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) {
- //unused for this render target
-}
-
-void RendererStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
- rt->size.x = p_width;
- rt->size.y = p_height;
- rt->view_count = p_view_count;
- _update_render_target(rt);
- }
-}
-
-RID RendererStorageRD::render_target_get_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- return rt->texture;
-}
-
-void RendererStorageRD::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
-}
-
-void RendererStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->flags[p_flag] = p_value;
- _update_render_target(rt);
-}
-
-bool RendererStorageRD::render_target_was_used(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
- return rt->was_used;
-}
-
-void RendererStorageRD::render_target_set_as_unused(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->was_used = false;
-}
-
-Size2 RendererStorageRD::render_target_get_size(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Size2());
-
- return rt->size;
-}
-
-RID RendererStorageRD::render_target_get_rd_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- return rt->framebuffer;
-}
-
-RID RendererStorageRD::render_target_get_rd_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- return rt->color;
-}
-
-RID RendererStorageRD::render_target_get_rd_backbuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- return rt->backbuffer;
-}
-
-RID RendererStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- return rt->backbuffer_fb;
-}
-
-void RendererStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->clear_requested = true;
- rt->clear_color = p_clear_color;
-}
-
-bool RendererStorageRD::render_target_is_clear_requested(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
- return rt->clear_requested;
-}
-
-Color RendererStorageRD::render_target_get_clear_request_color(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Color());
- return rt->clear_color;
-}
-
-void RendererStorageRD::render_target_disable_clear_request(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->clear_requested = false;
-}
-
-void RendererStorageRD::render_target_do_clear_request(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->clear_requested) {
- return;
- }
- Vector<Color> clear_colors;
- clear_colors.push_back(rt->clear_color);
- RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
- RD::get_singleton()->draw_list_end();
- rt->clear_requested = false;
-}
-
-void RendererStorageRD::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
- return;
- }
-
- rt->sdf_oversize = p_size;
- rt->sdf_scale = p_scale;
-
- _render_target_clear_sdf(rt);
-}
-
-Rect2i RendererStorageRD::_render_target_get_sdf_rect(const RenderTarget *rt) const {
- Size2i margin;
- int scale;
- switch (rt->sdf_oversize) {
- case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: {
- scale = 100;
- } break;
- case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: {
- scale = 120;
- } break;
- case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: {
- scale = 150;
- } break;
- case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: {
- scale = 200;
- } break;
- default: {
- }
- }
-
- margin = (rt->size * scale / 100) - rt->size;
-
- Rect2i r(Vector2i(), rt->size);
- r.position -= margin;
- r.size += margin * 2;
-
- return r;
-}
-
-Rect2i RendererStorageRD::render_target_get_sdf_rect(RID p_render_target) const {
- const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Rect2i());
-
- return _render_target_get_sdf_rect(rt);
-}
-
-void RendererStorageRD::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
-
- rt->sdf_enabled = p_enabled;
-}
-
-bool RendererStorageRD::render_target_is_sdf_enabled(RID p_render_target) const {
- const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, false);
-
- return rt->sdf_enabled;
-}
-
-RID RendererStorageRD::render_target_get_sdf_texture(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- if (rt->sdf_buffer_read.is_null()) {
- // no texture, create a dummy one for the 2D uniform set
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
- memset(pv.ptrw(), 0, 16 * 4);
- Vector<Vector<uint8_t>> vpv;
-
- rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- }
-
- return rt->sdf_buffer_read;
-}
-
-void RendererStorageRD::_render_target_allocate_sdf(RenderTarget *rt) {
- ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_valid());
- if (rt->sdf_buffer_read.is_valid()) {
- RD::get_singleton()->free(rt->sdf_buffer_read);
- rt->sdf_buffer_read = RID();
- }
-
- Size2i size = _render_target_get_sdf_rect(rt).size;
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8_UNORM;
- tformat.width = size.width;
- tformat.height = size.height;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
- rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView());
-
- {
- Vector<RID> write_fb;
- write_fb.push_back(rt->sdf_buffer_write);
- rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb);
- }
-
- int scale;
- switch (rt->sdf_scale) {
- case RS::VIEWPORT_SDF_SCALE_100_PERCENT: {
- scale = 100;
- } break;
- case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
- scale = 50;
- } break;
- case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
- scale = 25;
- } break;
- default: {
- scale = 100;
- } break;
- }
-
- rt->process_size = size * scale / 100;
- rt->process_size.x = MAX(rt->process_size.x, 1);
- rt->process_size.y = MAX(rt->process_size.y, 1);
-
- tformat.format = RD::DATA_FORMAT_R16G16_SINT;
- tformat.width = rt->process_size.width;
- tformat.height = rt->process_size.height;
- tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
-
- tformat.format = RD::DATA_FORMAT_R16_SNORM;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
-
- {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(rt->sdf_buffer_write);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.append_id(rt->sdf_buffer_read);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.append_id(rt->sdf_buffer_process[0]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 4;
- u.append_id(rt->sdf_buffer_process[1]);
- uniforms.push_back(u);
- }
-
- rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
- RID aux2 = uniforms.write[2].get_id(0);
- RID aux3 = uniforms.write[3].get_id(0);
- uniforms.write[2].set_id(0, aux3);
- uniforms.write[3].set_id(0, aux2);
- rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
- }
-}
-
-void RendererStorageRD::_render_target_clear_sdf(RenderTarget *rt) {
- if (rt->sdf_buffer_read.is_valid()) {
- RD::get_singleton()->free(rt->sdf_buffer_read);
- rt->sdf_buffer_read = RID();
- }
- if (rt->sdf_buffer_write_fb.is_valid()) {
- RD::get_singleton()->free(rt->sdf_buffer_write);
- RD::get_singleton()->free(rt->sdf_buffer_process[0]);
- RD::get_singleton()->free(rt->sdf_buffer_process[1]);
- rt->sdf_buffer_write = RID();
- rt->sdf_buffer_write_fb = RID();
- rt->sdf_buffer_process[0] = RID();
- rt->sdf_buffer_process[1] = RID();
- rt->sdf_buffer_process_uniform_sets[0] = RID();
- rt->sdf_buffer_process_uniform_sets[1] = RID();
- }
-}
-
-RID RendererStorageRD::render_target_get_sdf_framebuffer(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
-
- if (rt->sdf_buffer_write_fb.is_null()) {
- _render_target_allocate_sdf(rt);
- }
-
- return rt->sdf_buffer_write_fb;
-}
-void RendererStorageRD::render_target_sdf_process(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
-
- RenderTargetSDF::PushConstant push_constant;
-
- Rect2i r = _render_target_get_sdf_rect(rt);
-
- push_constant.size[0] = r.size.width;
- push_constant.size[1] = r.size.height;
- push_constant.stride = 0;
- push_constant.shift = 0;
- push_constant.base_size[0] = r.size.width;
- push_constant.base_size[1] = r.size.height;
-
- bool shrink = false;
-
- switch (rt->sdf_scale) {
- case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
- push_constant.size[0] >>= 1;
- push_constant.size[1] >>= 1;
- push_constant.shift = 1;
- shrink = true;
- } break;
- case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
- push_constant.size[0] >>= 2;
- push_constant.size[1] >>= 2;
- push_constant.shift = 2;
- shrink = true;
- } break;
- default: {
- };
- }
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- /* Load */
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
-
- /* Process */
-
- int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- bool swap = false;
-
- //jumpflood
- while (stride > 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
- push_constant.stride = stride;
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
- stride /= 2;
- swap = !swap;
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
-
- /* Store */
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-void RendererStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- Rect2i region;
- if (p_region == Rect2i()) {
- region.size = rt->size;
- } else {
- region = Rect2i(Size2i(), rt->size).intersection(p_region);
- if (region.size == Size2i()) {
- return; //nothing to do
- }
- }
-
- //single texture copy for backbuffer
- //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
- effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
-
- if (!p_gen_mipmaps) {
- return;
- }
- RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps");
- //then mipmap blur
- RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
-
- for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
- region.position.x >>= 1;
- region.position.y >>= 1;
- region.size.x = MAX(1, region.size.x >> 1);
- region.size.y = MAX(1, region.size.y >> 1);
-
- RID mipmap = rt->backbuffer_mipmaps[i];
- effects->gaussian_blur(prev_texture, mipmap, region, true);
- prev_texture = mipmap;
- }
- RD::get_singleton()->draw_command_end_label();
-}
-
-void RendererStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- Rect2i region;
- if (p_region == Rect2i()) {
- region.size = rt->size;
- } else {
- region = Rect2i(Size2i(), rt->size).intersection(p_region);
- if (region.size == Size2i()) {
- return; //nothing to do
- }
- }
-
- //single texture copy for backbuffer
- effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
-}
-
-void RendererStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- if (!rt->backbuffer.is_valid()) {
- _create_render_target_backbuffer(rt);
- }
-
- Rect2i region;
- if (p_region == Rect2i()) {
- region.size = rt->size;
- } else {
- region = Rect2i(Size2i(), rt->size).intersection(p_region);
- if (region.size == Size2i()) {
- return; //nothing to do
- }
- }
- RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2");
- //then mipmap blur
- RID prev_texture = rt->backbuffer_mipmap0;
-
- for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
- region.position.x >>= 1;
- region.position.y >>= 1;
- region.size.x = MAX(1, region.size.x >> 1);
- region.size.y = MAX(1, region.size.y >> 1);
-
- RID mipmap = rt->backbuffer_mipmaps[i];
- effects->gaussian_blur(prev_texture, mipmap, region, true);
- prev_texture = mipmap;
- }
- RD::get_singleton()->draw_command_end_label();
-}
-
-RID RendererStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- return rt->framebuffer_uniform_set;
-}
-RID RendererStorageRD::render_target_get_backbuffer_uniform_set(RID p_render_target) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, RID());
- return rt->backbuffer_uniform_set;
-}
-
-void RendererStorageRD::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->framebuffer_uniform_set = p_uniform_set;
-}
-void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
- RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND(!rt);
- rt->backbuffer_uniform_set = p_uniform_set;
-}
+/* misc */
void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) {
@@ -3652,26 +513,26 @@ void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_
if (multimesh->mesh.is_valid()) {
base_update_dependency(multimesh->mesh, p_instance);
}
- } else if (reflection_probe_owner.owns(p_base)) {
- ReflectionProbe *rp = reflection_probe_owner.get_or_null(p_base);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
+ RendererRD::ReflectionProbe *rp = RendererRD::LightStorage::get_singleton()->get_reflection_probe(p_base);
p_instance->update_dependency(&rp->dependency);
- } else if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_base)) {
- RendererRD::Decal *decal = RendererRD::DecalAtlasStorage::get_singleton()->get_decal(p_base);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_base)) {
+ RendererRD::Decal *decal = RendererRD::TextureStorage::get_singleton()->get_decal(p_base);
p_instance->update_dependency(&decal->dependency);
} else if (voxel_gi_owner.owns(p_base)) {
VoxelGI *gip = voxel_gi_owner.get_or_null(p_base);
p_instance->update_dependency(&gip->dependency);
- } else if (lightmap_owner.owns(p_base)) {
- Lightmap *lm = lightmap_owner.get_or_null(p_base);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_base)) {
+ RendererRD::Lightmap *lm = RendererRD::LightStorage::get_singleton()->get_lightmap(p_base);
p_instance->update_dependency(&lm->dependency);
- } else if (light_owner.owns(p_base)) {
- Light *l = light_owner.get_or_null(p_base);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_base)) {
+ RendererRD::Light *l = RendererRD::LightStorage::get_singleton()->get_light(p_base);
p_instance->update_dependency(&l->dependency);
- } else if (particles_owner.owns(p_base)) {
- Particles *p = particles_owner.get_or_null(p_base);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_base)) {
+ RendererRD::Particles *p = RendererRD::ParticlesStorage::get_singleton()->get_particles(p_base);
p_instance->update_dependency(&p->dependency);
- } else if (particles_collision_owner.owns(p_base)) {
- ParticlesCollision *pc = particles_collision_owner.get_or_null(p_base);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
+ RendererRD::ParticlesCollision *pc = RendererRD::ParticlesStorage::get_singleton()->get_particles_collision(p_base);
p_instance->update_dependency(&pc->dependency);
} else if (fog_volume_owner.owns(p_base)) {
FogVolume *fv = fog_volume_owner.get_or_null(p_base);
@@ -3689,25 +550,25 @@ RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
return RS::INSTANCE_MULTIMESH;
}
- if (reflection_probe_owner.owns(p_rid)) {
+ if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
return RS::INSTANCE_REFLECTION_PROBE;
}
- if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_rid)) {
+ if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
return RS::INSTANCE_DECAL;
}
if (voxel_gi_owner.owns(p_rid)) {
return RS::INSTANCE_VOXEL_GI;
}
- if (light_owner.owns(p_rid)) {
+ if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
return RS::INSTANCE_LIGHT;
}
- if (lightmap_owner.owns(p_rid)) {
+ if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
return RS::INSTANCE_LIGHTMAP;
}
- if (particles_owner.owns(p_rid)) {
+ if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
return RS::INSTANCE_PARTICLES;
}
- if (particles_collision_owner.owns(p_rid)) {
+ if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
return RS::INSTANCE_PARTICLES_COLLISION;
}
if (fog_volume_owner.owns(p_rid)) {
@@ -3725,7 +586,7 @@ void RendererStorageRD::update_dirty_resources() {
RendererRD::MaterialStorage::get_singleton()->_update_queued_materials();
RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes();
RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons();
- RendererRD::DecalAtlasStorage::get_singleton()->update_decal_atlas();
+ RendererRD::TextureStorage::get_singleton()->update_decal_atlas();
}
bool RendererStorageRD::has_os_feature(const String &p_feature) const {
@@ -3751,8 +612,8 @@ bool RendererStorageRD::has_os_feature(const String &p_feature) const {
bool RendererStorageRD::free(RID p_rid) {
if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) {
RendererRD::TextureStorage::get_singleton()->texture_free(p_rid);
- } else if (RendererRD::CanvasTextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
- RendererRD::CanvasTextureStorage::get_singleton()->canvas_texture_free(p_rid);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
+ RendererRD::TextureStorage::get_singleton()->canvas_texture_free(p_rid);
} else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid);
} else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) {
@@ -3765,66 +626,35 @@ bool RendererStorageRD::free(RID 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);
- reflection_probe_owner.free(p_rid);
- } else if (RendererRD::DecalAtlasStorage::get_singleton()->owns_decal(p_rid)) {
- RendererRD::DecalAtlasStorage::get_singleton()->decal_free(p_rid);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
+ RendererRD::LightStorage::get_singleton()->reflection_probe_free(p_rid);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
+ RendererRD::TextureStorage::get_singleton()->decal_free(p_rid);
} else if (voxel_gi_owner.owns(p_rid)) {
voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_rid);
voxel_gi->dependency.deleted_notify(p_rid);
voxel_gi_owner.free(p_rid);
- } else if (lightmap_owner.owns(p_rid)) {
- lightmap_set_textures(p_rid, RID(), false);
- Lightmap *lightmap = lightmap_owner.get_or_null(p_rid);
- lightmap->dependency.deleted_notify(p_rid);
- lightmap_owner.free(p_rid);
-
- } else if (light_owner.owns(p_rid)) {
- light_set_projector(p_rid, RID()); //clear projector
- // delete the texture
- Light *light = light_owner.get_or_null(p_rid);
- light->dependency.deleted_notify(p_rid);
- light_owner.free(p_rid);
-
- } else if (particles_owner.owns(p_rid)) {
- update_particles();
- Particles *particles = particles_owner.get_or_null(p_rid);
- particles->dependency.deleted_notify(p_rid);
- _particles_free_data(particles);
- particles_owner.free(p_rid);
- } else if (particles_collision_owner.owns(p_rid)) {
- ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
-
- if (particles_collision->heightfield_texture.is_valid()) {
- RD::get_singleton()->free(particles_collision->heightfield_texture);
- }
- particles_collision->dependency.deleted_notify(p_rid);
- particles_collision_owner.free(p_rid);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
+ RendererRD::LightStorage::get_singleton()->lightmap_free(p_rid);
+ } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
+ RendererRD::LightStorage::get_singleton()->light_free(p_rid);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
+ RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
+ RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid);
} else if (visibility_notifier_owner.owns(p_rid)) {
VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_rid);
vn->dependency.deleted_notify(p_rid);
visibility_notifier_owner.free(p_rid);
- } else if (particles_collision_instance_owner.owns(p_rid)) {
- particles_collision_instance_owner.free(p_rid);
+ } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) {
+ RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid);
} else if (fog_volume_owner.owns(p_rid)) {
FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
fog_volume->dependency.deleted_notify(p_rid);
fog_volume_owner.free(p_rid);
- } else if (render_target_owner.owns(p_rid)) {
- RenderTarget *rt = render_target_owner.get_or_null(p_rid);
-
- _clear_render_target(rt);
-
- if (rt->texture.is_valid()) {
- RendererRD::Texture *tex = RendererRD::TextureStorage::get_singleton()->get_texture(rt->texture);
- tex->is_render_target = false;
- free(rt->texture);
- }
-
- render_target_owner.free(p_rid);
+ } else if (RendererRD::TextureStorage::get_singleton()->owns_render_target(p_rid)) {
+ RendererRD::TextureStorage::get_singleton()->render_target_free(p_rid);
} else {
return false;
}
@@ -3901,309 +731,9 @@ RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
RendererStorageRD::RendererStorageRD() {
base_singleton = this;
-
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
- //default samplers
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- RD::SamplerState sampler_state;
- switch (i) {
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.max_lod = 0;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
- } break;
- case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
- sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
- sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
- if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- } else {
- sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
- }
- sampler_state.use_anisotropy = true;
- sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
-
- } break;
- default: {
- }
- }
- switch (j) {
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
-
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
- } break;
- case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
- sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- } break;
- default: {
- }
- }
-
- default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
- }
- }
-
- //custom sampler
- sampler_rd_configure_custom(0.0f);
-
- 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);
-
- if (textures_per_stage <= 256) {
- lightmap_textures.resize(32);
- } else {
- lightmap_textures.resize(1024);
- }
-
- for (int i = 0; i < lightmap_textures.size(); i++) {
- lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
- }
- }
-
- lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
-
- /* Particles */
-
- {
- // Initialize particles
- Vector<String> particles_modes;
- particles_modes.push_back("");
- particles_shader.shader.initialize(particles_modes, String());
- }
- RendererRD::MaterialStorage::get_singleton()->shader_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
- RendererRD::MaterialStorage::get_singleton()->material_set_data_request_function(RendererRD::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
-
- {
- ShaderCompiler::DefaultIdentifierActions actions;
-
- actions.renames["COLOR"] = "PARTICLE.color";
- actions.renames["VELOCITY"] = "PARTICLE.velocity";
- //actions.renames["MASS"] = "mass"; ?
- actions.renames["ACTIVE"] = "particle_active";
- actions.renames["RESTART"] = "restart";
- actions.renames["CUSTOM"] = "PARTICLE.custom";
- for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
- String udname = "USERDATA" + itos(i + 1);
- actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
- actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n";
- }
- actions.renames["TRANSFORM"] = "PARTICLE.xform";
- actions.renames["TIME"] = "frame_history.data[0].time";
- actions.renames["PI"] = _MKSTR(Math_PI);
- actions.renames["TAU"] = _MKSTR(Math_TAU);
- actions.renames["E"] = _MKSTR(Math_E);
- actions.renames["LIFETIME"] = "params.lifetime";
- actions.renames["DELTA"] = "local_delta";
- actions.renames["NUMBER"] = "particle_number";
- actions.renames["INDEX"] = "index";
- //actions.renames["GRAVITY"] = "current_gravity";
- actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
- actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
- actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
- actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
- actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY";
- actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR";
- actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM";
- actions.renames["RESTART_POSITION"] = "restart_position";
- actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale";
- actions.renames["RESTART_VELOCITY"] = "restart_velocity";
- actions.renames["RESTART_COLOR"] = "restart_color";
- actions.renames["RESTART_CUSTOM"] = "restart_custom";
- actions.renames["emit_subparticle"] = "emit_subparticle";
- actions.renames["COLLIDED"] = "collided";
- actions.renames["COLLISION_NORMAL"] = "collision_normal";
- actions.renames["COLLISION_DEPTH"] = "collision_depth";
- actions.renames["ATTRACTOR_FORCE"] = "attractor_force";
-
- actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
- actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
- actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
- actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n";
-
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = 3;
- actions.base_uniform_string = "material.";
- actions.base_varying_index = 10;
-
- actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
- actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
-
- particles_shader.compiler.initialize(actions);
- }
-
- {
- // default material and shader for particles shader
- particles_shader.default_shader = material_storage->shader_allocate();
- material_storage->shader_initialize(particles_shader.default_shader);
- material_storage->shader_set_code(particles_shader.default_shader, R"(
-// Default particles shader.
-
-shader_type particles;
-
-void process() {
- COLOR = vec4(1.0);
-}
-)");
- particles_shader.default_material = material_storage->material_allocate();
- material_storage->material_initialize(particles_shader.default_material);
- material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
-
- ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, RendererRD::SHADER_TYPE_PARTICLES));
- particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
-
- Vector<RD::Uniform> uniforms;
-
- {
- Vector<RID> ids;
- ids.resize(12);
- RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-
- RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(material_storage->global_variables_get_storage_buffer());
- uniforms.push_back(u);
- }
-
- particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0);
- }
-
- {
- Vector<String> copy_modes;
- for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
- if (i == 0) {
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n");
- copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n");
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n");
- } else {
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n");
- copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
- copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
- }
- }
-
- particles_shader.copy_shader.initialize(copy_modes);
-
- particles_shader.copy_shader_version = particles_shader.copy_shader.version_create();
-
- for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
- for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) {
- particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j));
- }
- }
- }
-
- {
- Vector<String> sdf_modes;
- sdf_modes.push_back("\n#define MODE_LOAD\n");
- sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n");
- sdf_modes.push_back("\n#define MODE_PROCESS\n");
- sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n");
- sdf_modes.push_back("\n#define MODE_STORE\n");
- sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n");
-
- rt_sdf.shader.initialize(sdf_modes);
-
- rt_sdf.shader_version = rt_sdf.shader.version_create();
-
- for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) {
- rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
- }
- }
}
RendererStorageRD::~RendererStorageRD() {
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
- //def samplers
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- RD::get_singleton()->free(default_rd_samplers[i][j]);
- }
- }
-
- //custom samplers
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- if (custom_rd_samplers[i][j].is_valid()) {
- RD::get_singleton()->free(custom_rd_samplers[i][j]);
- }
- }
- }
-
- particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
- rt_sdf.shader.version_free(rt_sdf.shader_version);
-
- material_storage->material_free(particles_shader.default_material);
- material_storage->shader_free(particles_shader.default_shader);
-
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 4c45dd4295..37c76f9c62 100644
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ b/servers/rendering/renderer_rd/renderer_storage_rd.h
@@ -36,9 +36,6 @@
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/effects_rd.h"
-#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/voxel_gi_sdf.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
@@ -126,363 +123,6 @@ public:
}
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];
-
- /* PARTICLES */
-
- struct ParticleData {
- float xform[16];
- float velocity[3];
- uint32_t active;
- float color[4];
- float custom[3];
- float lifetime;
- };
-
- struct ParticlesFrameParams {
- enum {
- MAX_ATTRACTORS = 32,
- MAX_COLLIDERS = 32,
- MAX_3D_TEXTURES = 7
- };
-
- enum AttractorType {
- ATTRACTOR_TYPE_SPHERE,
- ATTRACTOR_TYPE_BOX,
- ATTRACTOR_TYPE_VECTOR_FIELD,
- };
-
- struct Attractor {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
-
- uint32_t texture_index; //texture index for vector field
- float strength;
- float attenuation;
- float directionality;
- };
-
- enum CollisionType {
- COLLISION_TYPE_SPHERE,
- COLLISION_TYPE_BOX,
- COLLISION_TYPE_SDF,
- COLLISION_TYPE_HEIGHT_FIELD,
- COLLISION_TYPE_2D_SDF,
-
- };
-
- struct Collider {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
-
- uint32_t texture_index; //texture index for vector field
- real_t scale;
- uint32_t pad[2];
- };
-
- uint32_t emitting;
- float system_phase;
- float prev_system_phase;
- uint32_t cycle;
-
- real_t explosiveness;
- real_t randomness;
- float time;
- float delta;
-
- uint32_t frame;
- uint32_t pad0;
- uint32_t pad1;
- uint32_t pad2;
-
- uint32_t random_seed;
- uint32_t attractor_count;
- uint32_t collider_count;
- float particle_size;
-
- float emission_transform[16];
-
- Attractor attractors[MAX_ATTRACTORS];
- Collider colliders[MAX_COLLIDERS];
- };
-
- struct ParticleEmissionBufferData {
- };
-
- struct ParticleEmissionBuffer {
- struct Data {
- float xform[16];
- float velocity[3];
- uint32_t flags;
- float color[4];
- float custom[4];
- };
-
- int32_t particle_count;
- int32_t particle_max;
- uint32_t pad1;
- uint32_t pad2;
- Data data[1]; //its 2020 and empty arrays are still non standard in C++
- };
-
- struct Particles {
- RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
- bool inactive = true;
- double inactive_time = 0.0;
- bool emitting = false;
- bool one_shot = false;
- int amount = 0;
- double lifetime = 1.0;
- double pre_process_time = 0.0;
- real_t explosiveness = 0.0;
- real_t randomness = 0.0;
- bool restart_request = false;
- AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
- bool use_local_coords = true;
- bool has_collision_cache = false;
-
- bool has_sdf_collision = false;
- Transform2D sdf_collision_transform;
- Rect2 sdf_collision_to_screen;
- RID sdf_collision_texture;
-
- RID process_material;
- uint32_t frame_counter = 0;
- RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
-
- RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
-
- Vector<RID> draw_passes;
- Vector<Transform3D> trail_bind_poses;
- bool trail_bind_poses_dirty = false;
- RID trail_bind_pose_buffer;
- RID trail_bind_pose_uniform_set;
-
- RID particle_buffer;
- RID particle_instance_buffer;
- RID frame_params_buffer;
-
- uint32_t userdata_count = 0;
-
- RID particles_material_uniform_set;
- RID particles_copy_uniform_set;
- RID particles_transforms_buffer_uniform_set;
- RID collision_textures_uniform_set;
-
- RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
- uint32_t collision_3d_textures_used = 0;
- RID collision_heightmap_texture;
-
- RID particles_sort_buffer;
- RID particles_sort_uniform_set;
-
- bool dirty = false;
- Particles *update_list = nullptr;
-
- RID sub_emitter;
-
- double phase = 0.0;
- double prev_phase = 0.0;
- uint64_t prev_ticks = 0;
- uint32_t random_seed = 0;
-
- uint32_t cycle_number = 0;
-
- double speed_scale = 1.0;
-
- int fixed_fps = 30;
- bool interpolate = true;
- bool fractional_delta = false;
- double frame_remainder = 0;
- real_t collision_base_size = 0.01;
-
- bool clear = true;
-
- bool force_sub_emit = false;
-
- Transform3D emission_transform;
-
- Vector<uint8_t> emission_buffer_data;
-
- ParticleEmissionBuffer *emission_buffer = nullptr;
- RID emission_storage_buffer;
-
- Set<RID> collisions;
-
- Dependency dependency;
-
- double trail_length = 1.0;
- bool trails_enabled = false;
- LocalVector<ParticlesFrameParams> frame_history;
- LocalVector<ParticlesFrameParams> trail_params;
-
- Particles() {
- }
- };
-
- void _particles_process(Particles *p_particles, double p_delta);
- void _particles_allocate_emission_buffer(Particles *particles);
- void _particles_free_data(Particles *particles);
- void _particles_update_buffers(Particles *particles);
-
- struct ParticlesShader {
- struct PushConstant {
- float lifetime;
- uint32_t clear;
- uint32_t total_particles;
- uint32_t trail_size;
-
- uint32_t use_fractional_delta;
- uint32_t sub_emitter_mode;
- uint32_t can_emit;
- uint32_t trail_pass;
- };
-
- ParticlesShaderRD shader;
- ShaderCompiler compiler;
-
- RID default_shader;
- RID default_material;
- RID default_shader_rd;
-
- RID base_uniform_set;
-
- struct CopyPushConstant {
- float sort_direction[3];
- uint32_t total_particles;
-
- uint32_t trail_size;
- uint32_t trail_total;
- float frame_delta;
- float frame_remainder;
-
- float align_up[3];
- uint32_t align_mode;
-
- uint32_t order_by_lifetime;
- uint32_t lifetime_split;
- uint32_t lifetime_reverse;
- uint32_t copy_mode_2d;
-
- float inv_emission_transform[16];
- };
-
- enum {
- MAX_USERDATAS = 6
- };
- enum {
- COPY_MODE_FILL_INSTANCES,
- COPY_MODE_FILL_SORT_BUFFER,
- COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER,
- COPY_MODE_MAX,
- };
-
- ParticlesCopyShaderRD copy_shader;
- RID copy_shader_version;
- RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
-
- LocalVector<float> pose_update_buffer;
-
- } particles_shader;
-
- Particles *particle_update_list = nullptr;
-
- struct ParticlesShaderData : public RendererRD::ShaderData {
- bool valid;
- RID version;
- bool uses_collision = false;
-
- //PipelineCacheRD pipelines[SKY_VERSION_MAX];
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size;
-
- String path;
- String code;
- Map<StringName, Map<int, RID>> default_texture_params;
-
- RID pipeline;
-
- bool uses_time = false;
-
- bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {};
- uint32_t userdata_count = 0;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
- virtual bool is_animated() const;
- virtual bool casts_shadows() const;
- virtual Variant get_default_parameter(const StringName &p_parameter) const;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const;
-
- ParticlesShaderData();
- virtual ~ParticlesShaderData();
- };
-
- RendererRD::ShaderData *_create_particles_shader_func();
- static RendererRD::ShaderData *_create_particles_shader_funcs() {
- return base_singleton->_create_particles_shader_func();
- }
-
- struct ParticlesMaterialData : public RendererRD::MaterialData {
- ParticlesShaderData *shader_data = nullptr;
- RID uniform_set;
-
- virtual void set_render_priority(int p_priority) {}
- virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~ParticlesMaterialData();
- };
-
- RendererRD::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
- static RendererRD::MaterialData *_create_particles_material_funcs(RendererRD::ShaderData *p_shader) {
- return base_singleton->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
- }
-
- void update_particles();
-
- mutable RID_Owner<Particles, true> particles_owner;
-
- /* Particles Collision */
-
- struct ParticlesCollision {
- RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
- uint32_t cull_mask = 0xFFFFFFFF;
- float radius = 1.0;
- Vector3 extents = Vector3(1, 1, 1);
- float attractor_strength = 1.0;
- float attractor_attenuation = 1.0;
- float attractor_directionality = 0.0;
- RID field_texture;
- RID heightfield_texture;
- RID heightfield_fb;
- Size2i heightfield_fb_size;
-
- RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
-
- struct ParticlesCollisionInstance {
- RID collision;
- Transform3D transform;
- bool active = false;
- };
-
- mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
-
/* FOG VOLUMES */
struct FogVolume {
@@ -507,57 +147,6 @@ private:
mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
- /* LIGHT */
-
- struct Light {
- RS::LightType type;
- float param[RS::LIGHT_PARAM_MAX];
- Color color = Color(1, 1, 1, 1);
- RID projector;
- bool shadow = false;
- bool negative = false;
- bool reverse_cull = false;
- RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
- uint32_t max_sdfgi_cascade = 2;
- uint32_t cull_mask = 0xFFFFFFFF;
- bool distance_fade = false;
- real_t distance_fade_begin = 40.0;
- real_t distance_fade_shadow = 50.0;
- real_t distance_fade_length = 10.0;
- RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
- RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
- bool directional_blend_splits = false;
- RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
- uint64_t version = 0;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<Light, true> light_owner;
-
- /* REFLECTION PROBE */
-
- struct ReflectionProbe {
- RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
- int resolution = 256;
- float intensity = 1.0;
- RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
- Color ambient_color;
- float ambient_color_energy = 1.0;
- float max_distance = 0;
- Vector3 extents = Vector3(1, 1, 1);
- Vector3 origin_offset;
- bool interior = false;
- bool box_projection = false;
- bool enable_shadows = false;
- uint32_t cull_mask = (1 << 20) - 1;
- float mesh_lod_threshold = 0.01;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
-
/* VOXEL GI */
struct VoxelGI {
@@ -594,116 +183,6 @@ private:
mutable RID_Owner<VoxelGI, true> voxel_gi_owner;
- /* REFLECTION PROBE */
-
- struct Lightmap {
- RID light_texture;
- bool uses_spherical_harmonics = false;
- bool interior = false;
- AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
- int32_t array_index = -1; //unassigned
- PackedVector3Array points;
- PackedColorArray point_sh;
- PackedInt32Array tetrahedra;
- PackedInt32Array bsp_tree;
-
- struct BSP {
- static const int32_t EMPTY_LEAF = INT32_MIN;
- float plane[4];
- int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
- };
-
- Dependency dependency;
- };
-
- bool using_lightmap_array; //high end uses this
- /* for high end */
-
- Vector<RID> lightmap_textures;
-
- uint64_t lightmap_array_version = 0;
-
- mutable RID_Owner<Lightmap, true> lightmap_owner;
-
- float lightmap_probe_capture_update_speed = 4;
-
- /* RENDER TARGET */
-
- struct RenderTarget {
- Size2i size;
- uint32_t view_count;
- RID framebuffer;
- RID color;
-
- //used for retrieving from CPU
- RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- Image::Format image_format = Image::FORMAT_L8;
-
- bool flags[RENDER_TARGET_FLAG_MAX];
-
- bool sdf_enabled = false;
-
- RID backbuffer; //used for effects
- RID backbuffer_fb;
- RID backbuffer_mipmap0;
-
- Vector<RID> backbuffer_mipmaps;
-
- RID framebuffer_uniform_set;
- RID backbuffer_uniform_set;
-
- RID sdf_buffer_write;
- RID sdf_buffer_write_fb;
- RID sdf_buffer_process[2];
- RID sdf_buffer_read;
- RID sdf_buffer_process_uniform_sets[2];
- RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
- RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
- Size2i process_size;
-
- //texture generated for this owner (nor RD).
- RID texture;
- bool was_used;
-
- //clear request
- bool clear_requested;
- Color clear_color;
- };
-
- mutable RID_Owner<RenderTarget> render_target_owner;
-
- void _clear_render_target(RenderTarget *rt);
- void _update_render_target(RenderTarget *rt);
- void _create_render_target_backbuffer(RenderTarget *rt);
- void _render_target_allocate_sdf(RenderTarget *rt);
- void _render_target_clear_sdf(RenderTarget *rt);
- Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
-
- struct RenderTargetSDF {
- enum {
- SHADER_LOAD,
- SHADER_LOAD_SHRINK,
- SHADER_PROCESS,
- SHADER_PROCESS_OPTIMIZED,
- SHADER_STORE,
- SHADER_STORE_SHRINK,
- SHADER_MAX
- };
-
- struct PushConstant {
- int32_t size[2];
- int32_t stride;
- int32_t shift;
- int32_t base_size[2];
- int32_t pad[2];
- };
-
- CanvasSdfShaderRD shader;
- RID shader_version;
- RID pipelines[SHADER_MAX];
- } rt_sdf;
-
/* EFFECTS */
EffectsRD *effects = nullptr;
@@ -711,185 +190,6 @@ private:
public:
//internal usage
- _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
- return default_rd_samplers[p_filter][p_repeat];
- }
- _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
- return custom_rd_samplers[p_filter][p_repeat];
- }
-
- void sampler_rd_configure_custom(float mipmap_bias);
-
- void sampler_rd_set_default(float p_mipmap_bias);
-
- /* Light API */
-
- void _light_initialize(RID p_rid, RS::LightType p_type);
-
- RID directional_light_allocate();
- void directional_light_initialize(RID p_light);
-
- RID omni_light_allocate();
- void omni_light_initialize(RID p_light);
-
- RID spot_light_allocate();
- void spot_light_initialize(RID p_light);
-
- void light_set_color(RID p_light, const Color &p_color);
- void light_set_param(RID p_light, RS::LightParam p_param, float p_value);
- void light_set_shadow(RID p_light, bool p_enabled);
- void light_set_projector(RID p_light, RID p_texture);
- void light_set_negative(RID p_light, bool p_enable);
- void light_set_cull_mask(RID p_light, uint32_t p_mask);
- void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length);
- void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled);
- void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode);
- void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade);
-
- void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode);
-
- void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode);
- void light_directional_set_blend_splits(RID p_light, bool p_enable);
- bool light_directional_get_blend_splits(RID p_light) const;
- void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode);
- RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const;
-
- RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
- RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
-
- _FORCE_INLINE_ RS::LightType light_get_type(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return light->type;
- }
- AABB light_get_aabb(RID p_light) const;
-
- _FORCE_INLINE_ float light_get_param(RID p_light, RS::LightParam p_param) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->param[p_param];
- }
-
- _FORCE_INLINE_ RID light_get_projector(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RID());
-
- return light->projector;
- }
-
- _FORCE_INLINE_ Color light_get_color(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, Color());
-
- return light->color;
- }
-
- _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0);
-
- return light->cull_mask;
- }
-
- _FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- return light->distance_fade;
- }
-
- _FORCE_INLINE_ float light_get_distance_fade_begin(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- return light->distance_fade_begin;
- }
-
- _FORCE_INLINE_ float light_get_distance_fade_shadow(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- return light->distance_fade_shadow;
- }
-
- _FORCE_INLINE_ float light_get_distance_fade_length(RID p_light) {
- const Light *light = light_owner.get_or_null(p_light);
- return light->distance_fade_length;
- }
-
- _FORCE_INLINE_ bool light_has_shadow(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return light->shadow;
- }
-
- _FORCE_INLINE_ bool light_has_projector(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return light_owner.owns(light->projector);
- }
-
- _FORCE_INLINE_ bool light_is_negative(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
-
- return light->negative;
- }
-
- _FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0.0);
-
- return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
- }
-
- _FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0.0);
-
- return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
- }
-
- RS::LightBakeMode light_get_bake_mode(RID p_light);
- uint32_t light_get_max_sdfgi_cascade(RID p_light);
- uint64_t light_get_version(RID p_light) const;
-
- /* PROBE API */
-
- RID reflection_probe_allocate();
- void reflection_probe_initialize(RID p_reflection_probe);
-
- void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode);
- void reflection_probe_set_intensity(RID p_probe, float p_intensity);
- void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode);
- void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color);
- void reflection_probe_set_ambient_energy(RID p_probe, float p_energy);
- void reflection_probe_set_max_distance(RID p_probe, float p_distance);
- void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents);
- void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset);
- void reflection_probe_set_as_interior(RID p_probe, bool p_enable);
- void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable);
- void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable);
- void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers);
- void reflection_probe_set_resolution(RID p_probe, int p_resolution);
- void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio);
-
- AABB reflection_probe_get_aabb(RID p_probe) const;
- RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const;
- uint32_t reflection_probe_get_cull_mask(RID p_probe) const;
- Vector3 reflection_probe_get_extents(RID p_probe) const;
- Vector3 reflection_probe_get_origin_offset(RID p_probe) const;
- float reflection_probe_get_origin_max_distance(RID p_probe) const;
- float reflection_probe_get_mesh_lod_threshold(RID p_probe) const;
-
- int reflection_probe_get_resolution(RID p_probe) const;
- bool reflection_probe_renders_shadows(RID p_probe) const;
-
- float reflection_probe_get_intensity(RID p_probe) const;
- bool reflection_probe_is_interior(RID p_probe) const;
- bool reflection_probe_is_box_projection(RID p_probe) const;
- RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const;
- Color reflection_probe_get_ambient_color(RID p_probe) const;
- float reflection_probe_get_ambient_color_energy(RID p_probe) const;
-
void base_update_dependency(RID p_base, DependencyTracker *p_instance);
/* VOXEL GI API */
@@ -940,187 +240,6 @@ public:
RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
- /* LIGHTMAP CAPTURE */
-
- RID lightmap_allocate();
- void lightmap_initialize(RID p_lightmap);
-
- virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics);
- virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds);
- virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior);
- virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree);
- virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const;
- virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const;
- virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const;
- virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const;
- virtual AABB lightmap_get_aabb(RID p_lightmap) const;
- virtual bool lightmap_is_interior(RID p_lightmap) const;
- virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh);
- virtual void lightmap_set_probe_capture_update_speed(float p_speed);
- _FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {
- return lightmap_probe_capture_update_speed;
- }
- _FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND_V(!lm, RID());
- return lm->light_texture;
- }
- _FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
- ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- return lm->array_index;
- }
- _FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
- ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
- const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
- return lm->uses_spherical_harmonics;
- }
- _FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
- ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
- return lightmap_array_version;
- }
-
- _FORCE_INLINE_ int lightmap_array_get_size() const {
- ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
- return lightmap_textures.size();
- }
-
- _FORCE_INLINE_ const Vector<RID> &lightmap_array_get_textures() const {
- ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
- return lightmap_textures;
- }
-
- /* PARTICLES */
-
- RID particles_allocate();
- void particles_initialize(RID p_particles_collision);
-
- void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode);
- void particles_set_emitting(RID p_particles, bool p_emitting);
- void particles_set_amount(RID p_particles, int p_amount);
- void particles_set_lifetime(RID p_particles, double p_lifetime);
- void particles_set_one_shot(RID p_particles, bool p_one_shot);
- void particles_set_pre_process_time(RID p_particles, double p_time);
- void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio);
- void particles_set_randomness_ratio(RID p_particles, real_t p_ratio);
- void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb);
- void particles_set_speed_scale(RID p_particles, double p_scale);
- void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
- void particles_set_process_material(RID p_particles, RID p_material);
- RID particles_get_process_material(RID p_particles) const;
-
- void particles_set_fixed_fps(RID p_particles, int p_fps);
- void particles_set_interpolate(RID p_particles, bool p_enable);
- void particles_set_fractional_delta(RID p_particles, bool p_enable);
- void particles_set_collision_base_size(RID p_particles, real_t p_size);
- void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align);
-
- void particles_set_trails(RID p_particles, bool p_enable, double p_length);
- void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses);
-
- void particles_restart(RID p_particles);
- void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags);
-
- void particles_set_subemitter(RID p_particles, RID p_subemitter_particles);
-
- void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order);
-
- void particles_set_draw_passes(RID p_particles, int p_count);
- void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh);
-
- void particles_request_process(RID p_particles);
- AABB particles_get_current_aabb(RID p_particles);
- AABB particles_get_aabb(RID p_particles) const;
-
- void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform);
-
- bool particles_get_emitting(RID p_particles);
- int particles_get_draw_passes(RID p_particles) const;
- RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const;
-
- void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis);
-
- virtual bool particles_is_inactive(RID p_particles) const;
-
- _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
- return particles->mode;
- }
-
- _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, 0);
-
- if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- r_trail_divisor = particles->trail_bind_poses.size();
- } else {
- r_trail_divisor = 1;
- }
-
- return particles->amount * r_trail_divisor;
- }
-
- _FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, 0);
-
- return particles->has_collision_cache;
- }
-
- _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, false);
-
- return particles->use_local_coords;
- }
-
- _FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
- Particles *particles = particles_owner.get_or_null(p_particles);
- ERR_FAIL_COND_V(!particles, RID());
- if (particles->particles_transforms_buffer_uniform_set.is_null()) {
- _particles_update_buffers(particles);
-
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(particles->particle_instance_buffer);
- uniforms.push_back(u);
- }
-
- particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
- }
-
- return particles->particles_transforms_buffer_uniform_set;
- }
-
- virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance);
- virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance);
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture);
-
- /* PARTICLES COLLISION */
-
- RID particles_collision_allocate();
- void particles_collision_initialize(RID p_particles_collision);
-
- virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type);
- virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask);
- virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius); //for spheres
- virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents); //for non-spheres
- virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength);
- virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality);
- virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve);
- virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture); //for SDF and vector field, heightfield is dynamic
- virtual void particles_collision_height_field_update(RID p_particles_collision); //for SDF and vector field
- virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution); //for SDF and vector field
- virtual AABB particles_collision_get_aabb(RID p_particles_collision) const;
- virtual Vector3 particles_collision_get_extents(RID p_particles_collision) const;
- virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;
- RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
-
/* FOG VOLUMES */
virtual RID fog_volume_allocate();
@@ -1144,53 +263,6 @@ public:
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
- //used from 2D and 3D
- virtual RID particles_collision_instance_create(RID p_collision);
- virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform);
- virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active);
-
- /* RENDER TARGET API */
-
- RID render_target_create();
- void render_target_set_position(RID p_render_target, int p_x, int p_y);
- void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count);
- RID render_target_get_texture(RID p_render_target);
- void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id);
- void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value);
- bool render_target_was_used(RID p_render_target);
- void render_target_set_as_unused(RID p_render_target);
- void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
- void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
- void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
-
- RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
-
- virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color);
- virtual bool render_target_is_clear_requested(RID p_render_target);
- virtual Color render_target_get_clear_request_color(RID p_render_target);
- virtual void render_target_disable_clear_request(RID p_render_target);
- virtual void render_target_do_clear_request(RID p_render_target);
-
- virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale);
- RID render_target_get_sdf_texture(RID p_render_target);
- RID render_target_get_sdf_framebuffer(RID p_render_target);
- void render_target_sdf_process(RID p_render_target);
- virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const;
- void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled);
- bool render_target_is_sdf_enabled(RID p_render_target) const;
-
- Size2 render_target_get_size(RID p_render_target);
- RID render_target_get_rd_framebuffer(RID p_render_target);
- RID render_target_get_rd_texture(RID p_render_target);
- RID render_target_get_rd_backbuffer(RID p_render_target);
- RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
-
- RID render_target_get_framebuffer_uniform_set(RID p_render_target);
- RID render_target_get_backbuffer_uniform_set(RID p_render_target);
-
- void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
- void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
-
RS::InstanceType get_base_type(RID p_rid) const;
bool free(RID p_rid);
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 73766d14d8..fdfecf2d2c 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -382,8 +382,8 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
- FileAccessRef f = FileAccess::open(path, FileAccess::READ);
- if (!f) {
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
+ if (f.is_null()) {
return false;
}
@@ -445,8 +445,8 @@ void ShaderRD::_save_to_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
- FileAccessRef f = FileAccess::open(path, FileAccess::WRITE);
- ERR_FAIL_COND(!f);
+ Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
+ ERR_FAIL_COND(f.is_null());
f->store_buffer((const uint8_t *)shader_file_header, 4);
f->store_32(cache_file_version); //file version
uint32_t variant_count = variant_defines.size();
@@ -456,8 +456,6 @@ void ShaderRD::_save_to_cache(Version *p_version) {
f->store_32(p_version->variant_data[i].size()); //stage count
f->store_buffer(p_version->variant_data[i].ptr(), p_version->variant_data[i].size());
}
-
- f->close();
}
void ShaderRD::_compile_version(Version *p_version) {
@@ -652,8 +650,8 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
base_sha256 = hash_build.as_string().sha256_text();
- DirAccessRef d = DirAccess::open(shader_cache_dir);
- ERR_FAIL_COND(!d);
+ Ref<DirAccess> d = DirAccess::open(shader_cache_dir);
+ ERR_FAIL_COND(d.is_null());
if (d->change_dir(name) != OK) {
Error err = d->make_dir(name);
ERR_FAIL_COND(err != OK);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index abe1a09b06..58b4ded9f4 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -1479,62 +1479,78 @@ void main() {
} else { //no soft shadows
vec4 pssm_coord;
+ float blur_factor;
+
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 0)
pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ blur_factor = 1.0;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
-
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
}
pssm_coord /= pssm_coord.w;
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor, pssm_coord);
if (directional_lights.data[i].blend_splits) {
float pssm_blend;
+ float blur_factor2;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
+ blur_factor2 = 1.0;
}
pssm_coord /= pssm_coord.w;
- float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor2, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
}
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 6911cab27b..b6ba244665 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -1282,6 +1282,7 @@ void main() {
float depth_z = -vertex.z;
vec4 pssm_coord;
+ float blur_factor;
vec3 light_dir = directional_lights.data[i].direction;
vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
@@ -1297,56 +1298,71 @@ void main() {
BIAS_FUNC(v, 0)
pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ blur_factor = 1.0;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
+ ;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
-
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
}
pssm_coord /= pssm_coord.w;
- shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor, pssm_coord);
if (directional_lights.data[i].blend_splits) {
float pssm_blend;
+ float blur_factor2;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 1)
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.y;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 2)
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.z;
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
vec4 v = vec4(vertex, 1.0);
BIAS_FUNC(v, 3)
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
+ // Adjust shadow blur with reference to the first split to reduce discrepancy between shadow splits.
+ blur_factor2 = directional_lights.data[i].shadow_split_offsets.x / directional_lights.data[i].shadow_split_offsets.w;
} else {
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
+ blur_factor2 = 1.0;
}
pssm_coord /= pssm_coord.w;
- float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
+ float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale * blur_factor2, pssm_coord);
shadow = mix(shadow, shadow2, pssm_blend);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp
deleted file mode 100644
index 3299b93ee2..0000000000
--- a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/*************************************************************************/
-/* canvas_texture_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 "canvas_texture_storage.h"
-#include "texture_storage.h"
-
-// Until we move things into their own storage classes, also include our old class
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-
-using namespace RendererRD;
-
-///////////////////////////////////////////////////////////////////////////
-// CanvasTexture
-
-void CanvasTexture::clear_sets() {
- if (cleared_cache) {
- return;
- }
- for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
- for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
- if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
- RD::get_singleton()->free(uniform_sets[i][j]);
- uniform_sets[i][j] = RID();
- }
- }
- }
- cleared_cache = true;
-}
-
-CanvasTexture::~CanvasTexture() {
- clear_sets();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// CanvasTextureStorage
-
-CanvasTextureStorage *CanvasTextureStorage::singleton = nullptr;
-
-CanvasTextureStorage *CanvasTextureStorage::get_singleton() {
- return singleton;
-}
-
-CanvasTextureStorage::CanvasTextureStorage() {
- singleton = this;
-}
-
-CanvasTextureStorage::~CanvasTextureStorage() {
- singleton = nullptr;
-}
-
-RID CanvasTextureStorage::canvas_texture_allocate() {
- return canvas_texture_owner.allocate_rid();
-}
-
-void CanvasTextureStorage::canvas_texture_initialize(RID p_rid) {
- canvas_texture_owner.initialize_rid(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_free(RID p_rid) {
- canvas_texture_owner.free(p_rid);
-}
-
-void CanvasTextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ERR_FAIL_NULL(ct);
-
- switch (p_channel) {
- case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
- ct->diffuse = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
- ct->normal_map = p_texture;
- } break;
- case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
- ct->specular = p_texture;
- } break;
- }
-
- ct->clear_sets();
-}
-
-void CanvasTextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ERR_FAIL_NULL(ct);
-
- ct->specular_color.r = p_specular_color.r;
- ct->specular_color.g = p_specular_color.g;
- ct->specular_color.b = p_specular_color.b;
- ct->specular_color.a = p_shininess;
- ct->clear_sets();
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ERR_FAIL_NULL(ct);
-
- ct->texture_filter = p_filter;
- ct->clear_sets();
-}
-
-void CanvasTextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
- CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
- ERR_FAIL_NULL(ct);
- ct->texture_repeat = p_repeat;
- ct->clear_sets();
-}
-
-bool CanvasTextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
- RendererStorageRD *storage = RendererStorageRD::base_singleton;
-
- CanvasTexture *ct = nullptr;
- TextureStorage *texture_storage = TextureStorage::get_singleton();
- Texture *t = texture_storage->get_texture(p_texture);
-
- // TODO once we have our texture storage split off we'll look into moving this code into canvas_texture
-
- if (t) {
- //regular texture
- if (!t->canvas_texture) {
- t->canvas_texture = memnew(CanvasTexture);
- t->canvas_texture->diffuse = p_texture;
- }
-
- ct = t->canvas_texture;
- } else {
- ct = get_canvas_texture(p_texture);
- }
-
- if (!ct) {
- return false; //invalid texture RID
- }
-
- RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
- ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
-
- RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
- ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
-
- RID uniform_set = ct->uniform_sets[filter][repeat];
- if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- //create and update
- Vector<RD::Uniform> uniforms;
- { //diffuse
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 0;
-
- t = texture_storage->get_texture(ct->diffuse);
- if (!t) {
- u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
- ct->size_cache = Size2i(1, 1);
- } else {
- u.append_id(t->rd_texture);
- ct->size_cache = Size2i(t->width_2d, t->height_2d);
- }
- uniforms.push_back(u);
- }
- { //normal
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
-
- t = texture_storage->get_texture(ct->normal_map);
- if (!t) {
- u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
- ct->use_normal_cache = false;
- } else {
- u.append_id(t->rd_texture);
- ct->use_normal_cache = true;
- }
- uniforms.push_back(u);
- }
- { //specular
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
-
- t = texture_storage->get_texture(ct->specular);
- if (!t) {
- u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
- ct->use_specular_cache = false;
- } else {
- u.append_id(t->rd_texture);
- ct->use_specular_cache = true;
- }
- uniforms.push_back(u);
- }
- { //sampler
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 3;
- u.append_id(storage->sampler_rd_get_default(filter, repeat));
- uniforms.push_back(u);
- }
-
- uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
- ct->uniform_sets[filter][repeat] = uniform_set;
- ct->cleared_cache = false;
- }
-
- r_uniform_set = uniform_set;
- r_size = ct->size_cache;
- r_specular_shininess = ct->specular_color;
- r_use_normal = ct->use_normal_cache;
- r_use_specular = ct->use_specular_cache;
-
- return true;
-}
diff --git a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h b/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h
deleted file mode 100644
index 6d3868edd5..0000000000
--- a/servers/rendering/renderer_rd/storage_rd/canvas_texture_storage.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*************************************************************************/
-/* canvas_texture_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 CANVAS_TEXTURE_STORAGE_RD_H
-#define CANVAS_TEXTURE_STORAGE_RD_H
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-
-namespace RendererRD {
-
-class CanvasTexture {
-public:
- RID diffuse;
- RID normal_map;
- RID specular;
- Color specular_color = Color(1, 1, 1, 1);
- float shininess = 1.0;
-
- RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
- RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
- RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
-
- Size2i size_cache = Size2i(1, 1);
- bool use_normal_cache = false;
- bool use_specular_cache = false;
- bool cleared_cache = true;
-
- void clear_sets();
- ~CanvasTexture();
-};
-
-class CanvasTextureStorage : public RendererCanvasTextureStorage {
-private:
- static CanvasTextureStorage *singleton;
-
- RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner;
-
-public:
- static CanvasTextureStorage *get_singleton();
-
- CanvasTextureStorage();
- virtual ~CanvasTextureStorage();
-
- CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
- bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
-
- virtual RID canvas_texture_allocate() override;
- virtual void canvas_texture_initialize(RID p_rid) override;
- virtual void canvas_texture_free(RID p_rid) override;
-
- virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
- virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
-
- virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
- virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
-
- bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
-};
-
-} // namespace RendererRD
-
-#endif // !CANVAS_TEXTURE_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp b/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp
deleted file mode 100644
index 73acc0fdd6..0000000000
--- a/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.cpp
+++ /dev/null
@@ -1,437 +0,0 @@
-/*************************************************************************/
-/* decal_atlas_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 "decal_atlas_storage.h"
-#include "texture_storage.h"
-
-// Should be able to remove this once we move effects into their own file and include the correct effects
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-
-using namespace RendererRD;
-
-DecalAtlasStorage *DecalAtlasStorage::singleton = nullptr;
-
-DecalAtlasStorage *DecalAtlasStorage::get_singleton() {
- return singleton;
-}
-
-DecalAtlasStorage::DecalAtlasStorage() {
- singleton = this;
-
- { // default atlas texture
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = 4;
- tformat.height = 4;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
-
- Vector<uint8_t> pv;
- pv.resize(16 * 4);
-
- for (int i = 0; i < 16; i++) {
- pv.set(i * 4 + 0, 0);
- pv.set(i * 4 + 1, 0);
- pv.set(i * 4 + 2, 0);
- pv.set(i * 4 + 3, 255);
- }
-
- {
- //take the chance and initialize decal atlas to something
- Vector<Vector<uint8_t>> vpv;
- vpv.push_back(pv);
- decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
- decal_atlas.texture_srgb = decal_atlas.texture;
- }
- }
-}
-
-DecalAtlasStorage::~DecalAtlasStorage() {
- if (decal_atlas.textures.size()) {
- ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
- }
-
- if (decal_atlas.texture.is_valid()) {
- RD::get_singleton()->free(decal_atlas.texture);
- }
-
- singleton = nullptr;
-}
-
-RID DecalAtlasStorage::decal_atlas_get_texture() const {
- return decal_atlas.texture;
-}
-
-RID DecalAtlasStorage::decal_atlas_get_texture_srgb() const {
- return decal_atlas.texture_srgb;
-}
-
-RID DecalAtlasStorage::decal_allocate() {
- return decal_owner.allocate_rid();
-}
-
-void DecalAtlasStorage::decal_initialize(RID p_decal) {
- decal_owner.initialize_rid(p_decal, Decal());
-}
-
-void DecalAtlasStorage::decal_free(RID p_rid) {
- Decal *decal = decal_owner.get_or_null(p_rid);
- for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
- if (decal->textures[i].is_valid() && TextureStorage::get_singleton()->owns_texture(decal->textures[i])) {
- texture_remove_from_decal_atlas(decal->textures[i]);
- }
- }
- decal->dependency.deleted_notify(p_rid);
- decal_owner.free(p_rid);
-}
-
-void DecalAtlasStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->extents = p_extents;
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
-}
-
-void DecalAtlasStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
-
- if (decal->textures[p_type] == p_texture) {
- return;
- }
-
- ERR_FAIL_COND(p_texture.is_valid() && !TextureStorage::get_singleton()->owns_texture(p_texture));
-
- if (decal->textures[p_type].is_valid() && TextureStorage::get_singleton()->owns_texture(decal->textures[p_type])) {
- texture_remove_from_decal_atlas(decal->textures[p_type]);
- }
-
- decal->textures[p_type] = p_texture;
-
- if (decal->textures[p_type].is_valid()) {
- texture_add_to_decal_atlas(decal->textures[p_type]);
- }
-
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL);
-}
-
-void DecalAtlasStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->emission_energy = p_energy;
-}
-
-void DecalAtlasStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->albedo_mix = p_mix;
-}
-
-void DecalAtlasStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->modulate = p_modulate;
-}
-
-void DecalAtlasStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->cull_mask = p_layers;
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
-}
-
-void DecalAtlasStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->distance_fade = p_enabled;
- decal->distance_fade_begin = p_begin;
- decal->distance_fade_length = p_length;
-}
-
-void DecalAtlasStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->upper_fade = p_above;
- decal->lower_fade = p_below;
-}
-
-void DecalAtlasStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!decal);
- decal->normal_fade = p_fade;
-}
-
-void DecalAtlasStorage::decal_atlas_mark_dirty_on_texture(RID p_texture) {
- if (decal_atlas.textures.has(p_texture)) {
- //belongs to decal atlas..
-
- decal_atlas.dirty = true; //mark it dirty since it was most likely modified
- }
-}
-
-void DecalAtlasStorage::decal_atlas_remove_texture(RID p_texture) {
- if (decal_atlas.textures.has(p_texture)) {
- decal_atlas.textures.erase(p_texture);
- //there is not much a point of making it dirty, just let it be.
- }
-}
-
-AABB DecalAtlasStorage::decal_get_aabb(RID p_decal) const {
- Decal *decal = decal_owner.get_or_null(p_decal);
- ERR_FAIL_COND_V(!decal, AABB());
-
- return AABB(-decal->extents, decal->extents * 2.0);
-}
-
-void DecalAtlasStorage::update_decal_atlas() {
- EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
-
- if (!decal_atlas.dirty) {
- return; //nothing to do
- }
-
- decal_atlas.dirty = false;
-
- if (decal_atlas.texture.is_valid()) {
- RD::get_singleton()->free(decal_atlas.texture);
- decal_atlas.texture = RID();
- decal_atlas.texture_srgb = RID();
- decal_atlas.texture_mipmaps.clear();
- }
-
- int border = 1 << decal_atlas.mipmaps;
-
- if (decal_atlas.textures.size()) {
- //generate atlas
- Vector<DecalAtlas::SortItem> itemsv;
- itemsv.resize(decal_atlas.textures.size());
- int base_size = 8;
- const RID *K = nullptr;
-
- int idx = 0;
- while ((K = decal_atlas.textures.next(K))) {
- DecalAtlas::SortItem &si = itemsv.write[idx];
-
- Texture *src_tex = TextureStorage::get_singleton()->get_texture(*K);
-
- si.size.width = (src_tex->width / border) + 1;
- si.size.height = (src_tex->height / border) + 1;
- si.pixel_size = Size2i(src_tex->width, src_tex->height);
-
- if (base_size < si.size.width) {
- base_size = nearest_power_of_2_templated(si.size.width);
- }
-
- si.texture = *K;
- idx++;
- }
-
- //sort items by size
- itemsv.sort();
-
- //attempt to create atlas
- int item_count = itemsv.size();
- DecalAtlas::SortItem *items = itemsv.ptrw();
-
- int atlas_height = 0;
-
- while (true) {
- Vector<int> v_offsetsv;
- v_offsetsv.resize(base_size);
-
- int *v_offsets = v_offsetsv.ptrw();
- memset(v_offsets, 0, sizeof(int) * base_size);
-
- int max_height = 0;
-
- for (int i = 0; i < item_count; i++) {
- //best fit
- DecalAtlas::SortItem &si = items[i];
- int best_idx = -1;
- int best_height = 0x7FFFFFFF;
- for (int j = 0; j <= base_size - si.size.width; j++) {
- int height = 0;
- for (int k = 0; k < si.size.width; k++) {
- int h = v_offsets[k + j];
- if (h > height) {
- height = h;
- if (height > best_height) {
- break; //already bad
- }
- }
- }
-
- if (height < best_height) {
- best_height = height;
- best_idx = j;
- }
- }
-
- //update
- for (int k = 0; k < si.size.width; k++) {
- v_offsets[k + best_idx] = best_height + si.size.height;
- }
-
- si.pos.x = best_idx;
- si.pos.y = best_height;
-
- if (si.pos.y + si.size.height > max_height) {
- max_height = si.pos.y + si.size.height;
- }
- }
-
- if (max_height <= base_size * 2) {
- atlas_height = max_height;
- break; //good ratio, break;
- }
-
- base_size *= 2;
- }
-
- decal_atlas.size.width = base_size * border;
- decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
-
- for (int i = 0; i < item_count; i++) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
- t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
- t->uv_rect.size = items[i].pixel_size;
-
- t->uv_rect.position /= Size2(decal_atlas.size);
- t->uv_rect.size /= Size2(decal_atlas.size);
- }
- } else {
- //use border as size, so it at least has enough mipmaps
- decal_atlas.size.width = border;
- decal_atlas.size.height = border;
- }
-
- //blit textures
-
- RD::TextureFormat tformat;
- tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tformat.width = decal_atlas.size.width;
- tformat.height = decal_atlas.size.height;
- tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- tformat.texture_type = RD::TEXTURE_TYPE_2D;
- tformat.mipmaps = decal_atlas.mipmaps;
- tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
- tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
-
- decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
- RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1);
-
- {
- //create the framebuffer
-
- Size2i s = decal_atlas.size;
-
- for (int i = 0; i < decal_atlas.mipmaps; i++) {
- DecalAtlas::MipMap mm;
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
- Vector<RID> fb;
- fb.push_back(mm.texture);
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
- mm.size = s;
- decal_atlas.texture_mipmaps.push_back(mm);
-
- s.width = MAX(1, s.width >> 1);
- s.height = MAX(1, s.height >> 1);
- }
- {
- //create the SRGB variant
- RD::TextureView rd_view;
- rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
- decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
- }
- }
-
- RID prev_texture;
- for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
- const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
-
- Color clear_color(0, 0, 0, 0);
-
- if (decal_atlas.textures.size()) {
- if (i == 0) {
- Vector<Color> cc;
- cc.push_back(clear_color);
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
-
- const RID *K = nullptr;
- while ((K = decal_atlas.textures.next(K))) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
- Texture *src_tex = TextureStorage::get_singleton()->get_texture(*K);
- effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
- }
-
- RD::get_singleton()->draw_list_end();
-
- prev_texture = mm.texture;
- } else {
- effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
- prev_texture = mm.texture;
- }
- } else {
- RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1);
- }
- }
-}
-
-void DecalAtlasStorage::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
- if (!decal_atlas.textures.has(p_texture)) {
- DecalAtlas::Texture t;
- t.users = 1;
- t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0;
- decal_atlas.textures[p_texture] = t;
- decal_atlas.dirty = true;
- } else {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
- t->users++;
- if (p_panorama_to_dp) {
- t->panorama_to_dp_users++;
- }
- }
-}
-
-void DecalAtlasStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
- ERR_FAIL_COND(!t);
- t->users--;
- if (p_panorama_to_dp) {
- ERR_FAIL_COND(t->panorama_to_dp_users == 0);
- t->panorama_to_dp_users--;
- }
- if (t->users == 0) {
- decal_atlas.textures.erase(p_texture);
- //do not mark it dirty, there is no need to since it remains working
- }
-}
diff --git a/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h b/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h
deleted file mode 100644
index a217a0f8b6..0000000000
--- a/servers/rendering/renderer_rd/storage_rd/decal_atlas_storage.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/*************************************************************************/
-/* decal_atlas_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 DECAL_ATLAS_STORAGE_RD_H
-#define DECAL_ATLAS_STORAGE_RD_H
-
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/renderer_storage.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
-
-namespace RendererRD {
-
-struct DecalAtlas {
- struct Texture {
- int panorama_to_dp_users;
- int users;
- Rect2 uv_rect;
- };
-
- struct SortItem {
- RID texture;
- Size2i pixel_size;
- Size2i size;
- Point2i pos;
-
- bool operator<(const SortItem &p_item) const {
- //sort larger to smaller
- if (size.height == p_item.size.height) {
- return size.width > p_item.size.width;
- } else {
- return size.height > p_item.size.height;
- }
- }
- };
-
- HashMap<RID, Texture> textures;
- bool dirty = true;
- int mipmaps = 5;
-
- RID texture;
- RID texture_srgb;
- struct MipMap {
- RID fb;
- RID texture;
- Size2i size;
- };
- Vector<MipMap> texture_mipmaps;
-
- Size2i size;
-};
-
-struct Decal {
- Vector3 extents = Vector3(1, 1, 1);
- RID textures[RS::DECAL_TEXTURE_MAX];
- float emission_energy = 1.0;
- float albedo_mix = 1.0;
- Color modulate = Color(1, 1, 1, 1);
- uint32_t cull_mask = (1 << 20) - 1;
- float upper_fade = 0.3;
- float lower_fade = 0.3;
- bool distance_fade = false;
- float distance_fade_begin = 10;
- float distance_fade_length = 1;
- float normal_fade = 0.0;
-
- RendererStorage::Dependency dependency;
-};
-
-class DecalAtlasStorage : public RendererDecalAtlasStorage {
-private:
- static DecalAtlasStorage *singleton;
-
- DecalAtlas decal_atlas;
-
- mutable RID_Owner<Decal, true> decal_owner;
-
-public:
- static DecalAtlasStorage *get_singleton();
-
- void update_decal_atlas();
-
- DecalAtlasStorage();
- virtual ~DecalAtlasStorage();
-
- Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); };
- bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); };
-
- RID decal_atlas_get_texture() const;
- RID decal_atlas_get_texture_srgb() const;
- _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
- DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
- if (!t) {
- return Rect2();
- }
-
- return t->uv_rect;
- }
-
- virtual RID decal_allocate() override;
- virtual void decal_initialize(RID p_decal) override;
- virtual void decal_free(RID p_rid) override;
-
- virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
- virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
- virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
- virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
- virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
- virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
- virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
- virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
- virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
-
- void decal_atlas_mark_dirty_on_texture(RID p_texture);
- void decal_atlas_remove_texture(RID p_texture);
-
- virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
- virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
-
- _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->extents;
- }
-
- _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->textures[p_texture];
- }
-
- _FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->modulate;
- }
-
- _FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->emission_energy;
- }
-
- _FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->albedo_mix;
- }
-
- _FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->cull_mask;
- }
-
- _FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->upper_fade;
- }
-
- _FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->lower_fade;
- }
-
- _FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->normal_fade;
- }
-
- _FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->distance_fade;
- }
-
- _FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->distance_fade_begin;
- }
-
- _FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
- const Decal *decal = decal_owner.get_or_null(p_decal);
- return decal->distance_fade_length;
- }
-
- virtual AABB decal_get_aabb(RID p_decal) const override;
-};
-
-} // namespace RendererRD
-
-#endif // !DECAL_ATLAS_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
new file mode 100644
index 0000000000..56a4525b8e
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -0,0 +1,788 @@
+/*************************************************************************/
+/* light_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 "light_storage.h"
+#include "core/config/project_settings.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+LightStorage *LightStorage::singleton = nullptr;
+
+LightStorage *LightStorage::get_singleton() {
+ return singleton;
+}
+
+LightStorage::LightStorage() {
+ singleton = this;
+
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+
+ 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);
+
+ if (textures_per_stage <= 256) {
+ lightmap_textures.resize(32);
+ } else {
+ lightmap_textures.resize(1024);
+ }
+
+ for (int i = 0; i < lightmap_textures.size(); i++) {
+ lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ }
+ }
+
+ lightmap_probe_capture_update_speed = GLOBAL_GET("rendering/lightmapping/probe_capture/update_speed");
+}
+
+LightStorage::~LightStorage() {
+ singleton = nullptr;
+}
+
+/* LIGHT */
+
+void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
+ Light light;
+ light.type = p_type;
+
+ light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;
+ light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+ light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
+ light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
+ light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
+ light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;
+ light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45;
+ light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;
+ light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;
+ light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;
+ light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;
+ light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
+ light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+ light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
+ light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
+ light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
+ light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
+
+ light_owner.initialize_rid(p_light, light);
+}
+
+RID LightStorage::directional_light_allocate() {
+ return light_owner.allocate_rid();
+}
+
+void LightStorage::directional_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_DIRECTIONAL);
+}
+
+RID LightStorage::omni_light_allocate() {
+ return light_owner.allocate_rid();
+}
+
+void LightStorage::omni_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_OMNI);
+}
+
+RID LightStorage::spot_light_allocate() {
+ return light_owner.allocate_rid();
+}
+
+void LightStorage::spot_light_initialize(RID p_light) {
+ _light_initialize(p_light, RS::LIGHT_SPOT);
+}
+
+void LightStorage::light_free(RID p_rid) {
+ light_set_projector(p_rid, RID()); //clear projector
+
+ // delete the texture
+ Light *light = light_owner.get_or_null(p_rid);
+ light->dependency.deleted_notify(p_rid);
+ light_owner.free(p_rid);
+}
+
+void LightStorage::light_set_color(RID p_light, const Color &p_color) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->color = p_color;
+}
+
+void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_value) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+ ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
+
+ if (light->param[p_param] == p_value) {
+ return;
+ }
+
+ switch (p_param) {
+ case RS::LIGHT_PARAM_RANGE:
+ case RS::LIGHT_PARAM_SPOT_ANGLE:
+ case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
+ case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
+ case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
+ case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
+ case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
+ case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
+ case RS::LIGHT_PARAM_SHADOW_BIAS: {
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ } break;
+ case RS::LIGHT_PARAM_SIZE: {
+ if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
+ //changing from no size to size and the opposite
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ }
+ } break;
+ default: {
+ }
+ }
+
+ light->param[p_param] = p_value;
+}
+
+void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+ light->shadow = p_enabled;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_projector(RID p_light, RID p_texture) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ if (light->projector == p_texture) {
+ return;
+ }
+
+ if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
+ texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ }
+
+ light->projector = p_texture;
+
+ if (light->type != RS::LIGHT_DIRECTIONAL) {
+ if (light->projector.is_valid()) {
+ texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
+ }
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ }
+}
+
+void LightStorage::light_set_negative(RID p_light, bool p_enable) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->negative = p_enable;
+}
+
+void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->cull_mask = p_mask;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->distance_fade = p_enabled;
+ light->distance_fade_begin = p_begin;
+ light->distance_fade_shadow = p_shadow;
+ light->distance_fade_length = p_length;
+}
+
+void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->reverse_cull = p_enabled;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->bake_mode = p_bake_mode;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->max_sdfgi_cascade = p_cascade;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->omni_shadow_mode = p_mode;
+
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE);
+
+ return light->omni_shadow_mode;
+}
+
+void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_shadow_mode = p_mode;
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_blend_splits = p_enable;
+ light->version++;
+ light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+}
+
+bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, false);
+
+ return light->directional_blend_splits;
+}
+
+void LightStorage::light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND(!light);
+
+ light->directional_sky_mode = p_mode;
+}
+
+RS::LightDirectionalSkyMode LightStorage::light_directional_get_sky_mode(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY);
+
+ return light->directional_sky_mode;
+}
+
+RS::LightDirectionalShadowMode LightStorage::light_directional_get_shadow_mode(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
+
+ return light->directional_shadow_mode;
+}
+
+uint32_t LightStorage::light_get_max_sdfgi_cascade(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->max_sdfgi_cascade;
+}
+
+RS::LightBakeMode LightStorage::light_get_bake_mode(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED);
+
+ return light->bake_mode;
+}
+
+uint64_t LightStorage::light_get_version(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->version;
+}
+
+AABB LightStorage::light_get_aabb(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, AABB());
+
+ switch (light->type) {
+ case RS::LIGHT_SPOT: {
+ float len = light->param[RS::LIGHT_PARAM_RANGE];
+ float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
+ return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
+ };
+ case RS::LIGHT_OMNI: {
+ float r = light->param[RS::LIGHT_PARAM_RANGE];
+ return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2);
+ };
+ case RS::LIGHT_DIRECTIONAL: {
+ return AABB();
+ };
+ }
+
+ ERR_FAIL_V(AABB());
+}
+
+/* REFLECTION PROBE */
+
+RID LightStorage::reflection_probe_allocate() {
+ return reflection_probe_owner.allocate_rid();
+}
+
+void LightStorage::reflection_probe_initialize(RID p_reflection_probe) {
+ reflection_probe_owner.initialize_rid(p_reflection_probe, ReflectionProbe());
+}
+
+void LightStorage::reflection_probe_free(RID p_rid) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
+ reflection_probe->dependency.deleted_notify(p_rid);
+ reflection_probe_owner.free(p_rid);
+};
+
+void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->update_mode = p_mode;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->intensity = p_intensity;
+}
+
+void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->ambient_mode = p_mode;
+}
+
+void LightStorage::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->ambient_color = p_color;
+}
+
+void LightStorage::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->ambient_color_energy = p_energy;
+}
+
+void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distance) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->max_distance = p_distance;
+
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ if (reflection_probe->extents == p_extents) {
+ return;
+ }
+ reflection_probe->extents = p_extents;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->origin_offset = p_offset;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->interior = p_enable;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->box_projection = p_enable;
+}
+
+void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->enable_shadows = p_enable;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->cull_mask = p_layers;
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+ ERR_FAIL_COND(p_resolution < 32);
+
+ reflection_probe->resolution = p_resolution;
+}
+
+void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->mesh_lod_threshold = p_ratio;
+
+ reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, AABB());
+
+ AABB aabb;
+ aabb.position = -reflection_probe->extents;
+ aabb.size = reflection_probe->extents * 2.0;
+
+ return aabb;
+}
+
+RS::ReflectionProbeUpdateMode LightStorage::reflection_probe_get_update_mode(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS);
+
+ return reflection_probe->update_mode;
+}
+
+uint32_t LightStorage::reflection_probe_get_cull_mask(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->cull_mask;
+}
+
+Vector3 LightStorage::reflection_probe_get_extents(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->extents;
+}
+
+Vector3 LightStorage::reflection_probe_get_origin_offset(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Vector3());
+
+ return reflection_probe->origin_offset;
+}
+
+bool LightStorage::reflection_probe_renders_shadows(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->enable_shadows;
+}
+
+float LightStorage::reflection_probe_get_origin_max_distance(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->max_distance;
+}
+
+float LightStorage::reflection_probe_get_mesh_lod_threshold(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->mesh_lod_threshold;
+}
+
+int LightStorage::reflection_probe_get_resolution(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->resolution;
+}
+
+float LightStorage::reflection_probe_get_intensity(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->intensity;
+}
+
+bool LightStorage::reflection_probe_is_interior(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->interior;
+}
+
+bool LightStorage::reflection_probe_is_box_projection(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, false);
+
+ return reflection_probe->box_projection;
+}
+
+RS::ReflectionProbeAmbientMode LightStorage::reflection_probe_get_ambient_mode(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED);
+ return reflection_probe->ambient_mode;
+}
+
+Color LightStorage::reflection_probe_get_ambient_color(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, Color());
+
+ return reflection_probe->ambient_color;
+}
+float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 0);
+
+ return reflection_probe->ambient_color_energy;
+}
+
+/* LIGHTMAP API */
+
+RID LightStorage::lightmap_allocate() {
+ return lightmap_owner.allocate_rid();
+}
+
+void LightStorage::lightmap_initialize(RID p_lightmap) {
+ lightmap_owner.initialize_rid(p_lightmap, Lightmap());
+}
+
+void LightStorage::lightmap_free(RID p_rid) {
+ lightmap_set_textures(p_rid, RID(), false);
+ Lightmap *lightmap = lightmap_owner.get_or_null(p_rid);
+ lightmap->dependency.deleted_notify(p_rid);
+ lightmap_owner.free(p_rid);
+}
+
+void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ lightmap_array_version++;
+
+ //erase lightmap users
+ if (lm->light_texture.is_valid()) {
+ RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture);
+ if (t) {
+ t->lightmap_users.erase(p_lightmap);
+ }
+ }
+
+ RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light);
+ lm->light_texture = p_light;
+ lm->uses_spherical_harmonics = p_uses_spherical_haromics;
+
+ RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ if (!t) {
+ if (using_lightmap_array) {
+ if (lm->array_index >= 0) {
+ lightmap_textures.write[lm->array_index] = default_2d_array;
+ lm->array_index = -1;
+ }
+ }
+
+ return;
+ }
+
+ t->lightmap_users.insert(p_lightmap);
+
+ if (using_lightmap_array) {
+ if (lm->array_index < 0) {
+ //not in array, try to put in array
+ for (int i = 0; i < lightmap_textures.size(); i++) {
+ if (lightmap_textures[i] == default_2d_array) {
+ lm->array_index = i;
+ break;
+ }
+ }
+ }
+ ERR_FAIL_COND_MSG(lm->array_index < 0, "Maximum amount of lightmaps in use (" + itos(lightmap_textures.size()) + ") has been exceeded, lightmap will nod display properly.");
+
+ lightmap_textures.write[lm->array_index] = t->rd_texture;
+ }
+}
+
+void LightStorage::lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+ lm->bounds = p_bounds;
+}
+
+void LightStorage::lightmap_set_probe_interior(RID p_lightmap, bool p_interior) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+ lm->interior = p_interior;
+}
+
+void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ if (p_points.size()) {
+ ERR_FAIL_COND(p_points.size() * 9 != p_point_sh.size());
+ ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
+ ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
+ }
+
+ lm->points = p_points;
+ lm->bsp_tree = p_bsp_tree;
+ lm->point_sh = p_point_sh;
+ lm->tetrahedra = p_tetrahedra;
+}
+
+PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedVector3Array());
+
+ return lm->points;
+}
+
+PackedColorArray LightStorage::lightmap_get_probe_capture_sh(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedColorArray());
+ return lm->point_sh;
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedInt32Array());
+ return lm->tetrahedra;
+}
+
+PackedInt32Array LightStorage::lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, PackedInt32Array());
+ return lm->bsp_tree;
+}
+
+void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {
+ lightmap_probe_capture_update_speed = p_speed;
+}
+
+void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ for (int i = 0; i < 9; i++) {
+ r_sh[i] = Color(0, 0, 0, 0);
+ }
+
+ if (!lm->points.size() || !lm->bsp_tree.size() || !lm->tetrahedra.size()) {
+ return;
+ }
+
+ static_assert(sizeof(Lightmap::BSP) == 24);
+
+ const Lightmap::BSP *bsp = (const Lightmap::BSP *)lm->bsp_tree.ptr();
+ int32_t node = 0;
+ while (node >= 0) {
+ if (Plane(bsp[node].plane[0], bsp[node].plane[1], bsp[node].plane[2], bsp[node].plane[3]).is_point_over(p_point)) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(bsp[node].over >= 0 && bsp[node].over < node);
+#endif
+
+ node = bsp[node].over;
+ } else {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND(bsp[node].under >= 0 && bsp[node].under < node);
+#endif
+ node = bsp[node].under;
+ }
+ }
+
+ if (node == Lightmap::BSP::EMPTY_LEAF) {
+ return; //nothing could be done
+ }
+
+ node = ABS(node) - 1;
+
+ uint32_t *tetrahedron = (uint32_t *)&lm->tetrahedra[node * 4];
+ Vector3 points[4] = { lm->points[tetrahedron[0]], lm->points[tetrahedron[1]], lm->points[tetrahedron[2]], lm->points[tetrahedron[3]] };
+ const Color *sh_colors[4]{ &lm->point_sh[tetrahedron[0] * 9], &lm->point_sh[tetrahedron[1] * 9], &lm->point_sh[tetrahedron[2] * 9], &lm->point_sh[tetrahedron[3] * 9] };
+ Color barycentric = Geometry3D::tetrahedron_get_barycentric_coords(points[0], points[1], points[2], points[3], p_point);
+
+ for (int i = 0; i < 4; i++) {
+ float c = CLAMP(barycentric[i], 0.0, 1.0);
+ for (int j = 0; j < 9; j++) {
+ r_sh[j] += sh_colors[i][j] * c;
+ }
+ }
+}
+
+bool LightStorage::lightmap_is_interior(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, false);
+ return lm->interior;
+}
+
+AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, AABB());
+ return lm->bounds;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
new file mode 100644
index 0000000000..3cc455692d
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -0,0 +1,370 @@
+/*************************************************************************/
+/* light_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 LIGHT_STORAGE_RD_H
+#define LIGHT_STORAGE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "core/templates/self_list.h"
+#include "servers/rendering/storage/light_storage.h"
+
+namespace RendererRD {
+
+/* LIGHT */
+
+struct Light {
+ RS::LightType type;
+ float param[RS::LIGHT_PARAM_MAX];
+ Color color = Color(1, 1, 1, 1);
+ RID projector;
+ bool shadow = false;
+ bool negative = false;
+ bool reverse_cull = false;
+ RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
+ uint32_t max_sdfgi_cascade = 2;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ bool distance_fade = false;
+ real_t distance_fade_begin = 40.0;
+ real_t distance_fade_shadow = 50.0;
+ real_t distance_fade_length = 10.0;
+ RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+ RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+ bool directional_blend_splits = false;
+ RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
+ uint64_t version = 0;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* REFLECTION PROBE */
+
+struct ReflectionProbe {
+ RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
+ int resolution = 256;
+ float intensity = 1.0;
+ RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
+ Color ambient_color;
+ float ambient_color_energy = 1.0;
+ float max_distance = 0;
+ Vector3 extents = Vector3(1, 1, 1);
+ Vector3 origin_offset;
+ bool interior = false;
+ bool box_projection = false;
+ bool enable_shadows = false;
+ uint32_t cull_mask = (1 << 20) - 1;
+ float mesh_lod_threshold = 0.01;
+
+ RendererStorage::Dependency dependency;
+};
+
+/* LIGHTMAP */
+
+struct Lightmap {
+ RID light_texture;
+ bool uses_spherical_harmonics = false;
+ bool interior = false;
+ AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+ int32_t array_index = -1; //unassigned
+ PackedVector3Array points;
+ PackedColorArray point_sh;
+ PackedInt32Array tetrahedra;
+ PackedInt32Array bsp_tree;
+
+ struct BSP {
+ static const int32_t EMPTY_LEAF = INT32_MIN;
+ float plane[4];
+ int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+ };
+
+ RendererStorage::Dependency dependency;
+};
+
+class LightStorage : public RendererLightStorage {
+private:
+ static LightStorage *singleton;
+
+ /* LIGHT */
+ mutable RID_Owner<Light, true> light_owner;
+
+ /* REFLECTION PROBE */
+ mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
+
+ /* LIGHTMAP */
+
+ bool using_lightmap_array;
+ Vector<RID> lightmap_textures;
+ uint64_t lightmap_array_version = 0;
+ float lightmap_probe_capture_update_speed = 4;
+
+ mutable RID_Owner<Lightmap, true> lightmap_owner;
+
+public:
+ static LightStorage *get_singleton();
+
+ LightStorage();
+ virtual ~LightStorage();
+
+ /* LIGHT */
+
+ Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); };
+ bool owns_light(RID p_rid) { return light_owner.owns(p_rid); };
+
+ void _light_initialize(RID p_rid, RS::LightType p_type);
+
+ virtual RID directional_light_allocate() override;
+ virtual void directional_light_initialize(RID p_light) override;
+
+ virtual RID omni_light_allocate() override;
+ virtual void omni_light_initialize(RID p_light) override;
+
+ virtual RID spot_light_allocate() override;
+ virtual void spot_light_initialize(RID p_light) override;
+
+ virtual void light_free(RID p_rid) override;
+
+ virtual void light_set_color(RID p_light, const Color &p_color) override;
+ virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) override;
+ virtual void light_set_shadow(RID p_light, bool p_enabled) override;
+ virtual void light_set_projector(RID p_light, RID p_texture) override;
+ virtual void light_set_negative(RID p_light, bool p_enable) override;
+ virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
+ virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
+ virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
+ virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
+ virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override;
+
+ virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) override;
+
+ virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) override;
+ virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) override;
+ virtual bool light_directional_get_blend_splits(RID p_light) const override;
+ virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) override;
+ virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const override;
+
+ virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) override;
+ virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override;
+
+ virtual RS::LightType light_get_type(RID p_light) const override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light->type;
+ }
+ virtual AABB light_get_aabb(RID p_light) const override;
+
+ virtual float light_get_param(RID p_light, RS::LightParam p_param) override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->param[p_param];
+ }
+
+ _FORCE_INLINE_ RID light_get_projector(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RID());
+
+ return light->projector;
+ }
+
+ virtual Color light_get_color(RID p_light) override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, Color());
+
+ return light->color;
+ }
+
+ _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0);
+
+ return light->cull_mask;
+ }
+
+ _FORCE_INLINE_ bool light_is_distance_fade_enabled(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade;
+ }
+
+ _FORCE_INLINE_ float light_get_distance_fade_begin(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade_begin;
+ }
+
+ _FORCE_INLINE_ float light_get_distance_fade_shadow(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade_shadow;
+ }
+
+ _FORCE_INLINE_ float light_get_distance_fade_length(RID p_light) {
+ const Light *light = light_owner.get_or_null(p_light);
+ return light->distance_fade_length;
+ }
+
+ virtual bool light_has_shadow(RID p_light) const override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light->shadow;
+ }
+
+ virtual bool light_has_projector(RID p_light) const override {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light_owner.owns(light->projector);
+ }
+
+ _FORCE_INLINE_ bool light_is_negative(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
+
+ return light->negative;
+ }
+
+ _FORCE_INLINE_ float light_get_transmittance_bias(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0.0);
+
+ return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
+ }
+
+ _FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
+ const Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_COND_V(!light, 0.0);
+
+ return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
+ }
+
+ virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override;
+ virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
+ virtual uint64_t light_get_version(RID p_light) const override;
+
+ /* REFLECTION PROBE */
+
+ ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); };
+ bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
+
+ virtual RID reflection_probe_allocate() override;
+ virtual void reflection_probe_initialize(RID p_reflection_probe) override;
+ virtual void reflection_probe_free(RID p_rid) override;
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
+ virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
+ virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
+ virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) override;
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) override;
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) override;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) override;
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) override;
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
+ virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const override;
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const override;
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override;
+ virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
+
+ int reflection_probe_get_resolution(RID p_probe) const;
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
+
+ float reflection_probe_get_intensity(RID p_probe) const;
+ bool reflection_probe_is_interior(RID p_probe) const;
+ bool reflection_probe_is_box_projection(RID p_probe) const;
+ RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const;
+ Color reflection_probe_get_ambient_color(RID p_probe) const;
+ float reflection_probe_get_ambient_color_energy(RID p_probe) const;
+
+ /* LIGHTMAP */
+
+ Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
+ bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
+
+ virtual RID lightmap_allocate() override;
+ virtual void lightmap_initialize(RID p_lightmap) override;
+ virtual void lightmap_free(RID p_rid) override;
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) override;
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
+ virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const override;
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const override;
+ virtual bool lightmap_is_interior(RID p_lightmap) const override;
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
+
+ virtual float lightmap_get_probe_capture_update_speed() const override {
+ return lightmap_probe_capture_update_speed;
+ }
+ _FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, RID());
+ return lm->light_texture;
+ }
+ _FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
+ ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ return lm->array_index;
+ }
+ _FORCE_INLINE_ bool lightmap_uses_spherical_harmonics(RID p_lightmap) const {
+ ERR_FAIL_COND_V(!using_lightmap_array, false); //only for arrays
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ return lm->uses_spherical_harmonics;
+ }
+ _FORCE_INLINE_ uint64_t lightmap_array_get_version() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+ return lightmap_array_version;
+ }
+
+ _FORCE_INLINE_ int lightmap_array_get_size() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, 0); //only for arrays
+ return lightmap_textures.size();
+ }
+
+ _FORCE_INLINE_ const Vector<RID> &lightmap_array_get_textures() const {
+ ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
+ return lightmap_textures;
+ }
+};
+
+} // namespace RendererRD
+
+#endif // !LIGHT_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 9e3d124bbb..75c502c666 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -422,7 +422,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
if (i < s) {
Color color = a[i];
if (p_linear_color) {
- color = color.to_linear();
+ color = color.srgb_to_linear();
}
gui[j] = color.r;
gui[j + 1] = color.g;
@@ -459,7 +459,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
Color v = value;
if (p_linear_color) {
- v = v.to_linear();
+ v = v.srgb_to_linear();
}
gui[0] = v.r;
@@ -1298,6 +1298,94 @@ MaterialStorage *MaterialStorage::get_singleton() {
MaterialStorage::MaterialStorage() {
singleton = this;
+ //default samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::SamplerState sampler_state;
+ switch (i) {
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+ } break;
+ default: {
+ }
+ }
+ switch (j) {
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ } break;
+ default: {
+ }
+ }
+
+ default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+ }
+ }
+
+ //custom sampler
+ sampler_rd_configure_custom(0.0f);
+
for (int i = 0; i < SHADER_TYPE_MAX; i++) {
shader_data_request_func[i] = nullptr;
}
@@ -1319,9 +1407,121 @@ MaterialStorage::~MaterialStorage() {
memdelete_arr(global_variables.buffer_dirty_regions);
RD::get_singleton()->free(global_variables.buffer);
+ //def samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::get_singleton()->free(default_rd_samplers[i][j]);
+ }
+ }
+
+ //custom samplers
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+ }
+ }
+
singleton = nullptr;
}
+/* Samplers */
+
+void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ RD::SamplerState sampler_state;
+ switch (i) {
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.max_lod = 0;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: {
+ sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR;
+ sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR;
+ if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ } else {
+ sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR;
+ }
+ sampler_state.lod_bias = p_mipmap_bias;
+ sampler_state.use_anisotropy = true;
+ sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level"));
+
+ } break;
+ default: {
+ }
+ }
+ switch (j) {
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE;
+
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT;
+ } break;
+ case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: {
+ sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ } break;
+ default: {
+ }
+ }
+
+ if (custom_rd_samplers[i][j].is_valid()) {
+ RD::get_singleton()->free(custom_rd_samplers[i][j]);
+ }
+
+ custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state);
+ }
+ }
+}
+
/* GLOBAL VARIABLE API */
int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
@@ -1498,7 +1698,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.a;
GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
- v = v.to_linear();
+ v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
bv_linear.z = v.b;
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index 270d9f0982..c8cc418c3a 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -195,6 +195,11 @@ private:
friend struct MaterialData;
static MaterialStorage *singleton;
+ /* Samplers */
+
+ 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];
+
/* GLOBAL VARIABLE API */
GlobalVariables global_variables;
@@ -222,6 +227,19 @@ public:
MaterialStorage();
virtual ~MaterialStorage();
+ /* Samplers */
+
+ _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+ return default_rd_samplers[p_filter][p_repeat];
+ }
+ _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
+ return custom_rd_samplers[p_filter][p_repeat];
+ }
+
+ void sampler_rd_configure_custom(float mipmap_bias);
+
+ // void sampler_rd_set_default(float p_mipmap_bias);
+
/* GLOBAL VARIABLE API */
void _update_global_variables();
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
new file mode 100644
index 0000000000..75dd20bdbd
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -0,0 +1,1897 @@
+/*************************************************************************/
+/* particles_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 "particles_storage.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/rendering_server_globals.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+ParticlesStorage *ParticlesStorage::singleton = nullptr;
+
+ParticlesStorage *ParticlesStorage::get_singleton() {
+ return singleton;
+}
+
+ParticlesStorage::ParticlesStorage() {
+ singleton = this;
+
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ /* Particles */
+
+ {
+ // Initialize particles
+ Vector<String> particles_modes;
+ particles_modes.push_back("");
+ particles_shader.shader.initialize(particles_modes, String());
+ }
+ MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
+ MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
+
+ {
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["COLOR"] = "PARTICLE.color";
+ actions.renames["VELOCITY"] = "PARTICLE.velocity";
+ //actions.renames["MASS"] = "mass"; ?
+ actions.renames["ACTIVE"] = "particle_active";
+ actions.renames["RESTART"] = "restart";
+ actions.renames["CUSTOM"] = "PARTICLE.custom";
+ for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ String udname = "USERDATA" + itos(i + 1);
+ actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
+ actions.usage_defines[udname] = "#define USERDATA" + itos(i + 1) + "_USED\n";
+ }
+ actions.renames["TRANSFORM"] = "PARTICLE.xform";
+ actions.renames["TIME"] = "frame_history.data[0].time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["LIFETIME"] = "params.lifetime";
+ actions.renames["DELTA"] = "local_delta";
+ actions.renames["NUMBER"] = "particle_number";
+ actions.renames["INDEX"] = "index";
+ //actions.renames["GRAVITY"] = "current_gravity";
+ actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
+ actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
+ actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
+ actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
+ actions.renames["FLAG_EMIT_VELOCITY"] = "EMISSION_FLAG_HAS_VELOCITY";
+ actions.renames["FLAG_EMIT_COLOR"] = "EMISSION_FLAG_HAS_COLOR";
+ actions.renames["FLAG_EMIT_CUSTOM"] = "EMISSION_FLAG_HAS_CUSTOM";
+ actions.renames["RESTART_POSITION"] = "restart_position";
+ actions.renames["RESTART_ROT_SCALE"] = "restart_rotation_scale";
+ actions.renames["RESTART_VELOCITY"] = "restart_velocity";
+ actions.renames["RESTART_COLOR"] = "restart_color";
+ actions.renames["RESTART_CUSTOM"] = "restart_custom";
+ actions.renames["emit_subparticle"] = "emit_subparticle";
+ actions.renames["COLLIDED"] = "collided";
+ actions.renames["COLLISION_NORMAL"] = "collision_normal";
+ actions.renames["COLLISION_DEPTH"] = "collision_depth";
+ actions.renames["ATTRACTOR_FORCE"] = "attractor_force";
+
+ actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
+ actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
+ actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
+ actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = 3;
+ actions.base_uniform_string = "material.";
+ actions.base_varying_index = 10;
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+
+ particles_shader.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for particles shader
+ particles_shader.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(particles_shader.default_shader);
+ material_storage->shader_set_code(particles_shader.default_shader, R"(
+// Default particles shader.
+
+shader_type particles;
+
+void process() {
+ COLOR = vec4(1.0);
+}
+)");
+ particles_shader.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(particles_shader.default_material);
+ material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
+
+ ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(material_storage->global_variables_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 0);
+ }
+
+ {
+ Vector<String> copy_modes;
+ for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
+ if (i == 0) {
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n");
+ copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n");
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n");
+ } else {
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USERDATA_COUNT " + itos(i) + "\n");
+ copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
+ copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n#define USERDATA_COUNT " + itos(i) + "\n");
+ }
+ }
+
+ particles_shader.copy_shader.initialize(copy_modes);
+
+ particles_shader.copy_shader_version = particles_shader.copy_shader.version_create();
+
+ for (int i = 0; i <= ParticlesShader::MAX_USERDATAS; i++) {
+ for (int j = 0; j < ParticlesShader::COPY_MODE_MAX; j++) {
+ particles_shader.copy_pipelines[i * ParticlesShader::COPY_MODE_MAX + j] = RD::get_singleton()->compute_pipeline_create(particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, i * ParticlesShader::COPY_MODE_MAX + j));
+ }
+ }
+ }
+}
+
+ParticlesStorage::~ParticlesStorage() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ particles_shader.copy_shader.version_free(particles_shader.copy_shader_version);
+
+ material_storage->material_free(particles_shader.default_material);
+ material_storage->shader_free(particles_shader.default_shader);
+
+ singleton = nullptr;
+}
+
+/* PARTICLES */
+
+RID ParticlesStorage::particles_allocate() {
+ return particles_owner.allocate_rid();
+}
+
+void ParticlesStorage::particles_initialize(RID p_rid) {
+ particles_owner.initialize_rid(p_rid, Particles());
+}
+
+void ParticlesStorage::particles_free(RID p_rid) {
+ update_particles();
+ Particles *particles = particles_owner.get_or_null(p_rid);
+ particles->dependency.deleted_notify(p_rid);
+ _particles_free_data(particles);
+ particles_owner.free(p_rid);
+}
+
+void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ if (particles->mode == p_mode) {
+ return;
+ }
+
+ _particles_free_data(particles);
+
+ particles->mode = p_mode;
+}
+
+void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->emitting = p_emitting;
+}
+
+bool ParticlesStorage::particles_get_emitting(RID p_particles) {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->emitting;
+}
+
+void ParticlesStorage::_particles_free_data(Particles *particles) {
+ if (particles->particle_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->particle_buffer);
+ particles->particle_buffer = RID();
+ RD::get_singleton()->free(particles->particle_instance_buffer);
+ particles->particle_instance_buffer = RID();
+ }
+
+ particles->userdata_count = 0;
+
+ if (particles->frame_params_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->frame_params_buffer);
+ particles->frame_params_buffer = RID();
+ }
+ particles->particles_transforms_buffer_uniform_set = RID();
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->trail_bind_pose_uniform_set)) {
+ RD::get_singleton()->free(particles->trail_bind_pose_uniform_set);
+ }
+ particles->trail_bind_pose_uniform_set = RID();
+
+ if (particles->trail_bind_pose_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->trail_bind_pose_buffer);
+ particles->trail_bind_pose_buffer = RID();
+ }
+ if (RD::get_singleton()->uniform_set_is_valid(particles->collision_textures_uniform_set)) {
+ RD::get_singleton()->free(particles->collision_textures_uniform_set);
+ }
+ particles->collision_textures_uniform_set = RID();
+
+ if (particles->particles_sort_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->particles_sort_buffer);
+ particles->particles_sort_buffer = RID();
+ particles->particles_sort_uniform_set = RID();
+ }
+
+ if (particles->emission_buffer != nullptr) {
+ particles->emission_buffer = nullptr;
+ particles->emission_buffer_data.clear();
+ RD::get_singleton()->free(particles->emission_storage_buffer);
+ particles->emission_storage_buffer = RID();
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+ //will need to be re-created
+ RD::get_singleton()->free(particles->particles_material_uniform_set);
+ }
+ particles->particles_material_uniform_set = RID();
+}
+
+void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->amount == p_amount) {
+ return;
+ }
+
+ _particles_free_data(particles);
+
+ particles->amount = p_amount;
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->lifetime = p_lifetime;
+}
+
+void ParticlesStorage::particles_set_one_shot(RID p_particles, bool p_one_shot) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->one_shot = p_one_shot;
+}
+
+void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_time) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->pre_process_time = p_time;
+}
+void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->explosiveness = p_ratio;
+}
+void ParticlesStorage::particles_set_randomness_ratio(RID p_particles, real_t p_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->randomness = p_ratio;
+}
+
+void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->custom_aabb = p_aabb;
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->speed_scale = p_scale;
+}
+void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->use_local_coords = p_enable;
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fixed_fps = p_fps;
+
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->interpolate = p_enable;
+}
+
+void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_enable) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->fractional_delta = p_enable;
+}
+
+void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_COND(p_length < 0.1);
+ p_length = MIN(10.0, p_length);
+
+ particles->trails_enabled = p_enable;
+ particles->trail_length = p_length;
+
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses.size() != p_bind_poses.size()) {
+ _particles_free_data(particles);
+
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ }
+ particles->trail_bind_poses = p_bind_poses;
+ particles->trail_bind_poses_dirty = true;
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+}
+
+void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->collision_base_size = p_size;
+}
+
+void ParticlesStorage::particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->transform_align = p_transform_align;
+}
+
+void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_material) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->process_material = p_material;
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
+}
+
+RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+
+ return particles->process_material;
+}
+
+void ParticlesStorage::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_order = p_order;
+}
+
+void ParticlesStorage::particles_set_draw_passes(RID p_particles, int p_passes) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->draw_passes.resize(p_passes);
+}
+
+void ParticlesStorage::particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_INDEX(p_pass, particles->draw_passes.size());
+ particles->draw_passes.write[p_pass] = p_mesh;
+}
+
+void ParticlesStorage::particles_restart(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->restart_request = true;
+}
+
+void ParticlesStorage::_particles_allocate_emission_buffer(Particles *particles) {
+ ERR_FAIL_COND(particles->emission_buffer != nullptr);
+
+ particles->emission_buffer_data.resize(sizeof(ParticleEmissionBuffer::Data) * particles->amount + sizeof(uint32_t) * 4);
+ memset(particles->emission_buffer_data.ptrw(), 0, particles->emission_buffer_data.size());
+ particles->emission_buffer = reinterpret_cast<ParticleEmissionBuffer *>(particles->emission_buffer_data.ptrw());
+ particles->emission_buffer->particle_max = particles->amount;
+
+ particles->emission_storage_buffer = RD::get_singleton()->storage_buffer_create(particles->emission_buffer_data.size(), particles->emission_buffer_data);
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+ //will need to be re-created
+ RD::get_singleton()->free(particles->particles_material_uniform_set);
+ particles->particles_material_uniform_set = RID();
+ }
+}
+
+void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_COND(p_particles == p_subemitter_particles);
+
+ particles->sub_emitter = p_subemitter_particles;
+
+ if (RD::get_singleton()->uniform_set_is_valid(particles->particles_material_uniform_set)) {
+ RD::get_singleton()->free(particles->particles_material_uniform_set);
+ particles->particles_material_uniform_set = RID(); //clear and force to re create sub emitting
+ }
+}
+
+void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ ERR_FAIL_COND(particles->amount == 0);
+
+ if (particles->emitting) {
+ particles->clear = true;
+ particles->emitting = false;
+ }
+
+ if (particles->emission_buffer == nullptr) {
+ _particles_allocate_emission_buffer(particles);
+ }
+
+ if (particles->inactive) {
+ //in case it was inactive, make active again
+ particles->inactive = false;
+ particles->inactive_time = 0;
+ }
+
+ int32_t idx = particles->emission_buffer->particle_count;
+ if (idx < particles->emission_buffer->particle_max) {
+ RendererStorageRD::store_transform(p_transform, particles->emission_buffer->data[idx].xform);
+
+ particles->emission_buffer->data[idx].velocity[0] = p_velocity.x;
+ particles->emission_buffer->data[idx].velocity[1] = p_velocity.y;
+ particles->emission_buffer->data[idx].velocity[2] = p_velocity.z;
+
+ particles->emission_buffer->data[idx].custom[0] = p_custom.r;
+ particles->emission_buffer->data[idx].custom[1] = p_custom.g;
+ particles->emission_buffer->data[idx].custom[2] = p_custom.b;
+ particles->emission_buffer->data[idx].custom[3] = p_custom.a;
+
+ particles->emission_buffer->data[idx].color[0] = p_color.r;
+ particles->emission_buffer->data[idx].color[1] = p_color.g;
+ particles->emission_buffer->data[idx].color[2] = p_color.b;
+ particles->emission_buffer->data[idx].color[3] = p_color.a;
+
+ particles->emission_buffer->data[idx].flags = p_emit_flags;
+ particles->emission_buffer->particle_count++;
+ }
+}
+
+void ParticlesStorage::particles_request_process(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (!particles->dirty) {
+ particles->dirty = true;
+ particles->update_list = particle_update_list;
+ particle_update_list = particles;
+ }
+}
+
+AABB ParticlesStorage::particles_get_current_aabb(RID p_particles) {
+ if (RSG::threaded) {
+ WARN_PRINT_ONCE("Calling this function with threaded rendering enabled stalls the renderer, use with care.");
+ }
+
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ int total_amount = particles->amount;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ total_amount *= particles->trail_bind_poses.size();
+ }
+
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(particles->particle_buffer);
+ ERR_FAIL_COND_V(buffer.size() != (int)(total_amount * sizeof(ParticleData)), AABB());
+
+ Transform3D inv = particles->emission_transform.affine_inverse();
+
+ AABB aabb;
+ if (buffer.size()) {
+ bool first = true;
+
+ const uint8_t *data_ptr = (const uint8_t *)buffer.ptr();
+ uint32_t particle_data_size = sizeof(ParticleData) + sizeof(float) * particles->userdata_count;
+
+ for (int i = 0; i < total_amount; i++) {
+ const ParticleData &particle_data = *(const ParticleData *)&data_ptr[particle_data_size * i];
+ if (particle_data.active) {
+ Vector3 pos = Vector3(particle_data.xform[12], particle_data.xform[13], particle_data.xform[14]);
+ if (!particles->use_local_coords) {
+ pos = inv.xform(pos);
+ }
+ if (first) {
+ aabb.position = pos;
+ first = false;
+ } else {
+ aabb.expand_to(pos);
+ }
+ }
+ }
+ }
+
+ float longest_axis_size = 0;
+ for (int i = 0; i < particles->draw_passes.size(); i++) {
+ if (particles->draw_passes[i].is_valid()) {
+ AABB maabb = MeshStorage::get_singleton()->mesh_get_aabb(particles->draw_passes[i], RID());
+ longest_axis_size = MAX(maabb.get_longest_axis_size(), longest_axis_size);
+ }
+ }
+
+ aabb.grow_by(longest_axis_size);
+
+ return aabb;
+}
+
+AABB ParticlesStorage::particles_get_aabb(RID p_particles) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, AABB());
+
+ return particles->custom_aabb;
+}
+
+void ParticlesStorage::particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ particles->emission_transform = p_transform;
+}
+
+int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->draw_passes.size();
+}
+
+RID ParticlesStorage::particles_get_draw_pass_mesh(RID p_particles, int p_pass) const {
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+ ERR_FAIL_INDEX_V(p_pass, particles->draw_passes.size(), RID());
+
+ return particles->draw_passes[p_pass];
+}
+
+void ParticlesStorage::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.insert(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->collisions.erase(p_particles_collision_instance);
+}
+
+void ParticlesStorage::particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+ particles->has_sdf_collision = p_enable;
+ particles->sdf_collision_transform = p_xform;
+ particles->sdf_collision_to_screen = p_to_screen;
+ particles->sdf_collision_texture = p_texture;
+}
+
+void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta) {
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ if (p_particles->particles_material_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_particles->particles_material_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(p_particles->frame_params_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.append_id(p_particles->particle_buffer);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ if (p_particles->emission_storage_buffer.is_valid()) {
+ u.append_id(p_particles->emission_storage_buffer);
+ } else {
+ u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 3;
+ Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
+ if (sub_emitter) {
+ if (sub_emitter->emission_buffer == nullptr) { //no emission buffer, allocate emission buffer
+ _particles_allocate_emission_buffer(sub_emitter);
+ }
+ u.append_id(sub_emitter->emission_storage_buffer);
+ } else {
+ u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+ }
+ uniforms.push_back(u);
+ }
+
+ p_particles->particles_material_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 1);
+ }
+
+ double new_phase = Math::fmod((double)p_particles->phase + (p_delta / p_particles->lifetime) * p_particles->speed_scale, 1.0);
+
+ //move back history (if there is any)
+ for (uint32_t i = p_particles->frame_history.size() - 1; i > 0; i--) {
+ p_particles->frame_history[i] = p_particles->frame_history[i - 1];
+ }
+ //update current frame
+ ParticlesFrameParams &frame_params = p_particles->frame_history[0];
+
+ if (p_particles->clear) {
+ p_particles->cycle_number = 0;
+ p_particles->random_seed = Math::rand();
+ } else if (new_phase < p_particles->phase) {
+ if (p_particles->one_shot) {
+ p_particles->emitting = false;
+ }
+ p_particles->cycle_number++;
+ }
+
+ frame_params.emitting = p_particles->emitting;
+ frame_params.system_phase = new_phase;
+ frame_params.prev_system_phase = p_particles->phase;
+
+ p_particles->phase = new_phase;
+
+ frame_params.time = RendererCompositorRD::singleton->get_total_time();
+ frame_params.delta = p_delta * p_particles->speed_scale;
+ frame_params.random_seed = p_particles->random_seed;
+ frame_params.explosiveness = p_particles->explosiveness;
+ frame_params.randomness = p_particles->randomness;
+
+ if (p_particles->use_local_coords) {
+ RendererStorageRD::store_transform(Transform3D(), frame_params.emission_transform);
+ } else {
+ RendererStorageRD::store_transform(p_particles->emission_transform, frame_params.emission_transform);
+ }
+
+ frame_params.cycle = p_particles->cycle_number;
+ frame_params.frame = p_particles->frame_counter++;
+ frame_params.pad0 = 0;
+ frame_params.pad1 = 0;
+ frame_params.pad2 = 0;
+
+ { //collision and attractors
+
+ frame_params.collider_count = 0;
+ frame_params.attractor_count = 0;
+ frame_params.particle_size = p_particles->collision_base_size;
+
+ RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+ RID collision_heightmap_texture;
+
+ Transform3D to_particles;
+ if (p_particles->use_local_coords) {
+ to_particles = p_particles->emission_transform.affine_inverse();
+ }
+
+ if (p_particles->has_sdf_collision && RD::get_singleton()->texture_is_valid(p_particles->sdf_collision_texture)) {
+ //2D collision
+
+ Transform2D xform = p_particles->sdf_collision_transform; //will use dotproduct manually so invert beforehand
+ Transform2D revert = xform.affine_inverse();
+ frame_params.collider_count = 1;
+ frame_params.colliders[0].transform[0] = xform.elements[0][0];
+ frame_params.colliders[0].transform[1] = xform.elements[0][1];
+ frame_params.colliders[0].transform[2] = 0;
+ frame_params.colliders[0].transform[3] = xform.elements[2][0];
+
+ frame_params.colliders[0].transform[4] = xform.elements[1][0];
+ frame_params.colliders[0].transform[5] = xform.elements[1][1];
+ frame_params.colliders[0].transform[6] = 0;
+ frame_params.colliders[0].transform[7] = xform.elements[2][1];
+
+ frame_params.colliders[0].transform[8] = revert.elements[0][0];
+ frame_params.colliders[0].transform[9] = revert.elements[0][1];
+ frame_params.colliders[0].transform[10] = 0;
+ frame_params.colliders[0].transform[11] = revert.elements[2][0];
+
+ frame_params.colliders[0].transform[12] = revert.elements[1][0];
+ frame_params.colliders[0].transform[13] = revert.elements[1][1];
+ frame_params.colliders[0].transform[14] = 0;
+ frame_params.colliders[0].transform[15] = revert.elements[2][1];
+
+ frame_params.colliders[0].extents[0] = p_particles->sdf_collision_to_screen.size.x;
+ frame_params.colliders[0].extents[1] = p_particles->sdf_collision_to_screen.size.y;
+ frame_params.colliders[0].extents[2] = p_particles->sdf_collision_to_screen.position.x;
+ frame_params.colliders[0].scale = p_particles->sdf_collision_to_screen.position.y;
+ frame_params.colliders[0].texture_index = 0;
+ frame_params.colliders[0].type = ParticlesFrameParams::COLLISION_TYPE_2D_SDF;
+
+ collision_heightmap_texture = p_particles->sdf_collision_texture;
+
+ //replace in all other history frames where used because parameters are no longer valid if screen moves
+ for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) {
+ if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
+ p_particles->frame_history[i].colliders[0] = frame_params.colliders[0];
+ }
+ }
+ }
+
+ uint32_t collision_3d_textures_used = 0;
+ for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get());
+ if (!pci || !pci->active) {
+ continue;
+ }
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(pci->collision);
+ ERR_CONTINUE(!pc);
+
+ Transform3D to_collider = pci->transform;
+ if (p_particles->use_local_coords) {
+ to_collider = to_particles * to_collider;
+ }
+ Vector3 scale = to_collider.basis.get_scale();
+ to_collider.basis.orthonormalize();
+
+ if (pc->type <= RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT) {
+ //attractor
+ if (frame_params.attractor_count >= ParticlesFrameParams::MAX_ATTRACTORS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
+
+ RendererStorageRD::store_transform(to_collider, attr.transform);
+ attr.strength = pc->attractor_strength;
+ attr.attenuation = pc->attractor_attenuation;
+ attr.directionality = pc->attractor_directionality;
+
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ attr.extents[0] = radius;
+ attr.extents[1] = radius;
+ attr.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_ATTRACT: {
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ attr.extents[0] = extents.x;
+ attr.extents[1] = extents.y;
+ attr.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
+ if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
+ continue;
+ }
+ attr.type = ParticlesFrameParams::ATTRACTOR_TYPE_VECTOR_FIELD;
+ Vector3 extents = pc->extents * scale;
+ attr.extents[0] = extents.x;
+ attr.extents[1] = extents.y;
+ attr.extents[2] = extents.z;
+ attr.texture_index = collision_3d_textures_used;
+
+ collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
+ collision_3d_textures_used++;
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.attractor_count++;
+ } else {
+ //collider
+ if (frame_params.collider_count >= ParticlesFrameParams::MAX_COLLIDERS) {
+ continue;
+ }
+
+ ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
+
+ RendererStorageRD::store_transform(to_collider, col.transform);
+ switch (pc->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
+ float radius = pc->radius;
+ radius *= (scale.x + scale.y + scale.z) / 3.0;
+ col.extents[0] = radius;
+ col.extents[1] = radius;
+ col.extents[2] = radius;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_BOX_COLLIDE: {
+ col.type = ParticlesFrameParams::COLLISION_TYPE_BOX;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
+ if (collision_3d_textures_used >= ParticlesFrameParams::MAX_3D_TEXTURES) {
+ continue;
+ }
+ col.type = ParticlesFrameParams::COLLISION_TYPE_SDF;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ col.texture_index = collision_3d_textures_used;
+ col.scale = (scale.x + scale.y + scale.z) * 0.333333333333; //non uniform scale non supported
+
+ collision_3d_textures[collision_3d_textures_used] = pc->field_texture;
+ collision_3d_textures_used++;
+ } break;
+ case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
+ if (collision_heightmap_texture != RID()) { //already taken
+ continue;
+ }
+
+ col.type = ParticlesFrameParams::COLLISION_TYPE_HEIGHT_FIELD;
+ Vector3 extents = pc->extents * scale;
+ col.extents[0] = extents.x;
+ col.extents[1] = extents.y;
+ col.extents[2] = extents.z;
+ collision_heightmap_texture = pc->heightfield_texture;
+ } break;
+ default: {
+ }
+ }
+
+ frame_params.collider_count++;
+ }
+ }
+
+ bool different = false;
+ if (collision_3d_textures_used == p_particles->collision_3d_textures_used) {
+ for (int i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
+ if (p_particles->collision_3d_textures[i] != collision_3d_textures[i]) {
+ different = true;
+ break;
+ }
+ }
+ }
+
+ if (collision_heightmap_texture != p_particles->collision_heightmap_texture) {
+ different = true;
+ }
+
+ bool uniform_set_valid = RD::get_singleton()->uniform_set_is_valid(p_particles->collision_textures_uniform_set);
+
+ if (different || !uniform_set_valid) {
+ if (uniform_set_valid) {
+ RD::get_singleton()->free(p_particles->collision_textures_uniform_set);
+ }
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+ for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
+ RID rd_tex;
+ if (i < collision_3d_textures_used) {
+ Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]);
+ if (t && t->type == Texture::TYPE_3D) {
+ rd_tex = t->rd_texture;
+ }
+ }
+
+ if (rd_tex == RID()) {
+ rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ }
+ u.append_id(rd_tex);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ if (collision_heightmap_texture.is_valid()) {
+ u.append_id(collision_heightmap_texture);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK));
+ }
+ uniforms.push_back(u);
+ }
+ p_particles->collision_textures_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, 2);
+ }
+ }
+
+ ParticlesShader::PushConstant push_constant;
+
+ int process_amount = p_particles->amount;
+
+ if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
+ process_amount *= p_particles->trail_bind_poses.size();
+ }
+ push_constant.clear = p_particles->clear;
+ push_constant.total_particles = p_particles->amount;
+ push_constant.lifetime = p_particles->lifetime;
+ push_constant.trail_size = p_particles->trail_params.size();
+ push_constant.use_fractional_delta = p_particles->fractional_delta;
+ push_constant.sub_emitter_mode = !p_particles->emitting && p_particles->emission_buffer && (p_particles->emission_buffer->particle_count > 0 || p_particles->force_sub_emit);
+ push_constant.trail_pass = false;
+
+ p_particles->force_sub_emit = false; //reset
+
+ Particles *sub_emitter = particles_owner.get_or_null(p_particles->sub_emitter);
+
+ if (sub_emitter && sub_emitter->emission_storage_buffer.is_valid()) {
+ // print_line("updating subemitter buffer");
+ int32_t zero[4] = { 0, sub_emitter->amount, 0, 0 };
+ RD::get_singleton()->buffer_update(sub_emitter->emission_storage_buffer, 0, sizeof(uint32_t) * 4, zero);
+ push_constant.can_emit = true;
+
+ if (sub_emitter->emitting) {
+ sub_emitter->emitting = false;
+ sub_emitter->clear = true; //will need to clear if it was emitting, sorry
+ }
+ //make sure the sub emitter processes particles too
+ sub_emitter->inactive = false;
+ sub_emitter->inactive_time = 0;
+
+ sub_emitter->force_sub_emit = true;
+
+ } else {
+ push_constant.can_emit = false;
+ }
+
+ if (p_particles->emission_buffer && p_particles->emission_buffer->particle_count) {
+ RD::get_singleton()->buffer_update(p_particles->emission_storage_buffer, 0, sizeof(uint32_t) * 4 + sizeof(ParticleEmissionBuffer::Data) * p_particles->emission_buffer->particle_count, p_particles->emission_buffer);
+ p_particles->emission_buffer->particle_count = 0;
+ }
+
+ p_particles->clear = false;
+
+ if (p_particles->trail_params.size() > 1) {
+ //fill the trail params
+ for (uint32_t i = 0; i < p_particles->trail_params.size(); i++) {
+ uint32_t src_idx = i * p_particles->frame_history.size() / p_particles->trail_params.size();
+ p_particles->trail_params[i] = p_particles->frame_history[src_idx];
+ }
+ } else {
+ p_particles->trail_params[0] = p_particles->frame_history[0];
+ }
+
+ RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
+
+ ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES));
+ if (!m) {
+ m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ }
+
+ ERR_FAIL_COND(!m);
+
+ p_particles->has_collision_cache = m->shader_data->uses_collision;
+
+ //todo should maybe compute all particle systems together?
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, m->shader_data->pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles_shader.base_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->particles_material_uniform_set, 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_particles->collision_textures_uniform_set, 2);
+
+ if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, m->uniform_set, 3);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
+
+ if (p_particles->trails_enabled && p_particles->trail_bind_poses.size() > 1) {
+ //trails requires two passes in order to catch particle starts
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount / p_particles->trail_bind_poses.size(), 1, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ push_constant.trail_pass = true;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ParticlesShader::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount - p_particles->amount, 1, 1);
+ } else {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, process_amount, 1, 1);
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND(!particles);
+
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ return;
+ }
+
+ if (particles->particle_buffer.is_null()) {
+ return; //particles have not processed yet
+ }
+
+ bool do_sort = particles->draw_order == RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH;
+
+ //copy to sort buffer
+ if (do_sort && particles->particles_sort_buffer == RID()) {
+ uint32_t size = particles->amount;
+ if (size & 1) {
+ size++; //make multiple of 16
+ }
+ size *= sizeof(float) * 2;
+ particles->particles_sort_buffer = RD::get_singleton()->storage_buffer_create(size);
+
+ {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(particles->particles_sort_buffer);
+ uniforms.push_back(u);
+ }
+
+ particles->particles_sort_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, ParticlesShader::COPY_MODE_FILL_SORT_BUFFER), 1);
+ }
+ }
+
+ ParticlesShader::CopyPushConstant copy_push_constant;
+
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ int fixed_fps = 60.0;
+ if (particles->fixed_fps > 0) {
+ fixed_fps = particles->fixed_fps;
+ }
+
+ copy_push_constant.trail_size = particles->trail_bind_poses.size();
+ copy_push_constant.trail_total = particles->frame_history.size();
+ copy_push_constant.frame_delta = 1.0 / fixed_fps;
+ } else {
+ copy_push_constant.trail_size = 1;
+ copy_push_constant.trail_total = 1;
+ copy_push_constant.frame_delta = 0.0;
+ }
+
+ copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+ copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
+ copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
+ copy_push_constant.total_particles = particles->amount;
+ copy_push_constant.copy_mode_2d = false;
+
+ Vector3 axis = -p_axis; // cameras look to z negative
+
+ if (particles->use_local_coords) {
+ axis = particles->emission_transform.basis.xform_inv(axis).normalized();
+ }
+
+ copy_push_constant.sort_direction[0] = axis.x;
+ copy_push_constant.sort_direction[1] = axis.y;
+ copy_push_constant.sort_direction[2] = axis.z;
+
+ copy_push_constant.align_up[0] = p_up_axis.x;
+ copy_push_constant.align_up[1] = p_up_axis.y;
+ copy_push_constant.align_up[2] = p_up_axis.z;
+
+ copy_push_constant.align_mode = particles->transform_align;
+
+ if (do_sort) {
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_SORT_BUFFER + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
+
+ RD::get_singleton()->compute_list_end();
+ RendererStorageRD::base_singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
+ }
+
+ copy_push_constant.total_particles *= copy_push_constant.total_particles;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
+ copy_pipeline += particles->userdata_count * ParticlesShader::COPY_MODE_MAX;
+ copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[copy_pipeline]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+ if (do_sort) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, copy_push_constant.total_particles, 1, 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void ParticlesStorage::_particles_update_buffers(Particles *particles) {
+ uint32_t userdata_count = 0;
+
+ const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material);
+ if (material && material->shader && material->shader->data) {
+ const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
+ userdata_count = shader_data->userdata_count;
+ }
+
+ if (userdata_count != particles->userdata_count) {
+ // Mismatch userdata, re-create buffers.
+ _particles_free_data(particles);
+ }
+
+ if (particles->amount > 0 && particles->particle_buffer.is_null()) {
+ int total_amount = particles->amount;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ total_amount *= particles->trail_bind_poses.size();
+ }
+
+ uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3;
+
+ particles->particle_buffer = RD::get_singleton()->storage_buffer_create((sizeof(ParticleData) + userdata_count * sizeof(float) * 4) * total_amount);
+
+ particles->userdata_count = userdata_count;
+
+ particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount);
+ //needs to clear it
+
+ {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.append_id(particles->particle_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(particles->particle_instance_buffer);
+ uniforms.push_back(u);
+ }
+
+ particles->particles_copy_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 0);
+ }
+ }
+}
+void ParticlesStorage::update_particles() {
+ while (particle_update_list) {
+ //use transform feedback to process particles
+
+ Particles *particles = particle_update_list;
+
+ //take and remove
+ particle_update_list = particles->update_list;
+ particles->update_list = nullptr;
+ particles->dirty = false;
+
+ _particles_update_buffers(particles);
+
+ if (particles->restart_request) {
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ particles->restart_request = false;
+ }
+
+ if (particles->inactive && !particles->emitting) {
+ //go next
+ continue;
+ }
+
+ if (particles->emitting) {
+ if (particles->inactive) {
+ //restart system from scratch
+ particles->prev_ticks = 0;
+ particles->phase = 0;
+ particles->prev_phase = 0;
+ particles->clear = true;
+ }
+ particles->inactive = false;
+ particles->inactive_time = 0;
+ } else {
+ particles->inactive_time += particles->speed_scale * RendererCompositorRD::singleton->get_frame_delta_time();
+ if (particles->inactive_time > particles->lifetime * 1.2) {
+ particles->inactive = true;
+ continue;
+ }
+ }
+
+#ifndef _MSC_VER
+#warning Should use display refresh rate for all this
+#endif
+
+ float screen_hz = 60;
+
+ int fixed_fps = 0;
+ if (particles->fixed_fps > 0) {
+ fixed_fps = particles->fixed_fps;
+ } else if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ fixed_fps = screen_hz;
+ }
+ {
+ //update trails
+ int history_size = 1;
+ int trail_steps = 1;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ history_size = MAX(1, int(particles->trail_length * fixed_fps));
+ trail_steps = particles->trail_bind_poses.size();
+ }
+
+ if (uint32_t(history_size) != particles->frame_history.size()) {
+ particles->frame_history.resize(history_size);
+ memset(particles->frame_history.ptr(), 0, sizeof(ParticlesFrameParams) * history_size);
+ }
+
+ if (uint32_t(trail_steps) != particles->trail_params.size() || particles->frame_params_buffer.is_null()) {
+ particles->trail_params.resize(trail_steps);
+ if (particles->frame_params_buffer.is_valid()) {
+ RD::get_singleton()->free(particles->frame_params_buffer);
+ }
+ particles->frame_params_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticlesFrameParams) * trail_steps);
+ }
+
+ if (particles->trail_bind_poses.size() > 1 && particles->trail_bind_pose_buffer.is_null()) {
+ particles->trail_bind_pose_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 16 * particles->trail_bind_poses.size());
+ particles->trail_bind_poses_dirty = true;
+ }
+
+ if (particles->trail_bind_pose_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ if (particles->trail_bind_pose_buffer.is_valid()) {
+ u.append_id(particles->trail_bind_pose_buffer);
+ } else {
+ u.append_id(MeshStorage::get_singleton()->get_default_rd_storage_buffer());
+ }
+ uniforms.push_back(u);
+ }
+
+ particles->trail_bind_pose_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.copy_shader.version_get_shader(particles_shader.copy_shader_version, 0), 2);
+ }
+
+ if (particles->trail_bind_pose_buffer.is_valid() && particles->trail_bind_poses_dirty) {
+ if (particles_shader.pose_update_buffer.size() < uint32_t(particles->trail_bind_poses.size()) * 16) {
+ particles_shader.pose_update_buffer.resize(particles->trail_bind_poses.size() * 16);
+ }
+
+ for (int i = 0; i < particles->trail_bind_poses.size(); i++) {
+ RendererStorageRD::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
+ }
+
+ RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr());
+ }
+ }
+
+ bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
+
+ if (particles->clear && particles->pre_process_time > 0.0) {
+ double frame_time;
+ if (fixed_fps > 0) {
+ frame_time = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / 30.0;
+ }
+
+ double todo = particles->pre_process_time;
+
+ while (todo >= 0) {
+ _particles_process(particles, frame_time);
+ todo -= frame_time;
+ }
+ }
+
+ if (fixed_fps > 0) {
+ double frame_time;
+ double decr;
+ if (zero_time_scale) {
+ frame_time = 0.0;
+ decr = 1.0 / fixed_fps;
+ } else {
+ frame_time = 1.0 / fixed_fps;
+ decr = frame_time;
+ }
+ double delta = RendererCompositorRD::singleton->get_frame_delta_time();
+ if (delta > 0.1) { //avoid recursive stalls if fps goes below 10
+ delta = 0.1;
+ } else if (delta <= 0.0) { //unlikely but..
+ delta = 0.001;
+ }
+ double todo = particles->frame_remainder + delta;
+
+ while (todo >= frame_time) {
+ _particles_process(particles, frame_time);
+ todo -= decr;
+ }
+
+ particles->frame_remainder = todo;
+
+ } else {
+ if (zero_time_scale) {
+ _particles_process(particles, 0.0);
+ } else {
+ _particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time());
+ }
+ }
+
+ //copy particles to instance buffer
+
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ //does not need view dependent operation, do copy here
+ ParticlesShader::CopyPushConstant copy_push_constant;
+
+ int total_amount = particles->amount;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ total_amount *= particles->trail_bind_poses.size();
+ }
+
+ // Affect 2D only.
+ if (particles->use_local_coords) {
+ // In local mode, particle positions are calculated locally (relative to the node position)
+ // and they're also drawn locally.
+ // It works as expected, so we just pass an identity transform.
+ RendererStorageRD::store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
+ } else {
+ // In global mode, particle positions are calculated globally (relative to the canvas origin)
+ // but they're drawn locally.
+ // So, we need to pass the inverse of the emission transform to bring the
+ // particles to local coordinates before drawing.
+ Transform3D inv = particles->emission_transform.affine_inverse();
+ RendererStorageRD::store_transform(inv, copy_push_constant.inv_emission_transform);
+ }
+
+ copy_push_constant.total_particles = total_amount;
+ copy_push_constant.frame_remainder = particles->interpolate ? particles->frame_remainder : 0.0;
+ copy_push_constant.align_mode = particles->transform_align;
+ copy_push_constant.align_up[0] = 0;
+ copy_push_constant.align_up[1] = 0;
+ copy_push_constant.align_up[2] = 0;
+
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ copy_push_constant.trail_size = particles->trail_bind_poses.size();
+ copy_push_constant.trail_total = particles->frame_history.size();
+ copy_push_constant.frame_delta = 1.0 / fixed_fps;
+ } else {
+ copy_push_constant.trail_size = 1;
+ copy_push_constant.trail_total = 1;
+ copy_push_constant.frame_delta = 0.0;
+ }
+
+ copy_push_constant.order_by_lifetime = (particles->draw_order == RS::PARTICLES_DRAW_ORDER_LIFETIME || particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME);
+ copy_push_constant.lifetime_split = MIN(particles->amount * particles->phase, particles->amount - 1);
+ copy_push_constant.lifetime_reverse = particles->draw_order == RS::PARTICLES_DRAW_ORDER_REVERSE_LIFETIME;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ copy_push_constant.copy_mode_2d = particles->mode == RS::PARTICLES_MODE_2D ? 1 : 0;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES + particles->userdata_count * ParticlesShader::COPY_MODE_MAX]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &copy_push_constant, sizeof(ParticlesShader::CopyPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, total_amount, 1, 1);
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ }
+}
+
+bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
+ ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
+ const Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+ return !particles->emitting && particles->inactive;
+}
+
+/* Particles SHADER */
+
+void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
+ ParticlesStorage *particles_storage = ParticlesStorage::get_singleton();
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+ uses_collision = false;
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["start"] = ShaderCompiler::STAGE_COMPUTE;
+ actions.entry_point_stages["process"] = ShaderCompiler::STAGE_COMPUTE;
+
+ /*
+ uses_time = false;
+
+ actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
+ actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+*/
+
+ actions.usage_flag_pointers["COLLIDED"] = &uses_collision;
+
+ userdata_count = 0;
+ for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ userdatas_used[i] = false;
+ actions.usage_flag_pointers["USERDATA" + itos(i + 1)] = &userdatas_used[i];
+ }
+
+ actions.uniforms = &uniforms;
+
+ Error err = particles_storage->particles_shader.compiler.compile(RS::SHADER_PARTICLES, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+
+ if (version.is_null()) {
+ version = particles_storage->particles_shader.shader.version_create();
+ }
+
+ for (uint32_t i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
+ if (userdatas_used[i]) {
+ userdata_count++;
+ }
+ }
+
+ particles_storage->particles_shader.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
+ ERR_FAIL_COND(!particles_storage->particles_shader.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ //update pipelines
+
+ pipeline = RD::get_singleton()->compute_pipeline_create(particles_storage->particles_shader.shader.version_get_shader(version, 0));
+
+ valid = true;
+}
+
+void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = Map<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ Map<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void ParticlesStorage::ParticlesShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool ParticlesStorage::ParticlesShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool ParticlesStorage::ParticlesShaderData::is_animated() const {
+ return false;
+}
+
+bool ParticlesStorage::ParticlesShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant ParticlesStorage::ParticlesShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode ParticlesStorage::ParticlesShaderData::get_native_source_code() const {
+ return ParticlesStorage::get_singleton()->particles_shader.shader.version_get_native_source_code(version);
+}
+
+ParticlesStorage::ParticlesShaderData::ParticlesShaderData() {
+ valid = false;
+}
+
+ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() {
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ ParticlesStorage::get_singleton()->particles_shader.shader.version_free(version);
+ }
+}
+
+ShaderData *ParticlesStorage::_create_particles_shader_func() {
+ ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
+ return shader_data;
+}
+
+bool ParticlesStorage::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
+}
+
+ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
+
+MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
+ ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
+ material_data->shader_data = p_shader;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+////////
+
+/* PARTICLES COLLISION API */
+
+RID ParticlesStorage::particles_collision_allocate() {
+ return particles_collision_owner.allocate_rid();
+}
+void ParticlesStorage::particles_collision_initialize(RID p_rid) {
+ particles_collision_owner.initialize_rid(p_rid, ParticlesCollision());
+}
+
+void ParticlesStorage::particles_collision_free(RID p_rid) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_rid);
+
+ if (particles_collision->heightfield_texture.is_valid()) {
+ RD::get_singleton()->free(particles_collision->heightfield_texture);
+ }
+ particles_collision->dependency.deleted_notify(p_rid);
+ particles_collision_owner.free(p_rid);
+}
+
+RID ParticlesStorage::particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, RID());
+ ERR_FAIL_COND_V(particles_collision->type != RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE, RID());
+
+ if (particles_collision->heightfield_texture == RID()) {
+ //create
+ int resolutions[RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX] = { 256, 512, 1024, 2048, 4096, 8192 };
+ Size2i size;
+ if (particles_collision->extents.x > particles_collision->extents.z) {
+ size.x = resolutions[particles_collision->heightfield_resolution];
+ size.y = int32_t(particles_collision->extents.z / particles_collision->extents.x * size.x);
+ } else {
+ size.y = resolutions[particles_collision->heightfield_resolution];
+ size.x = int32_t(particles_collision->extents.x / particles_collision->extents.z * size.y);
+ }
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_D32_SFLOAT;
+ tf.width = size.x;
+ tf.height = size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ particles_collision->heightfield_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ Vector<RID> fb_tex;
+ fb_tex.push_back(particles_collision->heightfield_texture);
+ particles_collision->heightfield_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ particles_collision->heightfield_fb_size = size;
+ }
+
+ return particles_collision->heightfield_fb;
+}
+
+void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ if (p_type == particles_collision->type) {
+ return;
+ }
+
+ if (particles_collision->heightfield_texture.is_valid()) {
+ RD::get_singleton()->free(particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = RID();
+ }
+ particles_collision->type = p_type;
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ particles_collision->cull_mask = p_cull_mask;
+}
+
+void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->radius = p_radius;
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->extents = p_extents;
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_strength = p_strength;
+}
+
+void ParticlesStorage::particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_directionality = p_directionality;
+}
+
+void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->attractor_attenuation = p_curve;
+}
+
+void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+
+ particles_collision->field_texture = p_texture;
+}
+
+void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND(!particles_collision);
+ ERR_FAIL_INDEX(p_resolution, RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_MAX);
+
+ if (particles_collision->heightfield_resolution == p_resolution) {
+ return;
+ }
+
+ particles_collision->heightfield_resolution = p_resolution;
+
+ if (particles_collision->heightfield_texture.is_valid()) {
+ RD::get_singleton()->free(particles_collision->heightfield_texture);
+ particles_collision->heightfield_texture = RID();
+ }
+}
+
+AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) const {
+ ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, AABB());
+
+ switch (particles_collision->type) {
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT:
+ case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
+ AABB aabb;
+ aabb.position = -Vector3(1, 1, 1) * particles_collision->radius;
+ aabb.size = Vector3(2, 2, 2) * particles_collision->radius;
+ return aabb;
+ }
+ default: {
+ AABB aabb;
+ aabb.position = -particles_collision->extents;
+ aabb.size = particles_collision->extents * 2;
+ return aabb;
+ }
+ }
+
+ return AABB();
+}
+
+Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const {
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, Vector3());
+ return particles_collision->extents;
+}
+
+bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collision) const {
+ const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_COND_V(!particles_collision, false);
+ return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
+}
+
+RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
+ ParticlesCollisionInstance pci;
+ pci.collision = p_collision;
+ return particles_collision_instance_owner.make_rid(pci);
+}
+
+void ParticlesStorage::particles_collision_instance_free(RID p_rid) {
+ particles_collision_instance_owner.free(p_rid);
+}
+
+void ParticlesStorage::particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->transform = p_transform;
+}
+
+void ParticlesStorage::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) {
+ ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(p_collision_instance);
+ ERR_FAIL_COND(!pci);
+ pci->active = p_active;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
new file mode 100644
index 0000000000..7764af08f2
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -0,0 +1,565 @@
+/*************************************************************************/
+/* particles_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 PARTICLES_STORAGE_RD_H
+#define PARTICLES_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/particles.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/shader_compiler.h"
+#include "servers/rendering/storage/particles_storage.h"
+
+namespace RendererRD {
+
+/* PARTICLES */
+
+struct ParticleData {
+ float xform[16];
+ float velocity[3];
+ uint32_t active;
+ float color[4];
+ float custom[3];
+ float lifetime;
+};
+
+struct ParticlesFrameParams {
+ enum {
+ MAX_ATTRACTORS = 32,
+ MAX_COLLIDERS = 32,
+ MAX_3D_TEXTURES = 7
+ };
+
+ enum AttractorType {
+ ATTRACTOR_TYPE_SPHERE,
+ ATTRACTOR_TYPE_BOX,
+ ATTRACTOR_TYPE_VECTOR_FIELD,
+ };
+
+ struct Attractor {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
+
+ uint32_t texture_index; //texture index for vector field
+ float strength;
+ float attenuation;
+ float directionality;
+ };
+
+ enum CollisionType {
+ COLLISION_TYPE_SPHERE,
+ COLLISION_TYPE_BOX,
+ COLLISION_TYPE_SDF,
+ COLLISION_TYPE_HEIGHT_FIELD,
+ COLLISION_TYPE_2D_SDF,
+
+ };
+
+ struct Collider {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
+
+ uint32_t texture_index; //texture index for vector field
+ real_t scale;
+ uint32_t pad[2];
+ };
+
+ uint32_t emitting;
+ float system_phase;
+ float prev_system_phase;
+ uint32_t cycle;
+
+ real_t explosiveness;
+ real_t randomness;
+ float time;
+ float delta;
+
+ uint32_t frame;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
+
+ uint32_t random_seed;
+ uint32_t attractor_count;
+ uint32_t collider_count;
+ float particle_size;
+
+ float emission_transform[16];
+
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
+};
+
+struct ParticleEmissionBufferData {
+};
+
+struct ParticleEmissionBuffer {
+ struct Data {
+ float xform[16];
+ float velocity[3];
+ uint32_t flags;
+ float color[4];
+ float custom[4];
+ };
+
+ int32_t particle_count;
+ int32_t particle_max;
+ uint32_t pad1;
+ uint32_t pad2;
+ Data data[1]; //its 2020 and empty arrays are still non standard in C++
+};
+
+struct Particles {
+ RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
+ bool inactive = true;
+ double inactive_time = 0.0;
+ bool emitting = false;
+ bool one_shot = false;
+ int amount = 0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
+ real_t explosiveness = 0.0;
+ real_t randomness = 0.0;
+ bool restart_request = false;
+ AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
+ bool use_local_coords = true;
+ bool has_collision_cache = false;
+
+ bool has_sdf_collision = false;
+ Transform2D sdf_collision_transform;
+ Rect2 sdf_collision_to_screen;
+ RID sdf_collision_texture;
+
+ RID process_material;
+ uint32_t frame_counter = 0;
+ RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
+
+ RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
+
+ Vector<RID> draw_passes;
+ Vector<Transform3D> trail_bind_poses;
+ bool trail_bind_poses_dirty = false;
+ RID trail_bind_pose_buffer;
+ RID trail_bind_pose_uniform_set;
+
+ RID particle_buffer;
+ RID particle_instance_buffer;
+ RID frame_params_buffer;
+
+ uint32_t userdata_count = 0;
+
+ RID particles_material_uniform_set;
+ RID particles_copy_uniform_set;
+ RID particles_transforms_buffer_uniform_set;
+ RID collision_textures_uniform_set;
+
+ RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+ uint32_t collision_3d_textures_used = 0;
+ RID collision_heightmap_texture;
+
+ RID particles_sort_buffer;
+ RID particles_sort_uniform_set;
+
+ bool dirty = false;
+ Particles *update_list = nullptr;
+
+ RID sub_emitter;
+
+ double phase = 0.0;
+ double prev_phase = 0.0;
+ uint64_t prev_ticks = 0;
+ uint32_t random_seed = 0;
+
+ uint32_t cycle_number = 0;
+
+ double speed_scale = 1.0;
+
+ int fixed_fps = 30;
+ bool interpolate = true;
+ bool fractional_delta = false;
+ double frame_remainder = 0;
+ real_t collision_base_size = 0.01;
+
+ bool clear = true;
+
+ bool force_sub_emit = false;
+
+ Transform3D emission_transform;
+
+ Vector<uint8_t> emission_buffer_data;
+
+ ParticleEmissionBuffer *emission_buffer = nullptr;
+ RID emission_storage_buffer;
+
+ Set<RID> collisions;
+
+ RendererStorage::Dependency dependency;
+
+ double trail_length = 1.0;
+ bool trails_enabled = false;
+ LocalVector<ParticlesFrameParams> frame_history;
+ LocalVector<ParticlesFrameParams> trail_params;
+
+ Particles() {
+ }
+};
+
+/* Particles Collision */
+
+struct ParticlesCollision {
+ RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ float radius = 1.0;
+ Vector3 extents = Vector3(1, 1, 1);
+ float attractor_strength = 1.0;
+ float attractor_attenuation = 1.0;
+ float attractor_directionality = 0.0;
+ RID field_texture;
+ RID heightfield_texture;
+ RID heightfield_fb;
+ Size2i heightfield_fb_size;
+
+ RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+
+ RendererStorage::Dependency dependency;
+};
+
+struct ParticlesCollisionInstance {
+ RID collision;
+ Transform3D transform;
+ bool active = false;
+};
+
+class ParticlesStorage : public RendererParticlesStorage {
+private:
+ static ParticlesStorage *singleton;
+
+ /* PARTICLES */
+
+ void _particles_process(Particles *p_particles, double p_delta);
+ void _particles_allocate_emission_buffer(Particles *particles);
+ void _particles_free_data(Particles *particles);
+ void _particles_update_buffers(Particles *particles);
+
+ struct ParticlesShader {
+ struct PushConstant {
+ float lifetime;
+ uint32_t clear;
+ uint32_t total_particles;
+ uint32_t trail_size;
+
+ uint32_t use_fractional_delta;
+ uint32_t sub_emitter_mode;
+ uint32_t can_emit;
+ uint32_t trail_pass;
+ };
+
+ ParticlesShaderRD shader;
+ ShaderCompiler compiler;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ RID base_uniform_set;
+
+ struct CopyPushConstant {
+ float sort_direction[3];
+ uint32_t total_particles;
+
+ uint32_t trail_size;
+ uint32_t trail_total;
+ float frame_delta;
+ float frame_remainder;
+
+ float align_up[3];
+ uint32_t align_mode;
+
+ uint32_t order_by_lifetime;
+ uint32_t lifetime_split;
+ uint32_t lifetime_reverse;
+ uint32_t copy_mode_2d;
+
+ float inv_emission_transform[16];
+ };
+
+ enum {
+ MAX_USERDATAS = 6
+ };
+ enum {
+ COPY_MODE_FILL_INSTANCES,
+ COPY_MODE_FILL_SORT_BUFFER,
+ COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER,
+ COPY_MODE_MAX,
+ };
+
+ ParticlesCopyShaderRD copy_shader;
+ RID copy_shader_version;
+ RID copy_pipelines[COPY_MODE_MAX * (MAX_USERDATAS + 1)];
+
+ LocalVector<float> pose_update_buffer;
+
+ } particles_shader;
+
+ Particles *particle_update_list = nullptr;
+
+ mutable RID_Owner<Particles, true> particles_owner;
+
+ /* Particle Shader */
+
+ struct ParticlesShaderData : public ShaderData {
+ bool valid;
+ RID version;
+ bool uses_collision = false;
+
+ //PipelineCacheRD pipelines[SKY_VERSION_MAX];
+ Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ Map<StringName, Map<int, RID>> default_texture_params;
+
+ RID pipeline;
+
+ bool uses_time = false;
+
+ bool userdatas_used[ParticlesShader::MAX_USERDATAS] = {};
+ uint32_t userdata_count = 0;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ ParticlesShaderData();
+ virtual ~ParticlesShaderData();
+ };
+
+ ShaderData *_create_particles_shader_func();
+ static ShaderData *_create_particles_shader_funcs() {
+ return ParticlesStorage::get_singleton()->_create_particles_shader_func();
+ }
+
+ struct ParticlesMaterialData : public MaterialData {
+ ParticlesShaderData *shader_data = nullptr;
+ RID uniform_set;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~ParticlesMaterialData();
+ };
+
+ MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+ static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+ return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
+ }
+
+ /* Particles Collision */
+
+ mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
+
+ mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
+
+public:
+ static ParticlesStorage *get_singleton();
+
+ ParticlesStorage();
+ virtual ~ParticlesStorage();
+
+ /* PARTICLES */
+
+ Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); }
+ bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
+
+ virtual RID particles_allocate() override;
+ virtual void particles_initialize(RID p_particles_collision) override;
+ virtual void particles_free(RID p_rid) override;
+
+ virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
+ virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
+ virtual void particles_set_amount(RID p_particles, int p_amount) override;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
+ virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) override;
+ virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) override;
+ virtual void particles_set_process_material(RID p_particles, RID p_material) override;
+ virtual RID particles_get_process_material(RID p_particles) const override;
+
+ virtual void particles_set_fixed_fps(RID p_particles, int p_fps) override;
+ virtual void particles_set_interpolate(RID p_particles, bool p_enable) override;
+ virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) override;
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
+ virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
+
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
+
+ virtual void particles_restart(RID p_particles) override;
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override;
+
+ virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) override;
+
+ virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) override;
+
+ virtual void particles_set_draw_passes(RID p_particles, int p_count) override;
+ virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) override;
+
+ virtual void particles_request_process(RID p_particles) override;
+ virtual AABB particles_get_current_aabb(RID p_particles) override;
+ virtual AABB particles_get_aabb(RID p_particles) const override;
+
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
+
+ virtual bool particles_get_emitting(RID p_particles) override;
+ virtual int particles_get_draw_passes(RID p_particles) const override;
+ virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const override;
+
+ virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) override;
+
+ virtual bool particles_is_inactive(RID p_particles) const override;
+
+ _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D);
+ return particles->mode;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ r_trail_divisor = particles->trail_bind_poses.size();
+ } else {
+ r_trail_divisor = 1;
+ }
+
+ return particles->amount * r_trail_divisor;
+ }
+
+ _FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, 0);
+
+ return particles->has_collision_cache;
+ }
+
+ _FORCE_INLINE_ uint32_t particles_is_using_local_coords(RID p_particles) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, false);
+
+ return particles->use_local_coords;
+ }
+
+ _FORCE_INLINE_ RID particles_get_instance_buffer_uniform_set(RID p_particles, RID p_shader, uint32_t p_set) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_COND_V(!particles, RID());
+ if (particles->particles_transforms_buffer_uniform_set.is_null()) {
+ _particles_update_buffers(particles);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(particles->particle_instance_buffer);
+ uniforms.push_back(u);
+ }
+
+ particles->particles_transforms_buffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set);
+ }
+
+ return particles->particles_transforms_buffer_uniform_set;
+ }
+
+ virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) override;
+ virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) override;
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) override;
+
+ virtual void update_particles() override;
+
+ /* Particles Collision */
+
+ ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); }
+ bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
+
+ virtual RID particles_collision_allocate() override;
+ virtual void particles_collision_initialize(RID p_particles_collision) override;
+ virtual void particles_collision_free(RID p_rid) override;
+
+ virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) override;
+ virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) override;
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) override; //for spheres
+ virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) override; //for non-spheres
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) override;
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) override;
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) override;
+ virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) override; //for SDF and vector field, heightfield is dynamic
+ virtual void particles_collision_height_field_update(RID p_particles_collision) override; //for SDF and vector field
+ virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) override; //for SDF and vector field
+ virtual AABB particles_collision_get_aabb(RID p_particles_collision) const override;
+ Vector3 particles_collision_get_extents(RID p_particles_collision) const;
+ virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
+ virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+
+ //used from 2D and 3D
+ ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); }
+ bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); }
+
+ virtual RID particles_collision_instance_create(RID p_collision) override;
+ virtual void particles_collision_instance_free(RID p_rid) override;
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) override;
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) override;
+};
+
+} // namespace RendererRD
+
+#endif // !PARTICLES_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index a3ca7d3720..3b52a187f6 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -29,11 +29,34 @@
/*************************************************************************/
#include "texture_storage.h"
-#include "decal_atlas_storage.h"
+
+#include "../renderer_storage_rd.h"
using namespace RendererRD;
///////////////////////////////////////////////////////////////////////////
+// CanvasTexture
+
+void CanvasTexture::clear_sets() {
+ if (cleared_cache) {
+ return;
+ }
+ for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) {
+ for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) {
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) {
+ RD::get_singleton()->free(uniform_sets[i][j]);
+ uniform_sets[i][j] = RID();
+ }
+ }
+ }
+ cleared_cache = true;
+}
+
+CanvasTexture::~CanvasTexture() {
+ clear_sets();
+}
+
+///////////////////////////////////////////////////////////////////////////
// Texture
void Texture::cleanup() {
@@ -124,6 +147,26 @@ TextureStorage::TextureStorage() {
default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_D16_UNORM;
+ tf.width = 4;
+ tf.height = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> sv;
+ sv.resize(16 * 2);
+ uint16_t *ptr = (uint16_t *)sv.ptrw();
+ for (int i = 0; i < 16; i++) {
+ ptr[i] = Math::make_half_float(1.0f);
+ }
+
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(sv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_DEPTH] = RD::get_singleton()->texture_create(tf, RD::TextureView(), vpv);
+ }
+
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
@@ -295,9 +338,64 @@ TextureStorage::TextureStorage() {
default_rd_textures[DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
}
}
+
+ { // default atlas texture
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ //take the chance and initialize decal atlas to something
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ decal_atlas.texture_srgb = decal_atlas.texture;
+ }
+ }
+
+ {
+ Vector<String> sdf_modes;
+ sdf_modes.push_back("\n#define MODE_LOAD\n");
+ sdf_modes.push_back("\n#define MODE_LOAD_SHRINK\n");
+ sdf_modes.push_back("\n#define MODE_PROCESS\n");
+ sdf_modes.push_back("\n#define MODE_PROCESS_OPTIMIZED\n");
+ sdf_modes.push_back("\n#define MODE_STORE\n");
+ sdf_modes.push_back("\n#define MODE_STORE_SHRINK\n");
+
+ rt_sdf.shader.initialize(sdf_modes);
+
+ rt_sdf.shader_version = rt_sdf.shader.version_create();
+
+ for (int i = 0; i < RenderTargetSDF::SHADER_MAX; i++) {
+ rt_sdf.pipelines[i] = RD::get_singleton()->compute_pipeline_create(rt_sdf.shader.version_get_shader(rt_sdf.shader_version, i));
+ }
+ }
}
TextureStorage::~TextureStorage() {
+ rt_sdf.shader.version_free(rt_sdf.shader_version);
+
+ if (decal_atlas.textures.size()) {
+ ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
+ }
+
+ if (decal_atlas.texture.is_valid()) {
+ RD::get_singleton()->free(decal_atlas.texture);
+ }
+
//def textures
for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) {
if (default_rd_textures[i].is_valid()) {
@@ -312,6 +410,168 @@ bool TextureStorage::can_create_resources_async() const {
return true;
}
+/* Canvas Texture API */
+
+RID TextureStorage::canvas_texture_allocate() {
+ return canvas_texture_owner.allocate_rid();
+}
+
+void TextureStorage::canvas_texture_initialize(RID p_rid) {
+ canvas_texture_owner.initialize_rid(p_rid);
+}
+
+void TextureStorage::canvas_texture_free(RID p_rid) {
+ canvas_texture_owner.free(p_rid);
+}
+
+void TextureStorage::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
+ switch (p_channel) {
+ case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: {
+ ct->diffuse = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: {
+ ct->normal_map = p_texture;
+ } break;
+ case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: {
+ ct->specular = p_texture;
+ } break;
+ }
+
+ ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
+ ct->specular_color.r = p_specular_color.r;
+ ct->specular_color.g = p_specular_color.g;
+ ct->specular_color.b = p_specular_color.b;
+ ct->specular_color.a = p_shininess;
+ ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+
+ ct->texture_filter = p_filter;
+ ct->clear_sets();
+}
+
+void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) {
+ CanvasTexture *ct = canvas_texture_owner.get_or_null(p_canvas_texture);
+ ERR_FAIL_NULL(ct);
+ ct->texture_repeat = p_repeat;
+ ct->clear_sets();
+}
+
+bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ CanvasTexture *ct = nullptr;
+ Texture *t = get_texture(p_texture);
+
+ // TODO once we have our texture storage split off we'll look into moving this code into canvas_texture
+
+ if (t) {
+ //regular texture
+ if (!t->canvas_texture) {
+ t->canvas_texture = memnew(CanvasTexture);
+ t->canvas_texture->diffuse = p_texture;
+ }
+
+ ct = t->canvas_texture;
+ } else {
+ ct = get_canvas_texture(p_texture);
+ }
+
+ if (!ct) {
+ return false; //invalid texture RID
+ }
+
+ RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter;
+ ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false);
+
+ RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat;
+ ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false);
+
+ RID uniform_set = ct->uniform_sets[filter][repeat];
+ if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
+ //create and update
+ Vector<RD::Uniform> uniforms;
+ { //diffuse
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 0;
+
+ t = get_texture(ct->diffuse);
+ if (!t) {
+ u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+ ct->size_cache = Size2i(1, 1);
+ } else {
+ u.append_id(t->rd_texture);
+ ct->size_cache = Size2i(t->width_2d, t->height_2d);
+ }
+ uniforms.push_back(u);
+ }
+ { //normal
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+
+ t = get_texture(ct->normal_map);
+ if (!t) {
+ u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL));
+ ct->use_normal_cache = false;
+ } else {
+ u.append_id(t->rd_texture);
+ ct->use_normal_cache = true;
+ }
+ uniforms.push_back(u);
+ }
+ { //specular
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+
+ t = get_texture(ct->specular);
+ if (!t) {
+ u.append_id(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE));
+ ct->use_specular_cache = false;
+ } else {
+ u.append_id(t->rd_texture);
+ ct->use_specular_cache = true;
+ }
+ uniforms.push_back(u);
+ }
+ { //sampler
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 3;
+ u.append_id(material_storage->sampler_rd_get_default(filter, repeat));
+ uniforms.push_back(u);
+ }
+
+ uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set);
+ ct->uniform_sets[filter][repeat] = uniform_set;
+ ct->cleared_cache = false;
+ }
+
+ r_uniform_set = uniform_set;
+ r_size = ct->size_cache;
+ r_specular_shininess = ct->specular_color;
+ r_use_normal = ct->use_normal_cache;
+ r_use_specular = ct->use_specular_cache;
+
+ return true;
+}
+
+/* Texture API */
+
RID TextureStorage::texture_allocate() {
return texture_owner.allocate_rid();
}
@@ -330,7 +590,7 @@ void TextureStorage::texture_free(RID p_texture) {
}
}
- DecalAtlasStorage::get_singleton()->decal_atlas_remove_texture(p_texture);
+ decal_atlas_remove_texture(p_texture);
for (int i = 0; i < t->proxies.size(); i++) {
Texture *p = texture_owner.get_or_null(t->proxies[i]);
@@ -929,7 +1189,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
//delete last, so proxies can be updated
texture_owner.free(p_by_texture);
- DecalAtlasStorage::get_singleton()->decal_atlas_mark_dirty_on_texture(p_texture);
+ decal_atlas_mark_dirty_on_texture(p_texture);
}
void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
@@ -1418,3 +1678,1075 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T
return image;
}
+
+/* DECAL API */
+
+RID TextureStorage::decal_atlas_get_texture() const {
+ return decal_atlas.texture;
+}
+
+RID TextureStorage::decal_atlas_get_texture_srgb() const {
+ return decal_atlas.texture_srgb;
+}
+
+RID TextureStorage::decal_allocate() {
+ return decal_owner.allocate_rid();
+}
+
+void TextureStorage::decal_initialize(RID p_decal) {
+ decal_owner.initialize_rid(p_decal, Decal());
+}
+
+void TextureStorage::decal_free(RID p_rid) {
+ Decal *decal = decal_owner.get_or_null(p_rid);
+ for (int i = 0; i < RS::DECAL_TEXTURE_MAX; i++) {
+ if (decal->textures[i].is_valid() && owns_texture(decal->textures[i])) {
+ texture_remove_from_decal_atlas(decal->textures[i]);
+ }
+ }
+ decal->dependency.deleted_notify(p_rid);
+ decal_owner.free(p_rid);
+}
+
+void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->extents = p_extents;
+ decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ ERR_FAIL_INDEX(p_type, RS::DECAL_TEXTURE_MAX);
+
+ if (decal->textures[p_type] == p_texture) {
+ return;
+ }
+
+ ERR_FAIL_COND(p_texture.is_valid() && !owns_texture(p_texture));
+
+ if (decal->textures[p_type].is_valid() && owns_texture(decal->textures[p_type])) {
+ texture_remove_from_decal_atlas(decal->textures[p_type]);
+ }
+
+ decal->textures[p_type] = p_texture;
+
+ if (decal->textures[p_type].is_valid()) {
+ texture_add_to_decal_atlas(decal->textures[p_type]);
+ }
+
+ decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL);
+}
+
+void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->emission_energy = p_energy;
+}
+
+void TextureStorage::decal_set_albedo_mix(RID p_decal, float p_mix) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->albedo_mix = p_mix;
+}
+
+void TextureStorage::decal_set_modulate(RID p_decal, const Color &p_modulate) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->modulate = p_modulate;
+}
+
+void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->cull_mask = p_layers;
+ decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+}
+
+void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->distance_fade = p_enabled;
+ decal->distance_fade_begin = p_begin;
+ decal->distance_fade_length = p_length;
+}
+
+void TextureStorage::decal_set_fade(RID p_decal, float p_above, float p_below) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->upper_fade = p_above;
+ decal->lower_fade = p_below;
+}
+
+void TextureStorage::decal_set_normal_fade(RID p_decal, float p_fade) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND(!decal);
+ decal->normal_fade = p_fade;
+}
+
+void TextureStorage::decal_atlas_mark_dirty_on_texture(RID p_texture) {
+ if (decal_atlas.textures.has(p_texture)) {
+ //belongs to decal atlas..
+
+ decal_atlas.dirty = true; //mark it dirty since it was most likely modified
+ }
+}
+
+void TextureStorage::decal_atlas_remove_texture(RID p_texture) {
+ if (decal_atlas.textures.has(p_texture)) {
+ decal_atlas.textures.erase(p_texture);
+ //there is not much a point of making it dirty, just let it be.
+ }
+}
+
+AABB TextureStorage::decal_get_aabb(RID p_decal) const {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND_V(!decal, AABB());
+
+ return AABB(-decal->extents, decal->extents * 2.0);
+}
+
+void TextureStorage::update_decal_atlas() {
+ EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+ ERR_FAIL_NULL(effects);
+
+ if (!decal_atlas.dirty) {
+ return; //nothing to do
+ }
+
+ decal_atlas.dirty = false;
+
+ if (decal_atlas.texture.is_valid()) {
+ RD::get_singleton()->free(decal_atlas.texture);
+ decal_atlas.texture = RID();
+ decal_atlas.texture_srgb = RID();
+ decal_atlas.texture_mipmaps.clear();
+ }
+
+ int border = 1 << decal_atlas.mipmaps;
+
+ if (decal_atlas.textures.size()) {
+ //generate atlas
+ Vector<DecalAtlas::SortItem> itemsv;
+ itemsv.resize(decal_atlas.textures.size());
+ int base_size = 8;
+ const RID *K = nullptr;
+
+ int idx = 0;
+ while ((K = decal_atlas.textures.next(K))) {
+ DecalAtlas::SortItem &si = itemsv.write[idx];
+
+ Texture *src_tex = get_texture(*K);
+
+ si.size.width = (src_tex->width / border) + 1;
+ si.size.height = (src_tex->height / border) + 1;
+ si.pixel_size = Size2i(src_tex->width, src_tex->height);
+
+ if (base_size < si.size.width) {
+ base_size = nearest_power_of_2_templated(si.size.width);
+ }
+
+ si.texture = *K;
+ idx++;
+ }
+
+ //sort items by size
+ itemsv.sort();
+
+ //attempt to create atlas
+ int item_count = itemsv.size();
+ DecalAtlas::SortItem *items = itemsv.ptrw();
+
+ int atlas_height = 0;
+
+ while (true) {
+ Vector<int> v_offsetsv;
+ v_offsetsv.resize(base_size);
+
+ int *v_offsets = v_offsetsv.ptrw();
+ memset(v_offsets, 0, sizeof(int) * base_size);
+
+ int max_height = 0;
+
+ for (int i = 0; i < item_count; i++) {
+ //best fit
+ DecalAtlas::SortItem &si = items[i];
+ int best_idx = -1;
+ int best_height = 0x7FFFFFFF;
+ for (int j = 0; j <= base_size - si.size.width; j++) {
+ int height = 0;
+ for (int k = 0; k < si.size.width; k++) {
+ int h = v_offsets[k + j];
+ if (h > height) {
+ height = h;
+ if (height > best_height) {
+ break; //already bad
+ }
+ }
+ }
+
+ if (height < best_height) {
+ best_height = height;
+ best_idx = j;
+ }
+ }
+
+ //update
+ for (int k = 0; k < si.size.width; k++) {
+ v_offsets[k + best_idx] = best_height + si.size.height;
+ }
+
+ si.pos.x = best_idx;
+ si.pos.y = best_height;
+
+ if (si.pos.y + si.size.height > max_height) {
+ max_height = si.pos.y + si.size.height;
+ }
+ }
+
+ if (max_height <= base_size * 2) {
+ atlas_height = max_height;
+ break; //good ratio, break;
+ }
+
+ base_size *= 2;
+ }
+
+ decal_atlas.size.width = base_size * border;
+ decal_atlas.size.height = nearest_power_of_2_templated(atlas_height * border);
+
+ for (int i = 0; i < item_count; i++) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(items[i].texture);
+ t->uv_rect.position = items[i].pos * border + Vector2i(border / 2, border / 2);
+ t->uv_rect.size = items[i].pixel_size;
+
+ t->uv_rect.position /= Size2(decal_atlas.size);
+ t->uv_rect.size /= Size2(decal_atlas.size);
+ }
+ } else {
+ //use border as size, so it at least has enough mipmaps
+ decal_atlas.size.width = border;
+ decal_atlas.size.height = border;
+ }
+
+ //blit textures
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = decal_atlas.size.width;
+ tformat.height = decal_atlas.size.height;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+ tformat.mipmaps = decal_atlas.mipmaps;
+ tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_UNORM);
+ tformat.shareable_formats.push_back(RD::DATA_FORMAT_R8G8B8A8_SRGB);
+
+ decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ RD::get_singleton()->texture_clear(decal_atlas.texture, Color(0, 0, 0, 0), 0, decal_atlas.mipmaps, 0, 1);
+
+ {
+ //create the framebuffer
+
+ Size2i s = decal_atlas.size;
+
+ for (int i = 0; i < decal_atlas.mipmaps; i++) {
+ DecalAtlas::MipMap mm;
+ mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), decal_atlas.texture, 0, i);
+ Vector<RID> fb;
+ fb.push_back(mm.texture);
+ mm.fb = RD::get_singleton()->framebuffer_create(fb);
+ mm.size = s;
+ decal_atlas.texture_mipmaps.push_back(mm);
+
+ s.width = MAX(1, s.width >> 1);
+ s.height = MAX(1, s.height >> 1);
+ }
+ {
+ //create the SRGB variant
+ RD::TextureView rd_view;
+ rd_view.format_override = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ decal_atlas.texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, decal_atlas.texture);
+ }
+ }
+
+ RID prev_texture;
+ for (int i = 0; i < decal_atlas.texture_mipmaps.size(); i++) {
+ const DecalAtlas::MipMap &mm = decal_atlas.texture_mipmaps[i];
+
+ Color clear_color(0, 0, 0, 0);
+
+ if (decal_atlas.textures.size()) {
+ if (i == 0) {
+ Vector<Color> cc;
+ cc.push_back(clear_color);
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(mm.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, cc);
+
+ const RID *K = nullptr;
+ while ((K = decal_atlas.textures.next(K))) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(*K);
+ Texture *src_tex = get_texture(*K);
+ effects->copy_to_atlas_fb(src_tex->rd_texture, mm.fb, t->uv_rect, draw_list, false, t->panorama_to_dp_users > 0);
+ }
+
+ RD::get_singleton()->draw_list_end();
+
+ prev_texture = mm.texture;
+ } else {
+ effects->copy_to_fb_rect(prev_texture, mm.fb, Rect2i(Point2i(), mm.size));
+ prev_texture = mm.texture;
+ }
+ } else {
+ RD::get_singleton()->texture_clear(mm.texture, clear_color, 0, 1, 0, 1);
+ }
+ }
+}
+
+void TextureStorage::texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
+ if (!decal_atlas.textures.has(p_texture)) {
+ DecalAtlas::Texture t;
+ t.users = 1;
+ t.panorama_to_dp_users = p_panorama_to_dp ? 1 : 0;
+ decal_atlas.textures[p_texture] = t;
+ decal_atlas.dirty = true;
+ } else {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ t->users++;
+ if (p_panorama_to_dp) {
+ t->panorama_to_dp_users++;
+ }
+ }
+}
+
+void TextureStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ ERR_FAIL_COND(!t);
+ t->users--;
+ if (p_panorama_to_dp) {
+ ERR_FAIL_COND(t->panorama_to_dp_users == 0);
+ t->panorama_to_dp_users--;
+ }
+ if (t->users == 0) {
+ decal_atlas.textures.erase(p_texture);
+ //do not mark it dirty, there is no need to since it remains working
+ }
+}
+
+/* RENDER TARGET API */
+
+void TextureStorage::_clear_render_target(RenderTarget *rt) {
+ //free in reverse dependency order
+ if (rt->framebuffer.is_valid()) {
+ RD::get_singleton()->free(rt->framebuffer);
+ rt->framebuffer_uniform_set = RID(); //chain deleted
+ }
+
+ if (rt->color.is_valid()) {
+ RD::get_singleton()->free(rt->color);
+ }
+
+ if (rt->backbuffer.is_valid()) {
+ RD::get_singleton()->free(rt->backbuffer);
+ rt->backbuffer = RID();
+ rt->backbuffer_mipmaps.clear();
+ rt->backbuffer_uniform_set = RID(); //chain deleted
+ }
+
+ _render_target_clear_sdf(rt);
+
+ rt->framebuffer = RID();
+ rt->color = RID();
+}
+
+void TextureStorage::_update_render_target(RenderTarget *rt) {
+ if (rt->texture.is_null()) {
+ //create a placeholder until updated
+ rt->texture = texture_allocate();
+ texture_2d_placeholder_initialize(rt->texture);
+ Texture *tex = get_texture(rt->texture);
+ tex->is_render_target = true;
+ }
+
+ _clear_render_target(rt);
+
+ if (rt->size.width == 0 || rt->size.height == 0) {
+ return;
+ }
+ //until we implement support for HDR monitors (and render target is attached to screen), this is enough.
+ rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
+ rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
+
+ RD::TextureFormat rd_format;
+ RD::TextureView rd_view;
+ { //attempt register
+ rd_format.format = rt->color_format;
+ rd_format.width = rt->size.width;
+ rd_format.height = rt->size.height;
+ rd_format.depth = 1;
+ rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
+ rd_format.mipmaps = 1;
+ if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
+ rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ } else {
+ rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+ }
+ rd_format.samples = RD::TEXTURE_SAMPLES_1;
+ rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ rd_format.shareable_formats.push_back(rt->color_format);
+ rd_format.shareable_formats.push_back(rt->color_format_srgb);
+ }
+
+ rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
+ ERR_FAIL_COND(rt->color.is_null());
+
+ Vector<RID> fb_textures;
+ fb_textures.push_back(rt->color);
+ rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
+ if (rt->framebuffer.is_null()) {
+ _clear_render_target(rt);
+ ERR_FAIL_COND(rt->framebuffer.is_null());
+ }
+
+ { //update texture
+
+ Texture *tex = get_texture(rt->texture);
+
+ //free existing textures
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) {
+ RD::get_singleton()->free(tex->rd_texture);
+ }
+ if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) {
+ RD::get_singleton()->free(tex->rd_texture_srgb);
+ }
+
+ tex->rd_texture = RID();
+ tex->rd_texture_srgb = RID();
+
+ //create shared textures to the color buffer,
+ //so transparent can be supported
+ RD::TextureView view;
+ view.format_override = rt->color_format;
+ if (!rt->flags[RENDER_TARGET_TRANSPARENT]) {
+ view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE;
+ }
+ tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
+ if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
+ view.format_override = rt->color_format_srgb;
+ tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
+ }
+ tex->rd_view = view;
+ tex->width = rt->size.width;
+ tex->height = rt->size.height;
+ tex->width_2d = rt->size.width;
+ tex->height_2d = rt->size.height;
+ tex->rd_format = rt->color_format;
+ tex->rd_format_srgb = rt->color_format_srgb;
+ tex->format = rt->image_format;
+
+ Vector<RID> proxies = tex->proxies; //make a copy, since update may change it
+ for (int i = 0; i < proxies.size(); i++) {
+ texture_proxy_update(proxies[i], rt->texture);
+ }
+ }
+}
+
+void TextureStorage::_create_render_target_backbuffer(RenderTarget *rt) {
+ ERR_FAIL_COND(rt->backbuffer.is_valid());
+
+ uint32_t mipmaps_required = Image::get_image_required_mipmaps(rt->size.width, rt->size.height, Image::FORMAT_RGBA8);
+ RD::TextureFormat tf;
+ tf.format = rt->color_format;
+ tf.width = rt->size.width;
+ tf.height = rt->size.height;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tf.mipmaps = mipmaps_required;
+
+ rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rt->backbuffer, "Render Target Back Buffer");
+ rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0);
+ RD::get_singleton()->set_resource_name(rt->backbuffer_mipmap0, "Back Buffer slice mipmap 0");
+
+ {
+ Vector<RID> fb_tex;
+ fb_tex.push_back(rt->backbuffer_mipmap0);
+ rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+
+ if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) {
+ //the new one will require the backbuffer.
+ RD::get_singleton()->free(rt->framebuffer_uniform_set);
+ rt->framebuffer_uniform_set = RID();
+ }
+ //create mipmaps
+ for (uint32_t i = 1; i < mipmaps_required; i++) {
+ RID mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i);
+ RD::get_singleton()->set_resource_name(mipmap, "Back Buffer slice mip: " + itos(i));
+
+ rt->backbuffer_mipmaps.push_back(mipmap);
+ }
+}
+
+RID TextureStorage::render_target_create() {
+ RenderTarget render_target;
+
+ render_target.was_used = false;
+ render_target.clear_requested = false;
+
+ for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) {
+ render_target.flags[i] = false;
+ }
+ _update_render_target(&render_target);
+ return render_target_owner.make_rid(render_target);
+}
+
+void TextureStorage::render_target_free(RID p_rid) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_rid);
+
+ _clear_render_target(rt);
+
+ if (rt->texture.is_valid()) {
+ Texture *tex = get_texture(rt->texture);
+ tex->is_render_target = false;
+ texture_free(rt->texture);
+ }
+
+ render_target_owner.free(p_rid);
+}
+
+void TextureStorage::render_target_set_position(RID p_render_target, int p_x, int p_y) {
+ //unused for this render target
+}
+
+void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (rt->size.x != p_width || rt->size.y != p_height || rt->view_count != p_view_count) {
+ rt->size.x = p_width;
+ rt->size.y = p_height;
+ rt->view_count = p_view_count;
+ _update_render_target(rt);
+ }
+}
+
+RID TextureStorage::render_target_get_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->texture;
+}
+
+void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+}
+
+void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->flags[p_flag] = p_value;
+ _update_render_target(rt);
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+ return rt->was_used;
+}
+
+void TextureStorage::render_target_set_as_unused(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->was_used = false;
+}
+
+Size2 TextureStorage::render_target_get_size(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Size2());
+
+ return rt->size;
+}
+
+RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->framebuffer;
+}
+
+RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->color;
+}
+
+RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ return rt->backbuffer;
+}
+
+RID TextureStorage::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ return rt->backbuffer_fb;
+}
+
+void TextureStorage::render_target_request_clear(RID p_render_target, const Color &p_clear_color) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = true;
+ rt->clear_color = p_clear_color;
+}
+
+bool TextureStorage::render_target_is_clear_requested(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+ return rt->clear_requested;
+}
+
+Color TextureStorage::render_target_get_clear_request_color(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Color());
+ return rt->clear_color;
+}
+
+void TextureStorage::render_target_disable_clear_request(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_do_clear_request(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->clear_requested) {
+ return;
+ }
+ Vector<Color> clear_colors;
+ clear_colors.push_back(rt->clear_color);
+ RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
+ RD::get_singleton()->draw_list_end();
+ rt->clear_requested = false;
+}
+
+void TextureStorage::render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (rt->sdf_oversize == p_size && rt->sdf_scale == p_scale) {
+ return;
+ }
+
+ rt->sdf_oversize = p_size;
+ rt->sdf_scale = p_scale;
+
+ _render_target_clear_sdf(rt);
+}
+
+Rect2i TextureStorage::_render_target_get_sdf_rect(const RenderTarget *rt) const {
+ Size2i margin;
+ int scale;
+ switch (rt->sdf_oversize) {
+ case RS::VIEWPORT_SDF_OVERSIZE_100_PERCENT: {
+ scale = 100;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT: {
+ scale = 120;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_150_PERCENT: {
+ scale = 150;
+ } break;
+ case RS::VIEWPORT_SDF_OVERSIZE_200_PERCENT: {
+ scale = 200;
+ } break;
+ default: {
+ }
+ }
+
+ margin = (rt->size * scale / 100) - rt->size;
+
+ Rect2i r(Vector2i(), rt->size);
+ r.position -= margin;
+ r.size += margin * 2;
+
+ return r;
+}
+
+Rect2i TextureStorage::render_target_get_sdf_rect(RID p_render_target) const {
+ const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Rect2i());
+
+ return _render_target_get_sdf_rect(rt);
+}
+
+void TextureStorage::render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->sdf_enabled = p_enabled;
+}
+
+bool TextureStorage::render_target_is_sdf_enabled(RID p_render_target) const {
+ const RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->sdf_enabled;
+}
+
+RID TextureStorage::render_target_get_sdf_texture(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ if (rt->sdf_buffer_read.is_null()) {
+ // no texture, create a dummy one for the 2D uniform set
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ memset(pv.ptrw(), 0, 16 * 4);
+ Vector<Vector<uint8_t>> vpv;
+
+ rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ return rt->sdf_buffer_read;
+}
+
+void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) {
+ ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_valid());
+ if (rt->sdf_buffer_read.is_valid()) {
+ RD::get_singleton()->free(rt->sdf_buffer_read);
+ rt->sdf_buffer_read = RID();
+ }
+
+ Size2i size = _render_target_get_sdf_rect(rt).size;
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8_UNORM;
+ tformat.width = size.width;
+ tformat.height = size.height;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ rt->sdf_buffer_write = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ {
+ Vector<RID> write_fb;
+ write_fb.push_back(rt->sdf_buffer_write);
+ rt->sdf_buffer_write_fb = RD::get_singleton()->framebuffer_create(write_fb);
+ }
+
+ int scale;
+ switch (rt->sdf_scale) {
+ case RS::VIEWPORT_SDF_SCALE_100_PERCENT: {
+ scale = 100;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+ scale = 50;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+ scale = 25;
+ } break;
+ default: {
+ scale = 100;
+ } break;
+ }
+
+ rt->process_size = size * scale / 100;
+ rt->process_size.x = MAX(rt->process_size.x, 1);
+ rt->process_size.y = MAX(rt->process_size.y, 1);
+
+ tformat.format = RD::DATA_FORMAT_R16G16_SINT;
+ tformat.width = rt->process_size.width;
+ tformat.height = rt->process_size.height;
+ tformat.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ rt->sdf_buffer_process[0] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+ rt->sdf_buffer_process[1] = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ tformat.format = RD::DATA_FORMAT_R16_SNORM;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ rt->sdf_buffer_read = RD::get_singleton()->texture_create(tformat, RD::TextureView());
+
+ {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(rt->sdf_buffer_write);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.append_id(rt->sdf_buffer_read);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.append_id(rt->sdf_buffer_process[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 4;
+ u.append_id(rt->sdf_buffer_process[1]);
+ uniforms.push_back(u);
+ }
+
+ rt->sdf_buffer_process_uniform_sets[0] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+ RID aux2 = uniforms.write[2].get_id(0);
+ RID aux3 = uniforms.write[3].get_id(0);
+ uniforms.write[2].set_id(0, aux3);
+ uniforms.write[3].set_id(0, aux2);
+ rt->sdf_buffer_process_uniform_sets[1] = RD::get_singleton()->uniform_set_create(uniforms, rt_sdf.shader.version_get_shader(rt_sdf.shader_version, 0), 0);
+ }
+}
+
+void TextureStorage::_render_target_clear_sdf(RenderTarget *rt) {
+ if (rt->sdf_buffer_read.is_valid()) {
+ RD::get_singleton()->free(rt->sdf_buffer_read);
+ rt->sdf_buffer_read = RID();
+ }
+ if (rt->sdf_buffer_write_fb.is_valid()) {
+ RD::get_singleton()->free(rt->sdf_buffer_write);
+ RD::get_singleton()->free(rt->sdf_buffer_process[0]);
+ RD::get_singleton()->free(rt->sdf_buffer_process[1]);
+ rt->sdf_buffer_write = RID();
+ rt->sdf_buffer_write_fb = RID();
+ rt->sdf_buffer_process[0] = RID();
+ rt->sdf_buffer_process[1] = RID();
+ rt->sdf_buffer_process_uniform_sets[0] = RID();
+ rt->sdf_buffer_process_uniform_sets[1] = RID();
+ }
+}
+
+RID TextureStorage::render_target_get_sdf_framebuffer(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->sdf_buffer_write_fb.is_null()) {
+ _render_target_allocate_sdf(rt);
+ }
+
+ return rt->sdf_buffer_write_fb;
+}
+void TextureStorage::render_target_sdf_process(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ ERR_FAIL_COND(rt->sdf_buffer_write_fb.is_null());
+
+ RenderTargetSDF::PushConstant push_constant;
+
+ Rect2i r = _render_target_get_sdf_rect(rt);
+
+ push_constant.size[0] = r.size.width;
+ push_constant.size[1] = r.size.height;
+ push_constant.stride = 0;
+ push_constant.shift = 0;
+ push_constant.base_size[0] = r.size.width;
+ push_constant.base_size[1] = r.size.height;
+
+ bool shrink = false;
+
+ switch (rt->sdf_scale) {
+ case RS::VIEWPORT_SDF_SCALE_50_PERCENT: {
+ push_constant.size[0] >>= 1;
+ push_constant.size[1] >>= 1;
+ push_constant.shift = 1;
+ shrink = true;
+ } break;
+ case RS::VIEWPORT_SDF_SCALE_25_PERCENT: {
+ push_constant.size[0] >>= 2;
+ push_constant.size[1] >>= 2;
+ push_constant.shift = 2;
+ shrink = true;
+ } break;
+ default: {
+ };
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ /* Load */
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_LOAD_SHRINK : RenderTargetSDF::SHADER_LOAD]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[1], 0); //fill [0]
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+
+ /* Process */
+
+ int stride = nearest_power_of_2_templated(MAX(push_constant.size[0], push_constant.size[1]) / 2);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[RenderTargetSDF::SHADER_PROCESS]);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ bool swap = false;
+
+ //jumpflood
+ while (stride > 0) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+ push_constant.stride = stride;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+ stride /= 2;
+ swap = !swap;
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ /* Store */
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, rt_sdf.pipelines[shrink ? RenderTargetSDF::SHADER_STORE_SHRINK : RenderTargetSDF::SHADER_STORE]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rt->sdf_buffer_process_uniform_sets[swap ? 1 : 0], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(RenderTargetSDF::PushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.size[0], push_constant.size[1], 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void TextureStorage::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) {
+ EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+ ERR_FAIL_NULL(effects);
+
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).intersection(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ //single texture copy for backbuffer
+ //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true);
+ effects->copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true);
+
+ if (!p_gen_mipmaps) {
+ return;
+ }
+ RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps");
+ //then mipmap blur
+ RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps.
+
+ for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+ region.position.x >>= 1;
+ region.position.y >>= 1;
+ region.size.x = MAX(1, region.size.x >> 1);
+ region.size.y = MAX(1, region.size.y >> 1);
+
+ RID mipmap = rt->backbuffer_mipmaps[i];
+ effects->gaussian_blur(prev_texture, mipmap, region, true);
+ prev_texture = mipmap;
+ }
+ RD::get_singleton()->draw_command_end_label();
+}
+
+void TextureStorage::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+ ERR_FAIL_NULL(effects);
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).intersection(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+
+ //single texture copy for backbuffer
+ effects->set_color(rt->backbuffer_mipmap0, p_color, region, true);
+}
+
+void TextureStorage::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ EffectsRD *effects = RendererStorageRD::base_singleton->get_effects();
+ ERR_FAIL_NULL(effects);
+
+ if (!rt->backbuffer.is_valid()) {
+ _create_render_target_backbuffer(rt);
+ }
+
+ Rect2i region;
+ if (p_region == Rect2i()) {
+ region.size = rt->size;
+ } else {
+ region = Rect2i(Size2i(), rt->size).intersection(p_region);
+ if (region.size == Size2i()) {
+ return; //nothing to do
+ }
+ }
+ RD::get_singleton()->draw_command_begin_label("Gaussian Blur Mipmaps2");
+ //then mipmap blur
+ RID prev_texture = rt->backbuffer_mipmap0;
+
+ for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) {
+ region.position.x >>= 1;
+ region.position.y >>= 1;
+ region.size.x = MAX(1, region.size.x >> 1);
+ region.size.y = MAX(1, region.size.y >> 1);
+
+ RID mipmap = rt->backbuffer_mipmaps[i];
+ effects->gaussian_blur(prev_texture, mipmap, region, true);
+ prev_texture = mipmap;
+ }
+ RD::get_singleton()->draw_command_end_label();
+}
+
+RID TextureStorage::render_target_get_framebuffer_uniform_set(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ return rt->framebuffer_uniform_set;
+}
+RID TextureStorage::render_target_get_backbuffer_uniform_set(RID p_render_target) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+ return rt->backbuffer_uniform_set;
+}
+
+void TextureStorage::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->framebuffer_uniform_set = p_uniform_set;
+}
+
+void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+ rt->backbuffer_uniform_set = p_uniform_set;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 5d8d165a08..a6f50803e4 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -31,8 +31,9 @@
#ifndef TEXTURE_STORAGE_RD_H
#define TEXTURE_STORAGE_RD_H
-#include "canvas_texture_storage.h"
#include "core/templates/rid_owner.h"
+#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
+#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/storage/texture_storage.h"
namespace RendererRD {
@@ -42,6 +43,7 @@ enum DefaultRDTexture {
DEFAULT_RD_TEXTURE_BLACK,
DEFAULT_RD_TEXTURE_NORMAL,
DEFAULT_RD_TEXTURE_ANISO,
+ DEFAULT_RD_TEXTURE_DEPTH,
DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
@@ -53,6 +55,27 @@ enum DefaultRDTexture {
DEFAULT_RD_TEXTURE_MAX
};
+class CanvasTexture {
+public:
+ RID diffuse;
+ RID normal_map;
+ RID specular;
+ Color specular_color = Color(1, 1, 1, 1);
+ float shininess = 1.0;
+
+ RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+ RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+ RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+
+ Size2i size_cache = Size2i(1, 1);
+ bool use_normal_cache = false;
+ bool use_specular_cache = false;
+ bool cleared_cache = true;
+
+ void clear_sets();
+ ~CanvasTexture();
+};
+
class Texture {
public:
enum Type {
@@ -117,10 +140,138 @@ public:
void cleanup();
};
+struct DecalAtlas {
+ struct Texture {
+ int panorama_to_dp_users;
+ int users;
+ Rect2 uv_rect;
+ };
+
+ struct SortItem {
+ RID texture;
+ Size2i pixel_size;
+ Size2i size;
+ Point2i pos;
+
+ bool operator<(const SortItem &p_item) const {
+ //sort larger to smaller
+ if (size.height == p_item.size.height) {
+ return size.width > p_item.size.width;
+ } else {
+ return size.height > p_item.size.height;
+ }
+ }
+ };
+
+ HashMap<RID, Texture> textures;
+ bool dirty = true;
+ int mipmaps = 5;
+
+ RID texture;
+ RID texture_srgb;
+ struct MipMap {
+ RID fb;
+ RID texture;
+ Size2i size;
+ };
+ Vector<MipMap> texture_mipmaps;
+
+ Size2i size;
+};
+
+struct Decal {
+ Vector3 extents = Vector3(1, 1, 1);
+ RID textures[RS::DECAL_TEXTURE_MAX];
+ float emission_energy = 1.0;
+ float albedo_mix = 1.0;
+ Color modulate = Color(1, 1, 1, 1);
+ uint32_t cull_mask = (1 << 20) - 1;
+ float upper_fade = 0.3;
+ float lower_fade = 0.3;
+ bool distance_fade = false;
+ float distance_fade_begin = 10;
+ float distance_fade_length = 1;
+ float normal_fade = 0.0;
+
+ RendererStorage::Dependency dependency;
+};
+
+struct RenderTarget {
+ Size2i size;
+ uint32_t view_count;
+ RID framebuffer;
+ RID color;
+
+ //used for retrieving from CPU
+ RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ Image::Format image_format = Image::FORMAT_L8;
+
+ bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX];
+
+ bool sdf_enabled = false;
+
+ RID backbuffer; //used for effects
+ RID backbuffer_fb;
+ RID backbuffer_mipmap0;
+
+ Vector<RID> backbuffer_mipmaps;
+
+ RID framebuffer_uniform_set;
+ RID backbuffer_uniform_set;
+
+ RID sdf_buffer_write;
+ RID sdf_buffer_write_fb;
+ RID sdf_buffer_process[2];
+ RID sdf_buffer_read;
+ RID sdf_buffer_process_uniform_sets[2];
+ RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
+ RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
+ Size2i process_size;
+
+ //texture generated for this owner (nor RD).
+ RID texture;
+ bool was_used;
+
+ //clear request
+ bool clear_requested;
+ Color clear_color;
+};
+
+struct RenderTargetSDF {
+ enum {
+ SHADER_LOAD,
+ SHADER_LOAD_SHRINK,
+ SHADER_PROCESS,
+ SHADER_PROCESS_OPTIMIZED,
+ SHADER_STORE,
+ SHADER_STORE_SHRINK,
+ SHADER_MAX
+ };
+
+ struct PushConstant {
+ int32_t size[2];
+ int32_t stride;
+ int32_t shift;
+ int32_t base_size[2];
+ int32_t pad[2];
+ };
+
+ CanvasSdfShaderRD shader;
+ RID shader_version;
+ RID pipelines[SHADER_MAX];
+};
+
class TextureStorage : public RendererTextureStorage {
private:
static TextureStorage *singleton;
+ /* Canvas Texture API */
+
+ RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner;
+
+ /* Texture API */
+
//textures can be created from threads, so this RID_Owner is thread safe
mutable RID_Owner<Texture, true> texture_owner;
@@ -144,6 +295,25 @@ private:
Ref<Image> _validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format);
void _texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0, bool p_immediate = false);
+ /* DECAL API */
+
+ DecalAtlas decal_atlas;
+
+ mutable RID_Owner<Decal, true> decal_owner;
+
+ /* RENDER TARGET API */
+
+ mutable RID_Owner<RenderTarget> render_target_owner;
+
+ void _clear_render_target(RenderTarget *rt);
+ void _update_render_target(RenderTarget *rt);
+ void _create_render_target_backbuffer(RenderTarget *rt);
+ void _render_target_allocate_sdf(RenderTarget *rt);
+ void _render_target_clear_sdf(RenderTarget *rt);
+ Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
+
+ RenderTargetSDF rt_sdf;
+
public:
static TextureStorage *get_singleton();
@@ -156,6 +326,25 @@ public:
TextureStorage();
virtual ~TextureStorage();
+ /* Canvas Texture API */
+
+ CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
+ bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
+
+ virtual RID canvas_texture_allocate() override;
+ virtual void canvas_texture_initialize(RID p_rid) override;
+ virtual void canvas_texture_free(RID p_rid) override;
+
+ virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) override;
+ virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) override;
+
+ virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) override;
+ virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) override;
+
+ bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular);
+
+ /* Texture API */
+
Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
@@ -223,6 +412,153 @@ public:
}
return Size2i(tex->width_2d, tex->height_2d);
}
+
+ /* DECAL API */
+
+ void update_decal_atlas();
+
+ Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); };
+ bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); };
+
+ RID decal_atlas_get_texture() const;
+ RID decal_atlas_get_texture_srgb() const;
+ _FORCE_INLINE_ Rect2 decal_atlas_get_texture_rect(RID p_texture) {
+ DecalAtlas::Texture *t = decal_atlas.textures.getptr(p_texture);
+ if (!t) {
+ return Rect2();
+ }
+
+ return t->uv_rect;
+ }
+
+ virtual RID decal_allocate() override;
+ virtual void decal_initialize(RID p_decal) override;
+ virtual void decal_free(RID p_rid) override;
+
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) override;
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy) override;
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix) override;
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) override;
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) override;
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) override;
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below) override;
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade) override;
+
+ void decal_atlas_mark_dirty_on_texture(RID p_texture);
+ void decal_atlas_remove_texture(RID p_texture);
+
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override;
+
+ _FORCE_INLINE_ Vector3 decal_get_extents(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->extents;
+ }
+
+ _FORCE_INLINE_ RID decal_get_texture(RID p_decal, RS::DecalTexture p_texture) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->textures[p_texture];
+ }
+
+ _FORCE_INLINE_ Color decal_get_modulate(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->modulate;
+ }
+
+ _FORCE_INLINE_ float decal_get_emission_energy(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->emission_energy;
+ }
+
+ _FORCE_INLINE_ float decal_get_albedo_mix(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->albedo_mix;
+ }
+
+ _FORCE_INLINE_ uint32_t decal_get_cull_mask(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->cull_mask;
+ }
+
+ _FORCE_INLINE_ float decal_get_upper_fade(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->upper_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_lower_fade(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->lower_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_normal_fade(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->normal_fade;
+ }
+
+ _FORCE_INLINE_ bool decal_is_distance_fade_enabled(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->distance_fade;
+ }
+
+ _FORCE_INLINE_ float decal_get_distance_fade_begin(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->distance_fade_begin;
+ }
+
+ _FORCE_INLINE_ float decal_get_distance_fade_length(RID p_decal) {
+ const Decal *decal = decal_owner.get_or_null(p_decal);
+ return decal->distance_fade_length;
+ }
+
+ virtual AABB decal_get_aabb(RID p_decal) const override;
+
+ /* RENDER TARGET API */
+
+ RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
+ bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
+
+ virtual RID render_target_create() override;
+ virtual void render_target_free(RID p_rid) override;
+
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
+ virtual RID render_target_get_texture(RID p_render_target) override;
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+ virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override;
+ virtual bool render_target_was_used(RID p_render_target) override;
+ virtual void render_target_set_as_unused(RID p_render_target) override;
+
+ void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
+ void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
+ void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region);
+ RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader);
+
+ virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override;
+ virtual bool render_target_is_clear_requested(RID p_render_target) override;
+ virtual Color render_target_get_clear_request_color(RID p_render_target) override;
+ virtual void render_target_disable_clear_request(RID p_render_target) override;
+ virtual void render_target_do_clear_request(RID p_render_target) override;
+
+ virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override;
+ RID render_target_get_sdf_texture(RID p_render_target);
+ RID render_target_get_sdf_framebuffer(RID p_render_target);
+ void render_target_sdf_process(RID p_render_target);
+ virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override;
+ virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
+ bool render_target_is_sdf_enabled(RID p_render_target) const;
+
+ Size2 render_target_get_size(RID p_render_target);
+ RID render_target_get_rd_framebuffer(RID p_render_target);
+ RID render_target_get_rd_texture(RID p_render_target);
+ RID render_target_get_rd_backbuffer(RID p_render_target);
+ RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
+
+ RID render_target_get_framebuffer_uniform_set(RID p_render_target);
+ RID render_target_get_backbuffer_uniform_set(RID p_render_target);
+
+ void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set);
+ void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set);
};
} // namespace RendererRD
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 1304c811f7..55193a45f0 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -228,7 +228,7 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
voxel_gi->lights.insert(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
- RSG::storage->particles_add_collision(A->base, collision->instance);
+ RSG::particles_storage->particles_add_collision(A->base, collision->instance);
}
}
@@ -344,7 +344,7 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
voxel_gi->lights.erase(A);
} else if (B->base_type == RS::INSTANCE_PARTICLES_COLLISION && A->base_type == RS::INSTANCE_PARTICLES) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(B->base_data);
- RSG::storage->particles_remove_collision(A->base, collision->instance);
+ RSG::particles_storage->particles_remove_collision(A->base, collision->instance);
}
}
@@ -521,7 +521,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
- if (scenario && instance->visible && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (scenario && instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
scenario->dynamic_lights.erase(light->instance);
}
@@ -619,7 +619,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = memnew(InstanceLightData);
- if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
+ if (scenario && RSG::light_storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) {
light->D = scenario->directional_lights.push_back(instance);
}
@@ -659,8 +659,8 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
} break;
case RS::INSTANCE_PARTICLES_COLLISION: {
InstanceParticlesCollisionData *collision = memnew(InstanceParticlesCollisionData);
- collision->instance = RSG::storage->particles_collision_instance_create(p_base);
- RSG::storage->particles_collision_instance_set_active(collision->instance, instance->visible);
+ collision->instance = RSG::particles_storage->particles_collision_instance_create(p_base);
+ RSG::particles_storage->particles_collision_instance_set_active(collision->instance, instance->visible);
instance->base_data = collision;
} break;
case RS::INSTANCE_FOG_VOLUME: {
@@ -801,7 +801,7 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
- if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
+ if (RSG::light_storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) {
light->D = scenario->directional_lights.push_back(instance);
}
} break;
@@ -930,7 +930,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
if (instance->base_type == RS::INSTANCE_LIGHT) {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
- if (instance->scenario && RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ if (instance->scenario && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
if (p_visible) {
instance->scenario->dynamic_lights.push_back(light->instance);
} else {
@@ -941,7 +941,7 @@ void RendererSceneCull::instance_set_visible(RID p_instance, bool p_visible) {
if (instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
- RSG::storage->particles_collision_instance_set_active(collision->instance, p_visible);
+ RSG::particles_storage->particles_collision_instance_set_active(collision->instance, p_visible);
}
if (instance->base_type == RS::INSTANCE_FOG_VOLUME) {
@@ -1490,8 +1490,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb));
light->shadow_dirty = true;
- RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base);
- if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
+ RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);
+ if (RSG::light_storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) {
if (p_instance->visible && p_instance->scenario && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
p_instance->scenario->dynamic_lights.erase(light->instance);
}
@@ -1503,7 +1503,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
}
}
- uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base);
+ uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(p_instance->base);
if (light->max_sdfgi_cascade != max_sdfgi_cascade) {
light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario
}
@@ -1529,15 +1529,15 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
scene_render->voxel_gi_instance_set_transform_to_data(voxel_gi->probe_instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
- RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
+ RSG::particles_storage->particles_set_emission_transform(p_instance->base, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES_COLLISION) {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(p_instance->base_data);
//remove materials no longer used and un-own them
- if (RSG::storage->particles_collision_is_heightfield(p_instance->base)) {
+ if (RSG::particles_storage->particles_collision_is_heightfield(p_instance->base)) {
heightfield_particle_colliders_update_list.insert(p_instance);
}
- RSG::storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
+ RSG::particles_storage->particles_collision_instance_set_transform(collision->instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_FOG_VOLUME) {
InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(p_instance->base_data);
scene_render->fog_volume_instance_set_transform(volume->instance, p_instance->transform);
@@ -1646,8 +1646,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);
idata.instance_data_rid = light_data->instance.get_id();
- light_data->uses_projector = RSG::storage->light_has_projector(p_instance->base);
- light_data->uses_softshadow = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;
+ light_data->uses_projector = RSG::light_storage->light_has_projector(p_instance->base);
+ light_data->uses_softshadow = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
@@ -1740,7 +1740,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
pair.pair_mask |= RS::INSTANCE_GEOMETRY_MASK;
pair.bvh = &p_instance->scenario->indexers[Scenario::INDEXER_GEOMETRY];
- if (RSG::storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) {
+ if (RSG::light_storage->light_get_bake_mode(p_instance->base) == RS::LIGHT_BAKE_DYNAMIC) {
pair.pair_mask |= (1 << RS::INSTANCE_VOXEL_GI);
pair.bvh2 = &p_instance->scenario->indexers[Scenario::INDEXER_VOLUMES];
}
@@ -1864,12 +1864,12 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
if (p_instance->custom_aabb) {
new_aabb = *p_instance->custom_aabb;
} else {
- new_aabb = RSG::storage->particles_get_aabb(p_instance->base);
+ new_aabb = RSG::particles_storage->particles_get_aabb(p_instance->base);
}
} break;
case RenderingServer::INSTANCE_PARTICLES_COLLISION: {
- new_aabb = RSG::storage->particles_collision_get_aabb(p_instance->base);
+ new_aabb = RSG::particles_storage->particles_collision_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_FOG_VOLUME: {
@@ -1879,15 +1879,15 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_LIGHT: {
- new_aabb = RSG::storage->light_get_aabb(p_instance->base);
+ new_aabb = RSG::light_storage->light_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_REFLECTION_PROBE: {
- new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base);
+ new_aabb = RSG::light_storage->reflection_probe_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_DECAL: {
- new_aabb = RSG::decal_atlas_storage->decal_get_aabb(p_instance->base);
+ new_aabb = RSG::texture_storage->decal_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_VOXEL_GI: {
@@ -1895,7 +1895,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
} break;
case RenderingServer::INSTANCE_LIGHTMAP: {
- new_aabb = RSG::storage->lightmap_get_aabb(p_instance->base);
+ new_aabb = RSG::light_storage->lightmap_get_aabb(p_instance->base);
} break;
default: {
@@ -1923,7 +1923,7 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
for (Set<Instance *>::Element *E = geom->lightmap_captures.front(); E; E = E->next()) {
Instance *lightmap = E->get();
- bool interior = RSG::storage->lightmap_is_interior(lightmap->base);
+ bool interior = RSG::light_storage->lightmap_is_interior(lightmap->base);
if (inside && !interior) {
continue; //we are inside, ignore exteriors
@@ -1934,13 +1934,13 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
Vector3 lm_pos = to_bounds.xform(center);
- AABB bounds = RSG::storage->lightmap_get_aabb(lightmap->base);
+ AABB bounds = RSG::light_storage->lightmap_get_aabb(lightmap->base);
if (!bounds.has_point(lm_pos)) {
continue; //not in this lightmap
}
Color sh[9];
- RSG::storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
+ RSG::light_storage->lightmap_tap_sh_light(lightmap->base, lm_pos, sh);
//rotate it
Basis rot = lightmap->transform.basis.orthonormalized();
@@ -1997,19 +1997,19 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
light_transform.orthonormalize(); //scale does not count on lights
real_t max_distance = p_cam_projection.get_z_far();
- real_t shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+ real_t shadow_max = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera
max_distance = MIN(shadow_max, max_distance);
}
max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001);
real_t min_distance = MIN(p_cam_projection.get_z_near(), max_distance);
- real_t pancake_size = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+ real_t pancake_size = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
real_t range = max_distance - min_distance;
int splits = 0;
- switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
+ switch (RSG::light_storage->light_directional_get_shadow_mode(p_instance->base)) {
case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
splits = 1;
break;
@@ -2025,14 +2025,14 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
distances[0] = min_distance;
for (int i = 0; i < splits; i++) {
- distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
+ distances[i + 1] = min_distance + RSG::light_storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range;
};
distances[splits] = max_distance;
real_t texture_size = scene_render->get_directional_light_shadow_size(light->instance);
- bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base);
+ bool overlap = RSG::light_storage->light_directional_get_blend_splits(p_instance->base);
cull.shadow_count = p_shadow_index + 1;
cull.shadows[p_shadow_index].cascade_count = splits;
@@ -2139,7 +2139,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
z_min_cam = z_vec.dot(center) - radius;
{
- float soft_shadow_angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
+ float soft_shadow_angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE);
if (soft_shadow_angle > 0.0) {
float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
@@ -2215,11 +2215,11 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
bool animated_material_found = false;
- switch (RSG::storage->light_get_type(p_instance->base)) {
+ switch (RSG::light_storage->light_get_type(p_instance->base)) {
case RS::LIGHT_DIRECTIONAL: {
} break;
case RS::LIGHT_OMNI: {
- RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base);
+ RS::LightOmniShadowMode shadow_mode = RSG::light_storage->light_omni_get_shadow_mode(p_instance->base);
if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !scene_render->light_instances_can_render_shadow_cube()) {
if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) {
@@ -2229,7 +2229,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
//using this one ensures that raster deferred will have it
RENDER_TIMESTAMP("Cull OmniLight3D Shadow Paraboloid, Half " + itos(i));
- real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
real_t z = i == 0 ? -1 : 1;
Vector<Plane> planes;
@@ -2290,7 +2290,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return true;
}
- real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
CameraMatrix cm;
cm.set_perspective(90, 1, radius * 0.005f, radius);
@@ -2374,8 +2374,8 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return true;
}
- real_t radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
- real_t angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
+ real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
CameraMatrix cm;
cm.set_perspective(angle * 2.0, 1.0, 0.005f * radius, radius);
@@ -2623,7 +2623,7 @@ void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_d
void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cull_result, uint64_t p_from, uint64_t p_to) {
uint64_t frame_number = RSG::rasterizer->get_frame_number();
- float lightmap_probe_update_speed = RSG::storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
+ float lightmap_probe_update_speed = RSG::light_storage->lightmap_get_probe_capture_update_speed() * RSG::rasterizer->get_frame_delta_time();
uint32_t sdfgi_last_light_index = 0xFFFFFFFF;
uint32_t sdfgi_last_light_cascade = 0xFFFFFFFF;
@@ -2654,7 +2654,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
if (base_type == RS::INSTANCE_LIGHT) {
cull_result.lights.push_back(idata.instance);
cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
- if (cull_data.shadow_atlas.is_valid() && RSG::storage->light_has_shadow(idata.base_rid)) {
+ if (cull_data.shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(idata.base_rid)) {
scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
}
@@ -2714,14 +2714,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
mesh_visible = true;
} else if (base_type == RS::INSTANCE_PARTICLES) {
//particles visible? process them
- if (RSG::storage->particles_is_inactive(idata.base_rid)) {
+ if (RSG::particles_storage->particles_is_inactive(idata.base_rid)) {
//but if nothing is going on, don't do it.
keep = false;
} else {
cull_data.cull->lock.lock();
- RSG::storage->particles_request_process(idata.base_rid);
+ RSG::particles_storage->particles_request_process(idata.base_rid);
cull_data.cull->lock.unlock();
- RSG::storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
+ RSG::particles_storage->particles_set_view_axis(idata.base_rid, -cull_data.cam_transform.basis.get_axis(2).normalized(), cull_data.cam_transform.basis.get_axis(1).normalized());
//particles visible? request redraw
RenderingServerDefault::redraw_request();
}
@@ -2948,7 +2948,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
//check shadow..
if (light) {
- if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->base) && !(RSG::storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::storage->light_directional_get_sky_mode(E->base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY)) {
+ if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(E->base) && !(RSG::light_storage->light_get_type(E->base) == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(E->base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY)) {
lights_with_shadow.push_back(E);
}
//add to list
@@ -3070,7 +3070,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
for (uint32_t i = 0; i < (uint32_t)scene_cull_result.lights.size(); i++) {
Instance *ins = scene_cull_result.lights[i];
- if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) {
+ if (!p_shadow_atlas.is_valid() || !RSG::light_storage->light_has_shadow(ins->base)) {
continue;
}
@@ -3087,9 +3087,9 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
// near plane half width and height
Vector2 vp_half_extents = p_camera_data->main_projection.get_viewport_half_extents();
- switch (RSG::storage->light_get_type(ins->base)) {
+ switch (RSG::light_storage->light_get_type(ins->base)) {
case RS::LIGHT_OMNI: {
- float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+ float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
//get two points parallel to near plane
Vector3 points[2] = {
@@ -3112,8 +3112,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y);
} break;
case RS::LIGHT_SPOT: {
- float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
- float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
+ float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
float w = radius * Math::sin(Math::deg2rad(angle));
float d = radius * Math::cos(Math::deg2rad(angle));
@@ -3303,11 +3303,11 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
Vector3(0, -1, 0)
};
- Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base);
- Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base);
- float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
+ Vector3 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base);
+ Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base);
+ float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base);
float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas);
- float mesh_lod_threshold = RSG::storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size;
+ float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size;
Vector3 edge = view_normals[p_step] * extents;
float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
@@ -3325,7 +3325,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RID shadow_atlas;
- bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base);
+ bool use_shadows = RSG::light_storage->reflection_probe_renders_shadows(p_instance->base);
if (use_shadows) {
shadow_atlas = scenario->reflection_probe_shadow_atlas;
}
@@ -3341,7 +3341,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(xform, cm, false, false);
- _render_scene(&camera_data, RID(), environment, RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
+ _render_scene(&camera_data, RID(), environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done
@@ -3363,7 +3363,7 @@ void RendererSceneCull::render_probes() {
SelfList<InstanceReflectionProbeData> *next = ref_probe->next();
RID base = ref_probe->self()->owner->base;
- switch (RSG::storage->reflection_probe_get_update_mode(base)) {
+ switch (RSG::light_storage->reflection_probe_get_update_mode(base)) {
case RS::REFLECTION_PROBE_UPDATE_ONCE: {
if (busy) { //already rendering something
break;
@@ -3432,16 +3432,16 @@ void RendererSceneCull::render_probes() {
if (
instance_caches[idx] != instance_light->instance ||
- cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
- cache->type != RSG::storage->light_get_type(instance->base) ||
+ cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||
+ cache->type != RSG::light_storage->light_get_type(instance->base) ||
cache->transform != instance->transform ||
- cache->color != RSG::storage->light_get_color(instance->base) ||
- cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
- cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
- cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
- cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
- cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
- cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
+ cache->color != RSG::light_storage->light_get_color(instance->base) ||
+ cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+ cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+ cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+ cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+ cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+ cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) {
cache_dirty = true;
}
}
@@ -3463,17 +3463,17 @@ void RendererSceneCull::render_probes() {
if (
instance_caches[idx] != instance_light->instance ||
- cache->has_shadow != RSG::storage->light_has_shadow(instance->base) ||
- cache->type != RSG::storage->light_get_type(instance->base) ||
+ cache->has_shadow != RSG::light_storage->light_has_shadow(instance->base) ||
+ cache->type != RSG::light_storage->light_get_type(instance->base) ||
cache->transform != instance->transform ||
- cache->color != RSG::storage->light_get_color(instance->base) ||
- cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
- cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
- cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
- cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
- cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
- cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
- cache->sky_mode != RSG::storage->light_directional_get_sky_mode(instance->base)) {
+ cache->color != RSG::light_storage->light_get_color(instance->base) ||
+ cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+ cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
+ cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
+ cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
+ cache->spot_angle != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) ||
+ cache->spot_attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION) ||
+ cache->sky_mode != RSG::light_storage->light_directional_get_sky_mode(instance->base)) {
cache_dirty = true;
}
}
@@ -3509,16 +3509,16 @@ void RendererSceneCull::render_probes() {
InstanceVoxelGIData::LightCache *cache = &caches[idx];
instance_caches[idx] = instance_light->instance;
- cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
- cache->type = RSG::storage->light_get_type(instance->base);
+ cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);
+ cache->type = RSG::light_storage->light_get_type(instance->base);
cache->transform = instance->transform;
- cache->color = RSG::storage->light_get_color(instance->base);
- cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
- cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
- cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
- cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
- cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ cache->color = RSG::light_storage->light_get_color(instance->base);
+ cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+ cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+ cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+ cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -3531,17 +3531,17 @@ void RendererSceneCull::render_probes() {
InstanceVoxelGIData::LightCache *cache = &caches[idx];
instance_caches[idx] = instance_light->instance;
- cache->has_shadow = RSG::storage->light_has_shadow(instance->base);
- cache->type = RSG::storage->light_get_type(instance->base);
+ cache->has_shadow = RSG::light_storage->light_has_shadow(instance->base);
+ cache->type = RSG::light_storage->light_get_type(instance->base);
cache->transform = instance->transform;
- cache->color = RSG::storage->light_get_color(instance->base);
- cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
- cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
- cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
- cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
- cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
- cache->sky_mode = RSG::storage->light_directional_get_sky_mode(instance->base);
+ cache->color = RSG::light_storage->light_get_color(instance->base);
+ cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+ cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
+ cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
+ cache->spot_angle = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
+ cache->spot_attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ cache->sky_mode = RSG::light_storage->light_directional_get_sky_mode(instance->base);
idx++;
}
@@ -3592,7 +3592,7 @@ void RendererSceneCull::render_particle_colliders() {
while (heightfield_particle_colliders_update_list.front()) {
Instance *hfpc = heightfield_particle_colliders_update_list.front()->get();
- if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::storage->particles_collision_is_heightfield(hfpc->base)) {
+ if (hfpc->scenario && hfpc->base_type == RS::INSTANCE_PARTICLES_COLLISION && RSG::particles_storage->particles_collision_is_heightfield(hfpc->base)) {
//update heightfield
instance_cull_result.clear();
scene_cull_result.geometry_instances.clear();
@@ -3686,7 +3686,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
// update the process material dependency
- RID particle_material = RSG::storage->particles_get_process_material(p_instance->base);
+ RID particle_material = RSG::particles_storage->particles_get_process_material(p_instance->base);
if (particle_material.is_valid()) {
RSG::material_storage->material_update_dependency(particle_material, &p_instance->dependency_tracker);
}
@@ -3776,10 +3776,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
- int dp = RSG::storage->particles_get_draw_passes(p_instance->base);
+ int dp = RSG::particles_storage->particles_get_draw_passes(p_instance->base);
for (int i = 0; i < dp; i++) {
- RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i);
+ RID mesh = RSG::particles_storage->particles_get_draw_pass_mesh(p_instance->base, i);
if (!mesh.is_valid()) {
continue;
}
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
index 7bbd414465..ab7dbb87a3 100644
--- a/servers/rendering/renderer_storage.h
+++ b/servers/rendering/renderer_storage.h
@@ -119,80 +119,6 @@ public:
Set<Dependency *> dependencies;
};
- /* Light API */
-
- virtual RID directional_light_allocate() = 0;
- virtual void directional_light_initialize(RID p_rid) = 0;
-
- virtual RID omni_light_allocate() = 0;
- virtual void omni_light_initialize(RID p_rid) = 0;
-
- virtual RID spot_light_allocate() = 0;
- virtual void spot_light_initialize(RID p_rid) = 0;
-
- virtual void light_set_color(RID p_light, const Color &p_color) = 0;
- virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
- virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
- virtual void light_set_projector(RID p_light, RID p_texture) = 0;
- virtual void light_set_negative(RID p_light, bool p_enable) = 0;
- virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
- virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
- virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
- virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
- virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
-
- virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0;
-
- virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0;
- virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
- virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
- virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) = 0;
- virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const = 0;
-
- virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
- virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
-
- virtual bool light_has_shadow(RID p_light) const = 0;
-
- virtual bool light_has_projector(RID p_light) const = 0;
-
- virtual RS::LightType light_get_type(RID p_light) const = 0;
- virtual AABB light_get_aabb(RID p_light) const = 0;
- virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
- virtual Color light_get_color(RID p_light) = 0;
- virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0;
- virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0;
- virtual uint64_t light_get_version(RID p_light) const = 0;
-
- /* PROBE API */
-
- virtual RID reflection_probe_allocate() = 0;
- virtual void reflection_probe_initialize(RID p_rid) = 0;
-
- virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
- virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
- virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
- virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0;
- virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0;
- virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0;
- virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0;
- virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0;
- virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0;
- virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0;
- virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
- virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
- virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
- virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) = 0;
-
- virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
- virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
- virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0;
- virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0;
- virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0;
- virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
- virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
- 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;
/* VOXEL GI API */
@@ -237,103 +163,6 @@ public:
virtual uint32_t voxel_gi_get_version(RID p_probe) = 0;
- /* LIGHTMAP */
-
- virtual RID lightmap_allocate() = 0;
- virtual void lightmap_initialize(RID p_rid) = 0;
-
- virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
- virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
- virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
- virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
- virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
- virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
- virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
- virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0;
- virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0;
- virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0;
- virtual bool lightmap_is_interior(RID p_lightmap) const = 0;
- virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
- virtual float lightmap_get_probe_capture_update_speed() const = 0;
-
- /* PARTICLES */
-
- virtual RID particles_allocate() = 0;
- virtual void particles_initialize(RID p_rid) = 0;
- virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0;
-
- virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0;
- virtual bool particles_get_emitting(RID p_particles) = 0;
-
- virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
- virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
- virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
- virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
- virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
- virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0;
- virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
- virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
- virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
- virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
- virtual RID particles_get_process_material(RID p_particles) const = 0;
- virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
- virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
- virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
- virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
-
- virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
-
- virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
- virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
-
- virtual void particles_restart(RID p_particles) = 0;
- virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
- virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0;
-
- virtual bool particles_is_inactive(RID p_particles) const = 0;
-
- virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0;
-
- virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
- virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0;
-
- virtual void particles_request_process(RID p_particles) = 0;
- virtual AABB particles_get_current_aabb(RID p_particles) = 0;
- virtual AABB particles_get_aabb(RID p_particles) const = 0;
-
- virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
-
- virtual int particles_get_draw_passes(RID p_particles) const = 0;
- virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
-
- virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) = 0;
-
- virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
- virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
-
- virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
-
- virtual void update_particles() = 0;
-
- /* PARTICLES COLLISION */
-
- virtual RID particles_collision_allocate() = 0;
- virtual void particles_collision_initialize(RID p_rid) = 0;
-
- virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
- virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
- virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
- virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
- virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
- virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
- virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
- virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
- virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
- virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
- virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0;
- virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
- virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
-
/* FOG VOLUMES */
virtual RID fog_volume_allocate() = 0;
@@ -355,38 +184,6 @@ public:
virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
- //used from 2D and 3D
- virtual RID particles_collision_instance_create(RID p_collision) = 0;
- virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
- virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
-
- /* RENDER TARGET */
-
- enum RenderTargetFlags {
- RENDER_TARGET_TRANSPARENT,
- RENDER_TARGET_DIRECT_TO_SCREEN,
- RENDER_TARGET_FLAG_MAX
- };
-
- virtual RID render_target_create() = 0;
- virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
- virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
- virtual RID render_target_get_texture(RID p_render_target) = 0;
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
- virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
- virtual bool render_target_was_used(RID p_render_target) = 0;
- virtual void render_target_set_as_unused(RID p_render_target) = 0;
-
- virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
- virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
- virtual Color render_target_get_clear_request_color(RID p_render_target) = 0;
- virtual void render_target_disable_clear_request(RID p_render_target) = 0;
- virtual void render_target_do_clear_request(RID p_render_target) = 0;
-
- virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
- virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
- virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
-
virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
virtual bool free(RID p_rid) = 0;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index f492c5e9bd..8507e20648 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -34,6 +34,7 @@
#include "renderer_canvas_cull.h"
#include "renderer_scene_cull.h"
#include "rendering_server_globals.h"
+#include "storage/texture_storage.h"
static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport, RendererCanvasCull::Canvas *p_canvas, RendererViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
Transform2D xf = p_viewport->global_transform;
@@ -77,23 +78,21 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RSG::scene->free(p_viewport->render_buffers);
p_viewport->render_buffers = RID();
} else {
- float scaling_3d_scale = p_viewport->scaling_3d_scale;
-
+ const float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
bool scaling_enabled = true;
if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
- // FSR is not design for downsampling.
- // Throw a warning and fallback to VIEWPORT_SCALING_3D_MODE_BILINEAR
- WARN_PRINT_ONCE("FSR 3D resolution scaling does not support supersampling. Falling back to bilinear scaling.");
+ // FSR is not designed for downsampling.
+ // Fall back to bilinear scaling.
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
}
if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && !p_viewport->fsr_enabled) {
// FSR is not actually available.
- // Throw a warning and fallback to disable scaling
- WARN_PRINT_ONCE("FSR 3D resolution scaling is not available. Disabling 3D resolution scaling.");
- scaling_enabled = false;
+ // Fall back to bilinear scaling.
+ WARN_PRINT_ONCE("FSR 1.0 3D resolution scaling is not available. Falling back to bilinear 3D resolution scaling.");
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
}
if (scaling_3d_scale == 1.0) {
@@ -224,7 +223,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_configure_3d_render_buffers(p_viewport);
}
- RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
+ RSG::texture_storage->render_target_request_clear(p_viewport->render_target, bgcolor);
if (!scenario_draw_canvas_bg && can_draw_3d) {
_draw_3d(p_viewport);
@@ -245,7 +244,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (p_viewport->sdf_active) {
//process SDF
- Rect2 sdf_rect = RSG::storage->render_target_get_sdf_rect(p_viewport->render_target);
+ Rect2 sdf_rect = RSG::texture_storage->render_target_get_sdf_rect(p_viewport->render_target);
RendererCanvasRender::LightOccluderInstance *occluders = nullptr;
@@ -268,11 +267,11 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
}
RSG::canvas_render->render_sdf(p_viewport->render_target, occluders);
- RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
+ RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, true);
p_viewport->sdf_active = false; // if used, gets set active again
} else {
- RSG::storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
+ RSG::texture_storage->render_target_mark_sdf_enabled(p_viewport->render_target, false);
}
Rect2 shadow_rect;
@@ -531,9 +530,9 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
}
}
- if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) {
+ if (RSG::texture_storage->render_target_is_clear_requested(p_viewport->render_target)) {
//was never cleared in the end, force clear it
- RSG::storage->render_target_do_clear_request(p_viewport->render_target);
+ RSG::texture_storage->render_target_do_clear_request(p_viewport->render_target);
}
if (p_viewport->measure_render_time) {
@@ -597,7 +596,7 @@ void RendererViewport::draw_viewports() {
vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
vp->size = xr_size;
uint32_t view_count = xr_interface->get_view_count();
- RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
+ RSG::texture_storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
// Inform xr interface we're about to render its viewport, if this returns false we don't render
visible = xr_interface->pre_draw_viewport(vp->render_target);
@@ -612,7 +611,7 @@ void RendererViewport::draw_viewports() {
visible = true;
}
- if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::storage->render_target_was_used(vp->render_target)) {
+ if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::texture_storage->render_target_was_used(vp->render_target)) {
visible = true;
}
@@ -643,11 +642,11 @@ void RendererViewport::draw_viewports() {
RENDER_TIMESTAMP("> Render Viewport " + itos(i));
- RSG::storage->render_target_set_as_unused(vp->render_target);
+ RSG::texture_storage->render_target_set_as_unused(vp->render_target);
if (vp->use_xr && xr_interface.is_valid()) {
// check for an external texture destination (disabled for now, not yet supported)
- // RSG::storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
- RSG::storage->render_target_set_external_texture(vp->render_target, 0);
+ // RSG::texture_storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
+ RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
// render...
RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -669,7 +668,7 @@ void RendererViewport::draw_viewports() {
}
}
} else {
- RSG::storage->render_target_set_external_texture(vp->render_target, 0);
+ RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -728,7 +727,7 @@ void RendererViewport::viewport_initialize(RID p_rid) {
viewport_owner.initialize_rid(p_rid);
Viewport *viewport = viewport_owner.get_or_null(p_rid);
viewport->self = p_rid;
- viewport->render_target = RSG::storage->render_target_create();
+ viewport->render_target = RSG::texture_storage->render_target_create();
viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
@@ -810,7 +809,7 @@ void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_heig
viewport->size = Size2(p_width, p_height);
uint32_t view_count = viewport->get_view_count();
- RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
_configure_3d_render_buffers(viewport);
viewport->occlusion_buffer_dirty = true;
@@ -851,8 +850,8 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
- RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
viewport->viewport_to_screen_rect = p_rect;
@@ -860,8 +859,8 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
} else {
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
viewport->viewport_to_screen_rect = Rect2();
@@ -879,17 +878,17 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if disabled, reset render_target size and position
if (!p_enable) {
- RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
}
- RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
+ RSG::texture_storage->render_target_set_flag(viewport->render_target, RendererTextureStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
viewport->viewport_render_direct_to_screen = p_enable;
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
- RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
- RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}
@@ -904,7 +903,7 @@ RID RendererViewport::viewport_get_texture(RID p_viewport) const {
const Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND_V(!viewport, RID());
- return RSG::storage->render_target_get_texture(viewport->render_target);
+ return RSG::texture_storage->render_target_get_texture(viewport->render_target);
}
RID RendererViewport::viewport_get_occluder_debug_texture(RID p_viewport) const {
@@ -997,7 +996,7 @@ void RendererViewport::viewport_set_transparent_background(RID p_viewport, bool
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- RSG::storage->render_target_set_flag(viewport->render_target, RendererStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
+ RSG::texture_storage->render_target_set_flag(viewport->render_target, RendererTextureStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
viewport->transparent_bg = p_enabled;
}
@@ -1180,14 +1179,14 @@ void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::V
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- RSG::storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
+ RSG::texture_storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
}
bool RendererViewport::free(RID p_rid) {
if (viewport_owner.owns(p_rid)) {
Viewport *viewport = viewport_owner.get_or_null(p_rid);
- RSG::storage->free(viewport->render_target);
+ RSG::texture_storage->render_target_free(viewport->render_target);
RSG::scene->free(viewport->shadow_atlas);
if (viewport->render_buffers.is_valid()) {
RSG::scene->free(viewport->render_buffers);
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 2dab7cb84c..e42034dbb9 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -84,7 +84,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
frame_setup_time = double(OS::get_singleton()->get_ticks_usec() - time_usec) / 1000.0;
- RSG::storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
+ RSG::particles_storage->update_particles(); //need to be done after instances are updated (colliders and particle transforms), and colliders are rendered
RSG::scene->render_probes();
@@ -398,10 +398,10 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
RendererSceneCull *sr = memnew(RendererSceneCull);
RSG::scene = sr;
RSG::rasterizer = RendererCompositor::create();
- RSG::canvas_texture_storage = RSG::rasterizer->get_canvas_texture_storage();
- RSG::decal_atlas_storage = RSG::rasterizer->get_decal_atlas_storage();
+ RSG::light_storage = RSG::rasterizer->get_light_storage();
RSG::material_storage = RSG::rasterizer->get_material_storage();
RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
+ RSG::particles_storage = RSG::rasterizer->get_particles_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 cc1edc728a..8dfb5985f8 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -351,8 +351,8 @@ public:
#undef ServerName
#undef server_name
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererLightStorage
+#define server_name RSG::light_storage
FUNCRIDSPLIT(directional_light)
FUNCRIDSPLIT(omni_light)
@@ -394,13 +394,27 @@ public:
FUNC2(reflection_probe_set_resolution, RID, int)
FUNC2(reflection_probe_set_mesh_lod_threshold, RID, float)
+ /* LIGHTMAP */
+
+ FUNCRIDSPLIT(lightmap)
+
+ FUNC3(lightmap_set_textures, RID, RID, bool)
+ FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
+ FUNC2(lightmap_set_probe_interior, RID, bool)
+ FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+ FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
+ FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
+ FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
+ FUNC1(lightmap_set_probe_capture_update_speed, float)
+
/* DECAL API */
#undef ServerName
#undef server_name
-#define ServerName RendererDecalAtlasStorage
-#define server_name RSG::decal_atlas_storage
+#define ServerName RendererTextureStorage
+#define server_name RSG::texture_storage
FUNCRIDSPLIT(decal)
@@ -443,21 +457,13 @@ public:
FUNC2(voxel_gi_set_interior, RID, bool)
FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
- /* LIGHTMAP */
-
- FUNCRIDSPLIT(lightmap)
+ /* PARTICLES */
- FUNC3(lightmap_set_textures, RID, RID, bool)
- FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
- FUNC2(lightmap_set_probe_interior, RID, bool)
- FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
- FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
- FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
- FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
- FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
- FUNC1(lightmap_set_probe_capture_update_speed, float)
+#undef ServerName
+#undef server_name
- /* PARTICLES */
+#define ServerName RendererParticlesStorage
+#define server_name RSG::particles_storage
FUNCRIDSPLIT(particles)
@@ -514,6 +520,12 @@ public:
/* FOG VOLUME */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererStorage
+#define server_name RSG::storage
+
FUNCRIDSPLIT(fog_volume)
FUNC2(fog_volume_set_shape, RID, FogVolumeShape)
@@ -799,7 +811,7 @@ public:
FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
- FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
+ FUNC6(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float, bool)
FUNC5(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float, bool)
FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index 2be87c27b1..4d24dbf3b4 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -32,10 +32,10 @@
bool RenderingServerGlobals::threaded = false;
-RendererCanvasTextureStorage *RenderingServerGlobals::canvas_texture_storage = nullptr;
-RendererDecalAtlasStorage *RenderingServerGlobals::decal_atlas_storage = nullptr;
+RendererLightStorage *RenderingServerGlobals::light_storage = nullptr;
RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;
RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr;
+RendererParticlesStorage *RenderingServerGlobals::particles_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 40fd638425..ce11fae9e8 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -34,10 +34,10 @@
#include "servers/rendering/renderer_canvas_cull.h"
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_scene.h"
-#include "servers/rendering/storage/canvas_texture_storage.h"
-#include "servers/rendering/storage/decal_atlas_storage.h"
+#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/material_storage.h"
#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/particles_storage.h"
#include "servers/rendering/storage/texture_storage.h"
class RendererCanvasCull;
@@ -48,11 +48,11 @@ class RenderingServerGlobals {
public:
static bool threaded;
- static RendererCanvasTextureStorage *canvas_texture_storage;
+ static RendererLightStorage *light_storage;
static RendererMaterialStorage *material_storage;
static RendererMeshStorage *mesh_storage;
+ static RendererParticlesStorage *particles_storage;
static RendererTextureStorage *texture_storage;
- static RendererDecalAtlasStorage *decal_atlas_storage;
static RendererStorage *storage;
static RendererCanvasRender *canvas_render;
static RendererCompositor *rasterizer;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 7acd431397..af5da6ae6f 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -5144,7 +5144,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (!call_expression) {
return nullptr;
}
- data_type = call_expression->get_datatype();
} else if (tk.type == TK_BRACKET_OPEN) { // indexing
index_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (!index_expression) {
@@ -5598,15 +5597,13 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
if (p_block != nullptr) {
p_block->block_tag = SubClassTag::TAG_ARRAY;
}
- Node *call_expression = _parse_and_reduce_expression(p_block, p_function_info);
+ mn->call_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (p_block != nullptr) {
p_block->block_tag = SubClassTag::TAG_GLOBAL;
}
- if (!call_expression) {
+ if (!mn->call_expression) {
return nullptr;
}
- mn->datatype = call_expression->get_datatype();
- mn->call_expression = call_expression;
} else if (tk.type == TK_BRACKET_OPEN) {
Node *index_expression = _parse_and_reduce_expression(p_block, p_function_info);
if (!index_expression) {
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 25ec8760af..66ae220edf 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -451,8 +451,8 @@ public:
int array_size = 0;
bool is_local = false;
- virtual DataType get_datatype() const override { return datatype_cache; }
- virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual DataType get_datatype() const override { return call_expression ? call_expression->get_datatype() : datatype_cache; }
+ virtual String get_datatype_name() const override { return call_expression ? call_expression->get_datatype_name() : String(struct_name); }
virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr; }
@@ -558,8 +558,8 @@ public:
Node *call_expression = nullptr;
bool has_swizzling_duplicates = false;
- virtual DataType get_datatype() const override { return datatype; }
- virtual String get_datatype_name() const override { return String(struct_name); }
+ virtual DataType get_datatype() const override { return call_expression ? call_expression->get_datatype() : datatype; }
+ virtual String get_datatype_name() const override { return call_expression ? call_expression->get_datatype_name() : String(struct_name); }
virtual int get_array_size() const override { return (index_expression || call_expression) ? 0 : array_size; }
virtual bool is_indexed() const override { return index_expression != nullptr || call_expression != nullptr; }
diff --git a/servers/rendering/storage/decal_atlas_storage.h b/servers/rendering/storage/decal_atlas_storage.h
deleted file mode 100644
index 62cd76881b..0000000000
--- a/servers/rendering/storage/decal_atlas_storage.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*************************************************************************/
-/* decal_atlas_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 DECAL_ATLAS_STORAGE_H
-#define DECAL_ATLAS_STORAGE_H
-
-#include "servers/rendering_server.h"
-
-class RendererDecalAtlasStorage {
-public:
- virtual ~RendererDecalAtlasStorage(){};
-
- virtual RID decal_allocate() = 0;
- virtual void decal_initialize(RID p_rid) = 0;
- virtual void decal_free(RID p_rid) = 0;
-
- virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
- virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
- virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
- virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0;
- virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0;
- virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0;
- virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0;
- virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
- virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
-
- virtual AABB decal_get_aabb(RID p_decal) const = 0;
-
- virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
- virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
-};
-
-#endif // !DECAL_ATLAS_STORAGE_H
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
new file mode 100644
index 0000000000..0cb0f35570
--- /dev/null
+++ b/servers/rendering/storage/light_storage.h
@@ -0,0 +1,139 @@
+/*************************************************************************/
+/* light_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 LIGHT_STORAGE_H
+#define LIGHT_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererLightStorage {
+public:
+ virtual ~RendererLightStorage() {}
+
+ /* Light API */
+
+ virtual RID directional_light_allocate() = 0;
+ virtual void directional_light_initialize(RID p_rid) = 0;
+
+ virtual RID omni_light_allocate() = 0;
+ virtual void omni_light_initialize(RID p_rid) = 0;
+
+ virtual RID spot_light_allocate() = 0;
+ virtual void spot_light_initialize(RID p_rid) = 0;
+
+ virtual void light_free(RID p_rid) = 0;
+
+ virtual void light_set_color(RID p_light, const Color &p_color) = 0;
+ virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0;
+ virtual void light_set_shadow(RID p_light, bool p_enabled) = 0;
+ virtual void light_set_projector(RID p_light, RID p_texture) = 0;
+ virtual void light_set_negative(RID p_light, bool p_enable) = 0;
+ virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0;
+ virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) = 0;
+ virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0;
+ virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0;
+ virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0;
+
+ virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0;
+
+ virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0;
+ virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
+ virtual bool light_directional_get_blend_splits(RID p_light) const = 0;
+ virtual void light_directional_set_sky_mode(RID p_light, RS::LightDirectionalSkyMode p_mode) = 0;
+ virtual RS::LightDirectionalSkyMode light_directional_get_sky_mode(RID p_light) const = 0;
+
+ virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0;
+ virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0;
+
+ virtual bool light_has_shadow(RID p_light) const = 0;
+
+ virtual bool light_has_projector(RID p_light) const = 0;
+
+ virtual RS::LightType light_get_type(RID p_light) const = 0;
+ virtual AABB light_get_aabb(RID p_light) const = 0;
+ virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
+ virtual Color light_get_color(RID p_light) = 0;
+ virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0;
+ virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0;
+ virtual uint64_t light_get_version(RID p_light) const = 0;
+
+ /* PROBE API */
+
+ virtual RID reflection_probe_allocate() = 0;
+ virtual void reflection_probe_initialize(RID p_rid) = 0;
+ virtual void reflection_probe_free(RID p_rid) = 0;
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0;
+ virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0;
+ virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0;
+ virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0;
+ virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0;
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0;
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0;
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
+ virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) = 0;
+
+ virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
+ virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0;
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0;
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0;
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0;
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
+ virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
+
+ /* LIGHTMAP */
+
+ virtual RID lightmap_allocate() = 0;
+ virtual void lightmap_initialize(RID p_rid) = 0;
+ virtual void lightmap_free(RID p_rid) = 0;
+
+ virtual void lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) = 0;
+ virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
+ virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
+ virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
+ virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
+ virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
+ virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
+ virtual PackedInt32Array lightmap_get_probe_capture_bsp_tree(RID p_lightmap) const = 0;
+ virtual AABB lightmap_get_aabb(RID p_lightmap) const = 0;
+ virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) = 0;
+ virtual bool lightmap_is_interior(RID p_lightmap) const = 0;
+ virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
+ virtual float lightmap_get_probe_capture_update_speed() const = 0;
+};
+
+#endif // !LIGHT_STORAGE_H
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
new file mode 100644
index 0000000000..268b5473e2
--- /dev/null
+++ b/servers/rendering/storage/particles_storage.h
@@ -0,0 +1,129 @@
+/*************************************************************************/
+/* particles_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 PARTICLES_STORAGE_H
+#define PARTICLES_STORAGE_H
+
+#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
+
+class RendererParticlesStorage {
+public:
+ virtual ~RendererParticlesStorage() {}
+
+ /* PARTICLES */
+
+ virtual RID particles_allocate() = 0;
+ virtual void particles_initialize(RID p_rid) = 0;
+ virtual void particles_free(RID p_rid) = 0;
+
+ virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0;
+
+ virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0;
+ virtual bool particles_get_emitting(RID p_particles) = 0;
+
+ virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
+ virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
+ virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
+ virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
+ virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) = 0;
+ virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) = 0;
+ virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0;
+ virtual void particles_set_speed_scale(RID p_particles, double p_scale) = 0;
+ virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0;
+ virtual void particles_set_process_material(RID p_particles, RID p_material) = 0;
+ virtual RID particles_get_process_material(RID p_particles) const = 0;
+ virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0;
+ virtual void particles_set_interpolate(RID p_particles, bool p_enable) = 0;
+ virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0;
+ virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) = 0;
+
+ virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) = 0;
+
+ virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) = 0;
+ virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) = 0;
+
+ virtual void particles_restart(RID p_particles) = 0;
+ virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) = 0;
+ virtual void particles_set_subemitter(RID p_particles, RID p_subemitter_particles) = 0;
+
+ virtual bool particles_is_inactive(RID p_particles) const = 0;
+
+ virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0;
+
+ virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0;
+ virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0;
+
+ virtual void particles_request_process(RID p_particles) = 0;
+ virtual AABB particles_get_current_aabb(RID p_particles) = 0;
+ virtual AABB particles_get_aabb(RID p_particles) const = 0;
+
+ virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
+
+ virtual int particles_get_draw_passes(RID p_particles) const = 0;
+ virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
+
+ virtual void particles_set_view_axis(RID p_particles, const Vector3 &p_axis, const Vector3 &p_up_axis) = 0;
+
+ virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance) = 0;
+ virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance) = 0;
+
+ virtual void particles_set_canvas_sdf_collision(RID p_particles, bool p_enable, const Transform2D &p_xform, const Rect2 &p_to_screen, RID p_texture) = 0;
+
+ virtual void update_particles() = 0;
+
+ /* PARTICLES COLLISION */
+
+ virtual RID particles_collision_allocate() = 0;
+ virtual void particles_collision_initialize(RID p_rid) = 0;
+ virtual void particles_collision_free(RID p_rid) = 0;
+
+ virtual void particles_collision_set_collision_type(RID p_particles_collision, RS::ParticlesCollisionType p_type) = 0;
+ virtual void particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) = 0;
+ virtual void particles_collision_set_sphere_radius(RID p_particles_collision, real_t p_radius) = 0; //for spheres
+ virtual void particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) = 0; //for non-spheres
+ virtual void particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) = 0;
+ virtual void particles_collision_set_attractor_directionality(RID p_particles_collision, real_t p_directionality) = 0;
+ virtual void particles_collision_set_attractor_attenuation(RID p_particles_collision, real_t p_curve) = 0;
+ virtual void particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) = 0; //for SDF and vector field, heightfield is dynamic
+ virtual void particles_collision_height_field_update(RID p_particles_collision) = 0; //for SDF and vector field
+ virtual void particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) = 0; //for SDF and vector field
+ virtual AABB particles_collision_get_aabb(RID p_particles_collision) const = 0;
+ virtual bool particles_collision_is_heightfield(RID p_particles_collision) const = 0;
+ virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const = 0;
+
+ //used from 2D and 3D
+ virtual RID particles_collision_instance_create(RID p_collision) = 0;
+ virtual void particles_collision_instance_free(RID p_rid) = 0;
+ virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform3D &p_transform) = 0;
+ virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
+};
+
+#endif // !PARTICLES_STORAGE_H
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index bef5e3e146..4c4213d7c1 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -35,6 +35,19 @@
class RendererTextureStorage {
public:
+ /* Canvas Texture API */
+
+ virtual RID canvas_texture_allocate() = 0;
+ virtual void canvas_texture_initialize(RID p_rid) = 0;
+ virtual void canvas_texture_free(RID p_rid) = 0;
+
+ virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0;
+ virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0;
+
+ virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0;
+ virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0;
+
+ /* Texture API */
virtual bool can_create_resources_async() const = 0;
virtual ~RendererTextureStorage(){};
@@ -75,6 +88,55 @@ public:
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
virtual Size2 texture_size_with_proxy(RID p_proxy) = 0;
+
+ /* Decal API */
+ virtual RID decal_allocate() = 0;
+ virtual void decal_initialize(RID p_rid) = 0;
+ virtual void decal_free(RID p_rid) = 0;
+
+ virtual void decal_set_extents(RID p_decal, const Vector3 &p_extents) = 0;
+ virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) = 0;
+ virtual void decal_set_emission_energy(RID p_decal, float p_energy) = 0;
+ virtual void decal_set_albedo_mix(RID p_decal, float p_mix) = 0;
+ virtual void decal_set_modulate(RID p_decal, const Color &p_modulate) = 0;
+ virtual void decal_set_cull_mask(RID p_decal, uint32_t p_layers) = 0;
+ virtual void decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) = 0;
+ virtual void decal_set_fade(RID p_decal, float p_above, float p_below) = 0;
+ virtual void decal_set_normal_fade(RID p_decal, float p_fade) = 0;
+
+ virtual AABB decal_get_aabb(RID p_decal) const = 0;
+
+ virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
+ virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
+
+ /* RENDER TARGET */
+
+ enum RenderTargetFlags {
+ RENDER_TARGET_TRANSPARENT,
+ RENDER_TARGET_DIRECT_TO_SCREEN,
+ RENDER_TARGET_FLAG_MAX
+ };
+
+ virtual RID render_target_create() = 0;
+ virtual void render_target_free(RID p_rid) = 0;
+
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
+ virtual RID render_target_get_texture(RID p_render_target) = 0;
+ virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
+ virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0;
+ virtual bool render_target_was_used(RID p_render_target) = 0;
+ virtual void render_target_set_as_unused(RID p_render_target) = 0;
+
+ virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
+ virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
+ virtual Color render_target_get_clear_request_color(RID p_render_target) = 0;
+ virtual void render_target_disable_clear_request(RID p_render_target) = 0;
+ virtual void render_target_do_clear_request(RID p_render_target) = 0;
+
+ virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
+ virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
+ virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
};
#endif // !TEXTURE_STORAGE_H
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index fa6c3fac68..b58e6138eb 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2566,7 +2566,7 @@ void RenderingServer::_bind_methods() {
/* Primitives */
- ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 94692ba68d..71896e9d11 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -1293,7 +1293,7 @@ public:
NINE_PATCH_TILE_FIT,
};
- virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0) = 0;
+ virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0;
virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0) = 0;
virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 2f32e81f06..7e3fde6a1f 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -395,7 +395,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_range", "shaped"), &TextServer::shaped_text_get_range);
ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND));
- ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks, DEFVAL(GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION));
ClassDB::bind_method(D_METHOD("shaped_text_get_trim_pos", "shaped"), &TextServer::shaped_text_get_trim_pos);
ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_pos", "shaped"), &TextServer::shaped_text_get_ellipsis_pos);
@@ -979,6 +979,14 @@ TextServer::Direction TextServer::shaped_text_get_dominant_direction_in_range(co
}
}
+_FORCE_INLINE_ void _push_range(Vector<Vector2> &r_vector, real_t p_start, real_t p_end) {
+ if (!r_vector.is_empty() && Math::is_equal_approx(r_vector[r_vector.size() - 1].y, p_start, (real_t)UNIT_EPSILON)) {
+ r_vector.write[r_vector.size() - 1].y = p_end;
+ } else {
+ r_vector.push_back(Vector2(p_start, p_end));
+ }
+}
+
Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
Vector<Vector2> ranges;
@@ -1003,7 +1011,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
for (int j = 0; j < glyphs[i].count; j++) {
advance += glyphs[i + j].advance;
}
- ranges.push_back(Vector2(off, off + advance));
+ _push_range(ranges, off, off + advance);
}
// Only start of grapheme is in selection range.
if (glyphs[i].start >= start && glyphs[i].end > end) {
@@ -1013,9 +1021,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + advance));
+ _push_range(ranges, off + char_adv * (glyphs[i].end - end), off + advance);
} else {
- ranges.push_back(Vector2(off, off + char_adv * (end - glyphs[i].start)));
+ _push_range(ranges, off, off + char_adv * (end - glyphs[i].start));
}
}
// Only end of grapheme is in selection range.
@@ -1026,9 +1034,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off, off + char_adv * (glyphs[i].end - start)));
+ _push_range(ranges, off, off + char_adv * (glyphs[i].end - start));
} else {
- ranges.push_back(Vector2(off + char_adv * (start - glyphs[i].start), off + advance));
+ _push_range(ranges, off + char_adv * (start - glyphs[i].start), off + advance);
}
}
// Selection range is within grapheme.
@@ -1039,9 +1047,9 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
- ranges.push_back(Vector2(off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start)));
+ _push_range(ranges, off + char_adv * (glyphs[i].end - end), off + char_adv * (glyphs[i].end - start));
} else {
- ranges.push_back(Vector2(off + char_adv * (start - glyphs[i].start), off + char_adv * (end - glyphs[i].start)));
+ _push_range(ranges, off + char_adv * (start - glyphs[i].start), off + char_adv * (end - glyphs[i].start));
}
}
}
@@ -1050,25 +1058,6 @@ Vector<Vector2> TextServer::shaped_text_get_selection(const RID &p_shaped, int64
}
}
- // Merge intersecting ranges.
- int i = 0;
- while (i < ranges.size()) {
- i++;
- }
- i = 0;
- while (i < ranges.size()) {
- int j = i + 1;
- while (j < ranges.size()) {
- if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) {
- ranges.write[i].y = ranges[j].y;
- ranges.remove_at(j);
- continue;
- }
- j++;
- }
- i++;
- }
-
return ranges;
}
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index 18131c1e89..a0bec0f95b 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -30,6 +30,7 @@
#include "xr_interface_extension.h"
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/rendering_server_globals.h"
@@ -339,10 +340,10 @@ void XRInterfaceExtension::notification(int p_what) {
RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
// In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine.
// So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too.
- RendererStorageRD *rd_storage = RendererStorageRD::base_singleton;
- ERR_FAIL_NULL_V_MSG(rd_storage, RID(), "Renderer storage not setup");
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ ERR_FAIL_NULL_V_MSG(texture_storage, RID(), "Texture storage not setup");
- return rd_storage->render_target_get_rd_texture(p_render_target);
+ return texture_storage->render_target_get_rd_texture(p_render_target);
}
/*
diff --git a/tests/SCsub b/tests/SCsub
index 25b06f2312..c59ce69b92 100644
--- a/tests/SCsub
+++ b/tests/SCsub
@@ -18,11 +18,6 @@ if env_tests["platform"] == "windows":
if env_tests.msvc:
env_tests.Append(CCFLAGS=["/bigobj"])
-env_tests.add_source_files(env.tests_sources, "core/*.cpp")
-env_tests.add_source_files(env.tests_sources, "core/math/*.cpp")
-env_tests.add_source_files(env.tests_sources, "core/templates/*.cpp")
-env_tests.add_source_files(env.tests_sources, "scene/*.cpp")
-env_tests.add_source_files(env.tests_sources, "servers/*.cpp")
env_tests.add_source_files(env.tests_sources, "*.cpp")
lib = env_tests.add_library("tests", env.tests_sources)
diff --git a/tests/core/io/test_config_file.h b/tests/core/io/test_config_file.h
index 6e393c7a2d..355aca479e 100644
--- a/tests/core/io/test_config_file.h
+++ b/tests/core/io/test_config_file.h
@@ -155,7 +155,7 @@ antiAliasing=false
"a=b"=7
)");
- FileAccessRef file = FileAccess::open(config_path, FileAccess::READ);
+ Ref<FileAccess> file = FileAccess::open(config_path, FileAccess::READ);
CHECK_MESSAGE(file->get_as_utf8_string() == contents,
"The saved configuration file should match the expected format.");
}
diff --git a/tests/core/io/test_file_access.h b/tests/core/io/test_file_access.h
index eee57048cf..f0e1cceacf 100644
--- a/tests/core/io/test_file_access.h
+++ b/tests/core/io/test_file_access.h
@@ -38,7 +38,7 @@
namespace TestFileAccess {
TEST_CASE("[FileAccess] CSV read") {
- FileAccessRef f = FileAccess::open(TestUtils::get_data_path("translations.csv"), FileAccess::READ);
+ Ref<FileAccess> f = FileAccess::open(TestUtils::get_data_path("translations.csv"), FileAccess::READ);
Vector<String> header = f->get_csv_line(); // Default delimiter: ",".
REQUIRE(header.size() == 3);
@@ -77,8 +77,6 @@ TEST_CASE("[FileAccess] CSV read") {
CHECK(row5[0] == "What about");
CHECK(row5[1] == "tab separated");
CHECK(row5[2] == "lines, good?");
-
- f->close();
}
} // namespace TestFileAccess
diff --git a/tests/core/io/test_image.h b/tests/core/io/test_image.h
index dcf21dd7b0..1c778c3228 100644
--- a/tests/core/io/test_image.h
+++ b/tests/core/io/test_image.h
@@ -106,7 +106,7 @@ TEST_CASE("[Image] Saving and loading") {
// Load BMP
Ref<Image> image_bmp = memnew(Image());
- FileAccessRef f_bmp = FileAccess::open(TestUtils::get_data_path("images/icon.bmp"), FileAccess::READ, &err);
+ Ref<FileAccess> f_bmp = FileAccess::open(TestUtils::get_data_path("images/icon.bmp"), FileAccess::READ, &err);
PackedByteArray data_bmp;
data_bmp.resize(f_bmp->get_length() + 1);
f_bmp->get_buffer(data_bmp.ptrw(), f_bmp->get_length());
@@ -116,7 +116,7 @@ TEST_CASE("[Image] Saving and loading") {
// Load JPG
Ref<Image> image_jpg = memnew(Image());
- FileAccessRef f_jpg = FileAccess::open(TestUtils::get_data_path("images/icon.jpg"), FileAccess::READ, &err);
+ Ref<FileAccess> f_jpg = FileAccess::open(TestUtils::get_data_path("images/icon.jpg"), FileAccess::READ, &err);
PackedByteArray data_jpg;
data_jpg.resize(f_jpg->get_length() + 1);
f_jpg->get_buffer(data_jpg.ptrw(), f_jpg->get_length());
@@ -126,7 +126,7 @@ TEST_CASE("[Image] Saving and loading") {
// Load WEBP
Ref<Image> image_webp = memnew(Image());
- FileAccessRef f_webp = FileAccess::open(TestUtils::get_data_path("images/icon.webp"), FileAccess::READ, &err);
+ Ref<FileAccess> f_webp = FileAccess::open(TestUtils::get_data_path("images/icon.webp"), FileAccess::READ, &err);
PackedByteArray data_webp;
data_webp.resize(f_webp->get_length() + 1);
f_webp->get_buffer(data_webp.ptrw(), f_webp->get_length());
@@ -136,7 +136,7 @@ TEST_CASE("[Image] Saving and loading") {
// Load PNG
Ref<Image> image_png = memnew(Image());
- FileAccessRef f_png = FileAccess::open(TestUtils::get_data_path("images/icon.png"), FileAccess::READ, &err);
+ Ref<FileAccess> f_png = FileAccess::open(TestUtils::get_data_path("images/icon.png"), FileAccess::READ, &err);
PackedByteArray data_png;
data_png.resize(f_png->get_length() + 1);
f_png->get_buffer(data_png.ptrw(), f_png->get_length());
@@ -146,7 +146,7 @@ TEST_CASE("[Image] Saving and loading") {
// Load TGA
Ref<Image> image_tga = memnew(Image());
- FileAccessRef f_tga = FileAccess::open(TestUtils::get_data_path("images/icon.tga"), FileAccess::READ, &err);
+ Ref<FileAccess> f_tga = FileAccess::open(TestUtils::get_data_path("images/icon.tga"), FileAccess::READ, &err);
PackedByteArray data_tga;
data_tga.resize(f_tga->get_length() + 1);
f_tga->get_buffer(data_tga.ptrw(), f_tga->get_length());
diff --git a/tests/core/io/test_pck_packer.h b/tests/core/io/test_pck_packer.h
index 95adca6d68..d21fbdaf50 100644
--- a/tests/core/io/test_pck_packer.h
+++ b/tests/core/io/test_pck_packer.h
@@ -52,7 +52,7 @@ TEST_CASE("[PCKPacker] Pack an empty PCK file") {
"Flushing the PCK should return an OK error code.");
Error err;
- FileAccessRef f = FileAccess::open(output_pck_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(output_pck_path, FileAccess::READ, &err);
CHECK_MESSAGE(
err == OK,
"The generated empty PCK file should be opened successfully.");
@@ -106,7 +106,7 @@ TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") {
"Flushing the PCK should return an OK error code.");
Error err;
- FileAccessRef f = FileAccess::open(output_pck_path, FileAccess::READ, &err);
+ Ref<FileAccess> f = FileAccess::open(output_pck_path, FileAccess::READ, &err);
CHECK_MESSAGE(
err == OK,
"The generated non-empty PCK file should be opened successfully.");
diff --git a/tests/core/math/test_color.h b/tests/core/math/test_color.h
index 6f40f8ecc0..51c3bc8bdc 100644
--- a/tests/core/math/test_color.h
+++ b/tests/core/math/test_color.h
@@ -146,8 +146,8 @@ TEST_CASE("[Color] Conversion methods") {
TEST_CASE("[Color] Linear <-> sRGB conversion") {
const Color color = Color(0.35, 0.5, 0.6, 0.7);
- const Color color_linear = color.to_linear();
- const Color color_srgb = color.to_srgb();
+ const Color color_linear = color.srgb_to_linear();
+ const Color color_srgb = color.linear_to_srgb();
CHECK_MESSAGE(
color_linear.is_equal_approx(Color(0.100481, 0.214041, 0.318547, 0.7)),
"The color converted to linear color space should match the expected value.");
@@ -155,10 +155,10 @@ TEST_CASE("[Color] Linear <-> sRGB conversion") {
color_srgb.is_equal_approx(Color(0.62621, 0.735357, 0.797738, 0.7)),
"The color converted to sRGB color space should match the expected value.");
CHECK_MESSAGE(
- color_linear.to_srgb().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)),
+ color_linear.linear_to_srgb().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)),
"The linear color converted back to sRGB color space should match the expected value.");
CHECK_MESSAGE(
- color_srgb.to_linear().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)),
+ color_srgb.srgb_to_linear().is_equal_approx(Color(0.35, 0.5, 0.6, 0.7)),
"The sRGB color converted back to linear color space should match the expected value.");
}
diff --git a/tests/core/math/test_math.cpp b/tests/core/math/test_math.cpp
deleted file mode 100644
index 4182455b7a..0000000000
--- a/tests/core/math/test_math.cpp
+++ /dev/null
@@ -1,690 +0,0 @@
-/*************************************************************************/
-/* test_math.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 "test_math.h"
-
-#include "core/math/camera_matrix.h"
-#include "core/math/delaunay_3d.h"
-#include "core/math/geometry_2d.h"
-#include "core/os/main_loop.h"
-#include "core/os/os.h"
-
-namespace TestMath {
-
-class GetClassAndNamespace {
- String code;
- int idx;
- int line;
- String error_str;
- bool error;
- Variant value;
-
- String class_name;
-
- enum Token {
- TK_BRACKET_OPEN,
- TK_BRACKET_CLOSE,
- TK_CURLY_BRACKET_OPEN,
- TK_CURLY_BRACKET_CLOSE,
- TK_PERIOD,
- TK_COLON,
- TK_COMMA,
- TK_SYMBOL,
- TK_IDENTIFIER,
- TK_STRING,
- TK_NUMBER,
- TK_EOF,
- TK_ERROR
- };
-
- Token get_token() {
- while (true) {
- switch (code[idx]) {
- case '\n': {
- line++;
- idx++;
- break;
- };
- case 0: {
- return TK_EOF;
-
- } break;
- case '{': {
- idx++;
- return TK_CURLY_BRACKET_OPEN;
- };
- case '}': {
- idx++;
- return TK_CURLY_BRACKET_CLOSE;
- };
- case '[': {
- idx++;
- return TK_BRACKET_OPEN;
- };
- case ']': {
- idx++;
- return TK_BRACKET_CLOSE;
- };
- case ':': {
- idx++;
- return TK_COLON;
- };
- case ',': {
- idx++;
- return TK_COMMA;
- };
- case '.': {
- idx++;
- return TK_PERIOD;
- };
- case '#': {
- //compiler directive
- while (code[idx] != '\n' && code[idx] != 0) {
- idx++;
- }
- continue;
- } break;
- case '/': {
- switch (code[idx + 1]) {
- case '*': { // block comment
-
- idx += 2;
- while (true) {
- if (code[idx] == 0) {
- error_str = "Unterminated comment";
- error = true;
- return TK_ERROR;
- } else if (code[idx] == '*' && code[idx + 1] == '/') {
- idx += 2;
- break;
- } else if (code[idx] == '\n') {
- line++;
- }
-
- idx++;
- }
-
- } break;
- case '/': { // line comment skip
-
- while (code[idx] != '\n' && code[idx] != 0) {
- idx++;
- }
-
- } break;
- default: {
- value = "/";
- idx++;
- return TK_SYMBOL;
- }
- }
-
- continue; // a comment
- } break;
- case '\'':
- case '"': {
- char32_t begin_str = code[idx];
- idx++;
- String tk_string = String();
- while (true) {
- if (code[idx] == 0) {
- error_str = "Unterminated String";
- error = true;
- return TK_ERROR;
- } else if (code[idx] == begin_str) {
- idx++;
- break;
- } else if (code[idx] == '\\') {
- //escaped characters...
- idx++;
- char32_t next = code[idx];
- if (next == 0) {
- error_str = "Unterminated String";
- error = true;
- return TK_ERROR;
- }
- char32_t res = 0;
-
- switch (next) {
- case 'b':
- res = 8;
- break;
- case 't':
- res = 9;
- break;
- case 'n':
- res = 10;
- break;
- case 'f':
- res = 12;
- break;
- case 'r':
- res = 13;
- break;
- case '\"':
- res = '\"';
- break;
- case '\\':
- res = '\\';
- break;
- default: {
- res = next;
- } break;
- }
-
- tk_string += res;
-
- } else {
- if (code[idx] == '\n') {
- line++;
- }
- tk_string += code[idx];
- }
- idx++;
- }
-
- value = tk_string;
-
- return TK_STRING;
-
- } break;
- default: {
- if (code[idx] <= 32) {
- idx++;
- break;
- }
-
- if ((code[idx] >= 33 && code[idx] <= 47) || (code[idx] >= 58 && code[idx] <= 64) || (code[idx] >= 91 && code[idx] <= 96) || (code[idx] >= 123 && code[idx] <= 127)) {
- value = String::chr(code[idx]);
- idx++;
- return TK_SYMBOL;
- }
-
- if (code[idx] == '-' || is_digit(code[idx])) {
- //a number
- const char32_t *rptr;
- double number = String::to_float(&code[idx], &rptr);
- idx += (rptr - &code[idx]);
- value = number;
- return TK_NUMBER;
-
- } else if (is_ascii_char(code[idx]) || code[idx] > 127) {
- String id;
-
- while (is_ascii_char(code[idx]) || code[idx] > 127) {
- id += code[idx];
- idx++;
- }
-
- value = id;
- return TK_IDENTIFIER;
- } else {
- error_str = "Unexpected character.";
- error = true;
- return TK_ERROR;
- }
- }
- }
- }
- }
-
-public:
- Error parse(const String &p_code, const String &p_known_class_name = String()) {
- code = p_code;
- idx = 0;
- line = 0;
- error_str = String();
- error = false;
- value = Variant();
- class_name = String();
-
- bool use_next_class = false;
- Token tk = get_token();
-
- Map<int, String> namespace_stack;
- int curly_stack = 0;
-
- while (!error || tk != TK_EOF) {
- if (tk == TK_BRACKET_OPEN) {
- tk = get_token();
- if (tk == TK_IDENTIFIER && String(value) == "ScriptClass") {
- if (get_token() == TK_BRACKET_CLOSE) {
- use_next_class = true;
- }
- }
- } else if (tk == TK_IDENTIFIER && String(value) == "class") {
- tk = get_token();
- if (tk == TK_IDENTIFIER) {
- String name = value;
- if (use_next_class || p_known_class_name == name) {
- for (const KeyValue<int, String> &E : namespace_stack) {
- class_name += E.value + ".";
- }
- class_name += String(value);
- break;
- }
- }
-
- } else if (tk == TK_IDENTIFIER && String(value) == "namespace") {
- String name;
- int at_level = curly_stack;
- while (true) {
- tk = get_token();
- if (tk == TK_IDENTIFIER) {
- name += String(value);
- }
-
- tk = get_token();
- if (tk == TK_PERIOD) {
- name += ".";
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- curly_stack++;
- break;
- } else {
- break; //whatever else
- }
- }
-
- if (!name.is_empty()) {
- namespace_stack[at_level] = name;
- }
-
- } else if (tk == TK_CURLY_BRACKET_OPEN) {
- curly_stack++;
- } else if (tk == TK_CURLY_BRACKET_CLOSE) {
- curly_stack--;
- if (namespace_stack.has(curly_stack)) {
- namespace_stack.erase(curly_stack);
- }
- }
-
- tk = get_token();
- }
-
- if (error) {
- return ERR_PARSE_ERROR;
- }
-
- return OK;
- }
-
- String get_error() {
- return error_str;
- }
-
- String get_class() {
- return class_name;
- }
-};
-
-void test_vec(Plane p_vec) {
- CameraMatrix cm;
- cm.set_perspective(45, 1, 0, 100);
- Plane v0 = cm.xform4(p_vec);
-
- print_line("out: " + v0);
- v0.normal.z = (v0.d / 100.0 * 2.0 - 1.0) * v0.d;
- print_line("out_F: " + v0);
-}
-
-uint32_t ihash(uint32_t a) {
- a = (a + 0x7ed55d16) + (a << 12);
- a = (a ^ 0xc761c23c) ^ (a >> 19);
- a = (a + 0x165667b1) + (a << 5);
- a = (a + 0xd3a2646c) ^ (a << 9);
- a = (a + 0xfd7046c5) + (a << 3);
- a = (a ^ 0xb55a4f09) ^ (a >> 16);
- return a;
-}
-
-uint32_t ihash2(uint32_t a) {
- a = (a ^ 61) ^ (a >> 16);
- a = a + (a << 3);
- a = a ^ (a >> 4);
- a = a * 0x27d4eb2d;
- a = a ^ (a >> 15);
- return a;
-}
-
-uint32_t ihash3(uint32_t a) {
- a = (a + 0x479ab41d) + (a << 8);
- a = (a ^ 0xe4aa10ce) ^ (a >> 5);
- a = (a + 0x9942f0a6) - (a << 14);
- a = (a ^ 0x5aedd67d) ^ (a >> 3);
- a = (a + 0x17bea992) + (a << 7);
- return a;
-}
-
-MainLoop *test() {
- {
- Vector<Vector3> points;
- points.push_back(Vector3(0, 0, 0));
- points.push_back(Vector3(0, 0, 1));
- points.push_back(Vector3(0, 1, 0));
- points.push_back(Vector3(0, 1, 1));
- points.push_back(Vector3(1, 1, 0));
- points.push_back(Vector3(1, 0, 0));
- points.push_back(Vector3(1, 0, 1));
- points.push_back(Vector3(1, 1, 1));
-
- for (int i = 0; i < 800; i++) {
- points.push_back(Vector3(Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0, Math::randf() * 2.0 - 1.0) * Vector3(25, 30, 33));
- }
-
- Vector<Delaunay3D::OutputSimplex> os = Delaunay3D::tetrahedralize(points);
- print_line("simplices in the end: " + itos(os.size()));
- for (int i = 0; i < os.size(); i++) {
- print_line("Simplex " + itos(i) + ": ");
- print_line(points[os[i].points[0]]);
- print_line(points[os[i].points[1]]);
- print_line(points[os[i].points[2]]);
- print_line(points[os[i].points[3]]);
- }
-
- {
- FileAccessRef f = FileAccess::open("res://bsp.obj", FileAccess::WRITE);
- for (int i = 0; i < os.size(); i++) {
- f->store_line("o Simplex" + itos(i));
- for (int j = 0; j < 4; j++) {
- f->store_line(vformat("v %f %f %f", points[os[i].points[j]].x, points[os[i].points[j]].y, points[os[i].points[j]].z));
- }
- static const int face_order[4][3] = {
- { 1, 2, 3 },
- { 1, 3, 4 },
- { 1, 2, 4 },
- { 2, 3, 4 }
- };
-
- for (int j = 0; j < 4; j++) {
- f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2]));
- }
- }
- f->close();
- }
-
- return nullptr;
- }
-
- {
- float r = 1;
- float g = 0.5;
- float b = 0.1;
-
- const float pow2to9 = 512.0f;
- const float B = 15.0f;
- const float N = 9.0f;
-
- float sharedexp = 65408.000f;
-
- float cRed = MAX(0.0f, MIN(sharedexp, r));
- float cGreen = MAX(0.0f, MIN(sharedexp, g));
- float cBlue = MAX(0.0f, MIN(sharedexp, b));
-
- float cMax = MAX(cRed, MAX(cGreen, cBlue));
-
- float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B;
-
- float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
-
- float exps = expp + 1.0f;
-
- if (0.0 <= sMax && sMax < pow2to9) {
- exps = expp;
- }
-
- float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
- float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
- float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
-
- print_line("R: " + rtos(sRed) + " G: " + rtos(sGreen) + " B: " + rtos(sBlue) + " EXP: " + rtos(exps));
-
- uint32_t rgbe = (Math::fast_ftoi(sRed) & 0x1FF) | ((Math::fast_ftoi(sGreen) & 0x1FF) << 9) | ((Math::fast_ftoi(sBlue) & 0x1FF) << 18) | ((Math::fast_ftoi(exps) & 0x1F) << 27);
-
- float rb = rgbe & 0x1ff;
- float gb = (rgbe >> 9) & 0x1ff;
- float bb = (rgbe >> 18) & 0x1ff;
- float eb = (rgbe >> 27);
- float mb = Math::pow(2.0, eb - 15.0 - 9.0);
- float rd = rb * mb;
- float gd = gb * mb;
- float bd = bb * mb;
-
- print_line("RGBE: " + Color(rd, gd, bd));
- }
-
- Vector<int> ints;
- ints.resize(20);
-
- {
- int *w;
- w = ints.ptrw();
- for (int i = 0; i < ints.size(); i++) {
- w[i] = i;
- }
- }
-
- Vector<int> posho = ints;
-
- {
- const int *r = posho.ptr();
- for (int i = 0; i < posho.size(); i++) {
- print_line(itos(i) + " : " + itos(r[i]));
- }
- }
-
- List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
-
- if (cmdlargs.is_empty()) {
- //try editor!
- return nullptr;
- }
-
- String test = cmdlargs.back()->get();
- if (test == "math") {
- // Not a file name but the test name, abort.
- // FIXME: This test is ugly as heck, needs fixing :)
- return nullptr;
- }
-
- FileAccess *fa = FileAccess::open(test, FileAccess::READ);
- ERR_FAIL_COND_V_MSG(!fa, nullptr, "Could not open file: " + test);
-
- Vector<uint8_t> buf;
- uint64_t flen = fa->get_length();
- buf.resize(fa->get_length() + 1);
- fa->get_buffer(buf.ptrw(), flen);
- buf.write[flen] = 0;
-
- String code;
- code.parse_utf8((const char *)&buf[0]);
-
- GetClassAndNamespace getclass;
- if (getclass.parse(code)) {
- print_line("Parse error: " + getclass.get_error());
- } else {
- print_line("Found class: " + getclass.get_class());
- }
-
- {
- Vector<int> hashes;
- List<StringName> tl;
- ClassDB::get_class_list(&tl);
-
- for (const StringName &E : tl) {
- Vector<uint8_t> m5b = E.operator String().md5_buffer();
- hashes.push_back(hashes.size());
- }
-
- for (int i = nearest_shift(hashes.size()); i < 20; i++) {
- bool success = true;
- for (int s = 0; s < 10000; s++) {
- Set<uint32_t> existing;
- success = true;
-
- for (int j = 0; j < hashes.size(); j++) {
- uint32_t eh = ihash2(ihash3(hashes[j] + ihash(s) + s)) & ((1 << i) - 1);
- if (existing.has(eh)) {
- success = false;
- break;
- }
- existing.insert(eh);
- }
-
- if (success) {
- print_line("success at " + itos(i) + "/" + itos(nearest_shift(hashes.size())) + " shift " + itos(s));
- break;
- }
- }
- if (success) {
- break;
- }
- }
-
- print_line("DONE");
- }
-
- {
- print_line("NUM: " + itos(-128));
- }
-
- {
- Vector3 v(1, 2, 3);
- v.normalize();
- real_t a = 0.3;
-
- Basis m(v, a);
-
- Vector3 v2(7, 3, 1);
- v2.normalize();
- real_t a2 = 0.8;
-
- Basis m2(v2, a2);
-
- Quaternion q = m;
- Quaternion q2 = m2;
-
- Basis m3 = m.inverse() * m2;
- Quaternion q3 = (q.inverse() * q2); //.normalized();
-
- print_line(Quaternion(m3));
- print_line(q3);
-
- print_line("before v: " + v + " a: " + rtos(a));
- q.get_axis_angle(v, a);
- print_line("after v: " + v + " a: " + rtos(a));
- }
-
- String ret;
-
- List<String> args;
- args.push_back("-l");
- Error err = OS::get_singleton()->execute("/bin/ls", args, &ret);
- print_line("error: " + itos(err));
- print_line(ret);
-
- Basis m3;
- m3.rotate(Vector3(1, 0, 0), 0.2);
- m3.rotate(Vector3(0, 1, 0), 1.77);
- m3.rotate(Vector3(0, 0, 1), 212);
- Basis m32;
- m32.set_euler(m3.get_euler());
- print_line("ELEULEEEEEEEEEEEEEEEEEER: " + m3.get_euler() + " vs " + m32.get_euler());
-
- {
- Dictionary d;
- d["momo"] = 1;
- Dictionary b = d;
- b["44"] = 4;
- }
-
- print_line("inters: " + rtos(Geometry2D::segment_intersects_circle(Vector2(-5, 0), Vector2(-2, 0), Vector2(), 1.0)));
-
- print_line("cross: " + Vector3(1, 2, 3).cross(Vector3(4, 5, 7)));
- print_line("dot: " + rtos(Vector3(1, 2, 3).dot(Vector3(4, 5, 7))));
- print_line("abs: " + Vector3(-1, 2, -3).abs());
- print_line("distance_to: " + rtos(Vector3(1, 2, 3).distance_to(Vector3(4, 5, 7))));
- print_line("distance_squared_to: " + rtos(Vector3(1, 2, 3).distance_squared_to(Vector3(4, 5, 7))));
- print_line("plus: " + (Vector3(1, 2, 3) + Vector3(Vector3(4, 5, 7))));
- print_line("minus: " + (Vector3(1, 2, 3) - Vector3(Vector3(4, 5, 7))));
- print_line("mul: " + (Vector3(1, 2, 3) * Vector3(Vector3(4, 5, 7))));
- print_line("div: " + (Vector3(1, 2, 3) / Vector3(Vector3(4, 5, 7))));
- print_line("mul scalar: " + (Vector3(1, 2, 3) * 2.0));
- print_line("premul scalar: " + (2.0 * Vector3(1, 2, 3)));
- print_line("div scalar: " + (Vector3(1, 2, 3) / 3.0));
- print_line("length: " + rtos(Vector3(1, 2, 3).length()));
- print_line("length squared: " + rtos(Vector3(1, 2, 3).length_squared()));
- print_line("normalized: " + Vector3(1, 2, 3).normalized());
- print_line("inverse: " + Vector3(1, 2, 3).inverse());
-
- {
- Vector3 v(4, 5, 7);
- v.normalize();
- print_line("normalize: " + v);
- }
-
- {
- Vector3 v(4, 5, 7);
- v += Vector3(1, 2, 3);
- print_line("+=: " + v);
- }
-
- {
- Vector3 v(4, 5, 7);
- v -= Vector3(1, 2, 3);
- print_line("-=: " + v);
- }
-
- {
- Vector3 v(4, 5, 7);
- v *= Vector3(1, 2, 3);
- print_line("*=: " + v);
- }
-
- {
- Vector3 v(4, 5, 7);
- v /= Vector3(1, 2, 3);
- print_line("/=: " + v);
- }
-
- {
- Vector3 v(4, 5, 7);
- v *= 2.0;
- print_line("scalar *=: " + v);
- }
-
- {
- Vector3 v(4, 5, 7);
- v /= 2.0;
- print_line("scalar /=: " + v);
- }
-
- return nullptr;
-}
-} // namespace TestMath
diff --git a/tests/core/math/test_math.h b/tests/core/math/test_math.h
deleted file mode 100644
index a8aa8f6847..0000000000
--- a/tests/core/math/test_math.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* test_math.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 TEST_MATH_H
-#define TEST_MATH_H
-
-class MainLoop;
-
-namespace TestMath {
-
-MainLoop *test();
-}
-
-#endif
diff --git a/tests/core/templates/test_oa_hash_map.cpp b/tests/core/templates/test_oa_hash_map.cpp
deleted file mode 100644
index 87bf9feb83..0000000000
--- a/tests/core/templates/test_oa_hash_map.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/*************************************************************************/
-/* test_oa_hash_map.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 "test_oa_hash_map.h"
-
-#include "core/os/os.h"
-#include "core/templates/oa_hash_map.h"
-
-namespace TestOAHashMap {
-
-struct CountedItem {
- static int count;
-
- int id = -1;
- bool destroyed = false;
-
- CountedItem() {
- count++;
- }
-
- CountedItem(int p_id) :
- id(p_id) {
- count++;
- }
-
- CountedItem(const CountedItem &p_other) :
- id(p_other.id) {
- count++;
- }
-
- void operator=(const CountedItem &p_other) {
- id = p_other.id;
- count++;
- }
-
- ~CountedItem() {
- CRASH_COND(destroyed);
- count--;
- destroyed = true;
- }
-};
-
-int CountedItem::count;
-
-MainLoop *test() {
- OS::get_singleton()->print("\n\n\nHello from test\n");
-
- // test element tracking.
- {
- OAHashMap<int, int> map;
-
- map.set(42, 1337);
- map.set(1337, 21);
- map.set(42, 11880);
-
- int value = 0;
- map.lookup(42, value);
-
- OS::get_singleton()->print("capacity %d\n", map.get_capacity());
- OS::get_singleton()->print("elements %d\n", map.get_num_elements());
-
- OS::get_singleton()->print("map[42] = %d\n", value);
- }
-
- // rehashing and deletion
- {
- OAHashMap<int, int> map;
-
- for (int i = 0; i < 500; i++) {
- map.set(i, i * 2);
- }
-
- for (int i = 0; i < 500; i += 2) {
- map.remove(i);
- }
-
- uint32_t num_elems = 0;
- for (int i = 0; i < 500; i++) {
- int tmp;
- if (map.lookup(i, tmp) && tmp == i * 2) {
- num_elems++;
- }
- }
-
- OS::get_singleton()->print("elements %d == %d.\n", map.get_num_elements(), num_elems);
- }
-
- // iteration
- {
- OAHashMap<String, int> map;
-
- map.set("Hello", 1);
- map.set("World", 2);
- map.set("Godot rocks", 42);
-
- for (OAHashMap<String, int>::Iterator it = map.iter(); it.valid; it = map.next_iter(it)) {
- OS::get_singleton()->print("map[\"%s\"] = %d\n", it.key->utf8().get_data(), *it.value);
- }
- }
-
- // stress test / test for issue #22928
- {
- OAHashMap<int, int> map;
- int dummy = 0;
- const int N = 1000;
- uint32_t *keys = new uint32_t[N];
-
- Math::seed(0);
-
- // insert a couple of random keys (with a dummy value, which is ignored)
- for (int i = 0; i < N; i++) {
- keys[i] = Math::rand();
- map.set(keys[i], dummy);
-
- if (!map.lookup(keys[i], dummy)) {
- OS::get_singleton()->print("could not find 0x%X despite it was just inserted!\n", unsigned(keys[i]));
- }
- }
-
- // check whether the keys are still present
- for (int i = 0; i < N; i++) {
- if (!map.lookup(keys[i], dummy)) {
- OS::get_singleton()->print("could not find 0x%X despite it has been inserted previously! (not checking the other keys, breaking...)\n", unsigned(keys[i]));
- break;
- }
- }
-
- delete[] keys;
- }
-
- // regression test / test for issue related to #31402
- {
- OS::get_singleton()->print("test for issue #31402 started...\n");
-
- const int num_test_values = 12;
- int test_values[num_test_values] = { 0, 24, 48, 72, 96, 120, 144, 168, 192, 216, 240, 264 };
-
- int dummy = 0;
- OAHashMap<int, int> map;
- map.clear();
-
- for (int i = 0; i < num_test_values; ++i) {
- map.set(test_values[i], dummy);
- }
-
- OS::get_singleton()->print("test for issue #31402 passed.\n");
- }
-
- // test collision resolution, should not crash or run indefinitely
- {
- OAHashMap<int, int> map(4);
- map.set(1, 1);
- map.set(5, 1);
- map.set(9, 1);
- map.set(13, 1);
- map.remove(5);
- map.remove(9);
- map.remove(13);
- map.set(5, 1);
- }
-
- // test memory management of items, should not crash or leak items
- {
- // Exercise different patterns of removal
- for (int i = 0; i < 4; ++i) {
- {
- OAHashMap<String, CountedItem> map;
- int id = 0;
- for (int j = 0; j < 100; ++j) {
- map.insert(itos(j), CountedItem(id));
- }
- if (i <= 1) {
- for (int j = 0; j < 100; ++j) {
- map.remove(itos(j));
- }
- }
- if (i % 2 == 0) {
- map.clear();
- }
- }
-
- if (CountedItem::count != 0) {
- OS::get_singleton()->print("%d != 0 (not performing the other test sub-cases, breaking...)\n", CountedItem::count);
- break;
- }
- }
- }
-
- // Test map with 0 capacity.
- {
- OAHashMap<int, String> original_map(0);
- original_map.set(1, "1");
- OS::get_singleton()->print("OAHashMap 0 capacity initialization passed.\n");
- }
-
- // Test copy constructor.
- {
- OAHashMap<int, String> original_map;
- original_map.set(1, "1");
- original_map.set(2, "2");
- original_map.set(3, "3");
- original_map.set(4, "4");
- original_map.set(5, "5");
-
- OAHashMap<int, String> map_copy(original_map);
-
- bool pass = true;
- for (
- OAHashMap<int, String>::Iterator it = original_map.iter();
- it.valid;
- it = original_map.next_iter(it)) {
- if (map_copy.lookup_ptr(*it.key) == nullptr) {
- pass = false;
- }
- if (*it.value != *map_copy.lookup_ptr(*it.key)) {
- pass = false;
- }
- }
- if (pass) {
- OS::get_singleton()->print("OAHashMap copy constructor test passed.\n");
- } else {
- OS::get_singleton()->print("OAHashMap copy constructor test FAILED.\n");
- }
-
- map_copy.set(1, "Random String");
- if (*map_copy.lookup_ptr(1) == *original_map.lookup_ptr(1)) {
- OS::get_singleton()->print("OAHashMap copy constructor, atomic copy test FAILED.\n");
- } else {
- OS::get_singleton()->print("OAHashMap copy constructor, atomic copy test passed.\n");
- }
- }
-
- // Test assign operator.
- {
- OAHashMap<int, String> original_map;
- original_map.set(1, "1");
- original_map.set(2, "2");
- original_map.set(3, "3");
- original_map.set(4, "4");
- original_map.set(5, "5");
-
- OAHashMap<int, String> map_copy(100000);
- map_copy.set(1, "Just a string.");
- map_copy = original_map;
-
- bool pass = true;
- for (
- OAHashMap<int, String>::Iterator it = map_copy.iter();
- it.valid;
- it = map_copy.next_iter(it)) {
- if (original_map.lookup_ptr(*it.key) == nullptr) {
- pass = false;
- }
- if (*it.value != *original_map.lookup_ptr(*it.key)) {
- pass = false;
- }
- }
- if (pass) {
- OS::get_singleton()->print("OAHashMap assign operation test passed.\n");
- } else {
- OS::get_singleton()->print("OAHashMap assign operation test FAILED.\n");
- }
-
- map_copy.set(1, "Random String");
- if (*map_copy.lookup_ptr(1) == *original_map.lookup_ptr(1)) {
- OS::get_singleton()->print("OAHashMap assign operation atomic copy test FAILED.\n");
- } else {
- OS::get_singleton()->print("OAHashMap assign operation atomic copy test passed.\n");
- }
- }
-
- return nullptr;
-}
-} // namespace TestOAHashMap
diff --git a/tests/core/templates/test_oa_hash_map.h b/tests/core/templates/test_oa_hash_map.h
deleted file mode 100644
index d4b72af2ac..0000000000
--- a/tests/core/templates/test_oa_hash_map.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* test_oa_hash_map.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 TEST_OA_HASH_MAP_H
-#define TEST_OA_HASH_MAP_H
-
-class MainLoop;
-
-namespace TestOAHashMap {
-
-MainLoop *test();
-}
-
-#endif // TEST_OA_HASH_MAP_H
diff --git a/tests/scene/test_gui.cpp b/tests/scene/test_gui.cpp
deleted file mode 100644
index cd5624b70c..0000000000
--- a/tests/scene/test_gui.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-/*************************************************************************/
-/* test_gui.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. */
-/*************************************************************************/
-
-#ifndef _3D_DISABLED
-
-#include "test_gui.h"
-
-#include "scene/gui/button.h"
-#include "scene/gui/label.h"
-#include "scene/gui/line_edit.h"
-#include "scene/gui/menu_button.h"
-#include "scene/gui/option_button.h"
-#include "scene/gui/panel.h"
-#include "scene/gui/progress_bar.h"
-#include "scene/gui/rich_text_label.h"
-#include "scene/gui/scroll_bar.h"
-#include "scene/gui/spin_box.h"
-#include "scene/gui/tab_container.h"
-#include "scene/gui/tree.h"
-
-namespace TestGUI {
-
-class TestMainLoop : public SceneTree {
-public:
- virtual void request_quit() {
- quit();
- }
- virtual void initialize() {
- SceneTree::initialize();
-
- Panel *frame = memnew(Panel);
- frame->set_anchor(SIDE_RIGHT, Control::ANCHOR_END);
- frame->set_anchor(SIDE_BOTTOM, Control::ANCHOR_END);
- frame->set_end(Point2(0, 0));
-
- Ref<Theme> t = memnew(Theme);
- frame->set_theme(t);
-
- get_root()->add_child(frame);
-
- Label *label = memnew(Label);
-
- label->set_position(Point2(80, 90));
- label->set_size(Point2(170, 80));
- label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_FILL);
- label->set_text("There was once upon a time a beautiful unicorn that loved to play with little girls...");
-
- frame->add_child(label);
-
- Button *button = memnew(Button);
-
- button->set_position(Point2(20, 20));
- button->set_size(Point2(1, 1));
- button->set_text("This is a biggie button");
-
- frame->add_child(button);
-
- Tree *tree = memnew(Tree);
- tree->set_columns(2);
-
- tree->set_position(Point2(230, 210));
- tree->set_size(Point2(150, 250));
-
- TreeItem *item = tree->create_item();
- item->set_editable(0, true);
- item->set_text(0, "root");
- item = tree->create_item(tree->get_root());
- item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- item->set_editable(0, true);
- item->set_text(0, "check");
- item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK);
- item->set_editable(1, true);
- item->set_text(1, "check2");
- item = tree->create_item(tree->get_root());
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0, true);
- item->set_range_config(0, 0, 20, 0.1);
- item->set_range(0, 2);
- item->add_button(0, Theme::get_default()->get_icon("folder", "FileDialog"));
- item->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
- item->set_editable(1, true);
- item->set_range_config(1, 0, 20, 0.1);
- item->set_range(1, 3);
-
- item = tree->create_item(tree->get_root());
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0, true);
- item->set_text(0, "Have,Many,Several,Options!");
- item->set_range(0, 2);
-
- item = tree->create_item(item);
- item->set_editable(0, true);
- item->set_text(0, "Gershwin!");
-
- frame->add_child(tree);
-
- LineEdit *line_edit = memnew(LineEdit);
-
- line_edit->set_position(Point2(30, 190));
- line_edit->set_size(Point2(180, 1));
-
- frame->add_child(line_edit);
-
- HScrollBar *hscroll = memnew(HScrollBar);
-
- hscroll->set_position(Point2(30, 290));
- hscroll->set_size(Point2(180, 1));
- hscroll->set_max(10);
- hscroll->set_page(4);
-
- frame->add_child(hscroll);
-
- SpinBox *spin = memnew(SpinBox);
-
- spin->set_position(Point2(30, 260));
- spin->set_size(Point2(120, 1));
-
- frame->add_child(spin);
- hscroll->share(spin);
-
- ProgressBar *progress = memnew(ProgressBar);
-
- progress->set_position(Point2(30, 330));
- progress->set_size(Point2(120, 1));
-
- frame->add_child(progress);
- hscroll->share(progress);
-
- MenuButton *menu_button = memnew(MenuButton);
-
- menu_button->set_text("I'm a menu!");
- menu_button->set_position(Point2(30, 380));
- menu_button->set_size(Point2(1, 1));
-
- frame->add_child(menu_button);
-
- PopupMenu *popup = menu_button->get_popup();
-
- popup->add_item("Hello, testing");
- popup->add_item("My Dearest");
- popup->add_separator();
- popup->add_item("Popup");
- popup->add_check_item("Check Popup");
- popup->set_item_checked(4, true);
- popup->add_separator();
- popup->add_radio_check_item("Option A");
- popup->set_item_checked(6, true);
- popup->add_radio_check_item("Option B");
-
- OptionButton *options = memnew(OptionButton);
-
- options->add_item("Hello, testing");
- options->add_item("My Dearest");
-
- options->set_position(Point2(230, 180));
- options->set_size(Point2(1, 1));
-
- frame->add_child(options);
-
- RichTextLabel *richtext = memnew(RichTextLabel);
-
- richtext->set_position(Point2(600, 210));
- richtext->set_size(Point2(180, 250));
- richtext->set_anchor_and_offset(SIDE_RIGHT, Control::ANCHOR_END, -20);
-
- frame->add_child(richtext);
-
- richtext->add_text("Hello, My Friends!\n\nWelcome to the amazing world of ");
-
- richtext->add_newline();
- richtext->add_newline();
-
- richtext->push_color(Color(1, 0.5, 0.5));
- richtext->add_text("leprechauns");
- richtext->pop();
-
- richtext->add_text(" and ");
- richtext->push_color(Color(0, 1.0, 0.5));
- richtext->add_text("faeries.\n");
- richtext->pop();
- richtext->add_text("In this new episode, we will attempt to ");
- richtext->push_font(richtext->get_theme_font(SNAME("mono_font"), SNAME("Fonts")));
- richtext->push_color(Color(0.7, 0.5, 1.0));
- richtext->add_text("deliver something nice");
- richtext->pop();
- richtext->pop();
- richtext->add_text(" to all the viewers! Unfortunately, I need to ");
- richtext->push_underline();
- richtext->add_text("keep writing a lot of text");
- richtext->pop();
- richtext->add_text(" so the label control overflows and the scrollbar appears.\n");
- richtext->push_meta("http://www.scrollingcapabilities.xz");
- richtext->add_text("This allows to test for the scrolling capabilities ");
- richtext->pop();
- richtext->add_text("of the rich text label for huge text (not like this text will really be huge but, you know).\nAs long as it is so long that it will work nicely for a test/demo, then it's welcomed in my book...\nChanging subject, the day is cloudy today and I'm wondering if I'll get che chance to travel somewhere nice. Sometimes, watching the clouds from satellite images may give a nice insight about how pressure zones in our planet work, although it also makes it pretty obvious to see why most weather forecasts get it wrong so often.\nClouds are so difficult to predict!\nBut it's pretty cool how our civilization has adapted to having water falling from the sky each time it rains...");
-
- TabContainer *tabc = memnew(TabContainer);
-
- Control *ctl = memnew(Control);
- ctl->set_name("tab 1");
- tabc->add_child(ctl);
-
- ctl = memnew(Control);
- ctl->set_name("tab 2");
- tabc->add_child(ctl);
- label = memnew(Label);
- label->set_text("Some Label");
- label->set_position(Point2(20, 20));
- ctl->add_child(label);
-
- ctl = memnew(Control);
- ctl->set_name("tab 3");
- button = memnew(Button);
- button->set_text("Some Button");
- button->set_position(Point2(30, 50));
- ctl->add_child(button);
-
- tabc->add_child(ctl);
-
- frame->add_child(tabc);
-
- tabc->set_position(Point2(400, 210));
- tabc->set_size(Point2(180, 250));
- }
-};
-
-MainLoop *test() {
- return memnew(TestMainLoop);
-}
-} // namespace TestGUI
-
-#endif // _3D_DISABLED
diff --git a/tests/scene/test_gui.h b/tests/scene/test_gui.h
deleted file mode 100644
index a1807ed15c..0000000000
--- a/tests/scene/test_gui.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* test_gui.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 TEST_GUI_H
-#define TEST_GUI_H
-
-class MainLoop;
-
-namespace TestGUI {
-
-MainLoop *test();
-}
-
-#endif
diff --git a/tests/servers/test_physics_2d.cpp b/tests/servers/test_physics_2d.cpp
deleted file mode 100644
index 138412ec09..0000000000
--- a/tests/servers/test_physics_2d.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/*************************************************************************/
-/* test_physics_2d.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 "test_physics_2d.h"
-
-#include "core/os/main_loop.h"
-#include "servers/physics_server_2d.h"
-#include "servers/rendering_server.h"
-
-static const unsigned char convex_png[] = {
- 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0xaa, 0x69, 0x71, 0xde, 0x0, 0x0, 0x0, 0x1, 0x73, 0x52, 0x47, 0x42, 0x0, 0xae, 0xce, 0x1c, 0xe9, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf9, 0x43, 0xbb, 0x7f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xdb, 0x6, 0xa, 0x3, 0x13, 0x31, 0x66, 0xa7, 0xac, 0x79, 0x0, 0x0, 0x4, 0xef, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x9b, 0xdd, 0x4e, 0x2a, 0x57, 0x14, 0xc7, 0xf7, 0x1e, 0xc0, 0x19, 0x38, 0x32, 0x80, 0xa, 0x6a, 0xda, 0x18, 0xa3, 0xc6, 0x47, 0x50, 0x7b, 0xa1, 0xd9, 0x36, 0x27, 0x7e, 0x44, 0xed, 0x45, 0x4d, 0x93, 0x3e, 0x40, 0x1f, 0x64, 0x90, 0xf4, 0x1, 0xbc, 0xf0, 0xc2, 0x9c, 0x57, 0x30, 0x4d, 0xbc, 0xa8, 0x6d, 0xc, 0x69, 0x26, 0xb5, 0x68, 0x8b, 0x35, 0x7e, 0x20, 0xb4, 0xf5, 0x14, 0xbf, 0x51, 0x3c, 0x52, 0xe, 0xc, 0xe, 0xc8, 0xf0, 0xb1, 0x7a, 0x51, 0x3d, 0xb1, 0x9e, 0x19, 0x1c, 0x54, 0x70, 0x1c, 0xdc, 0x9, 0x17, 0x64, 0x8, 0xc9, 0xff, 0xb7, 0xd6, 0x7f, 0xcd, 0x3f, 0x2b, 0xd9, 0x8, 0xbd, 0x9c, 0xda, 0x3e, 0xf8, 0x31, 0xff, 0xc, 0x0, 0x8, 0x42, 0x88, 0x9c, 0x9f, 0x9f, 0xbf, 0xa, 0x87, 0xc3, 0xad, 0x7d, 0x7d, 0x7d, 0x7f, 0x23, 0x84, 0x78, 0x8c, 0x31, 0xaf, 0x55, 0x0, 0xc6, 0xc7, 0x14, 0x1e, 0x8f, 0xc7, 0xbf, 0x38, 0x3c, 0x3c, 0x6c, 0x9b, 0x9f, 0x9f, 0x6f, 0xb8, 0x82, 0x9b, 0xee, 0xe8, 0xe8, 0xf8, 0x12, 0x0, 0xbe, 0xd3, 0x2a, 0x8, 0xfc, 0x50, 0xd1, 0xf9, 0x7c, 0x9e, 0x8a, 0x46, 0xa3, 0x5f, 0x9d, 0x9e, 0x9e, 0x7e, 0xb2, 0xb0, 0xb0, 0x60, 0xe5, 0x79, 0x1e, 0xf1, 0xfc, 0x7f, 0x3a, 0x9, 0x21, 0x88, 0x10, 0x82, 0x26, 0x26, 0x26, 0xde, 0x77, 0x75, 0x75, 0x85, 0x59, 0x96, 0xfd, 0x5e, 0x6b, 0x20, 0xf0, 0x7d, 0x85, 0x4b, 0x92, 0xf4, 0xfa, 0xe0, 0xe0, 0xe0, 0xd3, 0xb9, 0xb9, 0xb9, 0x46, 0x49, 0x92, 0xea, 0x6f, 0xa, 0xbf, 0x7d, 0x8, 0x21, 0x68, 0x70, 0x70, 0xb0, 0x38, 0x39, 0x39, 0x79, 0xd6, 0xd9, 0xd9, 0xb9, 0xcf, 0x30, 0xcc, 0xa2, 0xd6, 0xad, 0x21, 0x2b, 0x1c, 0x0, 0x38, 0x41, 0x10, 0xfc, 0xdb, 0xdb, 0xdb, 0x27, 0x1e, 0x8f, 0x27, 0x4b, 0x8, 0x1, 0x84, 0x90, 0xea, 0xf, 0x21, 0x4, 0x3c, 0x1e, 0x4f, 0x76, 0x67, 0x67, 0x67, 0x3f, 0x9f, 0xcf, 0xff, 0x7c, 0x5, 0xf3, 0xd9, 0x0, 0xe0, 0x2, 0x81, 0xc0, 0xa9, 0xdb, 0xed, 0x2e, 0x94, 0x2b, 0x5c, 0xe, 0xc4, 0xca, 0xca, 0x8a, 0x18, 0x8d, 0x46, 0x3, 0x0, 0xc0, 0x69, 0x1e, 0x4, 0x0, 0x90, 0x48, 0x24, 0x12, 0xe4, 0x38, 0xee, 0x41, 0xc2, 0x6f, 0x43, 0xe0, 0x38, 0xe, 0xfc, 0x7e, 0xbf, 0x10, 0x8b, 0xc5, 0xd6, 0x35, 0xd, 0x22, 0x9b, 0xcd, 0x7a, 0x96, 0x97, 0x97, 0x33, 0xf, 0xad, 0x7c, 0x29, 0x10, 0x9b, 0x9b, 0x9b, 0xef, 0x2e, 0x2e, 0x2e, 0x7e, 0xd5, 0x1c, 0x8, 0x0, 0x20, 0xe1, 0x70, 0x38, 0xfc, 0x98, 0xd5, 0x57, 0x2, 0xe1, 0x76, 0xbb, 0xf3, 0xa1, 0x50, 0xe8, 0x38, 0x9b, 0xcd, 0xfe, 0xa2, 0x9, 0x8, 0x0, 0x40, 0x2e, 0x2f, 0x2f, 0x7d, 0x4b, 0x4b, 0x4b, 0xb9, 0x4a, 0x54, 0x5f, 0x9, 0xc4, 0xd2, 0xd2, 0x92, 0xb4, 0xb7, 0xb7, 0xf7, 0x36, 0x97, 0xcb, 0x4d, 0x3d, 0x29, 0x8, 0x0, 0xe0, 0x42, 0xa1, 0xd0, 0x71, 0xb5, 0xc4, 0xdf, 0xb6, 0xc5, 0x93, 0xe, 0x4a, 0x0, 0x20, 0xa9, 0x54, 0xea, 0x37, 0xb7, 0xdb, 0x5d, 0xa8, 0xa6, 0x78, 0x39, 0x10, 0x6b, 0x6b, 0x6b, 0xf1, 0x64, 0x32, 0xb9, 0x5a, 0x55, 0x10, 0x0, 0xc0, 0x6d, 0x6c, 0x6c, 0x9c, 0x57, 0xbb, 0xfa, 0x25, 0x40, 0x14, 0x3, 0x81, 0x40, 0x34, 0x93, 0xc9, 0x2c, 0x57, 0x1c, 0x4, 0x0, 0x90, 0x58, 0x2c, 0xb6, 0x5e, 0xe9, 0xc1, 0x77, 0x1f, 0x10, 0x53, 0x53, 0x53, 0x52, 0xc5, 0x83, 0x14, 0x0, 0x70, 0x7e, 0xbf, 0x5f, 0xd0, 0x42, 0xf5, 0x95, 0x40, 0xf8, 0x7c, 0xbe, 0xcb, 0xa3, 0xa3, 0xa3, 0x3f, 0x1e, 0xbd, 0x1b, 0x0, 0x80, 0x1c, 0x1f, 0x1f, 0x87, 0xb4, 0x56, 0xfd, 0xaa, 0x5, 0x29, 0x51, 0x14, 0xbf, 0xf5, 0xf9, 0x7c, 0x97, 0x5a, 0xad, 0xbe, 0x12, 0x88, 0xf5, 0xf5, 0xf5, 0xd8, 0x83, 0x83, 0x54, 0xb5, 0x42, 0x8f, 0x66, 0x83, 0x94, 0xd6, 0xbd, 0x5f, 0xce, 0x7c, 0x38, 0x3c, 0x3c, 0xfc, 0xb3, 0x50, 0x28, 0xb8, 0xcb, 0x2, 0x1, 0x0, 0xdc, 0xf4, 0xf4, 0xf4, 0xfe, 0x73, 0x15, 0x2f, 0x17, 0xa4, 0x22, 0x91, 0x48, 0x50, 0xb5, 0x2d, 0x0, 0x80, 0x9b, 0x99, 0x99, 0x79, 0xfb, 0xdc, 0x1, 0xc8, 0x5, 0xa9, 0x44, 0x22, 0xf1, 0xfb, 0x9d, 0x10, 0x0, 0x80, 0x9b, 0x9d, 0x9d, 0xd, 0xea, 0x5, 0xc0, 0xad, 0xfd, 0x43, 0x1a, 0x0, 0xb8, 0xdb, 0x9a, 0xa9, 0x8f, 0xb6, 0xa4, 0x46, 0xa3, 0xa4, 0xb7, 0xd5, 0x37, 0xcf, 0xf3, 0x68, 0x75, 0x75, 0xf5, 0x4c, 0xee, 0x99, 0x1c, 0x80, 0x9c, 0x1e, 0xf7, 0xff, 0x16, 0x8b, 0x45, 0x50, 0x5, 0xa0, 0xb7, 0xb7, 0xb7, 0x85, 0x10, 0xa2, 0x2b, 0xf1, 0x84, 0x10, 0xd4, 0xdf, 0xdf, 0x6f, 0x57, 0x3, 0x80, 0x37, 0x18, 0xc, 0x5, 0x3d, 0x2, 0xa0, 0x69, 0x3a, 0x8b, 0x10, 0xe2, 0x4b, 0x2, 0xc0, 0x18, 0xf3, 0xc1, 0x60, 0x70, 0x47, 0x8f, 0x16, 0x38, 0x3a, 0x3a, 0x5a, 0x93, 0x5b, 0xc3, 0x7f, 0x64, 0x81, 0xba, 0xba, 0x3a, 0x49, 0x8f, 0x0, 0x1a, 0x1a, 0x1a, 0xd4, 0xcd, 0x0, 0x93, 0xc9, 0xa4, 0xcb, 0x21, 0xe8, 0x74, 0x3a, 0xd5, 0x1, 0xa0, 0x69, 0x5a, 0x77, 0x1d, 0x80, 0x31, 0x2e, 0x38, 0x9d, 0x4e, 0xb1, 0x66, 0x1, 0x30, 0xc, 0x23, 0x28, 0x3d, 0x93, 0x9b, 0x1, 0xb9, 0x9a, 0x6, 0x60, 0x36, 0x9b, 0x75, 0xd7, 0x1, 0x4a, 0x21, 0xa8, 0x26, 0x0, 0x94, 0xa, 0x41, 0xb2, 0x0, 0x18, 0x86, 0xc9, 0xe9, 0xd, 0x80, 0x52, 0x8, 0x92, 0x5, 0x60, 0xb1, 0x58, 0x74, 0x67, 0x1, 0xa5, 0x10, 0xa4, 0x4, 0x40, 0x77, 0x43, 0xd0, 0xe1, 0x70, 0xa8, 0x9f, 0x1, 0x14, 0x45, 0x1, 0x45, 0x51, 0x79, 0x3d, 0x1, 0x68, 0x6e, 0x6e, 0x4e, 0xaa, 0x6, 0x80, 0x10, 0x42, 0x6, 0x83, 0x41, 0x37, 0x36, 0x28, 0x15, 0x82, 0x6a, 0x2, 0x0, 0x4d, 0xd3, 0xa9, 0x52, 0xcf, 0x95, 0x0, 0xe8, 0x66, 0xe, 0x98, 0xcd, 0x66, 0xa1, 0x6c, 0x0, 0x7a, 0x5a, 0x8b, 0x59, 0x2c, 0x96, 0x64, 0xcd, 0x2, 0xb8, 0x2b, 0x4, 0xe9, 0xde, 0x2, 0x77, 0x85, 0xa0, 0x9a, 0xb0, 0x40, 0xa9, 0x10, 0xa4, 0x8, 0xc0, 0x64, 0x32, 0xe9, 0x6, 0x40, 0xa9, 0x10, 0x54, 0xaa, 0x3, 0x74, 0xf3, 0x16, 0x70, 0xb9, 0x5c, 0xe5, 0x3, 0xe8, 0xe9, 0xe9, 0x69, 0xd5, 0xc3, 0x66, 0x18, 0x63, 0x5c, 0x68, 0x6a, 0x6a, 0x12, 0xcb, 0x5, 0xa0, 0x9b, 0xd5, 0x38, 0x4d, 0xd3, 0x29, 0x8a, 0xa2, 0xa0, 0x2c, 0x0, 0x18, 0x63, 0x3e, 0x14, 0xa, 0xfd, 0x55, 0xb, 0x21, 0x48, 0xd1, 0x2, 0x7a, 0x59, 0x8d, 0xdf, 0x1b, 0x80, 0x1e, 0x56, 0xe3, 0x84, 0x10, 0x34, 0x30, 0x30, 0x60, 0xbb, 0xeb, 0x77, 0x46, 0x5, 0xef, 0x48, 0xcf, 0x4d, 0xec, 0x8d, 0x99, 0x5, 0xf5, 0xf5, 0xf5, 0xef, 0x46, 0x47, 0x47, 0xb, 0x2e, 0x97, 0xeb, 0xbc, 0x54, 0x8, 0x52, 0x4, 0xc0, 0x30, 0x8c, 0xf4, 0x5c, 0x4, 0x9b, 0x4c, 0xa6, 0xf4, 0xf8, 0xf8, 0xb8, 0xc8, 0xb2, 0x6c, 0x32, 0x9d, 0x4e, 0xff, 0xd4, 0xdd, 0xdd, 0x7d, 0x66, 0x34, 0x1a, 0x8b, 0xd7, 0x3, 0xfd, 0xae, 0x5b, 0x29, 0xb2, 0x57, 0x66, 0xb6, 0xb6, 0xb6, 0xde, 0xc4, 0xe3, 0xf1, 0x6f, 0xae, 0xaf, 0xc1, 0x28, 0x5d, 0x85, 0x79, 0x2, 0xc1, 0x60, 0xb5, 0x5a, 0xa3, 0xa3, 0xa3, 0xa3, 0x45, 0xab, 0xd5, 0x9a, 0x2a, 0x16, 0x8b, 0x8b, 0x6d, 0x6d, 0x6d, 0xef, 0xd5, 0x8a, 0x55, 0xd, 0x20, 0x91, 0x48, 0xbc, 0x3e, 0x38, 0x38, 0xf8, 0xda, 0x6e, 0xb7, 0xf7, 0x5f, 0x5c, 0x5c, 0xd4, 0x7b, 0xbd, 0xde, 0xbc, 0x20, 0x8, 0xcd, 0x85, 0x42, 0x81, 0xfe, 0xf0, 0xae, 0xac, 0x10, 0x98, 0x9b, 0xd5, 0xc5, 0x18, 0x17, 0x59, 0x96, 0x3d, 0x1d, 0x19, 0x19, 0x1, 0x96, 0x65, 0x5, 0x8a, 0xa2, 0x7e, 0x6c, 0x69, 0x69, 0x49, 0x3d, 0x44, 0xb0, 0x2a, 0x0, 0x1f, 0xcc, 0x74, 0x75, 0x41, 0xea, 0xfa, 0x7b, 0x32, 0x99, 0x64, 0x76, 0x77, 0x77, 0x5d, 0xe, 0x87, 0xa3, 0x5f, 0x14, 0xc5, 0x57, 0x57, 0x60, 0x5a, 0x8b, 0xc5, 0xa2, 0xf1, 0xbe, 0x50, 0x6e, 0xa, 0x66, 0x18, 0x26, 0x31, 0x36, 0x36, 0x96, 0x65, 0x59, 0x36, 0x29, 0x49, 0x92, 0xb7, 0xbd, 0xbd, 0xfd, 0x9f, 0x72, 0xda, 0xf9, 0xd1, 0x1, 0xa8, 0x1, 0x93, 0xcf, 0xe7, 0xa9, 0x93, 0x93, 0x13, 0x1b, 0x4d, 0xd3, 0x9f, 0xb, 0x82, 0x60, 0xf5, 0x7a, 0xbd, 0xd9, 0x54, 0x2a, 0xe5, 0xcc, 0x64, 0x32, 0xe, 0xb9, 0x6e, 0xb9, 0x16, 0x8c, 0x31, 0x2e, 0xda, 0x6c, 0xb6, 0xc8, 0xd0, 0xd0, 0x10, 0x65, 0xb3, 0xd9, 0x92, 0x95, 0xa8, 0x6e, 0xc5, 0x0, 0xa8, 0xe9, 0x96, 0x68, 0x34, 0x6a, 0xdd, 0xdf, 0xdf, 0x6f, 0x76, 0xb9, 0x5c, 0x9f, 0x89, 0xa2, 0x58, 0xbf, 0xb8, 0xb8, 0x8, 0x26, 0x93, 0x29, 0x3b, 0x3c, 0x3c, 0x8c, 0xed, 0x76, 0x7b, 0xd2, 0x68, 0x34, 0xfe, 0xd0, 0xd8, 0xd8, 0x98, 0xae, 0xb6, 0xe0, 0x8a, 0x1, 0x50, 0xb, 0xe6, 0xa9, 0x5, 0xbf, 0x9c, 0x97, 0xf3, 0xff, 0xf3, 0x2f, 0x6a, 0x82, 0x7f, 0xf6, 0x4e, 0xca, 0x1b, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
-};
-
-class TestPhysics2DMainLoop : public MainLoop {
- GDCLASS(TestPhysics2DMainLoop, MainLoop);
-
- RID circle_img;
- RID circle_shape;
- RID space;
- RID canvas;
- RID ray;
- RID ray_query;
- Transform2D view_xform;
-
- Vector2 ray_from, ray_to;
-
- struct BodyShapeData {
- RID image;
- RID shape;
- };
-
- BodyShapeData body_shape_data[8];
-
- void _create_body_shape_data() {
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
-
- // SEGMENT
-
- {
- Vector<uint8_t> pixels;
- pixels.resize(32 * 2 * 2);
- for (int i = 0; i < 2; i++) {
- for (int j = 0; j < 32; j++) {
- pixels.set(i * 32 * 2 + j * 2 + 0, (j == 0) ? 255 : 0);
- pixels.set(i * 32 * 2 + j * 2 + 1, 255);
- }
- }
-
- Ref<Image> image = memnew(Image(32, 2, 0, Image::FORMAT_LA8, pixels));
-
- body_shape_data[PhysicsServer2D::SHAPE_SEGMENT].image = vs->texture_2d_create(image);
-
- RID segment_shape = ps->segment_shape_create();
- Rect2 sg(Point2(-16, 0), Point2(16, 0));
- ps->shape_set_data(segment_shape, sg);
-
- body_shape_data[PhysicsServer2D::SHAPE_SEGMENT].shape = segment_shape;
- }
-
- // CIRCLE
-
- {
- Vector<uint8_t> pixels;
- pixels.resize(32 * 32 * 2);
- for (int i = 0; i < 32; i++) {
- for (int j = 0; j < 32; j++) {
- bool black = Vector2(i - 16, j - 16).length_squared() < 16 * 16;
-
- pixels.set(i * 32 * 2 + j * 2 + 0, (i == 16 || j == 16) ? 255 : 0);
- pixels.set(i * 32 * 2 + j * 2 + 1, black ? 255 : 0);
- }
- }
-
- Ref<Image> image = memnew(Image(32, 32, 0, Image::FORMAT_LA8, pixels));
-
- body_shape_data[PhysicsServer2D::SHAPE_CIRCLE].image = vs->texture_2d_create(image);
-
- RID circle_shape = ps->circle_shape_create();
- ps->shape_set_data(circle_shape, 16);
-
- body_shape_data[PhysicsServer2D::SHAPE_CIRCLE].shape = circle_shape;
- }
-
- // BOX
-
- {
- Vector<uint8_t> pixels;
- pixels.resize(32 * 32 * 2);
- for (int i = 0; i < 32; i++) {
- for (int j = 0; j < 32; j++) {
- bool black = i > 0 && i < 31 && j > 0 && j < 31;
-
- pixels.set(i * 32 * 2 + j * 2 + 0, black ? 0 : 255);
- pixels.set(i * 32 * 2 + j * 2 + 1, 255);
- }
- }
-
- Ref<Image> image = memnew(Image(32, 32, 0, Image::FORMAT_LA8, pixels));
-
- body_shape_data[PhysicsServer2D::SHAPE_RECTANGLE].image = vs->texture_2d_create(image);
-
- RID rectangle_shape = ps->rectangle_shape_create();
- ps->shape_set_data(rectangle_shape, Vector2(16, 16));
-
- body_shape_data[PhysicsServer2D::SHAPE_RECTANGLE].shape = rectangle_shape;
- }
-
- // CAPSULE
-
- {
- Vector<uint8_t> pixels;
- pixels.resize(32 * 64 * 2);
- for (int i = 0; i < 64; i++) {
- for (int j = 0; j < 32; j++) {
- int si = i > 48 ? i - 32 : (i < 16 ? i : 16);
- bool black = Vector2(si - 16, j - 16).length_squared() < 16 * 16;
-
- pixels.set(i * 32 * 2 + j * 2 + 0, (i == 16 || j == 16 || i == 48) ? 255 : 0);
- pixels.set(i * 32 * 2 + j * 2 + 1, black ? 255 : 0);
- }
- }
-
- Ref<Image> image = memnew(Image(32, 64, 0, Image::FORMAT_LA8, pixels));
-
- body_shape_data[PhysicsServer2D::SHAPE_CAPSULE].image = vs->texture_2d_create(image);
-
- RID capsule_shape = ps->capsule_shape_create();
- ps->shape_set_data(capsule_shape, Vector2(16, 32));
-
- body_shape_data[PhysicsServer2D::SHAPE_CAPSULE].shape = capsule_shape;
- }
-
- // CONVEX
-
- {
- Ref<Image> image = memnew(Image(convex_png));
-
- body_shape_data[PhysicsServer2D::SHAPE_CONVEX_POLYGON].image = vs->texture_2d_create(image);
-
- RID convex_polygon_shape = ps->convex_polygon_shape_create();
-
- Vector<Vector2> arr;
- Point2 sb(32, 32);
- arr.push_back(Point2(20, 3) - sb);
- arr.push_back(Point2(58, 23) - sb);
- arr.push_back(Point2(55, 54) - sb);
- arr.push_back(Point2(27, 60) - sb);
- arr.push_back(Point2(5, 56) - sb);
- arr.push_back(Point2(4, 20) - sb);
- arr.push_back(Point2(11, 7) - sb);
- ps->shape_set_data(convex_polygon_shape, arr);
-
- body_shape_data[PhysicsServer2D::SHAPE_CONVEX_POLYGON].shape = convex_polygon_shape;
- }
- }
-
- void _do_ray_query() {
- // FIXME: Do something?
- }
-
-protected:
- void input_event(const Ref<InputEvent> &p_event) {
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid()) {
- if (mb->is_pressed()) {
- Point2 p = mb->get_position();
-
- if (mb->get_button_index() == MouseButton::LEFT) {
- ray_to = p;
- _do_ray_query();
- } else if (mb->get_button_index() == MouseButton::RIGHT) {
- ray_from = p;
- _do_ray_query();
- }
- }
- }
-
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
- Point2 p = mm->get_position();
-
- if ((mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
- ray_to = p;
- _do_ray_query();
- } else if ((mm->get_button_mask() & MouseButton::MASK_RIGHT) != MouseButton::NONE) {
- ray_from = p;
- _do_ray_query();
- }
- }
- }
-
- RID _add_body(PhysicsServer2D::ShapeType p_shape, const Transform2D &p_xform) {
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
-
- RID body = ps->body_create();
- ps->body_add_shape(body, body_shape_data[p_shape].shape);
- ps->body_set_space(body, space);
- ps->body_set_continuous_collision_detection_mode(body, PhysicsServer2D::CCD_MODE_CAST_SHAPE);
- ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, p_xform);
-
- RID sprite = vs->canvas_item_create();
- vs->canvas_item_set_parent(sprite, canvas);
- vs->canvas_item_set_transform(sprite, p_xform);
- Size2 imgsize(5, 5);
- vs->canvas_item_add_texture_rect(sprite, Rect2(-imgsize / 2.0, imgsize), body_shape_data[p_shape].image);
-
- ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics2DMainLoop::_body_moved), sprite);
-
- return body;
- }
-
- void _add_world_boundary(const Vector2 &p_normal, real_t p_d) {
- PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
-
- Array arr;
- arr.push_back(p_normal);
- arr.push_back(p_d);
-
- RID world_boundary = ps->world_boundary_shape_create();
- ps->shape_set_data(world_boundary, arr);
-
- RID plane_body = ps->body_create();
- ps->body_set_mode(plane_body, PhysicsServer2D::BODY_MODE_STATIC);
- ps->body_set_space(plane_body, space);
- ps->body_add_shape(plane_body, world_boundary);
- }
-
- void _add_concave(const Vector<Vector2> &p_points, const Transform2D &p_xform = Transform2D()) {
- PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
- RenderingServer *vs = RenderingServer::get_singleton();
-
- RID concave = ps->concave_polygon_shape_create();
- ps->shape_set_data(concave, p_points);
- RID body = ps->body_create();
- ps->body_set_mode(body, PhysicsServer2D::BODY_MODE_STATIC);
- ps->body_set_space(body, space);
- ps->body_add_shape(body, concave);
- ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, p_xform);
-
- RID sprite = vs->canvas_item_create();
- vs->canvas_item_set_parent(sprite, canvas);
- vs->canvas_item_set_transform(sprite, p_xform);
- for (int i = 0; i < p_points.size(); i += 2) {
- vs->canvas_item_add_line(sprite, p_points[i], p_points[i + 1], Color(0, 0, 0), 2);
- }
- }
-
- void _body_moved(Object *p_state, RID p_sprite) {
- PhysicsDirectBodyState2D *state = (PhysicsDirectBodyState2D *)p_state;
- RenderingServer::get_singleton()->canvas_item_set_transform(p_sprite, state->get_transform());
- }
-
- void _ray_query_callback(const RID &p_rid, ObjectID p_id, int p_shape, const Vector2 &p_point, const Vector2 &p_normal) {
- Vector2 ray_end;
-
- if (p_rid.is_valid()) {
- ray_end = p_point;
- } else {
- ray_end = ray_to;
- }
-
- RenderingServer *vs = RenderingServer::get_singleton();
-
- vs->canvas_item_clear(ray);
- vs->canvas_item_add_line(ray, ray_from, ray_end, p_rid.is_valid() ? Color(0, 1, 0.4) : Color(1, 0.4, 0), 2);
- if (p_rid.is_valid()) {
- vs->canvas_item_add_line(ray, ray_end, ray_end + p_normal * 20, p_rid.is_valid() ? Color(0, 1, 0.4) : Color(1, 0.4, 0), 2);
- }
- }
-
- static void _bind_methods() {
- ClassDB::bind_method(D_METHOD("_ray_query_callback"), &TestPhysics2DMainLoop::_ray_query_callback);
- }
-
-public:
- virtual void initialize() override {
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
-
- space = ps->space_create();
- ps->space_set_active(space, true);
- ps->set_active(true);
- ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, Vector2(0, 1));
- ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 980);
-
- {
- RID vp = vs->viewport_create();
- canvas = vs->canvas_create();
-
- Size2i screen_size = DisplayServer::get_singleton()->window_get_size();
- vs->viewport_attach_canvas(vp, canvas);
- vs->viewport_set_size(vp, screen_size.x, screen_size.y);
- vs->viewport_attach_to_screen(vp, Rect2(Vector2(), screen_size));
- vs->viewport_set_active(vp, true);
- vs->viewport_set_canvas_transform(vp, canvas, view_xform);
- }
-
- ray = vs->canvas_item_create();
- vs->canvas_item_set_parent(ray, canvas);
-
- for (int i = 0; i < 32; i++) {
- PhysicsServer2D::ShapeType types[4] = {
- PhysicsServer2D::SHAPE_CIRCLE,
- PhysicsServer2D::SHAPE_CAPSULE,
- PhysicsServer2D::SHAPE_RECTANGLE,
- PhysicsServer2D::SHAPE_CONVEX_POLYGON,
-
- };
-
- PhysicsServer2D::ShapeType type = types[i % 4];
- _add_body(type, Transform2D(i * 0.8, Point2(152 + i * 40, 100 - 40 * i)));
- }
-
- Point2 prev;
-
- Vector<Point2> parr;
- for (int i = 0; i < 30; i++) {
- Point2 p(i * 60, Math::randf() * 70 + 340);
- if (i > 0) {
- parr.push_back(prev);
- parr.push_back(p);
- }
- prev = p;
- }
-
- _add_concave(parr);
- }
-
- virtual bool process(double p_time) override {
- return false;
- }
- virtual void finalize() override {
- }
-
- TestPhysics2DMainLoop() {}
-};
-
-namespace TestPhysics2D {
-
-MainLoop *test() {
- return memnew(TestPhysics2DMainLoop);
-}
-} // namespace TestPhysics2D
diff --git a/tests/servers/test_physics_2d.h b/tests/servers/test_physics_2d.h
deleted file mode 100644
index b6c47574cd..0000000000
--- a/tests/servers/test_physics_2d.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* test_physics_2d.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 TEST_PHYSICS_2D_H
-#define TEST_PHYSICS_2D_H
-
-class MainLoop;
-
-namespace TestPhysics2D {
-
-MainLoop *test();
-}
-
-#endif // TEST_PHYSICS_2D_H
diff --git a/tests/servers/test_physics_3d.cpp b/tests/servers/test_physics_3d.cpp
deleted file mode 100644
index 3d38b9d901..0000000000
--- a/tests/servers/test_physics_3d.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*************************************************************************/
-/* test_physics_3d.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 "test_physics_3d.h"
-
-#include "core/math/convex_hull.h"
-#include "core/math/geometry_3d.h"
-#include "core/os/main_loop.h"
-#include "servers/physics_server_3d.h"
-#include "servers/rendering_server.h"
-
-class TestPhysics3DMainLoop : public MainLoop {
- GDCLASS(TestPhysics3DMainLoop, MainLoop);
-
- enum {
- LINK_COUNT = 20,
- };
-
- RID test_cube;
-
- RID plane;
- RID sphere;
- RID light;
- RID camera;
- RID mover;
- RID scenario;
- RID space;
-
- RID character;
-
- real_t ofs_x, ofs_y;
-
- Point2 joy_direction;
-
- List<RID> bodies;
- Map<PhysicsServer3D::ShapeType, RID> type_shape_map;
- Map<PhysicsServer3D::ShapeType, RID> type_mesh_map;
-
- void body_changed_transform(Object *p_state, RID p_visual_instance) {
- PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state;
- RenderingServer *vs = RenderingServer::get_singleton();
- Transform3D t = state->get_transform();
- vs->instance_set_transform(p_visual_instance, t);
- }
-
- bool quit;
-
-protected:
- RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform3D p_location, bool p_active_default = true, const Transform3D &p_shape_xform = Transform3D()) {
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
-
- RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape], scenario);
- RID body = ps->body_create();
- ps->body_set_mode(body, p_body);
- ps->body_set_state(body, PhysicsServer3D::BODY_STATE_SLEEPING, !p_active_default);
- ps->body_set_space(body, space);
- ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0);
- //todo set space
- ps->body_add_shape(body, type_shape_map[p_shape]);
- ps->body_set_force_integration_callback(body, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance);
-
- ps->body_set_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM, p_location);
- bodies.push_back(body);
-
- if (p_body == PhysicsServer3D::BODY_MODE_STATIC) {
- vs->instance_set_transform(mesh_instance, p_location);
- }
- return body;
- }
-
- RID create_world_boundary(const Plane &p_plane) {
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
-
- RID world_boundary_shape = ps->shape_create(PhysicsServer3D::SHAPE_WORLD_BOUNDARY);
- ps->shape_set_data(world_boundary_shape, p_plane);
-
- RID b = ps->body_create();
- ps->body_set_mode(b, PhysicsServer3D::BODY_MODE_STATIC);
-
- ps->body_set_space(b, space);
- ps->body_add_shape(b, world_boundary_shape);
- return b;
- }
-
- void configure_body(RID p_body, real_t p_mass, real_t p_friction, real_t p_bounce) {
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
- ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_MASS, p_mass);
- ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_FRICTION, p_friction);
- ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_BOUNCE, p_bounce);
- }
-
- void initialize_shapes() {
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
-
- /* SPHERE SHAPE */
- RID sphere_mesh = vs->make_sphere_mesh(10, 20, 0.5);
- type_mesh_map[PhysicsServer3D::SHAPE_SPHERE] = sphere_mesh;
-
- RID sphere_shape = ps->shape_create(PhysicsServer3D::SHAPE_SPHERE);
- ps->shape_set_data(sphere_shape, 0.5);
- type_shape_map[PhysicsServer3D::SHAPE_SPHERE] = sphere_shape;
-
- /* BOX SHAPE */
-
- Vector<Plane> box_planes = Geometry3D::build_box_planes(Vector3(0.5, 0.5, 0.5));
- RID box_mesh = vs->mesh_create();
- Geometry3D::MeshData box_data = Geometry3D::build_convex_mesh(box_planes);
- vs->mesh_add_surface_from_mesh_data(box_mesh, box_data);
- type_mesh_map[PhysicsServer3D::SHAPE_BOX] = box_mesh;
-
- RID box_shape = ps->shape_create(PhysicsServer3D::SHAPE_BOX);
- ps->shape_set_data(box_shape, Vector3(0.5, 0.5, 0.5));
- type_shape_map[PhysicsServer3D::SHAPE_BOX] = box_shape;
-
- /* CAPSULE SHAPE */
-
- Vector<Plane> capsule_planes = Geometry3D::build_capsule_planes(0.5, 0.7, 12, Vector3::AXIS_Z);
-
- RID capsule_mesh = vs->mesh_create();
- Geometry3D::MeshData capsule_data = Geometry3D::build_convex_mesh(capsule_planes);
- vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data);
-
- type_mesh_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_mesh;
-
- RID capsule_shape = ps->shape_create(PhysicsServer3D::SHAPE_CAPSULE);
- Dictionary capsule_params;
- capsule_params["radius"] = 0.5;
- capsule_params["height"] = 1.4;
- ps->shape_set_data(capsule_shape, capsule_params);
- type_shape_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_shape;
-
- /* CONVEX SHAPE */
-
- Vector<Plane> convex_planes = Geometry3D::build_cylinder_planes(0.5, 0.7, 5, Vector3::AXIS_Z);
-
- RID convex_mesh = vs->mesh_create();
- Geometry3D::MeshData convex_data = Geometry3D::build_convex_mesh(convex_planes);
- ConvexHullComputer::convex_hull(convex_data.vertices, convex_data);
- vs->mesh_add_surface_from_mesh_data(convex_mesh, convex_data);
-
- type_mesh_map[PhysicsServer3D::SHAPE_CONVEX_POLYGON] = convex_mesh;
-
- RID convex_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONVEX_POLYGON);
- ps->shape_set_data(convex_shape, convex_data.vertices);
- type_shape_map[PhysicsServer3D::SHAPE_CONVEX_POLYGON] = convex_shape;
- }
-
- void make_trimesh(Vector<Vector3> p_faces, const Transform3D &p_xform = Transform3D()) {
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
- RID trimesh_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON);
- Dictionary trimesh_params;
- trimesh_params["faces"] = p_faces;
- trimesh_params["backface_collision"] = false;
- ps->shape_set_data(trimesh_shape, trimesh_params);
- Vector<Vector3> normals; // for drawing
- for (int i = 0; i < p_faces.size() / 3; i++) {
- Plane p(p_faces[i * 3 + 0], p_faces[i * 3 + 1], p_faces[i * 3 + 2]);
- normals.push_back(p.normal);
- normals.push_back(p.normal);
- normals.push_back(p.normal);
- }
-
- RID trimesh_mesh = vs->mesh_create();
- Array d;
- d.resize(RS::ARRAY_MAX);
- d[RS::ARRAY_VERTEX] = p_faces;
- d[RS::ARRAY_NORMAL] = normals;
- vs->mesh_add_surface_from_arrays(trimesh_mesh, RS::PRIMITIVE_TRIANGLES, d);
-
- RID triins = vs->instance_create2(trimesh_mesh, scenario);
-
- RID tribody = ps->body_create();
- ps->body_set_mode(tribody, PhysicsServer3D::BODY_MODE_STATIC);
- ps->body_set_space(tribody, space);
- //todo set space
- ps->body_add_shape(tribody, trimesh_shape);
- Transform3D tritrans = p_xform;
- ps->body_set_state(tribody, PhysicsServer3D::BODY_STATE_TRANSFORM, tritrans);
- vs->instance_set_transform(triins, tritrans);
- }
-
- void make_grid(int p_width, int p_height, real_t p_cellsize, real_t p_cellheight, const Transform3D &p_xform = Transform3D()) {
- Vector<Vector<real_t>> grid;
-
- grid.resize(p_width);
-
- for (int i = 0; i < p_width; i++) {
- grid.write[i].resize(p_height);
-
- for (int j = 0; j < p_height; j++) {
- grid.write[i].write[j] = 1.0 + Math::random(-p_cellheight, p_cellheight);
- }
- }
-
- Vector<Vector3> faces;
-
- for (int i = 1; i < p_width; i++) {
- for (int j = 1; j < p_height; j++) {
-#define MAKE_VERTEX(m_x, m_z) \
- faces.push_back(Vector3((m_x - p_width / 2) * p_cellsize, grid[m_x][m_z], (m_z - p_height / 2) * p_cellsize))
-
- MAKE_VERTEX(i, j - 1);
- MAKE_VERTEX(i, j);
- MAKE_VERTEX(i - 1, j);
-
- MAKE_VERTEX(i - 1, j - 1);
- MAKE_VERTEX(i, j - 1);
- MAKE_VERTEX(i - 1, j);
- }
- }
-
- make_trimesh(faces, p_xform);
- }
-
-public:
- virtual void input_event(const Ref<InputEvent> &p_event) {
- Ref<InputEventMouseMotion> mm = p_event;
- if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_MIDDLE) != MouseButton::NONE) {
- ofs_y -= mm->get_relative().y / 200.0;
- ofs_x += mm->get_relative().x / 200.0;
- }
-
- if (mm.is_valid() && (mm->get_button_mask() & MouseButton::MASK_LEFT) != MouseButton::NONE) {
- real_t y = -mm->get_relative().y / 20.0;
- real_t x = mm->get_relative().x / 20.0;
-
- if (mover.is_valid()) {
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
- Transform3D t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM);
- t.origin += Vector3(x, y, 0);
-
- ps->body_set_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM, t);
- }
- }
- }
-
- virtual void request_quit() {
- quit = true;
- }
- virtual void initialize() override {
- ofs_x = ofs_y = 0;
- initialize_shapes();
-
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
- space = ps->space_create();
- ps->space_set_active(space, true);
-
- RenderingServer *vs = RenderingServer::get_singleton();
-
- /* LIGHT */
- RID lightaux = vs->directional_light_create();
- scenario = vs->scenario_create();
- vs->light_set_shadow(lightaux, true);
- light = vs->instance_create2(lightaux, scenario);
- Transform3D t;
- t.rotate(Vector3(1.0, 0, 0), 0.6);
- vs->instance_set_transform(light, t);
-
- /* CAMERA */
-
- camera = vs->camera_create();
-
- RID viewport = vs->viewport_create();
- Size2i screen_size = DisplayServer::get_singleton()->window_get_size();
- vs->viewport_set_size(viewport, screen_size.x, screen_size.y);
- vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size));
- vs->viewport_set_active(viewport, true);
- vs->viewport_attach_camera(viewport, camera);
- vs->viewport_set_scenario(viewport, scenario);
-
- vs->camera_set_perspective(camera, 60, 0.1, 40.0);
- vs->camera_set_transform(camera, Transform3D(Basis(), Vector3(0, 9, 12)));
-
- Transform3D gxf;
- gxf.basis.scale(Vector3(1.4, 0.4, 1.4));
- gxf.origin = Vector3(-2, 1, -2);
- make_grid(5, 5, 2.5, 1, gxf);
- test_fall();
- quit = false;
- }
- virtual bool physics_process(double p_time) override {
- if (mover.is_valid()) {
- static real_t joy_speed = 10;
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
- Transform3D t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM);
- t.origin += Vector3(joy_speed * joy_direction.x * p_time, -joy_speed * joy_direction.y * p_time, 0);
- ps->body_set_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM, t);
- };
-
- Transform3D cameratr;
- cameratr.rotate(Vector3(0, 1, 0), ofs_x);
- cameratr.rotate(Vector3(1, 0, 0), -ofs_y);
- cameratr.translate(Vector3(0, 2, 8));
- RenderingServer *vs = RenderingServer::get_singleton();
- vs->camera_set_transform(camera, cameratr);
-
- return quit;
- }
- virtual void finalize() override {
- }
-
- void test_joint() {
- }
-
- void test_hinge() {
- }
-
- void test_character() {
- RenderingServer *vs = RenderingServer::get_singleton();
- PhysicsServer3D *ps = PhysicsServer3D::get_singleton();
-
- Vector<Plane> capsule_planes = Geometry3D::build_capsule_planes(0.5, 1, 12, 5, Vector3::AXIS_Y);
-
- RID capsule_mesh = vs->mesh_create();
- Geometry3D::MeshData capsule_data = Geometry3D::build_convex_mesh(capsule_planes);
- vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data);
- type_mesh_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_mesh;
-
- RID capsule_shape = ps->shape_create(PhysicsServer3D::SHAPE_CAPSULE);
- Dictionary capsule_params;
- capsule_params["radius"] = 0.5;
- capsule_params["height"] = 1;
- Transform3D shape_xform;
- shape_xform.rotate(Vector3(1, 0, 0), Math_PI / 2.0);
- //shape_xform.origin=Vector3(1,1,1);
- ps->shape_set_data(capsule_shape, capsule_params);
-
- RID mesh_instance = vs->instance_create2(capsule_mesh, scenario);
- character = ps->body_create();
- ps->body_set_mode(character, PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR);
- ps->body_set_space(character, space);
- //todo add space
- ps->body_add_shape(character, capsule_shape);
- ps->body_set_force_integration_callback(character, callable_mp(this, &TestPhysics3DMainLoop::body_changed_transform), mesh_instance);
-
- ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform3D(Basis(), Vector3(-2, 5, -2)));
- bodies.push_back(character);
- }
-
- void test_fall() {
- for (int i = 0; i < 35; i++) {
- static const PhysicsServer3D::ShapeType shape_idx[] = {
- PhysicsServer3D::SHAPE_CAPSULE,
- PhysicsServer3D::SHAPE_BOX,
- PhysicsServer3D::SHAPE_SPHERE,
- PhysicsServer3D::SHAPE_CONVEX_POLYGON
- };
-
- PhysicsServer3D::ShapeType type = shape_idx[i % 4];
-
- Transform3D t;
-
- t.origin = Vector3(0.0 * i, 3.5 + 1.1 * i, 0.7 + 0.0 * i);
- t.basis.rotate(Vector3(0.2, -1, 0), Math_PI / 2 * 0.6);
-
- create_body(type, PhysicsServer3D::BODY_MODE_DYNAMIC, t);
- }
-
- create_world_boundary(Plane(Vector3(0, 1, 0), -1));
- }
-
- void test_activate() {
- create_body(PhysicsServer3D::SHAPE_BOX, PhysicsServer3D::BODY_MODE_DYNAMIC, Transform3D(Basis(), Vector3(0, 2, 0)), true);
- create_world_boundary(Plane(Vector3(0, 1, 0), -1));
- }
-
- virtual bool process(double p_time) override {
- return false;
- }
-
- TestPhysics3DMainLoop() {
- }
-};
-
-namespace TestPhysics3D {
-
-MainLoop *test() {
- return memnew(TestPhysics3DMainLoop);
-}
-} // namespace TestPhysics3D
diff --git a/tests/servers/test_physics_3d.h b/tests/servers/test_physics_3d.h
deleted file mode 100644
index f618d0fb4f..0000000000
--- a/tests/servers/test_physics_3d.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* test_physics_3d.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 TEST_PHYSICS_H
-#define TEST_PHYSICS_H
-
-class MainLoop;
-
-namespace TestPhysics3D {
-
-MainLoop *test();
-}
-
-#endif
diff --git a/tests/servers/test_render.cpp b/tests/servers/test_render.cpp
deleted file mode 100644
index 44403e3724..0000000000
--- a/tests/servers/test_render.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/*************************************************************************/
-/* test_render.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 "test_render.h"
-
-#include "core/math/convex_hull.h"
-#include "core/os/main_loop.h"
-#include "servers/rendering_server.h"
-
-#define OBJECT_COUNT 50
-
-namespace TestRender {
-
-class TestMainLoop : public MainLoop {
- RID test_cube;
- RID instance;
- RID camera;
- RID viewport;
- RID light;
- RID scenario;
-
- struct InstanceInfo {
- RID instance;
- Transform3D base;
- Vector3 rot_axis;
- };
-
- List<InstanceInfo> instances;
-
- float ofs;
- bool quit;
-
-protected:
-public:
- virtual void input_event(const Ref<InputEvent> &p_event) {
- if (p_event->is_pressed()) {
- quit = true;
- }
- }
-
- virtual void init() {
- print_line("INITIALIZING TEST RENDER");
- RenderingServer *vs = RenderingServer::get_singleton();
- test_cube = vs->get_test_cube();
- scenario = vs->scenario_create();
-
- Vector<Vector3> vts;
-
- /*
- Vector<Plane> sp = Geometry3D::build_sphere_planes(2,5,5);
- Geometry3D::MeshData md2 = Geometry3D::build_convex_mesh(sp);
- vts=md2.vertices;
-*/
- /*
-
- static const int s = 20;
- for(int i=0;i<s;i++) {
- Basis rot(Vector3(0,1,0),i*Math_PI/s);
-
- for(int j=0;j<s;j++) {
- Vector3 v;
- v.x=Math::sin(j*Math_PI*2/s);
- v.y=Math::cos(j*Math_PI*2/s);
-
- vts.push_back( rot.xform(v*2 ) );
- }
- }*/
- /*for(int i=0;i<100;i++) {
- vts.push_back( Vector3(Math::randf()*2-1.0,Math::randf()*2-1.0,Math::randf()*2-1.0).normalized()*2);
- }*/
- /*
- vts.push_back(Vector3(0,0,1));
- vts.push_back(Vector3(0,0,-1));
- vts.push_back(Vector3(0,1,0));
- vts.push_back(Vector3(0,-1,0));
- vts.push_back(Vector3(1,0,0));
- vts.push_back(Vector3(-1,0,0));*/
-
- vts.push_back(Vector3(1, 1, 1));
- vts.push_back(Vector3(1, -1, 1));
- vts.push_back(Vector3(-1, 1, 1));
- vts.push_back(Vector3(-1, -1, 1));
- vts.push_back(Vector3(1, 1, -1));
- vts.push_back(Vector3(1, -1, -1));
- vts.push_back(Vector3(-1, 1, -1));
- vts.push_back(Vector3(-1, -1, -1));
-
- Geometry3D::MeshData md;
- Error err = ConvexHullComputer::convex_hull(vts, md);
- print_line("ERR: " + itos(err));
- test_cube = vs->mesh_create();
- vs->mesh_add_surface_from_mesh_data(test_cube, md);
- //vs->scenario_set_debug(scenario,RS::SCENARIO_DEBUG_WIREFRAME);
-
- /*
- RID sm = vs->shader_create();
- //vs->shader_set_fragment_code(sm,"OUT_ALPHA=mod(TIME,1);");
- //vs->shader_set_vertex_code(sm,"OUT_VERTEX=IN_VERTEX*mod(TIME,1);");
- vs->shader_set_fragment_code(sm,"OUT_DIFFUSE=vec3(1,0,1);OUT_GLOW=abs(sin(TIME));");
- RID tcmat = vs->mesh_surface_get_material(test_cube,0);
- vs->material_set_shader(tcmat,sm);
- */
-
- List<String> cmdline = OS::get_singleton()->get_cmdline_args();
- int object_count = OBJECT_COUNT;
- if (cmdline.size() > 0 && cmdline[cmdline.size() - 1].to_int()) {
- object_count = cmdline[cmdline.size() - 1].to_int();
- };
-
- for (int i = 0; i < object_count; i++) {
- InstanceInfo ii;
-
- ii.instance = vs->instance_create2(test_cube, scenario);
-
- ii.base.translate(Math::random(-20, 20), Math::random(-20, 20), Math::random(-20, 18));
- ii.base.rotate(Vector3(0, 1, 0), Math::randf() * Math_PI);
- ii.base.rotate(Vector3(1, 0, 0), Math::randf() * Math_PI);
- vs->instance_set_transform(ii.instance, ii.base);
-
- ii.rot_axis = Vector3(Math::random(-1, 1), Math::random(-1, 1), Math::random(-1, 1)).normalized();
-
- instances.push_back(ii);
- }
-
- camera = vs->camera_create();
-
- // vs->camera_set_perspective( camera, 60.0,0.1, 100.0 );
-
- viewport = vs->viewport_create();
- Size2i screen_size = DisplayServer::get_singleton()->window_get_size();
- vs->viewport_set_size(viewport, screen_size.x, screen_size.y);
- vs->viewport_attach_to_screen(viewport, Rect2(Vector2(), screen_size));
- vs->viewport_set_active(viewport, true);
- vs->viewport_attach_camera(viewport, camera);
- vs->viewport_set_scenario(viewport, scenario);
- vs->camera_set_transform(camera, Transform3D(Basis(), Vector3(0, 3, 30)));
- vs->camera_set_perspective(camera, 60, 0.1, 1000);
-
- /*
- RID lightaux = vs->light_create( RenderingServer::LIGHT_OMNI );
- vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_RADIUS, 80 );
- vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_ATTENUATION, 1 );
- vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_ENERGY, 1.5 );
- light = vs->instance_create( lightaux );
- */
- RID lightaux;
-
- lightaux = vs->directional_light_create();
- //vs->light_set_color( lightaux, RenderingServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) );
- vs->light_set_color(lightaux, Color(1.0, 1.0, 1.0));
- //vs->light_set_shadow( lightaux, true );
- light = vs->instance_create2(lightaux, scenario);
- Transform3D lla;
- //lla.set_look_at(Vector3(),Vector3(1, -1, 1));
- lla.basis = Basis::looking_at(Vector3(0.0, -0.836026, -0.548690));
-
- vs->instance_set_transform(light, lla);
-
- lightaux = vs->omni_light_create();
- //vs->light_set_color( lightaux, RenderingServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,1.0) );
- vs->light_set_color(lightaux, Color(1.0, 1.0, 0.0));
- vs->light_set_param(lightaux, RenderingServer::LIGHT_PARAM_RANGE, 4);
- vs->light_set_param(lightaux, RenderingServer::LIGHT_PARAM_ENERGY, 8);
- //vs->light_set_shadow( lightaux, true );
- //light = vs->instance_create( lightaux );
-
- ofs = 0;
- quit = false;
- }
- virtual bool iteration(double p_time) {
- RenderingServer *vs = RenderingServer::get_singleton();
- //Transform3D t;
- //t.rotate(Vector3(0, 1, 0), ofs);
- //t.translate(Vector3(0,0,20 ));
- //vs->camera_set_transform(camera, t);
-
- ofs += p_time * 0.05;
-
- //return quit;
-
- for (const InstanceInfo &E : instances) {
- Transform3D pre(Basis(E.rot_axis, ofs), Vector3());
- vs->instance_set_transform(E.instance, pre * E.base);
- /*
- if( !E->next() ) {
- vs->free( E.instance );
- instances.erase(E );
- }*/
- }
-
- return quit;
- }
-
- virtual bool idle(double p_time) {
- return quit;
- }
-
- virtual void finish() {
- }
-};
-
-MainLoop *test() {
- return memnew(TestMainLoop);
-}
-} // namespace TestRender
diff --git a/tests/servers/test_render.h b/tests/servers/test_render.h
deleted file mode 100644
index d5a3e01ee5..0000000000
--- a/tests/servers/test_render.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* test_render.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 TEST_RENDER_H
-#define TEST_RENDER_H
-
-class MainLoop;
-
-namespace TestRender {
-
-MainLoop *test();
-}
-
-#endif // TEST_RENDER_H
diff --git a/tests/servers/test_shader_lang.cpp b/tests/servers/test_shader_lang.cpp
deleted file mode 100644
index 06e28212d2..0000000000
--- a/tests/servers/test_shader_lang.cpp
+++ /dev/null
@@ -1,364 +0,0 @@
-/*************************************************************************/
-/* test_shader_lang.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 "test_shader_lang.h"
-
-#include "core/os/main_loop.h"
-#include "core/os/os.h"
-#include "servers/rendering/shader_language.h"
-
-typedef ShaderLanguage SL;
-
-namespace TestShaderLang {
-
-static String _mktab(int p_level) {
- String tb;
- for (int i = 0; i < p_level; i++) {
- tb += "\t";
- }
-
- return tb;
-}
-
-static String _typestr(SL::DataType p_type) {
- return ShaderLanguage::get_datatype_name(p_type);
-}
-
-static String _prestr(SL::DataPrecision p_pres) {
- switch (p_pres) {
- case SL::PRECISION_LOWP:
- return "lowp ";
- case SL::PRECISION_MEDIUMP:
- return "mediump ";
- case SL::PRECISION_HIGHP:
- return "highp ";
- case SL::PRECISION_DEFAULT:
- return "";
- }
- return "";
-}
-
-static String _opstr(SL::Operator p_op) {
- return ShaderLanguage::get_operator_text(p_op);
-}
-
-static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) {
- switch (p_type) {
- case SL::TYPE_BOOL:
- return p_values[0].boolean ? "true" : "false";
- case SL::TYPE_BVEC2:
- return String() + "bvec2(" + (p_values[0].boolean ? "true" : "false") + (p_values[1].boolean ? "true" : "false") + ")";
- case SL::TYPE_BVEC3:
- return String() + "bvec3(" + (p_values[0].boolean ? "true" : "false") + "," + (p_values[1].boolean ? "true" : "false") + "," + (p_values[2].boolean ? "true" : "false") + ")";
- case SL::TYPE_BVEC4:
- return String() + "bvec4(" + (p_values[0].boolean ? "true" : "false") + "," + (p_values[1].boolean ? "true" : "false") + "," + (p_values[2].boolean ? "true" : "false") + "," + (p_values[3].boolean ? "true" : "false") + ")";
- case SL::TYPE_INT:
- return rtos(p_values[0].sint);
- case SL::TYPE_IVEC2:
- return String() + "ivec2(" + rtos(p_values[0].sint) + "," + rtos(p_values[1].sint) + ")";
- case SL::TYPE_IVEC3:
- return String() + "ivec3(" + rtos(p_values[0].sint) + "," + rtos(p_values[1].sint) + "," + rtos(p_values[2].sint) + ")";
- case SL::TYPE_IVEC4:
- return String() + "ivec4(" + rtos(p_values[0].sint) + "," + rtos(p_values[1].sint) + "," + rtos(p_values[2].sint) + "," + rtos(p_values[3].sint) + ")";
- case SL::TYPE_UINT:
- return rtos(p_values[0].real);
- case SL::TYPE_UVEC2:
- return String() + "uvec2(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + ")";
- case SL::TYPE_UVEC3:
- return String() + "uvec3(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + ")";
- case SL::TYPE_UVEC4:
- return String() + "uvec4(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + "," + rtos(p_values[3].real) + ")";
- case SL::TYPE_FLOAT:
- return rtos(p_values[0].real);
- case SL::TYPE_VEC2:
- return String() + "vec2(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + ")";
- case SL::TYPE_VEC3:
- return String() + "vec3(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + ")";
- case SL::TYPE_VEC4:
- return String() + "vec4(" + rtos(p_values[0].real) + "," + rtos(p_values[1].real) + "," + rtos(p_values[2].real) + "," + rtos(p_values[3].real) + ")";
- default:
- ERR_FAIL_V(String());
- }
-}
-
-static String dump_node_code(SL::Node *p_node, int p_level) {
- String code;
-
- switch (p_node->type) {
- case SL::Node::TYPE_SHADER: {
- SL::ShaderNode *pnode = (SL::ShaderNode *)p_node;
-
- for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
- String ucode = "uniform ";
- ucode += _prestr(E.value.precision);
- ucode += _typestr(E.value.type);
- ucode += " " + String(E.key);
- if (E.value.array_size > 0) {
- ucode += "[";
- ucode += itos(E.value.array_size);
- ucode += "]";
- } else {
- if (E.value.default_value.size()) {
- ucode += " = " + get_constant_text(E.value.type, E.value.default_value);
- }
-
- static const char *hint_name[SL::ShaderNode::Uniform::HINT_MAX] = {
- "",
- "color",
- "range",
- "albedo",
- "normal",
- "black",
- "white"
- };
-
- if (E.value.hint) {
- ucode += " : " + String(hint_name[E.value.hint]);
- }
- }
-
- code += ucode + "\n";
- }
-
- for (const KeyValue<StringName, SL::ShaderNode::Varying> &E : pnode->varyings) {
- String vcode = "varying ";
- vcode += _prestr(E.value.precision);
- vcode += _typestr(E.value.type);
- vcode += " " + String(E.key);
-
- code += vcode + "\n";
- }
- for (int i = 0; i < pnode->functions.size(); i++) {
- SL::FunctionNode *fnode = pnode->functions[i].function;
-
- String header;
- header = _typestr(fnode->return_type) + " " + fnode->name + "(";
- for (int j = 0; j < fnode->arguments.size(); j++) {
- if (j > 0) {
- header += ", ";
- }
- header += _prestr(fnode->arguments[j].precision) + _typestr(fnode->arguments[j].type) + " " + fnode->arguments[j].name;
- }
-
- header += ")\n";
- code += header;
- code += dump_node_code(fnode->body, p_level + 1);
- }
-
- //code+=dump_node_code(pnode->body,p_level);
- } break;
- case SL::Node::TYPE_STRUCT: {
- } break;
- case SL::Node::TYPE_FUNCTION: {
- } break;
- case SL::Node::TYPE_BLOCK: {
- SL::BlockNode *bnode = (SL::BlockNode *)p_node;
-
- //variables
- code += _mktab(p_level - 1) + "{\n";
- for (const KeyValue<StringName, SL::BlockNode::Variable> &E : bnode->variables) {
- code += _mktab(p_level) + _prestr(E.value.precision) + _typestr(E.value.type) + " " + E.key + ";\n";
- }
-
- for (int i = 0; i < bnode->statements.size(); i++) {
- String scode = dump_node_code(bnode->statements[i], p_level);
-
- if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) {
- code += scode; //use directly
- } else {
- code += _mktab(p_level) + scode + ";\n";
- }
- }
- code += _mktab(p_level - 1) + "}\n";
-
- } break;
- case SL::Node::TYPE_VARIABLE: {
- SL::VariableNode *vnode = (SL::VariableNode *)p_node;
- code = vnode->name;
-
- } break;
- case SL::Node::TYPE_VARIABLE_DECLARATION: {
- // FIXME: Implement
- } break;
- case SL::Node::TYPE_ARRAY: {
- SL::ArrayNode *vnode = (SL::ArrayNode *)p_node;
- code = vnode->name;
- } break;
- case SL::Node::TYPE_ARRAY_CONSTRUCT: {
- // FIXME: Implement
- } break;
- case SL::Node::TYPE_CONSTANT: {
- SL::ConstantNode *cnode = (SL::ConstantNode *)p_node;
- return get_constant_text(cnode->datatype, cnode->values);
-
- } break;
- case SL::Node::TYPE_OPERATOR: {
- SL::OperatorNode *onode = (SL::OperatorNode *)p_node;
-
- switch (onode->op) {
- case SL::OP_ASSIGN:
- case SL::OP_ASSIGN_ADD:
- case SL::OP_ASSIGN_SUB:
- case SL::OP_ASSIGN_MUL:
- case SL::OP_ASSIGN_DIV:
- case SL::OP_ASSIGN_SHIFT_LEFT:
- case SL::OP_ASSIGN_SHIFT_RIGHT:
- case SL::OP_ASSIGN_MOD:
- case SL::OP_ASSIGN_BIT_AND:
- case SL::OP_ASSIGN_BIT_OR:
- case SL::OP_ASSIGN_BIT_XOR:
- code = dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level);
- break;
- case SL::OP_BIT_INVERT:
- case SL::OP_NEGATE:
- case SL::OP_NOT:
- case SL::OP_DECREMENT:
- case SL::OP_INCREMENT:
- code = _opstr(onode->op) + dump_node_code(onode->arguments[0], p_level);
- break;
- case SL::OP_POST_DECREMENT:
- case SL::OP_POST_INCREMENT:
- code = dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op);
- break;
- case SL::OP_CALL:
- case SL::OP_CONSTRUCT:
- code = dump_node_code(onode->arguments[0], p_level) + "(";
- for (int i = 1; i < onode->arguments.size(); i++) {
- if (i > 1) {
- code += ", ";
- }
- code += dump_node_code(onode->arguments[i], p_level);
- }
- code += ")";
- break;
- case SL::OP_EMPTY:
- break;
- default: {
- code = "(" + dump_node_code(onode->arguments[0], p_level) + _opstr(onode->op) + dump_node_code(onode->arguments[1], p_level) + ")";
- break;
- }
- }
-
- } break;
- case SL::Node::TYPE_CONTROL_FLOW: {
- SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node;
- if (cfnode->flow_op == SL::FLOW_OP_IF) {
- code += _mktab(p_level) + "if (" + dump_node_code(cfnode->expressions[0], p_level) + ")\n";
- code += dump_node_code(cfnode->blocks[0], p_level + 1);
- if (cfnode->blocks.size() == 2) {
- code += _mktab(p_level) + "else\n";
- code += dump_node_code(cfnode->blocks[1], p_level + 1);
- }
-
- } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
- if (cfnode->blocks.size()) {
- code = "return " + dump_node_code(cfnode->blocks[0], p_level);
- } else {
- code = "return";
- }
- }
-
- } break;
- case SL::Node::TYPE_MEMBER: {
- SL::MemberNode *mnode = (SL::MemberNode *)p_node;
- code = dump_node_code(mnode->owner, p_level) + "." + mnode->name;
-
- } break;
- }
-
- return code;
-}
-
-static Error recreate_code(void *p_str, SL::ShaderNode *p_program) {
- String *str = (String *)p_str;
-
- *str = dump_node_code(p_program, 0);
-
- return OK;
-}
-
-MainLoop *test() {
- List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
-
- if (cmdlargs.is_empty()) {
- //try editor!
- print_line("usage: godot -test shader_lang <shader>");
- return nullptr;
- }
-
- String test = cmdlargs.back()->get();
-
- FileAccess *fa = FileAccess::open(test, FileAccess::READ);
-
- if (!fa) {
- ERR_FAIL_V(nullptr);
- }
-
- String code;
-
- while (true) {
- char32_t c = fa->get_8();
- if (fa->eof_reached()) {
- break;
- }
- code += c;
- }
-
- SL sl;
- print_line("tokens:\n\n" + sl.token_debug(code));
-
- Map<StringName, SL::FunctionInfo> dt;
- dt["fragment"].built_ins["ALBEDO"] = SL::TYPE_VEC3;
- dt["fragment"].can_discard = true;
-
- Vector<SL::ModeInfo> rm;
- rm.push_back({ "popo" });
- Set<String> types;
- types.insert("spatial");
-
- ShaderLanguage::ShaderCompileInfo info;
- info.functions = dt;
- info.render_modes = rm;
- info.shader_types = types;
-
- Error err = sl.compile(code, info);
-
- if (err) {
- print_line("Error at line: " + rtos(sl.get_error_line()) + ": " + sl.get_error_text());
- return nullptr;
- } else {
- String code2;
- recreate_code(&code2, sl.get_shader());
- print_line("code:\n\n" + code2);
- }
-
- return nullptr;
-}
-} // namespace TestShaderLang
diff --git a/tests/servers/test_shader_lang.h b/tests/servers/test_shader_lang.h
deleted file mode 100644
index 31e1bfbeea..0000000000
--- a/tests/servers/test_shader_lang.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*************************************************************************/
-/* test_shader_lang.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 TEST_SHADER_LANG_H
-#define TEST_SHADER_LANG_H
-
-class MainLoop;
-
-namespace TestShaderLang {
-
-MainLoop *test();
-}
-
-#endif // TEST_SHADER_LANG_H
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
index 830731abcd..344e2fa101 100644
--- a/tests/test_main.cpp
+++ b/tests/test_main.cpp
@@ -45,7 +45,6 @@
#include "tests/core/math/test_expression.h"
#include "tests/core/math/test_geometry_2d.h"
#include "tests/core/math/test_geometry_3d.h"
-#include "tests/core/math/test_math.h"
#include "tests/core/math/test_random_number_generator.h"
#include "tests/core/math/test_rect2.h"
#include "tests/core/math/test_rect2i.h"
@@ -63,7 +62,6 @@
#include "tests/core/templates/test_list.h"
#include "tests/core/templates/test_local_vector.h"
#include "tests/core/templates/test_lru.h"
-#include "tests/core/templates/test_oa_hash_map.h"
#include "tests/core/templates/test_ordered_hash_map.h"
#include "tests/core/templates/test_paged_array.h"
#include "tests/core/templates/test_vector.h"
@@ -77,12 +75,7 @@
#include "tests/scene/test_code_edit.h"
#include "tests/scene/test_curve.h"
#include "tests/scene/test_gradient.h"
-#include "tests/scene/test_gui.h"
#include "tests/scene/test_path_3d.h"
-#include "tests/servers/test_physics_2d.h"
-#include "tests/servers/test_physics_3d.h"
-#include "tests/servers/test_render.h"
-#include "tests/servers/test_shader_lang.h"
#include "tests/servers/test_text_server.h"
#include "tests/test_validate_testing.h"