summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format22
-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.cpp138
-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.cpp136
-rw-r--r--core/os/time.h2
-rw-r--r--core/string/print_string.h10
-rw-r--r--core/string/string_name.cpp1
-rw-r--r--core/string/string_name.h13
-rw-r--r--core/string/translation_po.cpp3
-rw-r--r--core/string/ustring.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/BaseMaterial3D.xml14
-rw-r--r--doc/classes/Camera3D.xml2
-rw-r--r--doc/classes/CanvasItem.xml7
-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/Control.xml22
-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/FontData.xml3
-rw-r--r--doc/classes/Image.xml8
-rw-r--r--doc/classes/Label.xml2
-rw-r--r--doc/classes/Label3D.xml173
-rw-r--r--doc/classes/LineEdit.xml2
-rw-r--r--doc/classes/LinkButton.xml2
-rw-r--r--doc/classes/NavigationServer2D.xml6
-rw-r--r--doc/classes/NavigationServer3D.xml6
-rw-r--r--doc/classes/Node.xml13
-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.xml30
-rw-r--r--doc/classes/Signal.xml2
-rw-r--r--doc/classes/SpriteBase3D.xml17
-rw-r--r--doc/classes/TextEdit.xml2
-rw-r--r--doc/classes/TextServer.xml72
-rw-r--r--doc/classes/TextServerExtension.xml41
-rw-r--r--doc/classes/Time.xml3
-rw-r--r--doc/classes/Tree.xml3
-rw-r--r--doc/classes/TreeItem.xml4
-rw-r--r--doc/classes/Vector3.xml2
-rw-r--r--doc/classes/Vector3i.xml2
-rw-r--r--doc/classes/Viewport.xml4
-rw-r--r--doc/classes/VisualShader.xml8
-rw-r--r--doc/classes/VisualShaderNode.xml11
-rw-r--r--doc/classes/VisualShaderNodeClamp.xml5
-rw-r--r--doc/classes/VisualShaderNodeCompare.xml9
-rw-r--r--doc/classes/VisualShaderNodeDerivativeFunc.xml5
-rw-r--r--doc/classes/VisualShaderNodeMix.xml8
-rw-r--r--doc/classes/VisualShaderNodeMultiplyAdd.xml5
-rw-r--r--doc/classes/VisualShaderNodeSmoothStep.xml8
-rw-r--r--doc/classes/VisualShaderNodeStep.xml8
-rw-r--r--doc/classes/VisualShaderNodeSwitch.xml9
-rw-r--r--doc/classes/VisualShaderNodeVec4Constant.xml16
-rw-r--r--doc/classes/VisualShaderNodeVec4Uniform.xml19
-rw-r--r--doc/classes/VisualShaderNodeVectorBase.xml5
-rw-r--r--doc/classes/VisualShaderNodeVectorCompose.xml4
-rw-r--r--doc/classes/VisualShaderNodeVectorDecompose.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/shaders/canvas.glsl4
-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/material_storage.cpp119
-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.cpp63
-rw-r--r--editor/animation_track_editor.h1
-rw-r--r--editor/create_dialog.cpp61
-rw-r--r--editor/debugger/script_editor_debugger.cpp6
-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.cpp8
-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.cpp47
-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_properties.cpp2
-rw-r--r--editor/editor_resource_preview.cpp30
-rw-r--r--editor/editor_settings.cpp34
-rw-r--r--editor/editor_themes.cpp5
-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.cpp58
-rw-r--r--editor/find_in_files.cpp18
-rw-r--r--editor/icons/AnimationLibrary.svg1
-rw-r--r--editor/icons/ExternalLink.svg1
-rw-r--r--editor/icons/GuiVsplitBg.svg1
-rw-r--r--editor/icons/Label3D.svg1
-rw-r--r--editor/icons/SceneUniqueName.svg1
-rw-r--r--editor/icons/Vector4.svg1
-rw-r--r--editor/import/dynamic_font_import_settings.cpp6
-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_dynamic_font.cpp3
-rw-r--r--editor/import/resource_importer_image.cpp11
-rw-r--r--editor/import/resource_importer_imagefont.cpp1
-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_gizmos.cpp33
-rw-r--r--editor/plugins/node_3d_editor_gizmos.h13
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp5
-rw-r--r--editor/plugins/ot_features_plugin.cpp30
-rw-r--r--editor/plugins/script_editor_plugin.cpp29
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-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/plugins/visual_shader_editor_plugin.cpp305
-rw-r--r--editor/plugins/visual_shader_editor_plugin.h2
-rw-r--r--editor/pot_generator.cpp6
-rw-r--r--editor/pot_generator.h2
-rw-r--r--editor/project_manager.cpp46
-rw-r--r--editor/project_manager.h4
-rw-r--r--editor/scene_tree_dock.cpp46
-rw-r--r--editor/scene_tree_dock.h2
-rw-r--r--editor/scene_tree_editor.cpp18
-rw-r--r--editor/scene_tree_editor.h1
-rw-r--r--editor/script_create_dialog.cpp14
-rw-r--r--editor/shader_create_dialog.cpp6
-rw-r--r--editor/shader_globals_editor.cpp4
-rw-r--r--main/main.cpp14
-rwxr-xr-xmisc/scripts/clang_format.sh2
-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_disassembler.cpp2
-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.cpp14
-rw-r--r--modules/gltf/editor/editor_scene_importer_blend.h4
-rw-r--r--modules/gltf/editor/editor_scene_importer_fbx.cpp7
-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/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.cpp141
-rw-r--r--modules/text_server_adv/text_server_adv.h7
-rw-r--r--modules/text_server_fb/text_server_fb.cpp132
-rw-r--r--modules/text_server_fb/text_server_fb.h6
-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.cpp42
-rw-r--r--modules/visual_script/editor/visual_script_editor.h1
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.cpp65
-rw-r--r--modules/visual_script/editor/visual_script_property_selector.h10
-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/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java4
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.java42
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java9
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java134
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java102
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java4
-rw-r--r--platform/android/java_godot_lib_jni.cpp2
-rw-r--r--platform/android/os_android.cpp3
-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/2d/cpu_particles_2d.cpp2
-rw-r--r--scene/3d/camera_3d.cpp4
-rw-r--r--scene/3d/label_3d.cpp962
-rw-r--r--scene/3d/label_3d.h228
-rw-r--r--scene/3d/lightmap_gi.cpp7
-rw-r--r--scene/3d/node_3d.cpp10
-rw-r--r--scene/3d/sprite_3d.cpp23
-rw-r--r--scene/3d/sprite_3d.h7
-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/control.cpp99
-rw-r--r--scene/gui/control.h13
-rw-r--r--scene/gui/file_dialog.cpp8
-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/label.cpp8
-rw-r--r--scene/gui/label.h6
-rw-r--r--scene/gui/line_edit.cpp4
-rw-r--r--scene/gui/line_edit.h6
-rw-r--r--scene/gui/link_button.cpp4
-rw-r--r--scene/gui/link_button.h6
-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.cpp193
-rw-r--r--scene/gui/rich_text_label.h38
-rw-r--r--scene/gui/text_edit.cpp79
-rw-r--r--scene/gui/text_edit.h6
-rw-r--r--scene/gui/tree.cpp163
-rw-r--r--scene/gui/tree.h11
-rw-r--r--scene/main/canvas_item.cpp6
-rw-r--r--scene/main/canvas_item.h2
-rw-r--r--scene/main/http_request.cpp15
-rw-r--r--scene/main/http_request.h3
-rw-r--r--scene/main/node.cpp94
-rw-r--r--scene/main/node.h9
-rw-r--r--scene/main/scene_tree.cpp2
-rw-r--r--scene/main/shader_globals_override.cpp2
-rw-r--r--scene/main/viewport.cpp6
-rw-r--r--scene/main/window.cpp11
-rw-r--r--scene/register_scene_types.cpp6
-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.cpp26
-rw-r--r--scene/resources/font.h4
-rw-r--r--scene/resources/material.cpp127
-rw-r--r--scene/resources/material.h18
-rw-r--r--scene/resources/packed_scene.cpp3
-rw-r--r--scene/resources/particles_material.cpp28
-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--scene/resources/visual_shader.cpp345
-rw-r--r--scene/resources/visual_shader.h4
-rw-r--r--scene/resources/visual_shader_nodes.cpp798
-rw-r--r--scene/resources/visual_shader_nodes.h115
-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.cpp39
-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/canvas.glsl4
-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.cpp15
-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/text_server_extension.cpp44
-rw-r--r--servers/text/text_server_extension.h14
-rw-r--r--servers/text_server.cpp137
-rw-r--r--servers/text_server.h18
-rw-r--r--servers/xr/xr_interface_extension.cpp7
-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
500 files changed, 18514 insertions, 13333 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/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 3ef895ab01..8d4dbc3f73 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -101,11 +101,11 @@ void ResourceLoaderBinary::_advance_padding(uint32_t p_len) {
}
}
-static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
- if (f.real_is_double) {
+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));
+ f->get_buffer((uint8_t *)dst, count * sizeof(double));
#ifdef BIG_ENDIAN_ENABLED
{
uint64_t *dst = (uint64_t *)dst;
@@ -117,7 +117,7 @@ static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
} 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();
+ dst[i] = f->get_double();
}
} else {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!");
@@ -125,7 +125,7 @@ static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
} else {
if (sizeof(real_t) == 4) {
// Ideal case with float-precision
- f.get_buffer((uint8_t *)dst, count * sizeof(float));
+ f->get_buffer((uint8_t *)dst, count * sizeof(float));
#ifdef BIG_ENDIAN_ENABLED
{
uint32_t *dst = (uint32_t *)dst;
@@ -136,7 +136,7 @@ static Error read_reals(real_t *dst, FileAccess &f, size_t count) {
#endif
} else if (sizeof(real_t) == 8) {
for (size_t i = 0; i < count; ++i) {
- dst[i] = f.get_float();
+ dst[i] = f->get_float();
}
} else {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "real_t size is neither 4 nor 8!");
@@ -573,7 +573,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
array.resize(len);
Vector2 *w = array.ptrw();
static_assert(sizeof(Vector2) == 2 * sizeof(real_t));
- const Error err = read_reals(reinterpret_cast<real_t *>(w), *f, len * 2);
+ const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 2);
ERR_FAIL_COND_V(err != OK, err);
r_v = array;
@@ -586,7 +586,7 @@ Error ResourceLoaderBinary::parse_variant(Variant &r_v) {
array.resize(len);
Vector3 *w = array.ptrw();
static_assert(sizeof(Vector3) == 3 * sizeof(real_t));
- const Error err = read_reals(reinterpret_cast<real_t *>(w), *f, len * 3);
+ const Error err = read_reals(reinterpret_cast<real_t *>(w), f, len * 3);
ERR_FAIL_COND_V(err != OK, err);
r_v = array;
@@ -789,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;
@@ -804,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);
@@ -834,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;
@@ -856,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;
@@ -864,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;
@@ -876,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 + ".");
}
@@ -901,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));
}
@@ -978,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;
@@ -991,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;
@@ -1003,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 "";
}
@@ -1017,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 "";
}
@@ -1026,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 + "'.");
@@ -1096,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);
@@ -1106,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();
@@ -1117,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);
@@ -1169,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");
}
@@ -1201,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));
@@ -1311,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
}
@@ -1343,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
}
@@ -1362,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++) {
@@ -1371,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);
@@ -1830,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) {
@@ -1853,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);
}
@@ -1902,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;
}
@@ -2061,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..f10a2ec186 100644
--- a/core/os/time.cpp
+++ b/core/os/time.cpp
@@ -95,16 +95,21 @@ 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 < 0, ret, "Invalid month value of: " + itos(month) + "."); \
+ 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(hour < 0, 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(minute < 0, 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)."); \
+ ERR_FAIL_COND_V_MSG(second < 0, ret, "Invalid second value of: " + itos(second) + "."); \
+ ERR_FAIL_COND_V_MSG(day == 0, ret, "Invalid day value of: " + itos(day) + ", days are 1-indexed and cannot be 0."); \
+ ERR_FAIL_COND_V_MSG(day < 0, ret, "Invalid day value of: " + itos(day) + "."); \
+ /* Do this check after month is tested as valid. */ \
+ 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,61 +129,65 @@ 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; \
+ int day = 1; \
+ int hour = 0; \
+ int minute = 0; \
+ int 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 \
/* Get all time values from the dictionary. If it doesn't exist, set the */ \
/* values to the default values for Unix epoch (1970-01-01 00:00:00). */ \
int64_t year = p_datetime.has(YEAR_KEY) ? int64_t(p_datetime[YEAR_KEY]) : UNIX_EPOCH_YEAR_AD; \
- Month month = Month((p_datetime.has(MONTH_KEY)) ? uint8_t(p_datetime[MONTH_KEY]) : 1); \
- uint8_t day = p_datetime.has(DAY_KEY) ? uint8_t(p_datetime[DAY_KEY]) : 1; \
- uint8_t hour = p_datetime.has(HOUR_KEY) ? uint8_t(p_datetime[HOUR_KEY]) : 0; \
- uint8_t minute = p_datetime.has(MINUTE_KEY) ? uint8_t(p_datetime[MINUTE_KEY]) : 0; \
- uint8_t second = p_datetime.has(SECOND_KEY) ? uint8_t(p_datetime[SECOND_KEY]) : 0;
+ Month month = Month((p_datetime.has(MONTH_KEY)) ? int(p_datetime[MONTH_KEY]) : 1); \
+ int day = p_datetime.has(DAY_KEY) ? int(p_datetime[DAY_KEY]) : 1; \
+ int hour = p_datetime.has(HOUR_KEY) ? int(p_datetime[HOUR_KEY]) : 0; \
+ int minute = p_datetime.has(MINUTE_KEY) ? int(p_datetime[MINUTE_KEY]) : 0; \
+ int second = p_datetime.has(SECOND_KEY) ? int(p_datetime[SECOND_KEY]) : 0;
Time *Time::singleton = nullptr;
@@ -253,7 +262,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 +282,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 +296,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/os/time.h b/core/os/time.h
index 0021c0ac6f..c4d10006fc 100644
--- a/core/os/time.h
+++ b/core/os/time.h
@@ -51,7 +51,7 @@ class Time : public Object {
public:
static Time *get_singleton();
- enum Month : uint8_t {
+ enum Month {
/// Start at 1 to follow Windows SYSTEMTIME structure
/// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
MONTH_JANUARY = 1,
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/string_name.cpp b/core/string/string_name.cpp
index 2e941b8037..9c4fc4e1b7 100644
--- a/core/string/string_name.cpp
+++ b/core/string/string_name.cpp
@@ -247,6 +247,7 @@ StringName::StringName(const char *p_name, bool p_static) {
_data->cname = nullptr;
_data->next = _table[idx];
_data->prev = nullptr;
+
#ifdef DEBUG_ENABLED
if (unlikely(debug_stringname)) {
// Keep in memory, force static.
diff --git a/core/string/string_name.h b/core/string/string_name.h
index f4233854ac..ff4c41af94 100644
--- a/core/string/string_name.h
+++ b/core/string/string_name.h
@@ -35,6 +35,8 @@
#include "core/string/ustring.h"
#include "core/templates/safe_refcount.h"
+#define UNIQUE_NODE_PREFIX "%"
+
class Main;
struct StaticCString {
@@ -100,6 +102,17 @@ public:
bool operator==(const String &p_name) const;
bool operator==(const char *p_name) const;
bool operator!=(const String &p_name) const;
+
+ _FORCE_INLINE_ bool is_node_unique_name() const {
+ if (!_data) {
+ return false;
+ }
+ if (_data->cname != nullptr) {
+ return (char32_t)_data->cname[0] == (char32_t)UNIQUE_NODE_PREFIX[0];
+ } else {
+ return (char32_t)_data->name[0] == (char32_t)UNIQUE_NODE_PREFIX[0];
+ }
+ }
_FORCE_INLINE_ bool operator<(const StringName &p_name) const {
return _data < p_name._data;
}
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/string/ustring.cpp b/core/string/ustring.cpp
index 7cfd34b53e..7199121932 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -35,6 +35,7 @@
#include "core/math/math_funcs.h"
#include "core/os/memory.h"
#include "core/string/print_string.h"
+#include "core/string/string_name.h"
#include "core/string/translation.h"
#include "core/string/ucaps.h"
#include "core/variant/variant.h"
@@ -4357,7 +4358,7 @@ String String::property_name_encode() const {
}
// Changes made to the set of invalid characters must also be reflected in the String documentation.
-const String String::invalid_node_name_characters = ". : @ / \"";
+const String String::invalid_node_name_characters = ". : @ / \" " UNIQUE_NODE_PREFIX;
String String::validate_node_name() const {
Vector<String> chars = String::invalid_node_name_characters.split(" ");
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/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml
index ae7b0afaa7..4b6f6eec67 100644
--- a/doc/classes/BaseMaterial3D.xml
+++ b/doc/classes/BaseMaterial3D.xml
@@ -63,6 +63,9 @@
<member name="albedo_tex_force_srgb" type="bool" setter="set_flag" getter="get_flag" default="false">
Forces a conversion of the [member albedo_texture] from sRGB space to linear space.
</member>
+ <member name="albedo_tex_msdf" type="bool" setter="set_flag" getter="get_flag" default="false">
+ Enables multichannel signed distance field rendering shader. Use [member msdf_pixel_range] and [member msdf_outline_size] to configure MSDF paramenters.
+ </member>
<member name="albedo_texture" type="Texture2D" setter="set_texture" getter="get_texture">
Texture to multiply by [member albedo_color]. Used for basic texturing of objects.
</member>
@@ -243,6 +246,12 @@
<member name="metallic_texture_channel" type="int" setter="set_metallic_texture_channel" getter="get_metallic_texture_channel" enum="BaseMaterial3D.TextureChannel" default="0">
Specifies the channel of the [member metallic_texture] in which the metallic information is stored. This is useful when you store the information for multiple effects in a single texture. For example if you stored metallic in the red channel, roughness in the blue, and ambient occlusion in the green you could reduce the number of textures you use.
</member>
+ <member name="msdf_outline_size" type="float" setter="set_msdf_outline_size" getter="get_msdf_outline_size" default="0.0">
+ The width of the shape outine.
+ </member>
+ <member name="msdf_pixel_range" type="float" setter="set_msdf_pixel_range" getter="get_msdf_pixel_range" default="4.0">
+ The width of the range around the shape between the minimum and maximum representable signed distance.
+ </member>
<member name="no_depth_test" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], depth testing is disabled and the object will be drawn in render order.
</member>
@@ -647,7 +656,10 @@
</constant>
<constant name="FLAG_PARTICLE_TRAILS_MODE" value="19" enum="Flags">
</constant>
- <constant name="FLAG_MAX" value="20" enum="Flags">
+ <constant name="FLAG_ALBEDO_TEXTURE_MSDF" value="20" enum="Flags">
+ Enables multichannel signed distance field rendering shader.
+ </constant>
+ <constant name="FLAG_MAX" value="21" enum="Flags">
Represents the size of the [enum Flags] enum.
</constant>
<constant name="DIFFUSE_BURLEY" value="0" enum="DiffuseMode">
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 baaf33956f..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">
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/Control.xml b/doc/classes/Control.xml
index 78150af9dd..7e1bceb888 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1358,27 +1358,5 @@
<constant name="TEXT_DIRECTION_RTL" value="2" enum="TextDirection">
Right-to-left text writing direction.
</constant>
- <constant name="STRUCTURED_TEXT_DEFAULT" value="0" enum="StructuredTextParser">
- Use default behavior. Same as [code]STRUCTURED_TEXT_NONE[/code] unless specified otherwise in the control description.
- </constant>
- <constant name="STRUCTURED_TEXT_URI" value="1" enum="StructuredTextParser">
- BiDi override for URI.
- </constant>
- <constant name="STRUCTURED_TEXT_FILE" value="2" enum="StructuredTextParser">
- BiDi override for file path.
- </constant>
- <constant name="STRUCTURED_TEXT_EMAIL" value="3" enum="StructuredTextParser">
- BiDi override for email.
- </constant>
- <constant name="STRUCTURED_TEXT_LIST" value="4" enum="StructuredTextParser">
- BiDi override for lists.
- Structured text options: list separator [code]String[/code].
- </constant>
- <constant name="STRUCTURED_TEXT_NONE" value="5" enum="StructuredTextParser">
- Use default Unicode BiDi algorithm.
- </constant>
- <constant name="STRUCTURED_TEXT_CUSTOM" value="6" enum="StructuredTextParser">
- User defined structured text BiDi override function.
- </constant>
</constants>
</class>
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/FontData.xml b/doc/classes/FontData.xml
index 313e3e31fc..a423d7a4e4 100644
--- a/doc/classes/FontData.xml
+++ b/doc/classes/FontData.xml
@@ -582,6 +582,9 @@
<member name="force_autohinter" type="bool" setter="set_force_autohinter" getter="is_force_autohinter" default="false">
If set to [code]true[/code], auto-hinting is supported and preferred over font built-in hinting. Used by dynamic fonts only.
</member>
+ <member name="generate_mipmaps" type="bool" setter="set_generate_mipmaps" getter="get_generate_mipmaps" default="false">
+ If set to [code]true[/code], generate mipmaps for the font textures.
+ </member>
<member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="TextServer.Hinting" default="1">
Font hinting mode. Used by dynamic fonts only.
</member>
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/Label.xml b/doc/classes/Label.xml
index b1046dea6b..d5744bbc42 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -85,7 +85,7 @@
[b]Note:[/b] Setting this property updates [member visible_characters] based on current [method get_total_character_count].
</member>
<member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="4" />
- <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">
+ <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0">
Set BiDi algorithm override for the structured text.
</member>
<member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]">
diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml
new file mode 100644
index 0000000000..c95b691bf3
--- /dev/null
+++ b/doc/classes/Label3D.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="Label3D" inherits="GeometryInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Displays plain text in a 3D world.
+ </brief_description>
+ <description>
+ Label3D displays plain text in a 3D world. It gives you control over the horizontal and vertical alignment.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="clear_opentype_features">
+ <return type="void" />
+ <description>
+ Removes all OpenType features.
+ </description>
+ </method>
+ <method name="generate_triangle_mesh" qualifiers="const">
+ <return type="TriangleMesh" />
+ <description>
+ Returns a [TriangleMesh] with the label's vertices following its current configuration (such as its [member pixel_size]).
+ </description>
+ </method>
+ <method name="get_draw_flag" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" />
+ <description>
+ Returns the value of the specified flag.
+ </description>
+ </method>
+ <method name="get_opentype_feature" qualifiers="const">
+ <return type="int" />
+ <argument index="0" name="tag" type="String" />
+ <description>
+ Returns OpenType feature [code]tag[/code].
+ </description>
+ </method>
+ <method name="set_draw_flag">
+ <return type="void" />
+ <argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" />
+ <argument index="1" name="enabled" type="bool" />
+ <description>
+ If [code]true[/code], the specified flag will be enabled. See [enum Label3D.DrawFlags] for a list of flags.
+ </description>
+ </method>
+ <method name="set_opentype_feature">
+ <return type="void" />
+ <argument index="0" name="tag" type="String" />
+ <argument index="1" name="value" type="int" />
+ <description>
+ Returns OpenType feature [code]tag[/code]. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="alpha_cut" type="int" setter="set_alpha_cut_mode" getter="get_alpha_cut_mode" enum="Label3D.AlphaCutMode" default="0">
+ The alpha cutting mode to use for the sprite. See [enum AlphaCutMode] for possible values.
+ </member>
+ <member name="alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold" default="0.5">
+ Threshold at which the alpha scissor will discard values.
+ </member>
+ <member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="Label3D.AutowrapMode" default="0">
+ If set to something other than [constant AUTOWRAP_OFF], the text gets wrapped inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. To see how each mode behaves, see [enum AutowrapMode].
+ </member>
+ <member name="billboard" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="BaseMaterial3D.BillboardMode" default="0">
+ The billboard mode to use for the label. See [enum BaseMaterial3D.BillboardMode] for possible values.
+ </member>
+ <member name="double_sided" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true">
+ If [code]true[/code], text can be seen from the back as well, if [code]false[/code], it is invisible when looking at it from behind.
+ </member>
+ <member name="fixed_size" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
+ If [code]true[/code], the label is rendered at the same size regardless of distance.
+ </member>
+ <member name="font" type="Font" setter="set_font" getter="get_font">
+ [Font] used for the [Label3D]'s text.
+ </member>
+ <member name="font_size" type="int" setter="set_font_size" getter="get_font_size" default="16">
+ Font size of the [Label3D]'s text.
+ </member>
+ <member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="HorizontalAlignment" default="1">
+ Controls the text's horizontal alignment. Supports left, center, right. Set it to one of the [enum HorizontalAlignment] constants.
+ </member>
+ <member name="language" type="String" setter="set_language" getter="get_language" default="&quot;&quot;">
+ Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
+ </member>
+ <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0">
+ Vertical space between lines in multiline [Label3D].
+ </member>
+ <member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color(1, 1, 1, 1)">
+ Text [Color] of the [Label3D].
+ </member>
+ <member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
+ If [code]true[/code], depth testing is disabled and the object will be drawn in render order.
+ </member>
+ <member name="outline_modulate" type="Color" setter="set_outline_modulate" getter="get_outline_modulate" default="Color(0, 0, 0, 1)">
+ The tint of [Font]'s outline.
+ </member>
+ <member name="outline_size" type="int" setter="set_outline_size" getter="get_outline_size" default="0">
+ Text outline size.
+ </member>
+ <member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01">
+ The size of one pixel's width on the label to scale it in 3D.
+ </member>
+ <member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
+ If [code]true[/code], the [Light3D] in the [Environment] has effects on the label.
+ </member>
+ <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0">
+ Set BiDi algorithm override for the structured text.
+ </member>
+ <member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]">
+ Set additional options for BiDi override.
+ </member>
+ <member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
+ The text to display on screen.
+ </member>
+ <member name="text_direction" type="int" setter="set_text_direction" getter="get_text_direction" enum="TextServer.Direction" default="0">
+ Base text writing direction.
+ </member>
+ <member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="BaseMaterial3D.TextureFilter" default="3">
+ Filter flags for the texture. See [enum BaseMaterial3D.TextureFilter] for options.
+ </member>
+ <member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase" default="false">
+ If [code]true[/code], all the text displays as UPPERCASE.
+ </member>
+ <member name="vertical_alignment" type="int" setter="set_vertical_alignment" getter="get_vertical_alignment" enum="VerticalAlignment" default="1">
+ Controls the text's vertical alignment. Supports top, center, bottom. Set it to one of the [enum VerticalAlignment] constants.
+ </member>
+ <member name="width" type="float" setter="set_width" getter="get_width" default="500.0">
+ Text width (in pixels), used for autowrap and fill alignment.
+ </member>
+ </members>
+ <constants>
+ <constant name="AUTOWRAP_OFF" value="0" enum="AutowrapMode">
+ Autowrap is disabled.
+ </constant>
+ <constant name="AUTOWRAP_ARBITRARY" value="1" enum="AutowrapMode">
+ Wraps the text inside the node's bounding rectangle by allowing to break lines at arbitrary positions, which is useful when very limited space is available.
+ </constant>
+ <constant name="AUTOWRAP_WORD" value="2" enum="AutowrapMode">
+ Wraps the text inside the node's bounding rectangle by soft-breaking between words.
+ </constant>
+ <constant name="AUTOWRAP_WORD_SMART" value="3" enum="AutowrapMode">
+ Behaves similarly to [constant AUTOWRAP_WORD], but force-breaks a word if that single word does not fit in one line.
+ </constant>
+ <constant name="FLAG_SHADED" value="0" enum="DrawFlags">
+ If set, lights in the environment affect the label.
+ </constant>
+ <constant name="FLAG_DOUBLE_SIDED" value="1" enum="DrawFlags">
+ If set, text can be seen from the back as well. If not, the texture is invisible when looking at it from behind.
+ </constant>
+ <constant name="FLAG_DISABLE_DEPTH_TEST" value="2" enum="DrawFlags">
+ Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it.
+ </constant>
+ <constant name="FLAG_FIXED_SIZE" value="3" enum="DrawFlags">
+ Label is scaled by depth so that it always appears the same size on screen.
+ </constant>
+ <constant name="FLAG_MAX" value="4" enum="DrawFlags">
+ Represents the size of the [enum DrawFlags] enum.
+ </constant>
+ <constant name="ALPHA_CUT_DISABLED" value="0" enum="AlphaCutMode">
+ This mode performs standard alpha blending. It can display translucent areas, but transparency sorting issues may be visible when multiple transparent materials are overlapping.
+ </constant>
+ <constant name="ALPHA_CUT_DISCARD" value="1" enum="AlphaCutMode">
+ This mode only allows fully transparent or fully opaque pixels. Harsh edges will be visible unless some form of screen-space antialiasing is enabled (see [member ProjectSettings.rendering/anti_aliasing/quality/screen_space_aa]). This mode is also known as [i]alpha testing[/i] or [i]1-bit transparency[/i].
+ [b]Note:[/b] This mode might have issues with anti-aliased fonts and outlines, try adjusting [member alpha_scissor_threshold] or using MSDF font.
+ [b]Note:[/b] When using text with overlapping glyphs (e.g., cursive scripts), this mode might have transparency sorting issues between the main text and the outline.
+ </constant>
+ <constant name="ALPHA_CUT_OPAQUE_PREPASS" value="2" enum="AlphaCutMode">
+ This mode draws fully opaque pixels in the depth prepass. This is slower than [constant ALPHA_CUT_DISABLED] or [constant ALPHA_CUT_DISCARD], but it allows displaying translucent areas and smooth edges while using proper sorting.
+ [b]Note:[/b] When using text with overlapping glyphs (e.g., cursive scripts), this mode might have transparency sorting issues between the main text and the outline.
+ </constant>
+ </constants>
+</class>
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 136147b4b0..55e012ee0c 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -251,7 +251,7 @@
<member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true">
If [code]false[/code], using shortcuts will be 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">
+ <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0">
Set BiDi algorithm override for the structured text.
</member>
<member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]">
diff --git a/doc/classes/LinkButton.xml b/doc/classes/LinkButton.xml
index 3b03d86644..ba80504caf 100644
--- a/doc/classes/LinkButton.xml
+++ b/doc/classes/LinkButton.xml
@@ -36,7 +36,7 @@
<member name="language" type="String" setter="set_language" getter="get_language" default="&quot;&quot;">
Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead.
</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">
+ <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0">
Set BiDi algorithm override for the structured text.
</member>
<member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]">
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/Node.xml b/doc/classes/Node.xml
index 7079036879..3efa49b309 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -492,6 +492,12 @@
Returns [code]true[/code] if the node is processing unhandled key input (see [method set_process_unhandled_key_input]).
</description>
</method>
+ <method name="is_unique_name_in_owner" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns whether the node is an unique name for all the other nodes owned by its [member owner].
+ </description>
+ </method>
<method name="move_child">
<return type="void" />
<argument index="0" name="child_node" type="Node" />
@@ -719,6 +725,13 @@
Sets whether this is an instance load placeholder. See [InstancePlaceholder].
</description>
</method>
+ <method name="set_unique_name_in_owner">
+ <return type="void" />
+ <argument index="0" name="enable" type="bool" />
+ <description>
+ Sets this node's name as the unique name in its [member owner]. This allows the node to be accessed as [code]%Name[/code] instead of the full path, from any node within that scene.
+ </description>
+ </method>
<method name="update_configuration_warnings">
<return type="void" />
<description>
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..828117a847 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>
@@ -329,7 +342,7 @@
<argument index="0" name="alignment" type="int" enum="HorizontalAlignment" />
<argument index="1" name="base_direction" type="int" enum="Control.TextDirection" default="0" />
<argument index="2" name="language" type="String" default="&quot;&quot;" />
- <argument index="3" name="st_parser" type="int" enum="Control.StructuredTextParser" default="0" />
+ <argument index="3" name="st_parser" type="int" enum="TextServer.StructuredTextParser" default="0" />
<description>
Adds a [code][p][/code] tag to the tag stack.
</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,7 +485,10 @@
<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="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="Control.StructuredTextParser" default="0">
+ <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="TextServer.StructuredTextParser" default="0">
Set BiDi algorithm override for the structured text.
</member>
<member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]">
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/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml
index 405fff0ce8..9733fa3a26 100644
--- a/doc/classes/SpriteBase3D.xml
+++ b/doc/classes/SpriteBase3D.xml
@@ -53,6 +53,9 @@
<member name="double_sided" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true">
If [code]true[/code], texture can be seen from the back as well, if [code]false[/code], it is invisible when looking at it from behind.
</member>
+ <member name="fixed_size" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
+ If [code]true[/code], the label is rendered at the same size regardless of distance.
+ </member>
<member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h" default="false">
If [code]true[/code], texture is flipped horizontally.
</member>
@@ -63,6 +66,9 @@
A color value used to [i]multiply[/i] the texture's colors. Can be used for mood-coloring or to simulate the color of light.
[b]Note:[/b] If a [member GeometryInstance3D.material_override] is defined on the [SpriteBase3D], the material override must be configured to take vertex colors into account for albedo. Otherwise, the color defined in [member modulate] will be ignored. For a [BaseMaterial3D], [member BaseMaterial3D.vertex_color_use_as_albedo] must be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function.
</member>
+ <member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
+ If [code]true[/code], depth testing is disabled and the object will be drawn in render order.
+ </member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)">
The texture's drawing offset.
</member>
@@ -72,6 +78,9 @@
<member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], the [Light3D] in the [Environment] has effects on the sprite.
</member>
+ <member name="texture_filter" type="int" setter="set_texture_filter" getter="get_texture_filter" enum="BaseMaterial3D.TextureFilter" default="3">
+ Filter flags for the texture. See [enum BaseMaterial3D.TextureFilter] for options.
+ </member>
<member name="transparent" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true">
If [code]true[/code], the texture's transparency and the opacity are used to make those parts of the sprite invisible.
</member>
@@ -86,7 +95,13 @@
<constant name="FLAG_DOUBLE_SIDED" value="2" enum="DrawFlags">
If set, texture can be seen from the back as well. If not, the texture is invisible when looking at it from behind.
</constant>
- <constant name="FLAG_MAX" value="3" enum="DrawFlags">
+ <constant name="FLAG_DISABLE_DEPTH_TEST" value="3" enum="DrawFlags">
+ Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it.
+ </constant>
+ <constant name="FLAG_FIXED_SIZE" value="4" enum="DrawFlags">
+ Label is scaled by depth so that it always appears the same size on screen.
+ </constant>
+ <constant name="FLAG_MAX" value="5" enum="DrawFlags">
Represents the size of the [enum DrawFlags] enum.
</constant>
<constant name="ALPHA_CUT_DISABLED" value="0" enum="AlphaCutMode">
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml
index a4edaa79c7..58fdd2d058 100644
--- a/doc/classes/TextEdit.xml
+++ b/doc/classes/TextEdit.xml
@@ -1017,7 +1017,7 @@
<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">
+ <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0">
Set BiDi algorithm override for the structured text.
</member>
<member name="structured_text_bidi_override_options" type="Array" setter="set_structured_text_bidi_override_options" getter="get_structured_text_bidi_override_options" default="[]">
diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml
index b4339bef11..dba4bd24a5 100644
--- a/doc/classes/TextServer.xml
+++ b/doc/classes/TextServer.xml
@@ -80,6 +80,7 @@
<description>
Draws single glyph into a canvas item at the position, using [code]font_rid[/code] at the size [code]size[/code].
[b]Note:[/b] Glyph index is specific to the font, use glyphs indices returned by [method shaped_text_get_glyphs] or [method font_get_glyph_index].
+ [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update.
</description>
</method>
<method name="font_draw_glyph_outline" qualifiers="const">
@@ -94,6 +95,7 @@
<description>
Draws single glyph outline of size [code]outline_size[/code] into a canvas item at the position, using [code]font_rid[/code] at the size [code]size[/code].
[b]Note:[/b] Glyph index is specific to the font, use glyphs indices returned by [method shaped_text_get_glyphs] or [method font_get_glyph_index].
+ [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update.
</description>
</method>
<method name="font_get_ascent" qualifiers="const">
@@ -126,6 +128,13 @@
Returns bitmap font fixed size.
</description>
</method>
+ <method name="font_get_generate_mipmaps" qualifiers="const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns [code]true[/code] if font texture mipmap generation is enabled.
+ </description>
+ </method>
<method name="font_get_global_oversampling" qualifiers="const">
<return type="float" />
<description>
@@ -199,6 +208,26 @@
Returns index of the cache texture containing the glyph.
</description>
</method>
+ <method name="font_get_glyph_texture_rid" qualifiers="const">
+ <return type="RID" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns resource id of the cache texture containing the glyph.
+ [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update.
+ </description>
+ </method>
+ <method name="font_get_glyph_texture_size" qualifiers="const">
+ <return type="Vector2" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns size of the cache texture containing the glyph.
+ [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update.
+ </description>
+ </method>
<method name="font_get_glyph_uv_rect" qualifiers="const">
<return type="Rect2" />
<argument index="0" name="font_rid" type="RID" />
@@ -580,6 +609,14 @@
If set to [code]true[/code] auto-hinting is preferred over font built-in hinting.
</description>
</method>
+ <method name="font_set_generate_mipmaps">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="generate_mipmaps" type="bool" />
+ <description>
+ If set to [code]true[/code] font texture mipmap generation is enabled.
+ </description>
+ </method>
<method name="font_set_global_oversampling">
<return type="void" />
<argument index="0" name="oversampling" type="float" />
@@ -927,6 +964,15 @@
Converts a number from the numeral systems used in [code]language[/code] to Western Arabic (0..9).
</description>
</method>
+ <method name="parse_structured_text" qualifiers="const">
+ <return type="Array" />
+ <argument index="0" name="parser_type" type="int" enum="TextServer.StructuredTextParser" />
+ <argument index="1" name="args" type="Array" />
+ <argument index="2" name="text" type="String" />
+ <description>
+ Default implementation of the BiDi algorithm override function. See [enum StructuredTextParser] for more info.
+ </description>
+ </method>
<method name="percent_sign" qualifiers="const">
<return type="String" />
<argument index="0" name="language" type="String" default="&quot;&quot;" />
@@ -1249,9 +1295,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">
@@ -1630,5 +1676,27 @@
<constant name="FONT_FIXED_WIDTH" value="4" enum="FontStyle">
Font have fixed-width characters.
</constant>
+ <constant name="STRUCTURED_TEXT_DEFAULT" value="0" enum="StructuredTextParser">
+ Use default behavior. Same as [code]STRUCTURED_TEXT_NONE[/code] unless specified otherwise in the control description.
+ </constant>
+ <constant name="STRUCTURED_TEXT_URI" value="1" enum="StructuredTextParser">
+ BiDi override for URI.
+ </constant>
+ <constant name="STRUCTURED_TEXT_FILE" value="2" enum="StructuredTextParser">
+ BiDi override for file path.
+ </constant>
+ <constant name="STRUCTURED_TEXT_EMAIL" value="3" enum="StructuredTextParser">
+ BiDi override for email.
+ </constant>
+ <constant name="STRUCTURED_TEXT_LIST" value="4" enum="StructuredTextParser">
+ BiDi override for lists.
+ Structured text options: list separator [code]String[/code].
+ </constant>
+ <constant name="STRUCTURED_TEXT_NONE" value="5" enum="StructuredTextParser">
+ Use default Unicode BiDi algorithm.
+ </constant>
+ <constant name="STRUCTURED_TEXT_CUSTOM" value="6" enum="StructuredTextParser">
+ User defined structured text BiDi override function.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml
index e7c5edd266..ef522d08a7 100644
--- a/doc/classes/TextServerExtension.xml
+++ b/doc/classes/TextServerExtension.xml
@@ -121,6 +121,13 @@
Returns bitmap font fixed size.
</description>
</method>
+ <method name="font_get_generate_mipmaps" qualifiers="virtual const">
+ <return type="bool" />
+ <argument index="0" name="font_rid" type="RID" />
+ <description>
+ Returns [code]true[/code] if font texture mipmap generation is enabled.
+ </description>
+ </method>
<method name="font_get_global_oversampling" qualifiers="virtual const">
<return type="float" />
<description>
@@ -193,6 +200,24 @@
Returns index of the cache texture containing the glyph.
</description>
</method>
+ <method name="font_get_glyph_texture_rid" qualifiers="virtual const">
+ <return type="RID" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns resource id of the cache texture containing the glyph.
+ </description>
+ </method>
+ <method name="font_get_glyph_texture_size" qualifiers="virtual const">
+ <return type="Vector2" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="size" type="Vector2i" />
+ <argument index="2" name="glyph" type="int" />
+ <description>
+ Returns size of the cache texture containing the glyph.
+ </description>
+ </method>
<method name="font_get_glyph_uv_rect" qualifiers="virtual const">
<return type="Rect2" />
<argument index="0" name="font_rid" type="RID" />
@@ -581,6 +606,14 @@
If set to [code]true[/code] auto-hinting is preferred over font built-in hinting.
</description>
</method>
+ <method name="font_set_generate_mipmaps" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="font_rid" type="RID" />
+ <argument index="1" name="generate_mipmaps" type="bool" />
+ <description>
+ If set to [code]true[/code] font texture mipmap generation is enabled.
+ </description>
+ </method>
<method name="font_set_global_oversampling" qualifiers="virtual">
<return type="void" />
<argument index="0" name="oversampling" type="float" />
@@ -927,6 +960,14 @@
Converts a number from the numeral systems used in [code]language[/code] to Western Arabic (0..9).
</description>
</method>
+ <method name="parse_structured_text" qualifiers="virtual const">
+ <return type="Array" />
+ <argument index="0" name="parser_type" type="int" enum="TextServer.StructuredTextParser" />
+ <argument index="1" name="args" type="Array" />
+ <argument index="2" name="text" type="String" />
+ <description>
+ </description>
+ </method>
<method name="percent_sign" qualifiers="virtual const">
<return type="String" />
<argument index="0" name="language" type="String" />
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/TreeItem.xml b/doc/classes/TreeItem.xml
index 396be2d9f8..d2e29bf3b1 100644
--- a/doc/classes/TreeItem.xml
+++ b/doc/classes/TreeItem.xml
@@ -284,7 +284,7 @@
</description>
</method>
<method name="get_structured_text_bidi_override" qualifiers="const">
- <return type="int" enum="Control.StructuredTextParser" />
+ <return type="int" enum="TextServer.StructuredTextParser" />
<argument index="0" name="column" type="int" />
<description>
</description>
@@ -620,7 +620,7 @@
<method name="set_structured_text_bidi_override">
<return type="void" />
<argument index="0" name="column" type="int" />
- <argument index="1" name="parser" type="int" enum="Control.StructuredTextParser" />
+ <argument index="1" name="parser" type="int" enum="TextServer.StructuredTextParser" />
<description>
</description>
</method>
diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml
index 1653b66003..18204943fd 100644
--- a/doc/classes/Vector3.xml
+++ b/doc/classes/Vector3.xml
@@ -4,7 +4,7 @@
Vector used for 3D math using floating point coordinates.
</brief_description>
<description>
- 3-element structure that can be used to represent positions in 3D space or any other pair of numeric values.
+ 3-element structure that can be used to represent positions in 3D space or any other triplet of numeric values.
It uses floating-point coordinates. See [Vector3i] for its integer counterpart.
[b]Note:[/b] In a boolean context, a Vector3 will evaluate to [code]false[/code] if it's equal to [code]Vector3(0, 0, 0)[/code]. Otherwise, a Vector3 will always evaluate to [code]true[/code].
</description>
diff --git a/doc/classes/Vector3i.xml b/doc/classes/Vector3i.xml
index 4c7f3badc5..a4c91a9299 100644
--- a/doc/classes/Vector3i.xml
+++ b/doc/classes/Vector3i.xml
@@ -4,7 +4,7 @@
Vector used for 3D math using integer coordinates.
</brief_description>
<description>
- 3-element structure that can be used to represent positions in 3D space or any other pair of numeric values.
+ 3-element structure that can be used to represent positions in 3D space or any other triplet of numeric values.
It uses integer coordinates and is therefore preferable to [Vector3] when exact precision is required.
[b]Note:[/b] In a boolean context, a Vector3i will evaluate to [code]false[/code] if it's equal to [code]Vector3i(0, 0, 0)[/code]. Otherwise, a Vector3i will always evaluate to [code]true[/code].
</description>
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/VisualShader.xml b/doc/classes/VisualShader.xml
index 138aad8d47..5f13e4e7bc 100644
--- a/doc/classes/VisualShader.xml
+++ b/doc/classes/VisualShader.xml
@@ -214,11 +214,13 @@
</constant>
<constant name="VARYING_TYPE_VECTOR_3D" value="2" enum="VaryingType">
</constant>
- <constant name="VARYING_TYPE_COLOR" value="3" enum="VaryingType">
+ <constant name="VARYING_TYPE_VECTOR_4D" value="3" enum="VaryingType">
</constant>
- <constant name="VARYING_TYPE_TRANSFORM" value="4" enum="VaryingType">
+ <constant name="VARYING_TYPE_COLOR" value="4" enum="VaryingType">
</constant>
- <constant name="VARYING_TYPE_MAX" value="5" enum="VaryingType">
+ <constant name="VARYING_TYPE_TRANSFORM" value="5" enum="VaryingType">
+ </constant>
+ <constant name="VARYING_TYPE_MAX" value="6" enum="VaryingType">
</constant>
<constant name="NODE_ID_INVALID" value="-1">
</constant>
diff --git a/doc/classes/VisualShaderNode.xml b/doc/classes/VisualShaderNode.xml
index b4a9c85625..7220731a8a 100644
--- a/doc/classes/VisualShaderNode.xml
+++ b/doc/classes/VisualShaderNode.xml
@@ -78,16 +78,19 @@
<constant name="PORT_TYPE_VECTOR_3D" value="3" enum="PortType">
3D vector of floating-point values. Translated to [code]vec3[/code] type in shader code.
</constant>
- <constant name="PORT_TYPE_BOOLEAN" value="4" enum="PortType">
+ <constant name="PORT_TYPE_VECTOR_4D" value="4" enum="PortType">
+ 4D vector of floating-point values. Translated to [code]vec4[/code] type in shader code.
+ </constant>
+ <constant name="PORT_TYPE_BOOLEAN" value="5" enum="PortType">
Boolean type. Translated to [code]bool[/code] type in shader code.
</constant>
- <constant name="PORT_TYPE_TRANSFORM" value="5" enum="PortType">
+ <constant name="PORT_TYPE_TRANSFORM" value="6" enum="PortType">
Transform type. Translated to [code]mat4[/code] type in shader code.
</constant>
- <constant name="PORT_TYPE_SAMPLER" value="6" enum="PortType">
+ <constant name="PORT_TYPE_SAMPLER" value="7" enum="PortType">
Sampler type. Translated to reference of sampler uniform in shader code. Can only be used for input ports in non-uniform nodes.
</constant>
- <constant name="PORT_TYPE_MAX" value="7" enum="PortType">
+ <constant name="PORT_TYPE_MAX" value="8" enum="PortType">
Represents the size of the [enum PortType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeClamp.xml b/doc/classes/VisualShaderNodeClamp.xml
index fd24b9cfc2..35f50a37c3 100644
--- a/doc/classes/VisualShaderNodeClamp.xml
+++ b/doc/classes/VisualShaderNodeClamp.xml
@@ -26,7 +26,10 @@
<constant name="OP_TYPE_VECTOR_3D" value="3" enum="OpType">
A 3D vector type.
</constant>
- <constant name="OP_TYPE_MAX" value="4" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="4" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_MAX" value="5" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeCompare.xml b/doc/classes/VisualShaderNodeCompare.xml
index d703181e2d..942ced2ebd 100644
--- a/doc/classes/VisualShaderNodeCompare.xml
+++ b/doc/classes/VisualShaderNodeCompare.xml
@@ -32,13 +32,16 @@
<constant name="CTYPE_VECTOR_3D" value="3" enum="ComparisonType">
A 3D vector type.
</constant>
- <constant name="CTYPE_BOOLEAN" value="4" enum="ComparisonType">
+ <constant name="CTYPE_VECTOR_4D" value="4" enum="ComparisonType">
+ A 4D vector type.
+ </constant>
+ <constant name="CTYPE_BOOLEAN" value="5" enum="ComparisonType">
A boolean type.
</constant>
- <constant name="CTYPE_TRANSFORM" value="5" enum="ComparisonType">
+ <constant name="CTYPE_TRANSFORM" value="6" enum="ComparisonType">
A transform ([code]mat4[/code]) type.
</constant>
- <constant name="CTYPE_MAX" value="6" enum="ComparisonType">
+ <constant name="CTYPE_MAX" value="7" enum="ComparisonType">
Represents the size of the [enum ComparisonType] enum.
</constant>
<constant name="FUNC_EQUAL" value="0" enum="Function">
diff --git a/doc/classes/VisualShaderNodeDerivativeFunc.xml b/doc/classes/VisualShaderNodeDerivativeFunc.xml
index ea1153ca25..9a1ad53394 100644
--- a/doc/classes/VisualShaderNodeDerivativeFunc.xml
+++ b/doc/classes/VisualShaderNodeDerivativeFunc.xml
@@ -26,7 +26,10 @@
<constant name="OP_TYPE_VECTOR_3D" value="2" enum="OpType">
A 3D vector type.
</constant>
- <constant name="OP_TYPE_MAX" value="3" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="3" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_MAX" value="4" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
<constant name="FUNC_SUM" value="0" enum="Function">
diff --git a/doc/classes/VisualShaderNodeMix.xml b/doc/classes/VisualShaderNodeMix.xml
index c8ca545183..3470e47726 100644
--- a/doc/classes/VisualShaderNodeMix.xml
+++ b/doc/classes/VisualShaderNodeMix.xml
@@ -29,7 +29,13 @@
<constant name="OP_TYPE_VECTOR_3D_SCALAR" value="4" enum="OpType">
The [code]a[/code] and [code]b[/code] ports use a 3D vector type. The [code]weight[/code] port uses a scalar type.
</constant>
- <constant name="OP_TYPE_MAX" value="5" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="5" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_VECTOR_4D_SCALAR" value="6" enum="OpType">
+ The [code]a[/code] and [code]b[/code] ports use a 4D vector type. The [code]weight[/code] port uses a scalar type.
+ </constant>
+ <constant name="OP_TYPE_MAX" value="7" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeMultiplyAdd.xml b/doc/classes/VisualShaderNodeMultiplyAdd.xml
index 811f01fc28..15d0d113e9 100644
--- a/doc/classes/VisualShaderNodeMultiplyAdd.xml
+++ b/doc/classes/VisualShaderNodeMultiplyAdd.xml
@@ -23,7 +23,10 @@
<constant name="OP_TYPE_VECTOR_3D" value="2" enum="OpType">
A 3D vector type.
</constant>
- <constant name="OP_TYPE_MAX" value="3" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="3" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_MAX" value="4" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeSmoothStep.xml b/doc/classes/VisualShaderNodeSmoothStep.xml
index b10e8b4433..e25fb72921 100644
--- a/doc/classes/VisualShaderNodeSmoothStep.xml
+++ b/doc/classes/VisualShaderNodeSmoothStep.xml
@@ -30,7 +30,13 @@
<constant name="OP_TYPE_VECTOR_3D_SCALAR" value="4" enum="OpType">
The [code]x[/code] port uses a 3D vector type. The first two ports use a floating-point scalar type.
</constant>
- <constant name="OP_TYPE_MAX" value="5" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="5" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_VECTOR_4D_SCALAR" value="6" enum="OpType">
+ The [code]a[/code] and [code]b[/code] ports use a 4D vector type. The [code]weight[/code] port uses a scalar type.
+ </constant>
+ <constant name="OP_TYPE_MAX" value="7" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeStep.xml b/doc/classes/VisualShaderNodeStep.xml
index 2d9e87e56c..497b86c85f 100644
--- a/doc/classes/VisualShaderNodeStep.xml
+++ b/doc/classes/VisualShaderNodeStep.xml
@@ -30,7 +30,13 @@
<constant name="OP_TYPE_VECTOR_3D_SCALAR" value="4" enum="OpType">
The [code]x[/code] port uses a 3D vector type, while the [code]edge[/code] port uses a floating-point scalar type.
</constant>
- <constant name="OP_TYPE_MAX" value="5" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="5" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_VECTOR_4D_SCALAR" value="6" enum="OpType">
+ The [code]a[/code] and [code]b[/code] ports use a 4D vector type. The [code]weight[/code] port uses a scalar type.
+ </constant>
+ <constant name="OP_TYPE_MAX" value="7" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeSwitch.xml b/doc/classes/VisualShaderNodeSwitch.xml
index 4cadf79b8e..e74ff6e162 100644
--- a/doc/classes/VisualShaderNodeSwitch.xml
+++ b/doc/classes/VisualShaderNodeSwitch.xml
@@ -26,13 +26,16 @@
<constant name="OP_TYPE_VECTOR_3D" value="3" enum="OpType">
A 3D vector type.
</constant>
- <constant name="OP_TYPE_BOOLEAN" value="4" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="4" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_BOOLEAN" value="5" enum="OpType">
A boolean type.
</constant>
- <constant name="OP_TYPE_TRANSFORM" value="5" enum="OpType">
+ <constant name="OP_TYPE_TRANSFORM" value="6" enum="OpType">
A transform type.
</constant>
- <constant name="OP_TYPE_MAX" value="6" enum="OpType">
+ <constant name="OP_TYPE_MAX" value="7" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeVec4Constant.xml b/doc/classes/VisualShaderNodeVec4Constant.xml
new file mode 100644
index 0000000000..ed3d8a673d
--- /dev/null
+++ b/doc/classes/VisualShaderNodeVec4Constant.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeVec4Constant" inherits="VisualShaderNodeConstant" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ A 4D vector (represented as a [Quaternion]) constant to be used within the visual shader graph.
+ </brief_description>
+ <description>
+ A constant 4D vector (represented as a [Quaternion]), which can be used as an input node.
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="constant" type="Quaternion" setter="set_constant" getter="get_constant" default="Quaternion(0, 0, 0, 1)">
+ A 4D vector (represented as a [Quaternion]) constant which represents the state of this node.
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/VisualShaderNodeVec4Uniform.xml b/doc/classes/VisualShaderNodeVec4Uniform.xml
new file mode 100644
index 0000000000..5bd13a440b
--- /dev/null
+++ b/doc/classes/VisualShaderNodeVec4Uniform.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="VisualShaderNodeVec4Uniform" inherits="VisualShaderNodeUniform" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ A 4D vector (represented as a [Quaternion]) uniform to be used within the visual shader graph.
+ </brief_description>
+ <description>
+ Translated to [code]uniform vec4[/code] in the shader language.
+ </description>
+ <tutorials>
+ </tutorials>
+ <members>
+ <member name="default_value" type="Quaternion" setter="set_default_value" getter="get_default_value" default="Quaternion(0, 0, 0, 1)">
+ A default value to be assigned within the shader.
+ </member>
+ <member name="default_value_enabled" type="bool" setter="set_default_value_enabled" getter="is_default_value_enabled" default="false">
+ Enables usage of the [member default_value].
+ </member>
+ </members>
+</class>
diff --git a/doc/classes/VisualShaderNodeVectorBase.xml b/doc/classes/VisualShaderNodeVectorBase.xml
index 21f70960ab..d9c9f2d79c 100644
--- a/doc/classes/VisualShaderNodeVectorBase.xml
+++ b/doc/classes/VisualShaderNodeVectorBase.xml
@@ -19,7 +19,10 @@
<constant name="OP_TYPE_VECTOR_3D" value="1" enum="OpType">
A 3D vector type.
</constant>
- <constant name="OP_TYPE_MAX" value="2" enum="OpType">
+ <constant name="OP_TYPE_VECTOR_4D" value="2" enum="OpType">
+ A 4D vector type.
+ </constant>
+ <constant name="OP_TYPE_MAX" value="3" enum="OpType">
Represents the size of the [enum OpType] enum.
</constant>
</constants>
diff --git a/doc/classes/VisualShaderNodeVectorCompose.xml b/doc/classes/VisualShaderNodeVectorCompose.xml
index 87947c088e..b7447894b7 100644
--- a/doc/classes/VisualShaderNodeVectorCompose.xml
+++ b/doc/classes/VisualShaderNodeVectorCompose.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeVectorCompose" inherits="VisualShaderNodeVectorBase" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Composes a [Vector3] from three scalars within the visual shader graph.
+ Composes a [Vector2], [Vector3] or 4D vector (represented as a [Quaternion]) from scalars within the visual shader graph.
</brief_description>
<description>
- Creates a [code]vec3[/code] using three scalar values that can be provided from separate inputs.
+ Creates a [code]vec2[/code], [code]vec3[/code] or [code]vec4[/code] using scalar values that can be provided from separate inputs.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/VisualShaderNodeVectorDecompose.xml b/doc/classes/VisualShaderNodeVectorDecompose.xml
index f5cff2a9f7..fa18e6b0b9 100644
--- a/doc/classes/VisualShaderNodeVectorDecompose.xml
+++ b/doc/classes/VisualShaderNodeVectorDecompose.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeVectorDecompose" inherits="VisualShaderNodeVectorBase" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
- Decomposes a [Vector3] into three scalars within the visual shader graph.
+ Decomposes a [Vector2], [Vector3] or 4D vector (represented as a [Quaternion]) into scalars within the visual shader graph.
</brief_description>
<description>
- Takes a [code]vec3[/code] and decomposes it into three scalar values that can be used as separate inputs.
+ Takes a [code]vec2[/code], [code]vec3[/code] or [code]vec4[/code] and decomposes it into scalar values that can be used as separate outputs.
</description>
<tutorials>
</tutorials>
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/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index 8812447f6e..f7db1d950c 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -478,10 +478,6 @@ float msdf_median(float r, float g, float b, float a) {
return min(max(min(r, g), min(max(r, g), b)), a);
}
-vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) {
- return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min);
-}
-
void main() {
vec4 color = color_interp;
vec2 uv = uv_interp;
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/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index e519c428d2..0a2922fbd6 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -105,7 +105,7 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
/* SHADER API */
-void MaterialStorage::_shader_make_dirty(Shader *p_shader) {
+void MaterialStorage::_shader_make_dirty(GLES3::Shader *p_shader) {
if (p_shader->dirty_list.in_list()) {
return;
}
@@ -114,7 +114,7 @@ void MaterialStorage::_shader_make_dirty(Shader *p_shader) {
}
RID MaterialStorage::shader_allocate() {
- Shader *shader = memnew(Shader);
+ GLES3::Shader *shader = memnew(GLES3::Shader);
shader->mode = RS::SHADER_CANVAS_ITEM;
//shader->shader = &scene->state.scene_shader;
RID rid = shader_owner.make_rid(shader);
@@ -129,7 +129,7 @@ void MaterialStorage::shader_initialize(RID p_rid) {
}
//RID MaterialStorage::shader_create() {
-// Shader *shader = memnew(Shader);
+// GLES3::Shader *shader = memnew(GLES3::Shader);
// shader->mode = RS::SHADER_SPATIAL;
// shader->shader = &scene->state.scene_shader;
// RID rid = shader_owner.make_rid(shader);
@@ -140,7 +140,7 @@ void MaterialStorage::shader_initialize(RID p_rid) {
//}
void MaterialStorage::shader_free(RID p_rid) {
- Shader *shader = shader_owner.get_or_null(p_rid);
+ GLES3::Shader *shader = shader_owner.get_or_null(p_rid);
if (shader->shader && shader->version.is_valid()) {
shader->shader->version_free(shader->version);
@@ -151,7 +151,7 @@ void MaterialStorage::shader_free(RID p_rid) {
}
while (shader->materials.first()) {
- Material *m = shader->materials.first()->self();
+ GLES3::Material *m = shader->materials.first()->self();
m->shader = nullptr;
_material_make_dirty(m);
@@ -164,7 +164,7 @@ void MaterialStorage::shader_free(RID p_rid) {
}
void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
- Shader *shader = shader_owner.get_or_null(p_shader);
+ GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
shader->code = p_code;
@@ -211,14 +211,14 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
}
String MaterialStorage::shader_get_code(RID p_shader) const {
- const Shader *shader = shader_owner.get_or_null(p_shader);
+ const GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, "");
return shader->code;
}
void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
- Shader *shader = shader_owner.get_or_null(p_shader);
+ GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (shader->dirty_list.in_list()) {
@@ -308,7 +308,7 @@ void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
pi.type = Variant::COLOR;
} else {
- pi.type = Variant::PLANE;
+ pi.type = Variant::QUATERNION;
}
} break;
@@ -359,7 +359,7 @@ void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_
}
void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
- Shader *shader = shader_owner.get_or_null(p_shader);
+ GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
ERR_FAIL_COND(p_texture.is_valid() && !TextureStorage::get_singleton()->owns_texture(p_texture));
@@ -382,7 +382,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin
}
RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
- const Shader *shader = shader_owner.get_or_null(p_shader);
+ const GLES3::Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
if (shader->default_textures.has(p_name) && shader->default_textures[p_name].has(p_index)) {
@@ -392,7 +392,7 @@ RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const String
return RID();
}
-void MaterialStorage::_update_shader(Shader *p_shader) const {
+void MaterialStorage::_update_shader(GLES3::Shader *p_shader) const {
_shader_dirty_list.remove(&p_shader->dirty_list);
p_shader->valid = false;
@@ -408,8 +408,8 @@ void MaterialStorage::_update_shader(Shader *p_shader) const {
switch (p_shader->mode) {
case RS::SHADER_CANVAS_ITEM: {
- p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
- p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
+ p_shader->canvas_item.light_mode = GLES3::Shader::CanvasItem::LIGHT_MODE_NORMAL;
+ p_shader->canvas_item.blend_mode = GLES3::Shader::CanvasItem::BLEND_MODE_MIX;
p_shader->canvas_item.uses_screen_texture = false;
p_shader->canvas_item.uses_screen_uv = false;
@@ -423,14 +423,14 @@ void MaterialStorage::_update_shader(Shader *p_shader) const {
p_shader->canvas_item.uses_projection_matrix = false;
p_shader->canvas_item.uses_instance_custom = false;
- shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
- shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
- shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_SUB);
- shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MUL);
- shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_PMALPHA);
+ shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_ADD);
+ shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_MIX);
+ shaders.actions_canvas.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_SUB);
+ shaders.actions_canvas.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_MUL);
+ shaders.actions_canvas.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, GLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA);
- shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED);
- shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
+ shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, GLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED);
+ shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, GLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY);
shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv;
shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv;
@@ -453,9 +453,9 @@ void MaterialStorage::_update_shader(Shader *p_shader) const {
case RS::SHADER_SPATIAL: {
// TODO remove once 3D is added back
return;
- p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX;
- p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE;
- p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK;
+ p_shader->spatial.blend_mode = GLES3::Shader::Spatial::BLEND_MODE_MIX;
+ p_shader->spatial.depth_draw_mode = GLES3::Shader::Spatial::DEPTH_DRAW_OPAQUE;
+ p_shader->spatial.cull_mode = GLES3::Shader::Spatial::CULL_MODE_BACK;
p_shader->spatial.uses_alpha = false;
p_shader->spatial.uses_alpha_scissor = false;
p_shader->spatial.uses_discard = false;
@@ -472,19 +472,19 @@ void MaterialStorage::_update_shader(Shader *p_shader) const {
p_shader->spatial.writes_modelview_or_projection = false;
p_shader->spatial.uses_world_coordinates = false;
- shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_ADD);
- shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MIX);
- shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_SUB);
- shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, Shader::Spatial::BLEND_MODE_MUL);
+ shaders.actions_scene.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_ADD);
+ shaders.actions_scene.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_MIX);
+ shaders.actions_scene.render_mode_values["blend_sub"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_SUB);
+ shaders.actions_scene.render_mode_values["blend_mul"] = Pair<int *, int>(&p_shader->spatial.blend_mode, GLES3::Shader::Spatial::BLEND_MODE_MUL);
- shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_OPAQUE);
- shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALWAYS);
- shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_NEVER);
- shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
+ shaders.actions_scene.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_OPAQUE);
+ shaders.actions_scene.render_mode_values["depth_draw_always"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_ALWAYS);
+ shaders.actions_scene.render_mode_values["depth_draw_never"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_NEVER);
+ shaders.actions_scene.render_mode_values["depth_draw_alpha_prepass"] = Pair<int *, int>(&p_shader->spatial.depth_draw_mode, GLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS);
- shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_FRONT);
- shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_BACK);
- shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, Shader::Spatial::CULL_MODE_DISABLED);
+ shaders.actions_scene.render_mode_values["cull_front"] = Pair<int *, int>(&p_shader->spatial.cull_mode, GLES3::Shader::Spatial::CULL_MODE_FRONT);
+ shaders.actions_scene.render_mode_values["cull_back"] = Pair<int *, int>(&p_shader->spatial.cull_mode, GLES3::Shader::Spatial::CULL_MODE_BACK);
+ shaders.actions_scene.render_mode_values["cull_disabled"] = Pair<int *, int>(&p_shader->spatial.cull_mode, GLES3::Shader::Spatial::CULL_MODE_DISABLED);
shaders.actions_scene.render_mode_flags["unshaded"] = &p_shader->spatial.unshaded;
shaders.actions_scene.render_mode_flags["depth_test_disable"] = &p_shader->spatial.no_depth_test;
@@ -539,7 +539,7 @@ void MaterialStorage::_update_shader(Shader *p_shader) const {
p_shader->uses_vertex_time = gen_code.uses_vertex_time;
p_shader->uses_fragment_time = gen_code.uses_fragment_time;
- for (SelfList<Material> *E = p_shader->materials.first(); E; E = E->next()) {
+ for (SelfList<GLES3::Material> *E = p_shader->materials.first(); E; E = E->next()) {
_material_make_dirty(E->self());
}
@@ -554,7 +554,7 @@ void MaterialStorage::update_dirty_shaders() {
/* MATERIAL API */
-void MaterialStorage::_material_make_dirty(Material *p_material) const {
+void MaterialStorage::_material_make_dirty(GLES3::Material *p_material) const {
if (p_material->dirty_list.in_list()) {
return;
}
@@ -562,7 +562,7 @@ void MaterialStorage::_material_make_dirty(Material *p_material) const {
_material_dirty_list.add(&p_material->dirty_list);
}
-void MaterialStorage::_update_material(Material *p_material) {
+void MaterialStorage::_update_material(GLES3::Material *p_material) {
if (p_material->dirty_list.in_list()) {
_material_dirty_list.remove(&p_material->dirty_list);
}
@@ -580,7 +580,8 @@ void MaterialStorage::_update_material(Material *p_material) {
bool can_cast_shadow = false;
bool is_animated = false;
- if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
+ if (p_material->shader->spatial.blend_mode == GLES3::Shader::Spatial::BLEND_MODE_MIX &&
+
(!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
can_cast_shadow = true;
}
@@ -645,7 +646,7 @@ void MaterialStorage::_update_material(Material *p_material) {
}
RID MaterialStorage::material_allocate() {
- Material *material = memnew(Material);
+ GLES3::Material *material = memnew(GLES3::Material);
return material_owner.make_rid(material);
}
@@ -659,7 +660,7 @@ void MaterialStorage::material_initialize(RID p_rid) {
//}
void MaterialStorage::material_free(RID p_rid) {
- Material *m = material_owner.get_or_null(p_rid);
+ GLES3::Material *m = material_owner.get_or_null(p_rid);
if (m->shader) {
m->shader->materials.remove(&m->list);
@@ -691,10 +692,10 @@ void MaterialStorage::material_free(RID p_rid) {
}
void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
- Shader *shader = get_shader(p_shader);
+ GLES3::Shader *shader = get_shader(p_shader);
if (material->shader) {
// if a shader is present, remove the old shader
@@ -711,7 +712,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
}
void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
if (p_value.get_type() == Variant::NIL) {
@@ -724,7 +725,7 @@ void MaterialStorage::material_set_param(RID p_material, const StringName &p_par
}
Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_param) const {
- const Material *material = material_owner.get_or_null(p_material);
+ const GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, RID());
if (material->params.has(p_param)) {
@@ -735,7 +736,7 @@ Variant MaterialStorage::material_get_param(RID p_material, const StringName &p_
}
void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
material->next_pass = p_next_material;
@@ -745,14 +746,14 @@ void MaterialStorage::material_set_render_priority(RID p_material, int priority)
ERR_FAIL_COND(priority < RS::MATERIAL_RENDER_PRIORITY_MIN);
ERR_FAIL_COND(priority > RS::MATERIAL_RENDER_PRIORITY_MAX);
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
material->render_priority = priority;
}
bool MaterialStorage::material_is_animated(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, false);
if (material->dirty_list.in_list()) {
_update_material(material);
@@ -766,7 +767,7 @@ bool MaterialStorage::material_is_animated(RID p_material) {
}
bool MaterialStorage::material_casts_shadows(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, false);
if (material->dirty_list.in_list()) {
_update_material(material);
@@ -782,7 +783,7 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
}
Variant MaterialStorage::material_get_param_default(RID p_material, const StringName &p_param) const {
- const Material *material = material_owner.get_or_null(p_material);
+ const GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, Variant());
if (material->shader) {
@@ -797,14 +798,14 @@ Variant MaterialStorage::material_get_param_default(RID p_material, const String
void MaterialStorage::update_dirty_materials() {
while (_material_dirty_list.first()) {
- Material *material = _material_dirty_list.first()->self();
+ GLES3::Material *material = _material_dirty_list.first()->self();
_update_material(material);
}
}
/* are these still used? */
RID MaterialStorage::material_get_shader(RID p_material) const {
- const Material *material = material_owner.get_or_null(p_material);
+ const GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, RID());
if (material->shader) {
@@ -815,14 +816,14 @@ RID MaterialStorage::material_get_shader(RID p_material) const {
}
void MaterialStorage::material_set_line_width(RID p_material, float p_width) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
material->line_width = p_width;
}
bool MaterialStorage::material_uses_tangents(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, false);
if (!material->shader) {
@@ -837,7 +838,7 @@ bool MaterialStorage::material_uses_tangents(RID p_material) {
}
bool MaterialStorage::material_uses_ensure_correct_normals(RID p_material) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND_V(!material, false);
if (!material->shader) {
@@ -853,7 +854,7 @@ bool MaterialStorage::material_uses_ensure_correct_normals(RID p_material) {
void MaterialStorage::material_add_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) {
/*
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
@@ -867,7 +868,7 @@ void MaterialStorage::material_add_instance_owner(RID p_material, RendererStorag
void MaterialStorage::material_remove_instance_owner(RID p_material, RendererStorage::DependencyTracker *p_instance) {
/*
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
Map<InstanceBaseDependency *, int>::Element *E = material->instance_owners.find(p_instance);
@@ -883,7 +884,7 @@ void MaterialStorage::material_remove_instance_owner(RID p_material, RendererSto
/*
void MaterialStorage::_material_add_geometry(RID p_material, Geometry *p_geometry) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
@@ -896,7 +897,7 @@ void MaterialStorage::_material_add_geometry(RID p_material, Geometry *p_geometr
}
void MaterialStorage::_material_remove_geometry(RID p_material, Geometry *p_geometry) {
- Material *material = material_owner.get_or_null(p_material);
+ GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
Map<Geometry *, int>::Element *I = material->geometry_owners.find(p_geometry);
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 53631c1e3b..685dde4d98 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -2252,6 +2252,8 @@ void AnimationTrackEdit::_notification(int p_what) {
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: {
@@ -2365,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.
@@ -2952,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 a8a5d11c12..0f6d12b4d4 100644
--- a/editor/animation_track_editor.h
+++ b/editor/animation_track_editor.h
@@ -173,6 +173,7 @@ class AnimationTrackEdit : public Control {
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..98391d286a 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);
@@ -1496,7 +1496,7 @@ void ScriptEditorDebugger::_error_tree_item_rmb_selected(const Vector2 &p_pos) {
if (error_tree->is_anything_selected()) {
item_menu->add_icon_item(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), TTR("Copy Error"), ACTION_COPY_ERROR);
- item_menu->add_icon_item(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), TTR("Open C++ Source on GitHub"), ACTION_OPEN_SOURCE);
+ item_menu->add_icon_item(get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), TTR("Open C++ Source on GitHub"), ACTION_OPEN_SOURCE);
}
if (item_menu->get_item_count() > 0) {
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..0ed0e9bcd7 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);
@@ -1632,7 +1631,7 @@ EditorFileDialog::EditorFileDialog() {
pathhb->add_child(drives_container);
dir = memnew(LineEdit);
- dir->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
pathhb->add_child(dir);
dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -1783,7 +1782,7 @@ EditorFileDialog::EditorFileDialog() {
file_box->add_child(l);
file = memnew(LineEdit);
- file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ file->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
file->set_h_size_flags(Control::SIZE_EXPAND_FILL);
file_box->add_child(file);
@@ -1827,7 +1826,7 @@ EditorFileDialog::EditorFileDialog() {
makedialog->add_child(makevb);
makedirname = memnew(LineEdit);
- makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ makedirname->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
makevb->add_margin_child(TTR("Name:"), makedirname);
add_child(makedialog);
makedialog->register_text_enter(makedirname);
@@ -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..6d2da5e047 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.
@@ -787,12 +787,12 @@ void EditorNode::_notification(int p_what) {
PopupMenu *p = help_menu->get_popup();
p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")));
- p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
- p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
- p->set_item_icon(p->get_item_index(HELP_REPORT_A_BUG), gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
- p->set_item_icon(p->get_item_index(HELP_SUGGEST_A_FEATURE), gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
- p->set_item_icon(p->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
- p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ p->set_item_icon(p->get_item_index(HELP_DOCS), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
+ p->set_item_icon(p->get_item_index(HELP_QA), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
+ p->set_item_icon(p->get_item_index(HELP_REPORT_A_BUG), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
+ p->set_item_icon(p->get_item_index(HELP_SUGGEST_A_FEATURE), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
+ p->set_item_icon(p->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
+ p->set_item_icon(p->get_item_index(HELP_COMMUNITY), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
p->set_item_icon(p->get_item_index(HELP_ABOUT), gui_base->get_theme_icon(SNAME("Godot"), SNAME("EditorIcons")));
p->set_item_icon(p->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), gui_base->get_theme_icon(SNAME("Heart"), SNAME("EditorIcons")));
@@ -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;
@@ -6579,12 +6583,12 @@ EditorNode::EditorNode() {
ED_SHORTCUT_OVERRIDE("editor/editor_help", "macos", KeyModifierMask::ALT | Key::SPACE);
p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH);
p->add_separator();
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/q&a", TTR("Questions & Answers")), HELP_QA);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
- p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/community", TTR("Community")), HELP_COMMUNITY);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/q&a", TTR("Questions & Answers")), HELP_QA);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
+ p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/community", TTR("Community")), HELP_COMMUNITY);
p->add_separator();
p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Godot"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/about", TTR("About Godot")), HELP_ABOUT);
p->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Heart"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT);
@@ -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_properties.cpp b/editor/editor_properties.cpp
index d2b8883b8a..4a3d195a69 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -485,7 +485,7 @@ EditorPropertyPath::EditorPropertyPath() {
HBoxContainer *path_hb = memnew(HBoxContainer);
add_child(path_hb);
path = memnew(LineEdit);
- path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
path_hb->add_child(path);
path->connect("text_submitted", callable_mp(this, &EditorPropertyPath::_path_selected));
path->connect("focus_exited", callable_mp(this, &EditorPropertyPath::_path_focus_exited));
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..17f9ed114d 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -489,6 +489,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("axis_x_color", "Editor", Color(0.96, 0.20, 0.32));
theme->set_color("axis_y_color", "Editor", Color(0.53, 0.84, 0.01));
theme->set_color("axis_z_color", "Editor", Color(0.16, 0.55, 0.96));
+ theme->set_color("axis_w_color", "Editor", Color(0.55, 0.55, 0.55));
const float prop_color_saturation = accent_color.get_s() * 0.75;
const float prop_color_value = accent_color.get_v();
@@ -1220,10 +1221,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..33c6ce9622 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -73,7 +73,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
}
subdirectory_item->set_text(0, dname);
- subdirectory_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE);
+ subdirectory_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE);
subdirectory_item->set_icon(0, get_theme_icon(SNAME("Folder"), SNAME("EditorIcons")));
subdirectory_item->set_icon_modulate(0, get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")));
subdirectory_item->set_selectable(0, true);
@@ -143,7 +143,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
for (const FileInfo &fi : file_list) {
TreeItem *file_item = tree->create_item(subdirectory_item);
file_item->set_text(0, fi.name);
- file_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE);
+ file_item->set_structured_text_bidi_override(0, TextServer::STRUCTURED_TEXT_FILE);
file_item->set_icon(0, _get_tree_item_icon(!fi.import_broken, fi.type));
String file_metadata = lpath.plus_file(fi.name);
file_item->set_metadata(0, file_metadata);
@@ -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()) {
@@ -3006,7 +3026,7 @@ FileSystemDock::FileSystemDock() {
toolbar_hbc->add_child(button_hist_next);
current_path = memnew(LineEdit);
- current_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ current_path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
current_path->set_h_size_flags(SIZE_EXPAND_FILL);
_set_current_path_text(path);
toolbar_hbc->add_child(current_path);
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/ExternalLink.svg b/editor/icons/ExternalLink.svg
new file mode 100644
index 0000000000..7fd78ae009
--- /dev/null
+++ b/editor/icons/ExternalLink.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m0 0h16v16h-16z"/></clipPath><g clip-path="url(#a)" fill="#e0e0e0"><path d="m-1940-64.061 5.5-5.5-2.44-2.439h7v7l-2.439-2.439-5.5 5.5z" transform="translate(1944.939 73)"/><path d="m12 15h-8a3.079 3.079 0 0 1 -3-3v-8a3.04 3.04 0 0 1 3-3h2a1 1 0 0 1 0 2h-2a1.04 1.04 0 0 0 -1 1v8a1.083 1.083 0 0 0 1 1h8a1.068 1.068 0 0 0 1-1v-2a1 1 0 0 1 2 0v2a3.063 3.063 0 0 1 -3 3z"/></g></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/Label3D.svg b/editor/icons/Label3D.svg
new file mode 100644
index 0000000000..76e1b7c276
--- /dev/null
+++ b/editor/icons/Label3D.svg
@@ -0,0 +1 @@
+<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io"><path d="M6 3a1 1 0 0 0-.707.293l-4 4a1 1 0 0 0 0 1.414l4 4A1 1 0 0 0 6 13h8a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H6ZM5 7a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z" fill="#fc7f7f" fill-rule="evenodd" vectornator:layerName="Untitled"/></svg>
diff --git a/editor/icons/SceneUniqueName.svg b/editor/icons/SceneUniqueName.svg
new file mode 100644
index 0000000000..34279a14a6
--- /dev/null
+++ b/editor/icons/SceneUniqueName.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M4.378 2.224q1.235 0 2.084.866.865.85.865 2.083 0 1.17-.881 2.036-.866.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.068t.866-2.051q.865-.866 2.083-.866zm.962 1.988q-.4-.4-.962-.4-.56 0-.961.4-.401.384-.401.93 0 .56.4.961.401.385.962.385.561 0 .962-.385.4-.4.4-.946 0-.56-.4-.945zm5.45-2.116h1.218L5.677 13.78H4.442Zm1.17 5.722q1.234 0 2.083.866.866.849.866 2.1 0 1.17-.882 2.035-.865.85-2.068.85-1.218 0-2.083-.85-.866-.866-.866-2.084 0-1.202.866-2.051.865-.866 2.083-.866zm.961 1.987q-.4-.4-.962-.4-.56 0-.961.4-.4.385-.4.946 0 .561.4.962.4.384.961.384.561 0 .962-.384.4-.4.4-.946 0-.56-.4-.962z" aria-label="%" style="font-weight:600;font-size:16.0277px;font-family:FreeSans;-inkscape-font-specification:'FreeSans Semi-Bold';letter-spacing:0;word-spacing:0;fill:#e0e0e0;fill-opacity:.996078;stroke-width:.400692"/></svg>
diff --git a/editor/icons/Vector4.svg b/editor/icons/Vector4.svg
new file mode 100644
index 0000000000..2797df4443
--- /dev/null
+++ b/editor/icons/Vector4.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg"><path d="M1 4v6h2a3 3 0 0 0 3-3V4H4v3a1 1 0 0 1-1 1V4zm5 3a3 3 0 0 0 3 3h1V8H9a1 1 0 0 1 0-2h1V4H9a3 3 0 0 0-3 3z" fill="#de66f0"/><path d="m12.467 1.523-1.526 5.694 3.02-.015.044 3.795h1.98V5.116h-2.373l.943-3.595z" fill="#eba2f6"/></svg>
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index 20349e8ccb..b72530f1e8 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -458,6 +458,10 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_antialiased(import_settings_data->get("antialiased"));
}
+ } else if (p_edited_property == "generate_mipmaps") {
+ if (font_preview->get_data_count() > 0) {
+ font_preview->get_data(0)->set_generate_mipmaps(import_settings_data->get("generate_mipmaps"));
+ }
} else if (p_edited_property == "multichannel_signed_distance_field") {
if (font_preview->get_data_count() > 0) {
font_preview->get_data(0)->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field"));
@@ -926,6 +930,7 @@ void DynamicFontImportSettings::_re_import() {
Map<StringName, Variant> main_settings;
main_settings["antialiased"] = import_settings_data->get("antialiased");
+ main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps");
main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field");
main_settings["msdf_pixel_range"] = import_settings_data->get("msdf_pixel_range");
main_settings["msdf_size"] = import_settings_data->get("msdf_size");
@@ -1340,6 +1345,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() {
singleton = this;
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true));
+ options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8));
options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48));
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_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp
index a7f6d09aed..2dc24c9d44 100644
--- a/editor/import/resource_importer_dynamic_font.cpp
+++ b/editor/import/resource_importer_dynamic_font.cpp
@@ -102,6 +102,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List<
bool msdf = p_preset == PRESET_MSDF;
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_RANGE, "1,250,1"), 48));
@@ -179,6 +180,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
print_verbose("Importing dynamic font from: " + p_source_file);
bool antialiased = p_options["antialiased"];
+ bool generate_mipmaps = p_options["generate_mipmaps"];
bool msdf = p_options["multichannel_signed_distance_field"];
int px_range = p_options["msdf_pixel_range"];
int px_size = p_options["msdf_size"];
@@ -199,6 +201,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str
font.instantiate();
font->set_data(data);
font->set_antialiased(antialiased);
+ font->set_generate_mipmaps(generate_mipmaps);
font->set_multichannel_signed_distance_field(msdf);
font->set_msdf_pixel_range(px_range);
font->set_msdf_size(px_size);
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_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp
index 1338cf03a8..2b67a171cc 100644
--- a/editor/import/resource_importer_imagefont.cpp
+++ b/editor/import/resource_importer_imagefont.cpp
@@ -96,6 +96,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin
Ref<FontData> font;
font.instantiate();
font->set_antialiased(false);
+ font->set_generate_mipmaps(false);
font->set_multichannel_signed_distance_field(false);
font->set_fixed_size(base_size);
font->set_subpixel_positioning(TextServer::SUBPIXEL_POSITIONING_DISABLED);
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_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp
index 51e2f6ff00..179f78325c 100644
--- a/editor/plugins/node_3d_editor_gizmos.cpp
+++ b/editor/plugins/node_3d_editor_gizmos.cpp
@@ -47,6 +47,7 @@
#include "scene/3d/gpu_particles_3d.h"
#include "scene/3d/gpu_particles_collision_3d.h"
#include "scene/3d/joint_3d.h"
+#include "scene/3d/label_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/lightmap_gi.h"
#include "scene/3d/lightmap_probe.h"
@@ -2170,6 +2171,38 @@ void Sprite3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
///
+Label3DGizmoPlugin::Label3DGizmoPlugin() {
+}
+
+bool Label3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
+ return Object::cast_to<Label3D>(p_spatial) != nullptr;
+}
+
+String Label3DGizmoPlugin::get_gizmo_name() const {
+ return "Label3D";
+}
+
+int Label3DGizmoPlugin::get_priority() const {
+ return -1;
+}
+
+bool Label3DGizmoPlugin::can_be_hidden() const {
+ return false;
+}
+
+void Label3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
+ Label3D *label = Object::cast_to<Label3D>(p_gizmo->get_spatial_node());
+
+ p_gizmo->clear();
+
+ Ref<TriangleMesh> tm = label->generate_triangle_mesh();
+ if (tm.is_valid()) {
+ p_gizmo->add_collision_triangles(tm);
+ }
+}
+
+///
+
Position3DGizmoPlugin::Position3DGizmoPlugin() {
pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
cursor_points = Vector<Vector3>();
diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h
index 3b67b898e3..8adb753a51 100644
--- a/editor/plugins/node_3d_editor_gizmos.h
+++ b/editor/plugins/node_3d_editor_gizmos.h
@@ -321,6 +321,19 @@ public:
Sprite3DGizmoPlugin();
};
+class Label3DGizmoPlugin : public EditorNode3DGizmoPlugin {
+ GDCLASS(Label3DGizmoPlugin, EditorNode3DGizmoPlugin);
+
+public:
+ bool has_gizmo(Node3D *p_spatial) override;
+ String get_gizmo_name() const override;
+ int get_priority() const override;
+ bool can_be_hidden() const override;
+ void redraw(EditorNode3DGizmo *p_gizmo) override;
+
+ Label3DGizmoPlugin();
+};
+
class Position3DGizmoPlugin : public EditorNode3DGizmoPlugin {
GDCLASS(Position3DGizmoPlugin, EditorNode3DGizmoPlugin);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 855fc2b2a9..6eed85e370 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();
+ }
}
}
@@ -7276,6 +7278,7 @@ void Node3DEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<OccluderInstance3DGizmoPlugin>(memnew(OccluderInstance3DGizmoPlugin)));
add_gizmo_plugin(Ref<SoftDynamicBody3DGizmoPlugin>(memnew(SoftDynamicBody3DGizmoPlugin)));
add_gizmo_plugin(Ref<Sprite3DGizmoPlugin>(memnew(Sprite3DGizmoPlugin)));
+ add_gizmo_plugin(Ref<Label3DGizmoPlugin>(memnew(Label3DGizmoPlugin)));
add_gizmo_plugin(Ref<Position3DGizmoPlugin>(memnew(Position3DGizmoPlugin)));
add_gizmo_plugin(Ref<RayCast3DGizmoPlugin>(memnew(RayCast3DGizmoPlugin)));
add_gizmo_plugin(Ref<SpringArm3DGizmoPlugin>(memnew(SpringArm3DGizmoPlugin)));
diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp
index 27b35d803c..ffa74173be 100644
--- a/editor/plugins/ot_features_plugin.cpp
+++ b/editor/plugins/ot_features_plugin.cpp
@@ -30,6 +30,8 @@
#include "ot_features_plugin.h"
+#include "scene/3d/label_3d.h"
+
void OpenTypeFeaturesEditor::_value_changed(double val) {
if (setting) {
return;
@@ -116,7 +118,25 @@ void OpenTypeFeaturesAdd::setup(Object *p_object) {
bool have_ss = false;
bool have_cv = false;
bool have_cu = false;
- Dictionary features = Object::cast_to<Control>(edited_object)->get_theme_font(SNAME("font"))->get_feature_list();
+
+ Ref<Font> font;
+
+ Control *ctrl = Object::cast_to<Control>(edited_object);
+ if (ctrl != nullptr) {
+ font = ctrl->get_theme_font(SNAME("font"));
+ } else {
+ Label3D *l3d = Object::cast_to<Label3D>(edited_object);
+ if (l3d != nullptr) {
+ font = l3d->_get_font_or_default();
+ }
+ }
+
+ if (font.is_null()) {
+ return;
+ }
+
+ Dictionary features = font->get_feature_list();
+
for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) {
String ftr_name = TS->tag_to_name(*ftr);
if (ftr_name.begins_with("stylistic_set_")) {
@@ -145,8 +165,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 +196,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));
@@ -183,7 +205,7 @@ OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() {
/*************************************************************************/
bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) {
- return (Object::cast_to<Control>(p_object) != nullptr);
+ return (Object::cast_to<Control>(p_object) != nullptr) || (Object::cast_to<Label3D>(p_object) != nullptr);
}
bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) {
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 0f45415c4d..a4bf28625d 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())) {
@@ -1613,7 +1613,7 @@ void ScriptEditor::_notification(int p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
help_search->set_icon(get_theme_icon(SNAME("HelpSearch"), SNAME("EditorIcons")));
- site_search->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ site_search->set_icon(get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
script_forward->set_icon(get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
@@ -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/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 070f1fac1e..1bf78cc107 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -439,7 +439,7 @@ void ShaderEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
PopupMenu *popup = help_menu->get_popup();
- popup->set_item_icon(popup->get_item_index(HELP_DOCS), get_theme_icon(SNAME("Instance"), SNAME("EditorIcons")));
+ popup->set_item_icon(popup->get_item_index(HELP_DOCS), get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")));
} break;
case NOTIFICATION_WM_WINDOW_FOCUS_IN: {
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/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 1e7648bc43..c4a5ec7a87 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -211,6 +211,10 @@ void VisualShaderGraphPlugin::set_input_port_default_value(VisualShader::Type p_
Vector3 v = p_value;
button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3));
} break;
+ case Variant::QUATERNION: {
+ Quaternion v = p_value;
+ button->set_text(String::num(v.x, 3) + "," + String::num(v.y, 3) + "," + String::num(v.z, 3) + "," + String::num(v.w, 3));
+ } break;
default: {
}
}
@@ -339,6 +343,7 @@ void VisualShaderGraphPlugin::update_theme() {
vector_expanded_color[0] = editor->get_theme_color(SNAME("axis_x_color"), SNAME("Editor")); // red
vector_expanded_color[1] = editor->get_theme_color(SNAME("axis_y_color"), SNAME("Editor")); // green
vector_expanded_color[2] = editor->get_theme_color(SNAME("axis_z_color"), SNAME("Editor")); // blue
+ vector_expanded_color[3] = editor->get_theme_color(SNAME("axis_w_color"), SNAME("Editor")); // alpha
}
void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
@@ -363,20 +368,22 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
static Ref<StyleBoxEmpty> label_style = make_empty_stylebox(2, 1, 2, 1);
- static const Color type_color[7] = {
+ static const Color type_color[] = {
Color(0.38, 0.85, 0.96), // scalar (float)
Color(0.49, 0.78, 0.94), // scalar (int)
Color(0.74, 0.57, 0.95), // vector2
Color(0.84, 0.49, 0.93), // vector3
+ Color(1.0, 0.125, 0.95), // vector4
Color(0.55, 0.65, 0.94), // boolean
Color(0.96, 0.66, 0.43), // transform
Color(1.0, 1.0, 0.0), // sampler
};
- static const String vector_expanded_name[3] = {
+ static const String vector_expanded_name[4] = {
"red",
"green",
- "blue"
+ "blue",
+ "alpha"
};
Ref<VisualShaderNode> vsnode = visual_shader->get_node(p_type, p_id);
@@ -610,6 +617,9 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
output_port_count += 3;
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ output_port_count += 4;
+ } break;
default:
break;
}
@@ -636,6 +646,13 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
i -= 3;
}
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ if (expanded_port_counter >= 4) {
+ expanded_type = VisualShaderNode::PORT_TYPE_SCALAR;
+ expanded_port_counter = 0;
+ i -= 4;
+ }
+ } break;
default:
break;
}
@@ -710,6 +727,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
type_box->add_item(TTR("Int"));
type_box->add_item(TTR("Vector2"));
type_box->add_item(TTR("Vector3"));
+ type_box->add_item(TTR("Vector4"));
type_box->add_item(TTR("Boolean"));
type_box->add_item(TTR("Transform"));
type_box->add_item(TTR("Sampler"));
@@ -772,6 +790,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
type_box->add_item(TTR("Int"));
type_box->add_item(TTR("Vector2"));
type_box->add_item(TTR("Vector3"));
+ type_box->add_item(TTR("Vector4"));
type_box->add_item(TTR("Boolean"));
type_box->add_item(TTR("Transform"));
type_box->select(group_node->get_output_port_type(i));
@@ -880,6 +899,41 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_3D;
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ port_offset++;
+ valid_left = (i + 1) < vsnode->get_input_port_count();
+ port_left = VisualShaderNode::PORT_TYPE_SCALAR;
+ if (valid_left) {
+ port_left = vsnode->get_input_port_type(i + 1);
+ }
+ node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[0]);
+ port_offset++;
+
+ valid_left = (i + 2) < vsnode->get_input_port_count();
+ port_left = VisualShaderNode::PORT_TYPE_SCALAR;
+ if (valid_left) {
+ port_left = vsnode->get_input_port_type(i + 2);
+ }
+ node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[1]);
+ port_offset++;
+
+ valid_left = (i + 3) < vsnode->get_input_port_count();
+ port_left = VisualShaderNode::PORT_TYPE_SCALAR;
+ if (valid_left) {
+ port_left = vsnode->get_input_port_type(i + 3);
+ }
+ node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[2]);
+ port_offset++;
+
+ valid_left = (i + 4) < vsnode->get_input_port_count();
+ port_left = VisualShaderNode::PORT_TYPE_SCALAR;
+ if (valid_left) {
+ port_left = vsnode->get_input_port_type(i + 4);
+ }
+ node->set_slot(i + port_offset, valid_left, port_left, type_color[port_left], true, VisualShaderNode::PORT_TYPE_SCALAR, vector_expanded_color[3]);
+
+ expanded_type = VisualShaderNode::PORT_TYPE_VECTOR_4D;
+ } break;
default:
break;
}
@@ -1467,6 +1521,9 @@ void VisualShaderEditor::_update_options_menu() {
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")));
break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")));
+ break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")));
break;
@@ -1568,6 +1625,7 @@ void VisualShaderEditor::_update_uniforms(bool p_update_refs) {
Ref<VisualShaderNodeIntUniform> int_uniform = vsnode;
Ref<VisualShaderNodeVec2Uniform> vec2_uniform = vsnode;
Ref<VisualShaderNodeVec3Uniform> vec3_uniform = vsnode;
+ Ref<VisualShaderNodeVec4Uniform> vec4_uniform = vsnode;
Ref<VisualShaderNodeColorUniform> color_uniform = vsnode;
Ref<VisualShaderNodeBooleanUniform> bool_uniform = vsnode;
Ref<VisualShaderNodeTransformUniform> transform_uniform = vsnode;
@@ -1583,6 +1641,8 @@ void VisualShaderEditor::_update_uniforms(bool p_update_refs) {
uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_VECTOR2;
} else if (vec3_uniform.is_valid()) {
uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_VECTOR3;
+ } else if (vec4_uniform.is_valid()) {
+ uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_VECTOR4;
} else if (transform_uniform.is_valid()) {
uniform_type = VisualShaderNodeUniformRef::UniformType::UNIFORM_TYPE_TRANSFORM;
} else if (color_uniform.is_valid()) {
@@ -1825,6 +1885,9 @@ void VisualShaderEditor::_expand_output_port(int p_node, int p_port, bool p_expa
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
type_size = 3;
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ type_size = 4;
+ } break;
default:
break;
}
@@ -2682,6 +2745,9 @@ void VisualShaderEditor::_add_node(int p_idx, const Vector<Variant> &p_ops, Stri
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
initial_expression_code = "output0 = vec3(1.0, 1.0, 1.0);";
break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D:
+ initial_expression_code = "output0 = vec4(1.0, 1.0, 1.0, 1.0);";
+ break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
initial_expression_code = "output0 = true;";
break;
@@ -3237,6 +3303,25 @@ void VisualShaderEditor::_convert_constants_to_uniforms(bool p_vice_versa) {
}
}
+ // vec4
+ if (!caught) {
+ if (!p_vice_versa) {
+ Ref<VisualShaderNodeVec4Constant> vec4_const = Object::cast_to<VisualShaderNodeVec4Constant>(node.ptr());
+ if (vec4_const.is_valid()) {
+ _replace_node(type_id, node_id, "VisualShaderNodeVec4Constant", "VisualShaderNodeVec4Uniform");
+ var = vec4_const->get_constant();
+ caught = true;
+ }
+ } else {
+ Ref<VisualShaderNodeVec4Uniform> vec4_uniform = Object::cast_to<VisualShaderNodeVec4Uniform>(node.ptr());
+ if (vec4_uniform.is_valid()) {
+ _replace_node(type_id, node_id, "VisualShaderNodeVec4Uniform", "VisualShaderNodeVec4Constant");
+ var = vec4_uniform->get_default_value();
+ caught = true;
+ }
+ }
+ }
+
// color
if (!caught) {
if (!p_vice_versa) {
@@ -3943,7 +4028,10 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input,
return;
}
- bool type_changed = p_input->get_input_type_by_name(p_name) != p_input->get_input_type_by_name(prev_name);
+ VisualShaderNode::PortType next_input_type = p_input->get_input_type_by_name(p_name);
+ VisualShaderNode::PortType prev_input_type = p_input->get_input_type_by_name(prev_name);
+
+ bool type_changed = next_input_type != prev_input_type;
UndoRedo *undo_redo = EditorNode::get_singleton()->get_undo_redo();
undo_redo->create_action(TTR("Visual Shader Input Type Changed"));
@@ -3951,31 +4039,54 @@ void VisualShaderEditor::_input_select_item(Ref<VisualShaderNodeInput> p_input,
undo_redo->add_do_method(p_input.ptr(), "set_input_name", p_name);
undo_redo->add_undo_method(p_input.ptr(), "set_input_name", prev_name);
- // update output port
- for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
- VisualShader::Type type = VisualShader::Type(type_id);
- int id = visual_shader->find_node_id(type, p_input);
- if (id != VisualShader::NODE_ID_INVALID) {
- if (type_changed) {
+ if (type_changed) {
+ for (int type_id = 0; type_id < VisualShader::TYPE_MAX; type_id++) {
+ VisualShader::Type type = VisualShader::Type(type_id);
+
+ int id = visual_shader->find_node_id(type, p_input);
+ if (id != VisualShader::NODE_ID_INVALID) {
+ bool is_expanded = p_input->is_output_port_expandable(0) && p_input->_is_output_port_expanded(0);
+
+ int type_size = 0;
+ if (is_expanded) {
+ switch (next_input_type) {
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ type_size = 2;
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
+ type_size = 3;
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ type_size = 4;
+ } break;
+ default:
+ break;
+ }
+ }
+
List<VisualShader::Connection> conns;
visual_shader->get_node_connections(type, &conns);
for (const VisualShader::Connection &E : conns) {
- if (E.from_node == id) {
- if (visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, E.to_node)->get_input_port_type(E.to_port))) {
- undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
- continue;
+ int from_node = E.from_node;
+ int from_port = E.from_port;
+ int to_node = E.to_node;
+ int to_port = E.to_port;
+
+ if (from_node == id) {
+ bool is_incompatible_types = !visual_shader->is_port_types_compatible(p_input->get_input_type_by_name(p_name), visual_shader->get_node(type, to_node)->get_input_port_type(to_port));
+
+ if (is_incompatible_types || from_port > type_size) {
+ undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, from_node, from_port, to_node, to_port);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, from_node, from_port, to_node, to_port);
}
- undo_redo->add_do_method(visual_shader.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
- undo_redo->add_undo_method(visual_shader.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
- undo_redo->add_do_method(graph_plugin.ptr(), "disconnect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
- undo_redo->add_undo_method(graph_plugin.ptr(), "connect_nodes", type, E.from_node, E.from_port, E.to_node, E.to_port);
}
}
+
+ undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
+ undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
}
- undo_redo->add_do_method(graph_plugin.ptr(), "update_node", type_id, id);
- undo_redo->add_undo_method(graph_plugin.ptr(), "update_node", type_id, id);
- break;
}
}
@@ -4176,6 +4287,9 @@ void VisualShaderEditor::_update_varying_tree() {
case VisualShader::VARYING_TYPE_VECTOR_3D:
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")));
break;
+ case VisualShader::VARYING_TYPE_VECTOR_4D:
+ item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")));
+ break;
case VisualShader::VARYING_TYPE_COLOR:
item->set_icon(0, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")));
break;
@@ -4547,6 +4661,7 @@ VisualShaderEditor::VisualShaderEditor() {
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_BOOLEAN);
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_2D);
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_3D);
+ graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_VECTOR_4D);
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_TRANSFORM);
graph->add_valid_right_disconnect_type(VisualShaderNode::PORT_TYPE_SAMPLER);
//graph->add_valid_left_disconnect_type(0);
@@ -4567,27 +4682,44 @@ VisualShaderEditor::VisualShaderEditor() {
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_SCALAR_INT);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_2D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_3D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_VECTOR_4D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR, VisualShaderNode::PORT_TYPE_BOOLEAN);
+
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR_INT);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_SCALAR);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_2D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_3D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_VECTOR_4D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShaderNode::PORT_TYPE_BOOLEAN);
+
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_2D, VisualShaderNode::PORT_TYPE_BOOLEAN);
+
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_3D, VisualShaderNode::PORT_TYPE_BOOLEAN);
+
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_SCALAR_INT);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_2D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_3D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_VECTOR_4D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_VECTOR_4D, VisualShaderNode::PORT_TYPE_BOOLEAN);
+
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_SCALAR_INT);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_2D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_3D);
+ graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_VECTOR_4D);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShaderNode::PORT_TYPE_BOOLEAN);
+
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShaderNode::PORT_TYPE_TRANSFORM);
graph->add_valid_connection_type(VisualShaderNode::PORT_TYPE_SAMPLER, VisualShaderNode::PORT_TYPE_SAMPLER);
@@ -4802,6 +4934,7 @@ VisualShaderEditor::VisualShaderEditor() {
varying_type->add_item("Float");
varying_type->add_item("Vector2");
varying_type->add_item("Vector3");
+ varying_type->add_item("Vector4");
varying_type->add_item("Color");
varying_type->add_item("Transform");
@@ -4962,8 +5095,7 @@ VisualShaderEditor::VisualShaderEditor() {
// CANVASITEM-FOR-ALL
- add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("TexturePixelSize", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "texture_pixel_size", "TEXTURE_PIXEL_SIZE"), { "texture_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Time", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "time", "TIME"), { "time" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("UV", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "uv", "UV"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, -1, Shader::MODE_CANVAS_ITEM));
@@ -4971,11 +5103,9 @@ VisualShaderEditor::VisualShaderEditor() {
// PARTICLES-FOR-ALL
add_options.push_back(AddOption("Active", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "active", "ACTIVE"), { "active" }, VisualShaderNode::PORT_TYPE_BOOLEAN, -1, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Alpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
add_options.push_back(AddOption("AttractorForce", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "attractor_force", "ATTRACTOR_FORCE"), { "attractor_force" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("Custom", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom", "CUSTOM.rgb"), { "custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, -1, Shader::MODE_PARTICLES));
- add_options.push_back(AddOption("CustomAlpha", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom_alpha", "CUSTOM.a"), { "custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Color", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_PARTICLES));
+ add_options.push_back(AddOption("Custom", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "custom", "CUSTOM"), { "custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, -1, Shader::MODE_PARTICLES));
add_options.push_back(AddOption("Delta", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "delta", "DELTA"), { "delta" }, VisualShaderNode::PORT_TYPE_SCALAR, -1, Shader::MODE_PARTICLES));
add_options.push_back(AddOption("EmissionTransform", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "emission_transform", "EMISSION_TRANSFORM"), { "emission_transform" }, VisualShaderNode::PORT_TYPE_TRANSFORM, -1, Shader::MODE_PARTICLES));
add_options.push_back(AddOption("Index", "Input", "All", "VisualShaderNodeInput", vformat(input_param_shader_modes, "index", "INDEX"), { "index" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, -1, Shader::MODE_PARTICLES));
@@ -5005,12 +5135,10 @@ VisualShaderEditor::VisualShaderEditor() {
// NODE3D INPUTS
- add_options.push_back(AddOption("Alpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Binormal", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("Color", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("InstanceId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM.rgb"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("InstanceCustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom_alpha", "INSTANCE_CUSTOM.a"), { "instance_custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ModelViewMatrix", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview_matrix", "MODELVIEW_MATRIX"), { "modelview_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size", "POINT_SIZE"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Tangent", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "tangent", "TANGENT"), { "tangent" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
@@ -5020,11 +5148,10 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("ViewMonoLeft", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_mono_left", "VIEW_MONO_LEFT"), { "view_mono_left" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ViewRight", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "view_right", "VIEW_RIGHT"), { "view_right" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha", "COLOR.a"), { "alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR.rgb"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("DepthTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture", "DEPTH_TEXTURE"), { "depth_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing", "FRONT_FACING"), { "front_facing" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture", "SCREEN_TEXTURE"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
@@ -5040,7 +5167,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Attenuation", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "attenuation", "ATTENUATION"), { "attenuation" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Backlight", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "backlight", "BACKLIGHT"), { "backlight" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Diffuse", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "diffuse", "DIFFUSE_LIGHT"), { "diffuse" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
- add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
+ add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("Metallic", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "metallic", "METALLIC"), { "metallic" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_SPATIAL));
@@ -5052,8 +5179,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("AtLightPass", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass", "AT_LIGHT_PASS"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("CanvasMatrix", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "canvas_matrix", "CANVAS_MATRIX"), { "canvas_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM.rgb"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("InstanceCustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom_alpha", "INSTANCE_CUSTOM.a"), { "instance_custom_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("InstanceCustom", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("InstanceId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("ModelMatrix", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "model_matrix", "MODEL_MATRIX"), { "model_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("PointSize", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "point_size", "POINT_SIZE"), { "point_size" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
@@ -5062,32 +5188,27 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("VertexId", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "vertex_id", "VERTEX_ID"), { "vertex_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("AtLightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "at_light_pass", "AT_LIGHT_PASS"), { "at_light_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("NormalTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture", "NORMAL_TEXTURE"), { "normal_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size", "SCREEN_PIXEL_SIZE"), { "screen_pixel_size" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture", "SCREEN_TEXTURE"), { "screen_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("SpecularShininess", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS.rgb"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("SpecularShininessAlpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess_alpha", "SPECULAR_SHININESS.a"), { "specular_shininess_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("SpecularShininess", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("SpecularShininessTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE"), { "specular_shininess_texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Texture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture", "TEXTURE"), { "texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Vertex", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_mode, "vertex", "VERTEX"), { "vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD.xyz"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT.rgb"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("LightAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_alpha", "LIGHT.a"), { "light_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR.rgb"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("LightColorAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color_alpha", "LIGHT_COLOR.a"), { "light_color_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord", "FRAGCOORD"), { "fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Light", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light", "LIGHT"), { "light" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("LightColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_color", "LIGHT_COLOR"), { "light_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("LightPosition", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_position", "LIGHT_POSITION"), { "light_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("LightVertex", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "light_vertex", "LIGHT_VERTEX"), { "light_vertex" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Normal", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "normal", "NORMAL"), { "normal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord", "POINT_COORD"), { "point_coord" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("Shadow", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow", "SHADOW_MODULATE.rgb"), { "shadow" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("ShadowAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_alpha", "SHADOW_MODULATE.a"), { "shadow_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("SpecularShininess", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS.rgb"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
- add_options.push_back(AddOption("SpecularShininessAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess_alpha", "SPECULAR_SHININESS.a"), { "specular_shininess_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("Shadow", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow", "SHADOW_MODULATE"), { "shadow" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
+ add_options.push_back(AddOption("SpecularShininess", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "specular_shininess", "SPECULAR_SHININESS"), { "specular_shininess" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
add_options.push_back(AddOption("Texture", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture", "TEXTURE"), { "texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_LIGHT, Shader::MODE_CANVAS_ITEM));
// SKY INPUTS
@@ -5096,8 +5217,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("AtHalfResPass", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_half_res_pass", "AT_HALF_RES_PASS"), { "at_half_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("AtQuarterResPass", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "at_quarter_res_pass", "AT_QUARTER_RES_PASS"), { "at_quarter_res_pass" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("EyeDir", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "eyedir", "EYEDIR"), { "eyedir" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
- add_options.push_back(AddOption("HalfResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_color", "HALF_RES_COLOR.rgb"), { "half_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
- add_options.push_back(AddOption("HalfResAlpha", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_alpha", "HALF_RES_COLOR.a"), { "half_res_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
+ add_options.push_back(AddOption("HalfResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "half_res_color", "HALF_RES_COLOR"), { "half_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Light0Color", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_color", "LIGHT0_COLOR"), { "light0_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Light0Direction", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_direction", "LIGHT0_DIRECTION"), { "light0_direction" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Light0Enabled", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light0_enabled", "LIGHT0_ENABLED"), { "light0_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
@@ -5115,8 +5235,7 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Light3Enabled", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_enabled", "LIGHT3_ENABLED"), { "light3_enabled" }, VisualShaderNode::PORT_TYPE_BOOLEAN, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Light3Energy", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "light3_energy", "LIGHT3_ENERGY"), { "light3_energy" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Position", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "position", "POSITION"), { "position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
- add_options.push_back(AddOption("QuarterResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_color", "QUARTER_RES_COLOR.rgb"), { "quarter_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
- add_options.push_back(AddOption("QuarterResAlpha", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_alpha", "QUARTER_RES_COLOR.a"), { "quarter_res_alpha" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_SKY, Shader::MODE_SKY));
+ add_options.push_back(AddOption("QuarterResColor", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "quarter_res_color", "QUARTER_RES_COLOR"), { "quarter_res_color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("Radiance", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "radiance", "RADIANCE"), { "radiance" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("ScreenUV", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "screen_uv", "SCREEN_UV"), { "screen_uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
add_options.push_back(AddOption("SkyCoords", "Input", "Sky", "VisualShaderNodeInput", vformat(input_param_for_sky_shader_mode, "sky_coords", "SKY_COORDS"), { "sky_coords" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_SKY, Shader::MODE_SKY));
@@ -5297,137 +5416,196 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("VectorFunc", "Vector", "Common", "VisualShaderNodeVectorFunc", TTR("Vector function."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("VectorOp", "Vector", "Common", "VisualShaderNodeVectorOp", TTR("Vector operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
- add_options.push_back(AddOption("VectorCompose", "Vector", "Common", "VisualShaderNodeVectorCompose", TTR("Composes vector from three scalars.")));
- add_options.push_back(AddOption("VectorDecompose", "Vector", "Common", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to three scalars.")));
+ add_options.push_back(AddOption("VectorCompose", "Vector", "Common", "VisualShaderNodeVectorCompose", TTR("Composes vector from scalars.")));
+ add_options.push_back(AddOption("VectorDecompose", "Vector", "Common", "VisualShaderNodeVectorDecompose", TTR("Decomposes vector to scalars.")));
- add_options.push_back(AddOption("Vector2Compose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes 2D vector from three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
- add_options.push_back(AddOption("Vector2Decompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 2D vector to three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_2D }));
+ add_options.push_back(AddOption("Vector2Compose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes 2D vector from two scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
+ add_options.push_back(AddOption("Vector2Decompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 2D vector to two scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_2D }));
add_options.push_back(AddOption("Vector3Compose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes 3D vector from three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
- add_options.push_back(AddOption("Vector3Decompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 3D vector to three scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_3D }));
+ add_options.push_back(AddOption("Vector3Decompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 3D vector to three scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_3D }));
+ add_options.push_back(AddOption("Vector4Compose", "Vector", "Composition", "VisualShaderNodeVectorCompose", TTR("Composes 4D vector from four scalars."), { VisualShaderNodeVectorCompose::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
+ add_options.push_back(AddOption("Vector4Decompose", "Vector", "Composition", "VisualShaderNodeVectorDecompose", TTR("Decomposes 4D vector to four scalars."), { VisualShaderNodeVectorDecompose::OP_TYPE_VECTOR_4D }));
add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Abs", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the absolute value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ABS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("ACos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("ACosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ACOSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("ASin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("ASinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ASINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("ATan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the arc-tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("ATan2", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the arc-tangent of the parameters."), { VisualShaderNodeVectorOp::OP_ATAN2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("ATanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_ATANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Ceil", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer that is greater than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_CEIL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Clamp", "Vector", "Functions", "VisualShaderNodeClamp", TTR("Constrains a value to lie between two further values."), { VisualShaderNodeClamp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Cos", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("CosH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic cosine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_COSH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Cross", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Calculates the cross product of two vectors."), { VisualShaderNodeVectorOp::OP_CROSS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Degrees", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in radians to degrees."), { VisualShaderNodeVectorFunc::FUNC_DEGREES, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("DFdX", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
add_options.push_back(AddOption("DFdX", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
+ add_options.push_back(AddOption("DFdX", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'x' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_X, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
add_options.push_back(AddOption("DFdY", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
add_options.push_back(AddOption("DFdY", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
+ add_options.push_back(AddOption("DFdY", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Derivative in 'y' using local differencing."), { VisualShaderNodeDerivativeFunc::FUNC_Y, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
add_options.push_back(AddOption("Distance2D", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Distance3D", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_SCALAR));
+ add_options.push_back(AddOption("Distance4D", "Vector", "Functions", "VisualShaderNodeVectorDistance", TTR("Returns the distance between two points."), { VisualShaderNodeVectorDistance::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Dot", "Vector", "Functions", "VisualShaderNodeDotProduct", TTR("Calculates the dot product of two vectors."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Exp", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-e Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Exp2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 Exponential."), { VisualShaderNodeVectorFunc::FUNC_EXP2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("FaceForward", "Vector", "Functions", "VisualShaderNodeFaceForward", TTR("Returns the vector that points in the same direction as a reference vector. The function has three vector parameters : N, the vector to orient, I, the incident vector, and Nref, the reference vector. If the dot product of I and Nref is smaller than zero the return value is N. Otherwise -N is returned."), { VisualShaderNodeFaceForward::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Floor", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer less than or equal to the parameter."), { VisualShaderNodeVectorFunc::FUNC_FLOOR, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRAC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRAC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Fract", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Computes the fractional part of the argument."), { VisualShaderNodeVectorFunc::FUNC_FRAC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Fresnel", "Vector", "Functions", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("InverseSqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the inverse of the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_INVERSE_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_SCALAR));
+ add_options.push_back(AddOption("Length", "Vector", "Functions", "VisualShaderNodeVectorLen", TTR("Calculates the length of a vector."), { VisualShaderNodeVectorLen::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Log", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Natural logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Log2", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Base-2 logarithm."), { VisualShaderNodeVectorFunc::FUNC_LOG2, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Max", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the greater of two values."), { VisualShaderNodeVectorOp::OP_MAX, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Min", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the lesser of two values."), { VisualShaderNodeVectorOp::OP_MIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Mix", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors."), { VisualShaderNodeMix::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("MixS", "Vector", "Functions", "VisualShaderNodeMix", TTR("Linear interpolation between two vectors using scalar."), { VisualShaderNodeMix::OP_TYPE_VECTOR_4D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("MultiplyAdd", "Vector", "Functions", "VisualShaderNodeMultiplyAdd", TTR("Performs a fused multiply-add operation (a * b + c) on vectors."), { VisualShaderNodeMultiplyAdd::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Negate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the opposite value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_NEGATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Normalize", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Calculates the normalize product of vector."), { VisualShaderNodeVectorFunc::FUNC_NORMALIZE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("OneMinus", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 - vector"), { VisualShaderNodeVectorFunc::FUNC_ONEMINUS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Pow", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the value of the first parameter raised to the power of the second."), { VisualShaderNodeVectorOp::OP_POW, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Radians", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts a quantity in degrees to radians."), { VisualShaderNodeVectorFunc::FUNC_RADIANS, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Reciprocal", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("1.0 / vector"), { VisualShaderNodeVectorFunc::FUNC_RECIPROCAL, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Reflect", "Vector", "Functions", "VisualShaderNodeVectorOp", TTR("Returns the vector that points in the direction of reflection ( a : incident vector, b : normal vector )."), { VisualShaderNodeVectorOp::OP_REFLECT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("Refract", "Vector", "Functions", "VisualShaderNodeVectorRefract", TTR("Returns the vector that points in the direction of refraction."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Round", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUND, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("RoundEven", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the nearest even integer to the parameter."), { VisualShaderNodeVectorFunc::FUNC_ROUNDEVEN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Saturate", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Clamps the value between 0.0 and 1.0."), { VisualShaderNodeVectorFunc::FUNC_SATURATE, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Sign", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Extracts the sign of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIGN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Sin", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SIN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("SinH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic sine of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SINH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Sqrt", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the square root of the parameter."), { VisualShaderNodeVectorFunc::FUNC_SQRT, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("SmoothStep", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( vector(edge0), vector(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("SmoothStepS", "Vector", "Functions", "VisualShaderNodeSmoothStep", TTR("SmoothStep function( scalar(edge0), scalar(edge1), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge0' and 1.0 if 'x' is larger than 'edge1'. Otherwise the return value is interpolated between 0.0 and 1.0 using Hermite polynomials."), { VisualShaderNodeSmoothStep::OP_TYPE_VECTOR_4D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Step", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Step", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( vector(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_2D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_3D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("StepS", "Vector", "Functions", "VisualShaderNodeStep", TTR("Step function( scalar(edge), vector(x) ).\n\nReturns 0.0 if 'x' is smaller than 'edge' and otherwise 1.0."), { VisualShaderNodeStep::OP_TYPE_VECTOR_4D_SCALAR }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Sum", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
add_options.push_back(AddOption("Sum", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
+ add_options.push_back(AddOption("Sum", "Vector", "Functions", "VisualShaderNodeDerivativeFunc", TTR("(Fragment/Light mode only) (Vector) Sum of absolute derivative in 'x' and 'y'."), { VisualShaderNodeDerivativeFunc::FUNC_SUM, VisualShaderNodeDerivativeFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_FRAGMENT | TYPE_FLAGS_LIGHT, -1, true));
add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Tan", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TAN, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("TanH", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Returns the hyperbolic tangent of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TANH, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Trunc", "Vector", "Functions", "VisualShaderNodeVectorFunc", TTR("Finds the truncated value of the parameter."), { VisualShaderNodeVectorFunc::FUNC_TRUNC, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds 2D vector to 2D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds 3D vector to 3D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Add", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Adds 4D vector to 4D vector."), { VisualShaderNodeVectorOp::OP_ADD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides 2D vector by 2D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides 3D vector by 3D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Divide", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Divides 4D vector by 4D vector."), { VisualShaderNodeVectorOp::OP_DIV, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 2D vector by 2D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 3D vector by 3D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Multiply", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Multiplies 4D vector by 4D vector."), { VisualShaderNodeVectorOp::OP_MUL, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 2D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 3D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Remainder", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Returns the remainder of the two 4D vectors."), { VisualShaderNodeVectorOp::OP_MOD, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 2D vector from 2D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_2D }, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 3D vector from 3D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Subtract", "Vector", "Operators", "VisualShaderNodeVectorOp", TTR("Subtracts 4D vector from 4D vector."), { VisualShaderNodeVectorOp::OP_SUB, VisualShaderNodeVectorOp::OP_TYPE_VECTOR_4D }, VisualShaderNode::PORT_TYPE_VECTOR_4D));
add_options.push_back(AddOption("Vector2Constant", "Vector", "Variables", "VisualShaderNodeVec2Constant", TTR("2D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Vector2Uniform", "Vector", "Variables", "VisualShaderNodeVec2Uniform", TTR("2D vector uniform."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D));
add_options.push_back(AddOption("Vector3Constant", "Vector", "Variables", "VisualShaderNodeVec3Constant", TTR("3D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("Vector3Uniform", "Vector", "Variables", "VisualShaderNodeVec3Uniform", TTR("3D vector uniform."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
+ add_options.push_back(AddOption("Vector4Constant", "Vector", "Variables", "VisualShaderNodeVec4Constant", TTR("4D vector constant."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
+ add_options.push_back(AddOption("Vector4Uniform", "Vector", "Variables", "VisualShaderNodeVec4Uniform", TTR("4D vector uniform."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
// SPECIAL
@@ -5525,11 +5703,12 @@ public:
void setup(const Ref<VisualShaderNodeInput> &p_input) {
input = p_input;
- Ref<Texture2D> type_icon[7] = {
+ Ref<Texture2D> type_icon[] = {
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")),
@@ -5578,6 +5757,7 @@ public:
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
};
@@ -5652,12 +5832,13 @@ public:
void setup(const Ref<VisualShaderNodeUniformRef> &p_uniform_ref) {
uniform_ref = p_uniform_ref;
- Ref<Texture2D> type_icon[8] = {
+ Ref<Texture2D> type_icon[] = {
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("float"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("int"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("bool"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector2"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector3"), SNAME("EditorIcons")),
+ EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Vector4"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Transform3D"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Color"), SNAME("EditorIcons")),
EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("ImageTexture"), SNAME("EditorIcons")),
@@ -5864,6 +6045,8 @@ Control *VisualShaderNodePluginDefault::create_editor(const Ref<Resource> &p_par
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
} else if (Object::cast_to<EditorPropertyTransform3D>(prop) || Object::cast_to<EditorPropertyVector3>(prop)) {
prop->set_custom_minimum_size(Size2(250 * EDSCALE, 0));
+ } else if (Object::cast_to<EditorPropertyQuaternion>(prop)) {
+ prop->set_custom_minimum_size(Size2(320 * EDSCALE, 0));
} else if (Object::cast_to<EditorPropertyFloat>(prop)) {
prop->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
} else if (Object::cast_to<EditorPropertyEnum>(prop)) {
diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h
index 4087fc583c..9f82b2ed7f 100644
--- a/editor/plugins/visual_shader_editor_plugin.h
+++ b/editor/plugins/visual_shader_editor_plugin.h
@@ -85,7 +85,7 @@ private:
List<VisualShader::Connection> connections;
bool dirty = false;
- Color vector_expanded_color[3];
+ Color vector_expanded_color[4];
protected:
static void _bind_methods();
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..81df7ee30a 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());
}
@@ -808,7 +802,7 @@ public:
project_path = memnew(LineEdit);
project_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- project_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ project_path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
pphb->add_child(project_path);
install_path_container = memnew(VBoxContainer);
@@ -823,7 +817,7 @@ public:
install_path = memnew(LineEdit);
install_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- install_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ install_path->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
iphb->add_child(install_path);
// status icon
@@ -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);
@@ -1446,7 +1440,7 @@ void ProjectList::create_project_item_control(int p_index) {
}
Label *fpath = memnew(Label(item.path));
- fpath->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ fpath->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
path_hb->add_child(fpath);
fpath->set_h_size_flags(Control::SIZE_EXPAND_FILL);
fpath->set_modulate(Color(1, 1, 1, 0.5));
@@ -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..c63471720b 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -1061,6 +1061,28 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
}
}
} break;
+ case TOOL_TOGGLE_SCENE_UNIQUE_NAME: {
+ List<Node *> selection = editor_selection->get_selected_node_list();
+ List<Node *>::Element *e = selection.front();
+ if (e) {
+ UndoRedo *undo_redo = &editor_data->get_undo_redo();
+ Node *node = e->get();
+ bool enabled = node->is_unique_name_in_owner();
+ if (!enabled && get_tree()->get_edited_scene_root()->get_node_or_null(UNIQUE_NODE_PREFIX + String(node->get_name())) != nullptr) {
+ accept->set_text(TTR("Another node already uses this unique name in the scene."));
+ accept->popup_centered();
+ return;
+ }
+ if (!enabled) {
+ undo_redo->create_action(TTR("Enable Scene Unique Name"));
+ } else {
+ undo_redo->create_action(TTR("Disable Scene Unique Name"));
+ }
+ undo_redo->add_do_method(node, "set_unique_name_in_owner", !enabled);
+ undo_redo->add_undo_method(node, "set_unique_name_in_owner", enabled);
+ undo_redo->commit_action();
+ }
+ } break;
case TOOL_CREATE_2D_SCENE:
case TOOL_CREATE_3D_SCENE:
case TOOL_CREATE_USER_INTERFACE:
@@ -1309,8 +1331,17 @@ void SceneTreeDock::_node_replace_owner(Node *p_base, Node *p_node, Node *p_root
UndoRedo *undo_redo = &editor_data->get_undo_redo();
switch (p_mode) {
case MODE_BIDI: {
+ bool is_unique = p_node->is_unique_name_in_owner() && p_base->get_node_or_null(UNIQUE_NODE_PREFIX + String(p_node->get_name())) != nullptr;
+ if (is_unique) {
+ // Will create a unique name conflict. Disable before setting owner.
+ undo_redo->add_do_method(p_node, "set_unique_name_in_owner", false);
+ }
undo_redo->add_do_method(p_node, "set_owner", p_root);
undo_redo->add_undo_method(p_node, "set_owner", p_base);
+ if (is_unique) {
+ // Will create a unique name conflict. Enable after setting owner.
+ undo_redo->add_undo_method(p_node, "set_unique_name_in_owner", true);
+ }
} break;
case MODE_DO: {
@@ -2774,11 +2805,19 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) {
menu->add_separator();
menu->add_icon_shortcut(get_theme_icon(SNAME("CreateNewSceneFrom"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM);
}
+
if (full_selection.size() == 1) {
menu->add_separator();
menu->add_icon_shortcut(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH);
}
+ if (selection[0]->get_owner() == EditorNode::get_singleton()->get_edited_scene()) {
+ // Only for nodes owned by the edited scene root.
+ menu->add_separator();
+ menu->add_icon_check_item(get_theme_icon(SNAME("SceneUniqueName"), SNAME("EditorIcons")), TTR("Access as Scene Unique Name"), TOOL_TOGGLE_SCENE_UNIQUE_NAME);
+ menu->set_item_checked(menu->get_item_index(TOOL_TOGGLE_SCENE_UNIQUE_NAME), selection[0]->is_unique_name_in_owner());
+ }
+
bool is_external = (!selection[0]->get_scene_file_path().is_empty());
if (is_external) {
bool is_inherited = selection[0]->get_scene_inherited_state() != nullptr;
@@ -3149,9 +3188,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 +3206,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/scene_tree_dock.h b/editor/scene_tree_dock.h
index 599fb01203..842995dfe3 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -91,7 +91,7 @@ class SceneTreeDock : public VBoxContainer {
TOOL_SCENE_CLEAR_INHERITANCE,
TOOL_SCENE_CLEAR_INHERITANCE_CONFIRM,
TOOL_SCENE_OPEN_INHERITED,
-
+ TOOL_TOGGLE_SCENE_UNIQUE_NAME,
TOOL_CREATE_2D_SCENE,
TOOL_CREATE_3D_SCENE,
TOOL_CREATE_USER_INTERFACE,
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 44eb5c670d..aa48395152 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -148,6 +148,13 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
TabContainer *tab_container = Object::cast_to<TabContainer>(NodeDock::get_singleton()->get_parent());
NodeDock::get_singleton()->get_parent()->call("set_current_tab", tab_container->get_tab_idx_from_control(NodeDock::get_singleton()));
NodeDock::get_singleton()->show_groups();
+ } else if (p_id == BUTTON_UNIQUE) {
+ undo_redo->create_action(TTR("Disable Scene Unique Name"));
+ undo_redo->add_do_method(n, "set_unique_name_in_owner", false);
+ undo_redo->add_undo_method(n, "set_unique_name_in_owner", true);
+ undo_redo->add_do_method(this, "_update_tree");
+ undo_redo->add_undo_method(this, "_update_tree");
+ undo_redo->commit_action();
}
}
@@ -260,6 +267,10 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll
item->add_button(0, get_theme_icon(SNAME("NodeWarning"), SNAME("EditorIcons")), BUTTON_WARNING, false, TTR("Node configuration warning:") + "\n" + warning);
}
+ if (p_node->is_unique_name_in_owner()) {
+ item->add_button(0, get_theme_icon(SNAME("SceneUniqueName"), SNAME("EditorIcons")), BUTTON_UNIQUE, false, vformat(TTR("This node can be accessed from within anywhere in the scene by preceding it with the '%s' prefix in a node path.\nClick to disable this."), UNIQUE_NODE_PREFIX));
+ }
+
int num_connections = p_node->get_persistent_signal_connection_count();
int num_groups = p_node->get_persistent_group_count();
@@ -832,6 +843,13 @@ void SceneTreeEditor::_renamed() {
// Trim leading/trailing whitespace to prevent node names from containing accidental whitespace, which would make it more difficult to get the node via `get_node()`.
new_name = new_name.strip_edges();
+ if (n->is_unique_name_in_owner() && get_tree()->get_edited_scene_root()->get_node_or_null("%" + new_name) != nullptr) {
+ error->set_text(TTR("Another node already uses this unique name in the scene."));
+ error->popup_centered();
+ which->set_text(0, n->get_name());
+ return;
+ }
+
if (!undo_redo) {
n->set_name(new_name);
which->set_metadata(0, n->get_path());
diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h
index 547a5b57ca..3d88081ab1 100644
--- a/editor/scene_tree_editor.h
+++ b/editor/scene_tree_editor.h
@@ -53,6 +53,7 @@ class SceneTreeEditor : public Control {
BUTTON_SIGNALS = 6,
BUTTON_GROUPS = 7,
BUTTON_PIN = 8,
+ BUTTON_UNIQUE = 9,
};
Tree *tree = nullptr;
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/editor/shader_globals_editor.cpp b/editor/shader_globals_editor.cpp
index 864afa5c1c..81e672c5c3 100644
--- a/editor/shader_globals_editor.cpp
+++ b/editor/shader_globals_editor.cpp
@@ -183,7 +183,7 @@ protected:
pinfo.type = Variant::VECTOR3;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- pinfo.type = Variant::PLANE;
+ pinfo.type = Variant::QUATERNION;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
pinfo.type = Variant::RECT2;
@@ -304,7 +304,7 @@ static Variant create_var(RS::GlobalVariableType p_type) {
return Vector3();
}
case RS::GLOBAL_VAR_TYPE_VEC4: {
- return Plane();
+ return Quaternion();
}
case RS::GLOBAL_VAR_TYPE_RECT2: {
return Rect2();
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/misc/scripts/clang_format.sh b/misc/scripts/clang_format.sh
index 5ab9c1bbb9..6d19044d96 100755
--- a/misc/scripts/clang_format.sh
+++ b/misc/scripts/clang_format.sh
@@ -17,8 +17,6 @@ while read -r f; do
continue
elif [[ "$f" == *"glsl" ]]; then
continue
- elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/input/InputManager"* ]]; then
- continue
elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView"* ]]; then
continue
elif [[ "$f" == "platform/android/java/lib/src/org/godotengine/godot/gl/EGLLogWrapper"* ]]; then
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_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_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 ae05c1b68d..173d5131cf 100644
--- a/modules/gltf/editor/editor_scene_importer_blend.cpp
+++ b/modules/gltf/editor/editor_scene_importer_blend.cpp
@@ -238,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;
@@ -254,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 24564f55be..893d2efcec 100644
--- a/modules/gltf/editor/editor_scene_importer_fbx.cpp
+++ b/modules/gltf/editor/editor_scene_importer_fbx.cpp
@@ -105,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/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..0ae8219e23 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
@@ -996,8 +994,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
int w = (bounds.r - bounds.l);
int h = (bounds.t - bounds.b);
- int mw = w + p_rect_margin * 2;
- int mh = h + p_rect_margin * 2;
+ int mw = w + p_rect_margin * 4;
+ int mh = h + p_rect_margin * 4;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
@@ -1031,7 +1029,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * 4;
+ int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * 4;
ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph());
wr[ofs + 0] = (uint8_t)(CLAMP(image(j, i)[0] * 256.f, 0.f, 255.f));
wr[ofs + 1] = (uint8_t)(CLAMP(image(j, i)[1] * 256.f, 0.f, 255.f));
@@ -1051,8 +1049,9 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(
chr.texture_idx = tex_pos.index;
- chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h);
- chr.rect.position = Vector2(bounds.l, -bounds.t);
+ chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2);
+ chr.rect.position = Vector2(bounds.l - p_rect_margin, -bounds.t - p_rect_margin);
+
chr.rect.size = chr.uv_rect.size;
}
return chr;
@@ -1064,8 +1063,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
int w = bitmap.width;
int h = bitmap.rows;
- int mw = w + p_rect_margin * 2;
- int mh = h + p_rect_margin * 2;
+ int mw = w + p_rect_margin * 4;
+ int mh = h + p_rect_margin * 4;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
@@ -1085,7 +1084,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * color_size;
+ int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * color_size;
ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph());
switch (bitmap.pixel_mode) {
case FT_PIXEL_MODE_MONO: {
@@ -1126,8 +1125,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma
chr.texture_idx = tex_pos.index;
chr.found = true;
- chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h);
- chr.rect.position = Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling;
+ chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2);
+ chr.rect.position = Vector2(xofs - p_rect_margin, -yofs - p_rect_margin) * p_data->scale / p_data->oversampling;
chr.rect.size = chr.uv_rect.size * p_data->scale / p_data->oversampling;
return chr;
}
@@ -1798,6 +1797,29 @@ bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const {
return fd->antialiased;
}
+void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->mipmaps != p_generate_mipmaps) {
+ for (KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) {
+ for (int i = 0; i < E.value->textures.size(); i++) {
+ E.value->textures.write[i].dirty = true;
+ }
+ }
+ fd->mipmaps = p_generate_mipmaps;
+ }
+}
+
+bool TextServerAdvanced::font_get_generate_mipmaps(const RID &p_font_rid) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, false);
+
+ MutexLock lock(fd->mutex);
+ return fd->mipmaps;
+}
+
void TextServerAdvanced::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -2278,6 +2300,9 @@ void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vec
Ref<Image> img;
img.instantiate();
img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
tex.texture = Ref<ImageTexture>();
tex.texture.instantiate();
@@ -2561,6 +2586,86 @@ void TextServerAdvanced::font_set_glyph_texture_idx(const RID &p_font_rid, const
gl[p_glyph].found = true;
}
+RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, RID());
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size_outline(fd, p_size);
+
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID());
+ if (!_ensure_glyph(fd, size, p_glyph)) {
+ return RID(); // Invalid or non graphicl glyph, do not display errors.
+ }
+
+ const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
+ ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), RID());
+
+ if (RenderingServer::get_singleton() != nullptr) {
+ if (gl[p_glyph].texture_idx != -1) {
+ if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) {
+ FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx];
+ Ref<Image> img;
+ img.instantiate();
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
+ if (tex.texture.is_null()) {
+ tex.texture.instantiate();
+ tex.texture->create_from_image(img);
+ } else {
+ tex.texture->update(img);
+ }
+ tex.dirty = false;
+ }
+ return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_rid();
+ }
+ }
+
+ return RID();
+}
+
+Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, Size2());
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size_outline(fd, p_size);
+
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2());
+ if (!_ensure_glyph(fd, size, p_glyph)) {
+ return Size2(); // Invalid or non graphicl glyph, do not display errors.
+ }
+
+ const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
+ ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), Size2());
+
+ if (RenderingServer::get_singleton() != nullptr) {
+ if (gl[p_glyph].texture_idx != -1) {
+ if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) {
+ FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx];
+ Ref<Image> img;
+ img.instantiate();
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
+ if (tex.texture.is_null()) {
+ tex.texture.instantiate();
+ tex.texture->create_from_image(img);
+ } else {
+ tex.texture->update(img);
+ }
+ tex.dirty = false;
+ }
+ return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_size();
+ }
+ }
+
+ return Size2();
+}
+
Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const {
FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
@@ -2867,6 +2972,9 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can
Ref<Image> img;
img.instantiate();
img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
if (tex.texture.is_null()) {
tex.texture.instantiate();
tex.texture->create_from_image(img);
@@ -2943,6 +3051,9 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI
Ref<Image> img;
img.instantiate();
img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
if (tex.texture.is_null()) {
tex.texture.instantiate();
tex.texture->create_from_image(img);
@@ -3306,7 +3417,9 @@ void TextServerAdvanced::shaped_text_set_bidi_override(const RID &p_shaped, cons
}
sd->bidi_override.clear();
for (int i = 0; i < p_override.size(); i++) {
- sd->bidi_override.push_back(p_override[i]);
+ if (p_override[i].get_type() == Variant::VECTOR2I) {
+ sd->bidi_override.push_back(p_override[i]);
+ }
}
invalidate(sd, false);
}
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 8afba6adca..fa59566a94 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -216,6 +216,7 @@ class TextServerAdvanced : public TextServerExtension {
Mutex mutex;
bool antialiased = true;
+ bool mipmaps = false;
bool msdf = false;
int msdf_range = 14;
int msdf_source_size = 48;
@@ -483,6 +484,9 @@ public:
virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override;
virtual bool font_is_antialiased(const RID &p_font_rid) const override;
+ virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
+ virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;
+
virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override;
virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override;
@@ -567,6 +571,9 @@ public:
virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override;
+ virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+
virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override;
virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 47c6a73b24..1251aaf2b9 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -438,8 +438,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
int w = (bounds.r - bounds.l);
int h = (bounds.t - bounds.b);
- int mw = w + p_rect_margin * 2;
- int mh = h + p_rect_margin * 2;
+ int mw = w + p_rect_margin * 4;
+ int mh = h + p_rect_margin * 4;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
@@ -473,7 +473,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * 4;
+ int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * 4;
ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph());
wr[ofs + 0] = (uint8_t)(CLAMP(image(j, i)[0] * 256.f, 0.f, 255.f));
wr[ofs + 1] = (uint8_t)(CLAMP(image(j, i)[1] * 256.f, 0.f, 255.f));
@@ -493,8 +493,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(
chr.texture_idx = tex_pos.index;
- chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h);
- chr.rect.position = Vector2(bounds.l, -bounds.t);
+ chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2);
+ chr.rect.position = Vector2(bounds.l - p_rect_margin, -bounds.t - p_rect_margin);
chr.rect.size = chr.uv_rect.size;
}
return chr;
@@ -506,8 +506,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
int w = bitmap.width;
int h = bitmap.rows;
- int mw = w + p_rect_margin * 2;
- int mh = h + p_rect_margin * 2;
+ int mw = w + p_rect_margin * 4;
+ int mh = h + p_rect_margin * 4;
ERR_FAIL_COND_V(mw > 4096, FontGlyph());
ERR_FAIL_COND_V(mh > 4096, FontGlyph());
@@ -527,7 +527,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
- int ofs = ((i + tex_pos.y + p_rect_margin) * tex.texture_w + j + tex_pos.x + p_rect_margin) * color_size;
+ int ofs = ((i + tex_pos.y + p_rect_margin * 2) * tex.texture_w + j + tex_pos.x + p_rect_margin * 2) * color_size;
ERR_FAIL_COND_V(ofs >= tex.imgdata.size(), FontGlyph());
switch (bitmap.pixel_mode) {
case FT_PIXEL_MODE_MONO: {
@@ -568,8 +568,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma
chr.texture_idx = tex_pos.index;
chr.found = true;
- chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w, h);
- chr.rect.position = Vector2(xofs, -yofs) * p_data->scale / p_data->oversampling;
+ chr.uv_rect = Rect2(tex_pos.x + p_rect_margin, tex_pos.y + p_rect_margin, w + p_rect_margin * 2, h + p_rect_margin * 2);
+ chr.rect.position = Vector2(xofs - p_rect_margin, -yofs - p_rect_margin) * p_data->scale / p_data->oversampling;
chr.rect.size = chr.uv_rect.size * p_data->scale / p_data->oversampling;
return chr;
}
@@ -959,6 +959,29 @@ bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const {
return fd->antialiased;
}
+void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND(!fd);
+
+ MutexLock lock(fd->mutex);
+ if (fd->mipmaps != p_generate_mipmaps) {
+ for (KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) {
+ for (int i = 0; i < E.value->textures.size(); i++) {
+ E.value->textures.write[i].dirty = true;
+ }
+ }
+ fd->mipmaps = p_generate_mipmaps;
+ }
+}
+
+bool TextServerFallback::font_get_generate_mipmaps(const RID &p_font_rid) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, false);
+
+ MutexLock lock(fd->mutex);
+ return fd->mipmaps;
+}
+
void TextServerFallback::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND(!fd);
@@ -1439,6 +1462,9 @@ void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vec
Ref<Image> img;
img.instantiate();
img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
tex.texture = Ref<ImageTexture>();
tex.texture.instantiate();
@@ -1708,6 +1734,86 @@ void TextServerFallback::font_set_glyph_texture_idx(const RID &p_font_rid, const
gl[p_glyph].found = true;
}
+RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, RID());
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size_outline(fd, p_size);
+
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID());
+ if (!_ensure_glyph(fd, size, p_glyph)) {
+ return RID(); // Invalid or non graphicl glyph, do not display errors.
+ }
+
+ const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
+ ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), RID());
+
+ if (RenderingServer::get_singleton() != nullptr) {
+ if (gl[p_glyph].texture_idx != -1) {
+ if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) {
+ FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx];
+ Ref<Image> img;
+ img.instantiate();
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
+ if (tex.texture.is_null()) {
+ tex.texture.instantiate();
+ tex.texture->create_from_image(img);
+ } else {
+ tex.texture->update(img);
+ }
+ tex.dirty = false;
+ }
+ return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_rid();
+ }
+ }
+
+ return RID();
+}
+
+Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
+ ERR_FAIL_COND_V(!fd, Size2());
+
+ MutexLock lock(fd->mutex);
+ Vector2i size = _get_size_outline(fd, p_size);
+
+ ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2());
+ if (!_ensure_glyph(fd, size, p_glyph)) {
+ return Size2(); // Invalid or non graphicl glyph, do not display errors.
+ }
+
+ const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map;
+ ERR_FAIL_COND_V(gl[p_glyph].texture_idx < -1 || gl[p_glyph].texture_idx >= fd->cache[size]->textures.size(), Size2());
+
+ if (RenderingServer::get_singleton() != nullptr) {
+ if (gl[p_glyph].texture_idx != -1) {
+ if (fd->cache[size]->textures[gl[p_glyph].texture_idx].dirty) {
+ FontTexture &tex = fd->cache[size]->textures.write[gl[p_glyph].texture_idx];
+ Ref<Image> img;
+ img.instantiate();
+ img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
+ if (tex.texture.is_null()) {
+ tex.texture.instantiate();
+ tex.texture->create_from_image(img);
+ } else {
+ tex.texture->update(img);
+ }
+ tex.dirty = false;
+ }
+ return fd->cache[size]->textures[gl[p_glyph].texture_idx].texture->get_size();
+ }
+ }
+
+ return Size2();
+}
+
Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const {
FontDataFallback *fd = font_owner.get_or_null(p_font_rid);
ERR_FAIL_COND_V(!fd, Dictionary());
@@ -1996,6 +2102,9 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can
Ref<Image> img;
img.instantiate();
img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
if (tex.texture.is_null()) {
tex.texture.instantiate();
tex.texture->create_from_image(img);
@@ -2072,6 +2181,9 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI
Ref<Image> img;
img.instantiate();
img->create_from_data(tex.texture_w, tex.texture_h, false, tex.format, tex.imgdata);
+ if (fd->mipmaps) {
+ img->generate_mipmaps();
+ }
if (tex.texture.is_null()) {
tex.texture.instantiate();
tex.texture->create_from_image(img);
diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h
index ea77659b5d..d6f61e02f8 100644
--- a/modules/text_server_fb/text_server_fb.h
+++ b/modules/text_server_fb/text_server_fb.h
@@ -179,6 +179,7 @@ class TextServerFallback : public TextServerExtension {
Mutex mutex;
bool antialiased = true;
+ bool mipmaps = false;
bool msdf = false;
int msdf_range = 14;
int msdf_source_size = 48;
@@ -375,6 +376,9 @@ public:
virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override;
virtual bool font_is_antialiased(const RID &p_font_rid) const override;
+ virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
+ virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;
+
virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override;
virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override;
@@ -458,6 +462,8 @@ public:
virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override;
+ virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override;
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..06fa90eb29 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);
@@ -3390,6 +3390,8 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_NODE_PATH);
n->set_base_path(drop_path);
}
+ } else {
+ n->set_call_mode(VisualScriptFunctionCall::CALL_MODE_INSTANCE);
}
if (drop_node) {
n->set_base_type(drop_node->get_class());
@@ -3702,8 +3704,13 @@ void VisualScriptEditor::_selected_connect_node(const String &p_text, const Stri
Object::cast_to<VisualScriptTypeCast>(vnode.ptr())->set_base_type(base_type);
Object::cast_to<VisualScriptTypeCast>(vnode.ptr())->set_base_script(base_script);
} else if (Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())) {
- Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_type(base_type);
- Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_script(base_script);
+ if (base_type_map.has(base_type)) {
+ Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_basic_type(base_type_map[base_type]);
+ Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_call_mode(VisualScriptFunctionCall::CALL_MODE_BASIC_TYPE);
+ } else {
+ Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_type(base_type);
+ Object::cast_to<VisualScriptFunctionCall>(vnode.ptr())->set_base_script(base_script);
+ }
} else if (Object::cast_to<VisualScriptPropertySet>(vnode.ptr())) {
Object::cast_to<VisualScriptPropertySet>(vnode.ptr())->set_base_type(base_type);
Object::cast_to<VisualScriptPropertySet>(vnode.ptr())->set_base_script(base_script);
@@ -4751,6 +4758,35 @@ VisualScriptEditor::VisualScriptEditor() {
popup_menu->add_item(TTR("Duplicate"), EDIT_DUPLICATE_NODES);
popup_menu->add_item(TTR("Clear Copy Buffer"), EDIT_CLEAR_COPY_BUFFER);
popup_menu->connect("id_pressed", callable_mp(this, &VisualScriptEditor::_menu_option));
+
+ base_type_map.insert("String", Variant::STRING);
+ base_type_map.insert("Vector2", Variant::VECTOR2);
+ base_type_map.insert("Vector2i", Variant::VECTOR2I);
+ base_type_map.insert("Rect2", Variant::RECT2);
+ base_type_map.insert("Rect2i", Variant::RECT2I);
+ base_type_map.insert("Vector3", Variant::VECTOR3);
+ base_type_map.insert("Vector3i", Variant::VECTOR3I);
+ base_type_map.insert("Transform2D", Variant::TRANSFORM2D);
+ base_type_map.insert("Plane", Variant::PLANE);
+ base_type_map.insert("Quaternion", Variant::QUATERNION);
+ base_type_map.insert("AABB", Variant::AABB);
+ base_type_map.insert("Basis", Variant::BASIS);
+ base_type_map.insert("Transform3D", Variant::TRANSFORM3D);
+ base_type_map.insert("Color", Variant::COLOR);
+ base_type_map.insert("NodePath", Variant::NODE_PATH);
+ base_type_map.insert("RID", Variant::RID);
+ base_type_map.insert("Callable", Variant::CALLABLE);
+ base_type_map.insert("Dictionary", Variant::DICTIONARY);
+ base_type_map.insert("Array", Variant::ARRAY);
+ base_type_map.insert("PackedByteArray", Variant::PACKED_BYTE_ARRAY);
+ base_type_map.insert("PackedInt32Array", Variant::PACKED_INT32_ARRAY);
+ base_type_map.insert("PackedFloat32Array", Variant::PACKED_FLOAT32_ARRAY);
+ base_type_map.insert("PackedInt64Array", Variant::PACKED_INT64_ARRAY);
+ base_type_map.insert("PackedFloat64Array", Variant::PACKED_FLOAT64_ARRAY);
+ base_type_map.insert("PackedStringArray", Variant::PACKED_STRING_ARRAY);
+ base_type_map.insert("PackedVector2Array", Variant::PACKED_VECTOR2_ARRAY);
+ base_type_map.insert("PackedVector3Array", Variant::PACKED_VECTOR3_ARRAY);
+ base_type_map.insert("PackedColorArray", Variant::PACKED_COLOR_ARRAY);
}
VisualScriptEditor::~VisualScriptEditor() {
diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h
index 5b355a71df..fcfd44cecd 100644
--- a/modules/visual_script/editor/visual_script_editor.h
+++ b/modules/visual_script/editor/visual_script_editor.h
@@ -144,6 +144,7 @@ class VisualScriptEditor : public ScriptEditorBase {
Map<StringName, Color> node_colors;
HashMap<StringName, Ref<StyleBox>> node_styles;
+ Map<StringName, Variant::Type> base_type_map;
void _update_graph_connections();
void _update_graph(int p_only_id = -1);
diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp
index 31406a2a6f..07929e5c0e 100644
--- a/modules/visual_script/editor/visual_script_property_selector.cpp
+++ b/modules/visual_script/editor/visual_script_property_selector.cpp
@@ -86,6 +86,13 @@ void VisualScriptPropertySelector::_update_results_s(String p_string) {
_update_results();
}
+void VisualScriptPropertySelector::_update_results_search_all() {
+ if (search_classes->is_pressed()) {
+ scope_combo->select(COMBO_ALL);
+ }
+ _update_results();
+}
+
void VisualScriptPropertySelector::_update_results() {
_update_icons();
search_runner = Ref<SearchRunner>(memnew(SearchRunner(this, results_tree)));
@@ -167,7 +174,7 @@ void VisualScriptPropertySelector::select_method_from_base_type(const String &p_
search_properties->set_pressed(false);
search_theme_items->set_pressed(false);
- scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated"
+ scope_combo->select(COMBO_BASE);
results_tree->clear();
show_window(.5f);
@@ -201,8 +208,7 @@ void VisualScriptPropertySelector::select_from_base_type(const String &p_base, c
search_properties->set_pressed(true);
search_theme_items->set_pressed(false);
- // When class is Input only show inheritors
- scope_combo->select(0); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated"
+ scope_combo->select(COMBO_RELATED);
results_tree->clear();
show_window(.5f);
@@ -234,7 +240,7 @@ void VisualScriptPropertySelector::select_from_script(const Ref<Script> &p_scrip
search_properties->set_pressed(true);
search_theme_items->set_pressed(false);
- scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated"
+ scope_combo->select(COMBO_BASE);
results_tree->clear();
show_window(.5f);
@@ -264,7 +270,7 @@ void VisualScriptPropertySelector::select_from_basic_type(Variant::Type p_type,
search_properties->set_pressed(true);
search_theme_items->set_pressed(false);
- scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All"
+ scope_combo->select(COMBO_BASE);
results_tree->clear();
show_window(.5f);
@@ -294,7 +300,7 @@ void VisualScriptPropertySelector::select_from_action(const String &p_type, cons
search_properties->set_pressed(false);
search_theme_items->set_pressed(false);
- scope_combo->select(0); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All"
+ scope_combo->select(COMBO_RELATED);
results_tree->clear();
show_window(.5f);
@@ -330,7 +336,7 @@ void VisualScriptPropertySelector::select_from_instance(Object *p_instance, cons
search_properties->set_pressed(true);
search_theme_items->set_pressed(false);
- scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All"
+ scope_combo->select(COMBO_BASE);
results_tree->clear();
show_window(.5f);
@@ -363,7 +369,7 @@ void VisualScriptPropertySelector::select_from_visual_script(const Ref<Script> &
search_properties->set_pressed(true);
search_theme_items->set_pressed(false);
- scope_combo->select(2); //id0 = "Search Related" //id2 = "Search Base" //id3 = "Search Inheriters" //id4 = "Search Unrelated" //id5 "Search All"
+ scope_combo->select(COMBO_BASE);
results_tree->clear();
show_window(.5f);
@@ -418,7 +424,7 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() {
search_classes = memnew(Button);
search_classes->set_flat(true);
search_classes->set_tooltip(TTR("Search Classes"));
- search_classes->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results));
+ search_classes->connect("pressed", callable_mp(this, &VisualScriptPropertySelector::_update_results_search_all));
search_classes->set_toggle_mode(true);
search_classes->set_pressed(true);
search_classes->set_focus_mode(Control::FOCUS_NONE);
@@ -739,49 +745,46 @@ bool VisualScriptPropertySelector::SearchRunner::_phase_node_classes_build() {
if (vs_nodes.is_empty()) {
return true;
}
- String registerd_node_name = vs_nodes[0];
+ String registered_node_name = vs_nodes[0];
vs_nodes.pop_front();
- Vector<String> path = registerd_node_name.split("/");
+ Vector<String> path = registered_node_name.split("/");
if (path[0] == "constants") {
- _add_class_doc(registerd_node_name, "", "constants");
+ _add_class_doc(registered_node_name, "", "constants");
} else if (path[0] == "custom") {
- _add_class_doc(registerd_node_name, "", "custom");
+ _add_class_doc(registered_node_name, "", "custom");
} else if (path[0] == "data") {
- _add_class_doc(registerd_node_name, "", "data");
+ _add_class_doc(registered_node_name, "", "data");
} else if (path[0] == "flow_control") {
- _add_class_doc(registerd_node_name, "", "flow_control");
+ _add_class_doc(registered_node_name, "", "flow_control");
} else if (path[0] == "functions") {
if (path[1] == "built_in") {
- _add_class_doc(registerd_node_name, "functions", "built_in");
+ _add_class_doc(registered_node_name, "functions", "built_in");
} else if (path[1] == "by_type") {
- if (search_flags & SEARCH_CLASSES) {
- _add_class_doc(registerd_node_name, path[2], "by_type_class");
- }
+ // No action is required.
+ // Using function references from ClassDB to remove confusion for users.
} else if (path[1] == "constructors") {
- if (search_flags & SEARCH_CLASSES) {
- _add_class_doc(registerd_node_name, path[2].substr(0, path[2].find_char('(')), "constructors_class");
- }
+ _add_class_doc(registered_node_name, "", "constructors");
} else if (path[1] == "deconstruct") {
- _add_class_doc(registerd_node_name, "", "deconstruct");
+ _add_class_doc(registered_node_name, "", "deconstruct");
} else if (path[1] == "wait") {
- _add_class_doc(registerd_node_name, "functions", "yield");
+ _add_class_doc(registered_node_name, "functions", "yield");
} else {
- _add_class_doc(registerd_node_name, "functions", "");
+ _add_class_doc(registered_node_name, "functions", "");
}
} else if (path[0] == "index") {
- _add_class_doc(registerd_node_name, "", "index");
+ _add_class_doc(registered_node_name, "", "index");
} else if (path[0] == "operators") {
if (path[1] == "bitwise") {
- _add_class_doc(registerd_node_name, "operators", "bitwise");
+ _add_class_doc(registered_node_name, "operators", "bitwise");
} else if (path[1] == "compare") {
- _add_class_doc(registerd_node_name, "operators", "compare");
+ _add_class_doc(registered_node_name, "operators", "compare");
} else if (path[1] == "logic") {
- _add_class_doc(registerd_node_name, "operators", "logic");
+ _add_class_doc(registered_node_name, "operators", "logic");
} else if (path[1] == "math") {
- _add_class_doc(registerd_node_name, "operators", "math");
+ _add_class_doc(registered_node_name, "operators", "math");
} else {
- _add_class_doc(registerd_node_name, "operators", "");
+ _add_class_doc(registered_node_name, "operators", "");
}
}
return false;
diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h
index faf39a14e4..1b32ee2967 100644
--- a/modules/visual_script/editor/visual_script_property_selector.h
+++ b/modules/visual_script/editor/visual_script_property_selector.h
@@ -62,6 +62,15 @@ class VisualScriptPropertySelector : public ConfirmationDialog {
SCOPE_ALL = SCOPE_BASE | SCOPE_INHERITERS | SCOPE_UNRELATED
};
+ enum ScopeCombo {
+ COMBO_RELATED,
+ COMBO_SEPARATOR,
+ COMBO_BASE,
+ COMBO_INHERITERS,
+ COMBO_UNRELATED,
+ COMBO_ALL,
+ };
+
LineEdit *search_box = nullptr;
Button *case_sensitive_button = nullptr;
@@ -88,6 +97,7 @@ class VisualScriptPropertySelector : public ConfirmationDialog {
void _sbox_input(const Ref<InputEvent> &p_ie);
void _update_results_i(int p_int);
void _update_results_s(String p_string);
+ void _update_results_search_all();
void _update_results();
void _confirmed();
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/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
index e8ffbb9481..fb1604f6af 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
@@ -65,10 +65,6 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God
} else {
Log.v(TAG, "Creating new Godot fragment instance.");
godotFragment = initGodotInstance();
- if (godotFragment == null) {
- throw new IllegalStateException("Godot instance must be non-null.");
- }
-
getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss();
}
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
index 8a86136daf..6e597163ab 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java
@@ -509,17 +509,14 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
use_debug_opengl = true;
} else if (command_line[i].equals("--use_immersive")) {
use_immersive = true;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
- window.getDecorView().setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
- View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
-
- UiChangeListener();
- }
+ window.getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar
+ View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ UiChangeListener();
} else if (command_line[i].equals("--use_apk_expansion")) {
use_apk_expansion = true;
} else if (has_extra && command_line[i].equals("--apk_expansion_md5")) {
@@ -699,7 +696,7 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME);
- if (use_immersive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+
+ if (use_immersive) {
Window window = getActivity().getWindow();
window.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
@@ -719,15 +716,13 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
final View decorView = getActivity().getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(visibility -> {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- decorView.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
- View.SYSTEM_UI_FLAG_FULLSCREEN |
- View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
- }
+ decorView.setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+ View.SYSTEM_UI_FLAG_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
});
}
@@ -888,9 +883,8 @@ public class Godot extends Fragment implements SensorEventListener, IDownloaderC
// Create Hex String
StringBuilder hexString = new StringBuilder();
- for (int i = 0; i < messageDigest.length; i++) {
- String s = Integer.toHexString(0xFF & messageDigest[i]);
-
+ for (byte b : messageDigest) {
+ String s = Integer.toHexString(0xFF & b);
if (s.length() == 1) {
s = "0" + s;
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
index c06d89b843..8694bb91e1 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java
@@ -34,8 +34,9 @@ import static org.godotengine.godot.utils.GLUtils.DEBUG;
import org.godotengine.godot.GodotLib;
import org.godotengine.godot.GodotRenderView;
-import org.godotengine.godot.input.InputManagerCompat.InputDeviceListener;
+import android.content.Context;
+import android.hardware.input.InputManager;
import android.os.Build;
import android.util.Log;
import android.util.SparseArray;
@@ -53,9 +54,9 @@ import java.util.Set;
/**
* Handles input related events for the {@link GodotRenderView} view.
*/
-public class GodotInputHandler implements InputDeviceListener {
+public class GodotInputHandler implements InputManager.InputDeviceListener {
private final GodotRenderView mRenderView;
- private final InputManagerCompat mInputManager;
+ private final InputManager mInputManager;
private final String tag = this.getClass().getSimpleName();
@@ -64,7 +65,7 @@ public class GodotInputHandler implements InputDeviceListener {
public GodotInputHandler(GodotRenderView godotView) {
mRenderView = godotView;
- mInputManager = InputManagerCompat.Factory.getInputManager(mRenderView.getView().getContext());
+ mInputManager = (InputManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_SERVICE);
mInputManager.registerInputDeviceListener(this, null);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
deleted file mode 100644
index 21fdc658bb..0000000000
--- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.godotengine.godot.input;
-
-import android.content.Context;
-import android.os.Handler;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-
-public interface InputManagerCompat {
- /**
- * Gets information about the input device with the specified id.
- *
- * @param id The device id
- * @return The input device or null if not found
- */
- InputDevice getInputDevice(int id);
-
- /**
- * Gets the ids of all input devices in the system.
- *
- * @return The input device ids.
- */
- int[] getInputDeviceIds();
-
- /**
- * Registers an input device listener to receive notifications about when
- * input devices are added, removed or changed.
- *
- * @param listener The listener to register.
- * @param handler The handler on which the listener should be invoked, or
- * null if the listener should be invoked on the calling thread's
- * looper.
- */
- void registerInputDeviceListener(InputManagerCompat.InputDeviceListener listener,
- Handler handler);
-
- /**
- * Unregisters an input device listener.
- *
- * @param listener The listener to unregister.
- */
- void unregisterInputDeviceListener(InputManagerCompat.InputDeviceListener listener);
-
- /*
- * The following three calls are to simulate V16 behavior on pre-Jellybean
- * devices. If you don't call them, your callback will never be called
- * pre-API 16.
- */
-
- /**
- * Pass the motion events to the InputManagerCompat. This is used to
- * optimize for polling for controllers. If you do not pass these events in,
- * polling will cause regular object creation.
- *
- * @param event the motion event from the app
- */
- void onGenericMotionEvent(MotionEvent event);
-
- /**
- * Tell the V9 input manager that it should stop polling for disconnected
- * devices. You can call this during onPause in your activity, although you
- * might want to call it whenever your game is not active (or whenever you
- * don't care about being notified of new input devices)
- */
- void onPause();
-
- /**
- * Tell the V9 input manager that it should start polling for disconnected
- * devices. You can call this during onResume in your activity, although you
- * might want to call it less often (only when the gameplay is actually
- * active)
- */
- void onResume();
-
- interface InputDeviceListener {
- /**
- * Called whenever the input manager detects that a device has been
- * added. This will only be called in the V9 version when a motion event
- * is detected.
- *
- * @param deviceId The id of the input device that was added.
- */
- void onInputDeviceAdded(int deviceId);
-
- /**
- * Called whenever the properties of an input device have changed since
- * they were last queried. This will not be called for the V9 version of
- * the API.
- *
- * @param deviceId The id of the input device that changed.
- */
- void onInputDeviceChanged(int deviceId);
-
- /**
- * Called whenever the input manager detects that a device has been
- * removed. For the V9 version, this can take some time depending on the
- * poll rate.
- *
- * @param deviceId The id of the input device that was removed.
- */
- void onInputDeviceRemoved(int deviceId);
- }
-
- /**
- * Use this to construct a compatible InputManager.
- */
- class Factory {
- /**
- * Constructs and returns a compatible InputManger
- *
- * @param context the Context that will be used to get the system
- * service from
- * @return a compatible implementation of InputManager
- */
- public static InputManagerCompat getInputManager(Context context) {
- return new InputManagerV16(context);
- }
- }
-}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java b/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java
deleted file mode 100644
index 0dbc13c77b..0000000000
--- a/platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.godotengine.godot.input;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.hardware.input.InputManager;
-import android.os.Build;
-import android.os.Handler;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-public class InputManagerV16 implements InputManagerCompat {
- private final InputManager mInputManager;
- private final Map<InputManagerCompat.InputDeviceListener, V16InputDeviceListener> mListeners;
-
- public InputManagerV16(Context context) {
- mInputManager = (InputManager)context.getSystemService(Context.INPUT_SERVICE);
- mListeners = new HashMap<>();
- }
-
- @Override
- public InputDevice getInputDevice(int id) {
- return mInputManager.getInputDevice(id);
- }
-
- @Override
- public int[] getInputDeviceIds() {
- return mInputManager.getInputDeviceIds();
- }
-
- static class V16InputDeviceListener implements InputManager.InputDeviceListener {
- final InputManagerCompat.InputDeviceListener mIDL;
-
- public V16InputDeviceListener(InputDeviceListener idl) {
- mIDL = idl;
- }
-
- @Override
- public void onInputDeviceAdded(int deviceId) {
- mIDL.onInputDeviceAdded(deviceId);
- }
-
- @Override
- public void onInputDeviceChanged(int deviceId) {
- mIDL.onInputDeviceChanged(deviceId);
- }
-
- @Override
- public void onInputDeviceRemoved(int deviceId) {
- mIDL.onInputDeviceRemoved(deviceId);
- }
- }
-
- @Override
- public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
- V16InputDeviceListener v16Listener = new V16InputDeviceListener(listener);
- mInputManager.registerInputDeviceListener(v16Listener, handler);
- mListeners.put(listener, v16Listener);
- }
-
- @Override
- public void unregisterInputDeviceListener(InputDeviceListener listener) {
- V16InputDeviceListener curListener = mListeners.remove(listener);
- if (null != curListener) {
- mInputManager.unregisterInputDeviceListener(curListener);
- }
- }
-
- @Override
- public void onGenericMotionEvent(MotionEvent event) {
- // unused in V16
- }
-
- @Override
- public void onPause() {
- // unused in V16
- }
-
- @Override
- public void onResume() {
- // unused in V16
- }
-}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java
index 39a57f587a..47df23fe1a 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/Crypt.java
@@ -43,8 +43,8 @@ public class Crypt {
// Create Hex String
StringBuilder hexString = new StringBuilder();
- for (int i = 0; i < messageDigest.length; i++)
- hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
+ for (byte b : messageDigest)
+ hexString.append(Integer.toHexString(0xFF & b));
return hexString.toString();
} catch (Exception e) {
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index ea72bc0e15..5e0a9d967b 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -503,6 +503,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNI
return;
}
+ // We force redraw to ensure we render at least once when resuming the app.
+ Main::force_redraw();
if (os_android->get_main_loop()) {
os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED);
}
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index ef53415f16..54124c22d0 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -187,10 +187,11 @@ bool OS_Android::main_loop_iterate(bool *r_should_swap_buffers) {
return false;
}
DisplayServerAndroid::get_singleton()->process_events();
+ uint64_t current_frames_drawn = Engine::get_singleton()->get_frames_drawn();
bool exit = Main::iteration();
if (r_should_swap_buffers) {
- *r_should_swap_buffers = !is_in_low_processor_usage_mode() || RenderingServer::get_singleton()->has_changed();
+ *r_should_swap_buffers = !is_in_low_processor_usage_mode() || RenderingServer::get_singleton()->has_changed() || current_frames_drawn != Engine::get_singleton()->get_frames_drawn();
}
return exit;
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/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp
index bad1488d5a..24c66622f1 100644
--- a/scene/2d/cpu_particles_2d.cpp
+++ b/scene/2d/cpu_particles_2d.cpp
@@ -743,7 +743,7 @@ void CPUParticles2D::_particles_process(double p_delta) {
real_t angle1_rad = direction.angle() + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread);
Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad));
- p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf());
+ p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf());
real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand);
p.rotation = Math::deg2rad(base_angle);
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/label_3d.cpp b/scene/3d/label_3d.cpp
new file mode 100644
index 0000000000..7dc90da4be
--- /dev/null
+++ b/scene/3d/label_3d.cpp
@@ -0,0 +1,962 @@
+/*************************************************************************/
+/* label_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 "label_3d.h"
+
+#include "core/core_string_names.h"
+#include "scene/resources/theme.h"
+#include "scene/scene_string_names.h"
+
+void Label3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &Label3D::set_horizontal_alignment);
+ ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &Label3D::get_horizontal_alignment);
+
+ ClassDB::bind_method(D_METHOD("set_vertical_alignment", "alignment"), &Label3D::set_vertical_alignment);
+ ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &Label3D::get_vertical_alignment);
+
+ ClassDB::bind_method(D_METHOD("set_modulate", "modulate"), &Label3D::set_modulate);
+ ClassDB::bind_method(D_METHOD("get_modulate"), &Label3D::get_modulate);
+
+ ClassDB::bind_method(D_METHOD("set_outline_modulate", "modulate"), &Label3D::set_outline_modulate);
+ ClassDB::bind_method(D_METHOD("get_outline_modulate"), &Label3D::get_outline_modulate);
+
+ ClassDB::bind_method(D_METHOD("set_text", "text"), &Label3D::set_text);
+ ClassDB::bind_method(D_METHOD("get_text"), &Label3D::get_text);
+
+ ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Label3D::set_text_direction);
+ ClassDB::bind_method(D_METHOD("get_text_direction"), &Label3D::get_text_direction);
+
+ ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Label3D::set_opentype_feature);
+ ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Label3D::get_opentype_feature);
+ ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Label3D::clear_opentype_features);
+
+ ClassDB::bind_method(D_METHOD("set_language", "language"), &Label3D::set_language);
+ ClassDB::bind_method(D_METHOD("get_language"), &Label3D::get_language);
+
+ ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override", "parser"), &Label3D::set_structured_text_bidi_override);
+ ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override"), &Label3D::get_structured_text_bidi_override);
+
+ ClassDB::bind_method(D_METHOD("set_structured_text_bidi_override_options", "args"), &Label3D::set_structured_text_bidi_override_options);
+ ClassDB::bind_method(D_METHOD("get_structured_text_bidi_override_options"), &Label3D::get_structured_text_bidi_override_options);
+
+ ClassDB::bind_method(D_METHOD("set_uppercase", "enable"), &Label3D::set_uppercase);
+ ClassDB::bind_method(D_METHOD("is_uppercase"), &Label3D::is_uppercase);
+
+ ClassDB::bind_method(D_METHOD("set_font", "font"), &Label3D::set_font);
+ ClassDB::bind_method(D_METHOD("get_font"), &Label3D::get_font);
+
+ ClassDB::bind_method(D_METHOD("set_font_size", "size"), &Label3D::set_font_size);
+ ClassDB::bind_method(D_METHOD("get_font_size"), &Label3D::get_font_size);
+
+ ClassDB::bind_method(D_METHOD("set_outline_size", "outline_size"), &Label3D::set_outline_size);
+ ClassDB::bind_method(D_METHOD("get_outline_size"), &Label3D::get_outline_size);
+
+ ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &Label3D::set_line_spacing);
+ ClassDB::bind_method(D_METHOD("get_line_spacing"), &Label3D::get_line_spacing);
+
+ ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &Label3D::set_autowrap_mode);
+ ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &Label3D::get_autowrap_mode);
+
+ ClassDB::bind_method(D_METHOD("set_width", "width"), &Label3D::set_width);
+ ClassDB::bind_method(D_METHOD("get_width"), &Label3D::get_width);
+
+ ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &Label3D::set_pixel_size);
+ ClassDB::bind_method(D_METHOD("get_pixel_size"), &Label3D::get_pixel_size);
+
+ ClassDB::bind_method(D_METHOD("set_draw_flag", "flag", "enabled"), &Label3D::set_draw_flag);
+ ClassDB::bind_method(D_METHOD("get_draw_flag", "flag"), &Label3D::get_draw_flag);
+
+ ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &Label3D::set_billboard_mode);
+ ClassDB::bind_method(D_METHOD("get_billboard_mode"), &Label3D::get_billboard_mode);
+
+ ClassDB::bind_method(D_METHOD("set_alpha_cut_mode", "mode"), &Label3D::set_alpha_cut_mode);
+ ClassDB::bind_method(D_METHOD("get_alpha_cut_mode"), &Label3D::get_alpha_cut_mode);
+
+ ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &Label3D::set_alpha_scissor_threshold);
+ ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &Label3D::get_alpha_scissor_threshold);
+
+ ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &Label3D::set_texture_filter);
+ ClassDB::bind_method(D_METHOD("get_texture_filter"), &Label3D::get_texture_filter);
+
+ ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &Label3D::generate_triangle_mesh);
+
+ ClassDB::bind_method(D_METHOD("_queue_update"), &Label3D::_queue_update);
+ ClassDB::bind_method(D_METHOD("_font_changed"), &Label3D::_font_changed);
+ ClassDB::bind_method(D_METHOD("_im_update"), &Label3D::_im_update);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
+
+ ADD_GROUP("Flags", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard"), "set_billboard_mode", "get_billboard_mode");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "alpha_scissor_threshold", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_alpha_scissor_threshold", "get_alpha_scissor_threshold");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
+
+ ADD_GROUP("Text", "");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "modulate"), "set_modulate", "get_modulate");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_modulate"), "set_outline_modulate", "get_outline_modulate");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,127,1"), "set_font_size", "get_font_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1"), "set_outline_size", "get_outline_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing"), "set_line_spacing", "get_line_spacing");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width"), "set_width", "get_width");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "structured_text_bidi_override", PROPERTY_HINT_ENUM, "Default,URI,File,Email,List,None,Custom"), "set_structured_text_bidi_override", "get_structured_text_bidi_override");
+ ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "structured_text_bidi_override_options"), "set_structured_text_bidi_override_options", "get_structured_text_bidi_override_options");
+
+ ADD_GROUP("Locale", "");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language");
+
+ BIND_ENUM_CONSTANT(AUTOWRAP_OFF);
+ BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY);
+ BIND_ENUM_CONSTANT(AUTOWRAP_WORD);
+ BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART);
+
+ BIND_ENUM_CONSTANT(FLAG_SHADED);
+ BIND_ENUM_CONSTANT(FLAG_DOUBLE_SIDED);
+ BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST);
+ BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE);
+ BIND_ENUM_CONSTANT(FLAG_MAX);
+
+ BIND_ENUM_CONSTANT(ALPHA_CUT_DISABLED);
+ BIND_ENUM_CONSTANT(ALPHA_CUT_DISCARD);
+ BIND_ENUM_CONSTANT(ALPHA_CUT_OPAQUE_PREPASS);
+}
+
+bool Label3D::_set(const StringName &p_name, const Variant &p_value) {
+ String str = p_name;
+ if (str.begins_with("opentype_features/")) {
+ String name = str.get_slicec('/', 1);
+ int32_t tag = TS->name_to_tag(name);
+ int value = p_value;
+ if (value == -1) {
+ if (opentype_features.has(tag)) {
+ opentype_features.erase(tag);
+ dirty_font = true;
+ _queue_update();
+ }
+ } else {
+ if (!opentype_features.has(tag) || (int)opentype_features[tag] != value) {
+ opentype_features[tag] = value;
+ dirty_font = true;
+ _queue_update();
+ }
+ }
+ notify_property_list_changed();
+ return true;
+ }
+
+ return false;
+}
+
+bool Label3D::_get(const StringName &p_name, Variant &r_ret) const {
+ String str = p_name;
+ if (str.begins_with("opentype_features/")) {
+ String name = str.get_slicec('/', 1);
+ int32_t tag = TS->name_to_tag(name);
+ if (opentype_features.has(tag)) {
+ r_ret = opentype_features[tag];
+ return true;
+ } else {
+ r_ret = -1;
+ return true;
+ }
+ }
+ return false;
+}
+
+void Label3D::_get_property_list(List<PropertyInfo> *p_list) const {
+ for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
+ String name = TS->tag_to_name(*ftr);
+ p_list->push_back(PropertyInfo(Variant::INT, "opentype_features/" + name));
+ }
+ p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
+}
+
+void Label3D::_validate_property(PropertyInfo &property) const {
+ if (property.name == "material_override" || property.name == "material_overlay") {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+}
+
+void Label3D::_notification(int p_what) {
+ switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ if (!pending_update) {
+ _im_update();
+ }
+ } break;
+ case NOTIFICATION_TRANSLATION_CHANGED: {
+ String new_text = tr(text);
+ if (new_text == xl_text) {
+ return; // Nothing new.
+ }
+ xl_text = new_text;
+ dirty_text = true;
+ _queue_update();
+ } break;
+ }
+}
+
+void Label3D::_im_update() {
+ _shape();
+
+ triangle_mesh.unref();
+ update_gizmos();
+
+ pending_update = false;
+}
+
+void Label3D::_queue_update() {
+ if (pending_update) {
+ return;
+ }
+
+ pending_update = true;
+ call_deferred(SceneStringNames::get_singleton()->_im_update);
+}
+
+AABB Label3D::get_aabb() const {
+ return aabb;
+}
+
+Ref<TriangleMesh> Label3D::generate_triangle_mesh() const {
+ if (triangle_mesh.is_valid()) {
+ return triangle_mesh;
+ }
+
+ Ref<Font> font = _get_font_or_default();
+ if (font.is_null()) {
+ return Ref<TriangleMesh>();
+ }
+
+ Vector<Vector3> faces;
+ faces.resize(6);
+ Vector3 *facesw = faces.ptrw();
+
+ float total_h = 0.0;
+ float max_line_w = 0.0;
+ for (int i = 0; i < lines_rid.size(); i++) {
+ total_h += TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing;
+ max_line_w = MAX(max_line_w, TS->shaped_text_get_width(lines_rid[i]));
+ }
+
+ float vbegin = 0;
+ switch (vertical_alignment) {
+ case VERTICAL_ALIGNMENT_FILL:
+ case VERTICAL_ALIGNMENT_TOP: {
+ // Nothing.
+ } break;
+ case VERTICAL_ALIGNMENT_CENTER: {
+ vbegin = (total_h - line_spacing) / 2.0;
+ } break;
+ case VERTICAL_ALIGNMENT_BOTTOM: {
+ vbegin = (total_h - line_spacing);
+ } break;
+ }
+
+ Vector2 offset = Vector2(0, vbegin);
+ switch (horizontal_alignment) {
+ case HORIZONTAL_ALIGNMENT_LEFT:
+ break;
+ case HORIZONTAL_ALIGNMENT_FILL:
+ case HORIZONTAL_ALIGNMENT_CENTER: {
+ offset.x = -max_line_w / 2.0;
+ } break;
+ case HORIZONTAL_ALIGNMENT_RIGHT: {
+ offset.x = -max_line_w;
+ } break;
+ }
+
+ Rect2 final_rect = Rect2(offset, Size2(max_line_w, total_h));
+
+ if (final_rect.size.x == 0 || final_rect.size.y == 0) {
+ return Ref<TriangleMesh>();
+ }
+
+ real_t pixel_size = get_pixel_size();
+
+ Vector2 vertices[4] = {
+
+ (final_rect.position + Vector2(0, -final_rect.size.y)) * pixel_size,
+ (final_rect.position + Vector2(final_rect.size.x, -final_rect.size.y)) * pixel_size,
+ (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size,
+ final_rect.position * pixel_size,
+
+ };
+
+ static const int indices[6] = {
+ 0, 1, 2,
+ 0, 2, 3
+ };
+
+ for (int j = 0; j < 6; j++) {
+ int i = indices[j];
+ Vector3 vtx;
+ vtx[0] = vertices[i][0];
+ vtx[1] = vertices[i][1];
+ facesw[j] = vtx;
+ }
+
+ triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh));
+ triangle_mesh->create(faces);
+
+ return triangle_mesh;
+}
+
+void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, const Color &p_modulate, int p_priority, int p_outline_size) {
+ for (int j = 0; j < p_glyph.repeat; j++) {
+ Vector2 gl_of;
+ Vector2 gl_sz;
+ Rect2 gl_uv;
+ Size2 texs;
+ RID tex;
+
+ if (p_glyph.font_rid != RID()) {
+ tex = TS->font_get_glyph_texture_rid(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index);
+ if (tex != RID()) {
+ gl_of = (TS->font_get_glyph_offset(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index) + Vector2(p_glyph.x_off, p_glyph.y_off)) * pixel_size;
+ gl_sz = TS->font_get_glyph_size(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index) * pixel_size;
+ gl_uv = TS->font_get_glyph_uv_rect(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index);
+ texs = TS->font_get_glyph_texture_size(p_glyph.font_rid, Vector2i(p_glyph.font_size, p_outline_size), p_glyph.index);
+ }
+ } else {
+ gl_sz = TS->get_hex_code_box_size(p_glyph.font_size, p_glyph.index) * pixel_size;
+ gl_of = Vector2(0, -gl_sz.y);
+ }
+
+ bool msdf = TS->font_is_multichannel_signed_distance_field(p_glyph.font_rid);
+
+ uint64_t mat_hash;
+ if (tex != RID()) {
+ mat_hash = hash_one_uint64(tex.get_id());
+ } else {
+ mat_hash = hash_one_uint64(0);
+ }
+ mat_hash = hash_djb2_one_64(p_priority | (p_outline_size << 31), mat_hash);
+
+ if (!surfaces.has(mat_hash)) {
+ SurfaceData surf;
+ surf.material = RenderingServer::get_singleton()->material_create();
+ // Set defaults for material, names need to match up those in StandardMaterial3D
+ RS::get_singleton()->material_set_param(surf.material, "albedo", Color(1, 1, 1, 1));
+ RS::get_singleton()->material_set_param(surf.material, "specular", 0.5);
+ RS::get_singleton()->material_set_param(surf.material, "metallic", 0.0);
+ RS::get_singleton()->material_set_param(surf.material, "roughness", 1.0);
+ RS::get_singleton()->material_set_param(surf.material, "uv1_offset", Vector3(0, 0, 0));
+ RS::get_singleton()->material_set_param(surf.material, "uv1_scale", Vector3(1, 1, 1));
+ RS::get_singleton()->material_set_param(surf.material, "uv2_offset", Vector3(0, 0, 0));
+ RS::get_singleton()->material_set_param(surf.material, "uv2_scale", Vector3(1, 1, 1));
+ RS::get_singleton()->material_set_param(surf.material, "alpha_scissor_threshold", alpha_scissor_threshold);
+ if (msdf) {
+ RS::get_singleton()->material_set_param(surf.material, "msdf_pixel_range", TS->font_get_msdf_pixel_range(p_glyph.font_rid));
+ RS::get_singleton()->material_set_param(surf.material, "msdf_outline_size", p_outline_size);
+ }
+
+ RID shader_rid;
+ StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), true, get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, msdf, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), texture_filter, &shader_rid);
+
+ RS::get_singleton()->material_set_shader(surf.material, shader_rid);
+ RS::get_singleton()->material_set_param(surf.material, "texture_albedo", tex);
+ if (get_alpha_cut_mode() == ALPHA_CUT_DISABLED) {
+ RS::get_singleton()->material_set_render_priority(surf.material, p_priority);
+ } else {
+ surf.z_shift = p_priority * pixel_size;
+ }
+
+ surfaces[mat_hash] = surf;
+ }
+ SurfaceData &s = surfaces[mat_hash];
+
+ s.mesh_vertices.resize((s.offset + 1) * 4);
+ s.mesh_normals.resize((s.offset + 1) * 4);
+ s.mesh_tangents.resize((s.offset + 1) * 16);
+ s.mesh_colors.resize((s.offset + 1) * 4);
+ s.mesh_uvs.resize((s.offset + 1) * 4);
+
+ s.mesh_vertices.write[(s.offset * 4) + 3] = Vector3(r_offset.x + gl_of.x, r_offset.y - gl_of.y - gl_sz.y, s.z_shift);
+ s.mesh_vertices.write[(s.offset * 4) + 2] = Vector3(r_offset.x + gl_of.x + gl_sz.x, r_offset.y - gl_of.y - gl_sz.y, s.z_shift);
+ s.mesh_vertices.write[(s.offset * 4) + 1] = Vector3(r_offset.x + gl_of.x + gl_sz.x, r_offset.y - gl_of.y, s.z_shift);
+ s.mesh_vertices.write[(s.offset * 4) + 0] = Vector3(r_offset.x + gl_of.x, r_offset.y - gl_of.y, s.z_shift);
+
+ for (int i = 0; i < 4; i++) {
+ s.mesh_normals.write[(s.offset * 4) + i] = Vector3(0.0, 0.0, 1.0);
+ s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 0] = 1.0;
+ s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 1] = 0.0;
+ s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 2] = 0.0;
+ s.mesh_tangents.write[(s.offset * 16) + (i * 4) + 3] = 1.0;
+ s.mesh_colors.write[(s.offset * 4) + i] = p_modulate;
+ s.mesh_uvs.write[(s.offset * 4) + i] = Vector2();
+
+ if (aabb == AABB()) {
+ aabb.position = s.mesh_vertices[(s.offset * 4) + i];
+ } else {
+ aabb.expand_to(s.mesh_vertices[(s.offset * 4) + i]);
+ }
+ }
+
+ if (tex != RID()) {
+ s.mesh_uvs.write[(s.offset * 4) + 3] = Vector2(gl_uv.position.x / texs.x, (gl_uv.position.y + gl_uv.size.y) / texs.y);
+ s.mesh_uvs.write[(s.offset * 4) + 2] = Vector2((gl_uv.position.x + gl_uv.size.x) / texs.x, (gl_uv.position.y + gl_uv.size.y) / texs.y);
+ s.mesh_uvs.write[(s.offset * 4) + 1] = Vector2((gl_uv.position.x + gl_uv.size.x) / texs.x, gl_uv.position.y / texs.y);
+ s.mesh_uvs.write[(s.offset * 4) + 0] = Vector2(gl_uv.position.x / texs.x, gl_uv.position.y / texs.y);
+ }
+
+ s.indices.resize((s.offset + 1) * 6);
+ s.indices.write[(s.offset * 6) + 0] = (s.offset * 4) + 0;
+ s.indices.write[(s.offset * 6) + 1] = (s.offset * 4) + 1;
+ s.indices.write[(s.offset * 6) + 2] = (s.offset * 4) + 2;
+ s.indices.write[(s.offset * 6) + 3] = (s.offset * 4) + 0;
+ s.indices.write[(s.offset * 6) + 4] = (s.offset * 4) + 2;
+ s.indices.write[(s.offset * 6) + 5] = (s.offset * 4) + 3;
+
+ s.offset++;
+ r_offset.x += p_glyph.advance * pixel_size;
+ }
+}
+
+void Label3D::_shape() {
+ // Clear mesh.
+ RS::get_singleton()->mesh_clear(mesh);
+ aabb = AABB();
+
+ // Clear materials.
+ for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) {
+ RenderingServer::get_singleton()->free(E->get().material);
+ }
+ surfaces.clear();
+
+ Ref<Font> font = _get_font_or_default();
+ ERR_FAIL_COND(font.is_null());
+
+ // Update text buffer.
+ if (dirty_text) {
+ TS->shaped_text_clear(text_rid);
+ TS->shaped_text_set_direction(text_rid, text_direction);
+
+ String text = (uppercase) ? TS->string_to_upper(xl_text, language) : xl_text;
+ TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, language);
+
+ Array stt;
+ if (st_parser == TextServer::STRUCTURED_TEXT_CUSTOM) {
+ GDVIRTUAL_CALL(_structured_text_parser, st_args, text, stt);
+ } else {
+ stt = TS->parse_structured_text(st_parser, st_args, text);
+ }
+ TS->shaped_text_set_bidi_override(text_rid, stt);
+
+ dirty_text = false;
+ dirty_font = false;
+ dirty_lines = true;
+ } else if (dirty_font) {
+ int spans = TS->shaped_get_span_count(text_rid);
+ for (int i = 0; i < spans; i++) {
+ TS->shaped_set_span_update_font(text_rid, i, font->get_rids(), font_size, opentype_features);
+ }
+
+ dirty_font = false;
+ dirty_lines = true;
+ }
+
+ if (dirty_lines) {
+ for (int i = 0; i < lines_rid.size(); i++) {
+ TS->free_rid(lines_rid[i]);
+ }
+ lines_rid.clear();
+
+ uint16_t autowrap_flags = TextServer::BREAK_MANDATORY;
+ switch (autowrap_mode) {
+ case AUTOWRAP_WORD_SMART:
+ autowrap_flags = TextServer::BREAK_WORD_BOUND_ADAPTIVE | TextServer::BREAK_MANDATORY;
+ break;
+ case AUTOWRAP_WORD:
+ autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY;
+ break;
+ case AUTOWRAP_ARBITRARY:
+ autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY;
+ break;
+ case AUTOWRAP_OFF:
+ break;
+ }
+ PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags);
+
+ float max_line_w = 0.0;
+ for (int i = 0; i < line_breaks.size(); i = i + 2) {
+ RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]);
+ max_line_w = MAX(max_line_w, TS->shaped_text_get_width(line));
+ lines_rid.push_back(line);
+ }
+
+ if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ for (int i = 0; i < lines_rid.size() - 1; i++) {
+ TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
+ }
+ }
+ dirty_lines = false;
+ }
+
+ // Generate surfaces and materials.
+ float total_h = 0.0;
+ for (int i = 0; i < lines_rid.size(); i++) {
+ total_h += (TS->shaped_text_get_size(lines_rid[i]).y + font->get_spacing(TextServer::SPACING_TOP) + font->get_spacing(TextServer::SPACING_BOTTOM) + line_spacing) * pixel_size;
+ }
+
+ float vbegin = 0.0;
+ switch (vertical_alignment) {
+ case VERTICAL_ALIGNMENT_FILL:
+ case VERTICAL_ALIGNMENT_TOP: {
+ // Nothing.
+ } break;
+ case VERTICAL_ALIGNMENT_CENTER: {
+ vbegin = (total_h - line_spacing * pixel_size) / 2.0;
+ } break;
+ case VERTICAL_ALIGNMENT_BOTTOM: {
+ vbegin = (total_h - line_spacing * pixel_size);
+ } break;
+ }
+
+ Vector2 offset = Vector2(0, vbegin);
+ for (int i = 0; i < lines_rid.size(); i++) {
+ const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]);
+ int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]);
+ float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size;
+
+ switch (horizontal_alignment) {
+ case HORIZONTAL_ALIGNMENT_LEFT:
+ offset.x = 0.0;
+ break;
+ case HORIZONTAL_ALIGNMENT_FILL:
+ case HORIZONTAL_ALIGNMENT_CENTER: {
+ offset.x = -line_width / 2.0;
+ } break;
+ case HORIZONTAL_ALIGNMENT_RIGHT: {
+ offset.x = -line_width;
+ } break;
+ }
+ offset.y -= (TS->shaped_text_get_ascent(lines_rid[i]) + font->get_spacing(TextServer::SPACING_TOP)) * pixel_size;
+
+ if (outline_modulate.a != 0.0 && outline_size > 0) {
+ // Outline surfaces.
+ Vector2 ol_offset = offset;
+ for (int j = 0; j < gl_size; j++) {
+ _generate_glyph_surfaces(glyphs[j], ol_offset, outline_modulate, -1, outline_size);
+ }
+ }
+
+ // Main text surfaces.
+ for (int j = 0; j < gl_size; j++) {
+ _generate_glyph_surfaces(glyphs[j], offset, modulate, 0);
+ }
+ offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM)) * pixel_size;
+ }
+
+ for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) {
+ Array mesh_array;
+ mesh_array.resize(RS::ARRAY_MAX);
+ mesh_array[RS::ARRAY_VERTEX] = E->get().mesh_vertices;
+ mesh_array[RS::ARRAY_NORMAL] = E->get().mesh_normals;
+ mesh_array[RS::ARRAY_TANGENT] = E->get().mesh_tangents;
+ mesh_array[RS::ARRAY_COLOR] = E->get().mesh_colors;
+ mesh_array[RS::ARRAY_TEX_UV] = E->get().mesh_uvs;
+ mesh_array[RS::ARRAY_INDEX] = E->get().indices;
+
+ RS::SurfaceData sd;
+ RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, mesh_array);
+
+ sd.material = E->get().material;
+
+ RS::get_singleton()->mesh_add_surface(mesh, sd);
+ }
+}
+
+void Label3D::set_text(const String &p_string) {
+ text = p_string;
+ xl_text = tr(p_string);
+ dirty_text = true;
+ _queue_update();
+}
+
+String Label3D::get_text() const {
+ return text;
+}
+
+void Label3D::set_horizontal_alignment(HorizontalAlignment p_alignment) {
+ ERR_FAIL_INDEX((int)p_alignment, 4);
+ if (horizontal_alignment != p_alignment) {
+ if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
+ dirty_lines = true; // Reshape lines.
+ }
+ horizontal_alignment = p_alignment;
+ _queue_update();
+ }
+}
+
+HorizontalAlignment Label3D::get_horizontal_alignment() const {
+ return horizontal_alignment;
+}
+
+void Label3D::set_vertical_alignment(VerticalAlignment p_alignment) {
+ ERR_FAIL_INDEX((int)p_alignment, 4);
+ if (vertical_alignment != p_alignment) {
+ vertical_alignment = p_alignment;
+ _queue_update();
+ }
+}
+
+VerticalAlignment Label3D::get_vertical_alignment() const {
+ return vertical_alignment;
+}
+
+void Label3D::set_text_direction(TextServer::Direction p_text_direction) {
+ ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
+ if (text_direction != p_text_direction) {
+ text_direction = p_text_direction;
+ dirty_text = true;
+ _queue_update();
+ }
+}
+
+TextServer::Direction Label3D::get_text_direction() const {
+ return text_direction;
+}
+
+void Label3D::clear_opentype_features() {
+ opentype_features.clear();
+ dirty_font = true;
+ _queue_update();
+}
+
+void Label3D::set_opentype_feature(const String &p_name, int p_value) {
+ int32_t tag = TS->name_to_tag(p_name);
+ if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
+ opentype_features[tag] = p_value;
+ dirty_font = true;
+ _queue_update();
+ }
+}
+
+int Label3D::get_opentype_feature(const String &p_name) const {
+ int32_t tag = TS->name_to_tag(p_name);
+ if (!opentype_features.has(tag)) {
+ return -1;
+ }
+ return opentype_features[tag];
+}
+
+void Label3D::set_language(const String &p_language) {
+ if (language != p_language) {
+ language = p_language;
+ dirty_text = true;
+ _queue_update();
+ }
+}
+
+String Label3D::get_language() const {
+ return language;
+}
+
+void Label3D::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
+ if (st_parser != p_parser) {
+ st_parser = p_parser;
+ dirty_text = true;
+ _queue_update();
+ }
+}
+
+TextServer::StructuredTextParser Label3D::get_structured_text_bidi_override() const {
+ return st_parser;
+}
+
+void Label3D::set_structured_text_bidi_override_options(Array p_args) {
+ if (st_args != p_args) {
+ st_args = p_args;
+ dirty_text = true;
+ _queue_update();
+ }
+}
+
+Array Label3D::get_structured_text_bidi_override_options() const {
+ return st_args;
+}
+
+void Label3D::set_uppercase(bool p_uppercase) {
+ if (uppercase != p_uppercase) {
+ uppercase = p_uppercase;
+ dirty_text = true;
+ _queue_update();
+ }
+}
+
+bool Label3D::is_uppercase() const {
+ return uppercase;
+}
+
+void Label3D::_font_changed() {
+ dirty_font = true;
+ _queue_update();
+}
+
+void Label3D::set_font(const Ref<Font> &p_font) {
+ if (font_override != p_font) {
+ if (font_override.is_valid()) {
+ font_override->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed"));
+ }
+ font_override = p_font;
+ dirty_font = true;
+ if (font_override.is_valid()) {
+ font_override->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_font_changed"));
+ }
+ _queue_update();
+ }
+}
+
+Ref<Font> Label3D::get_font() const {
+ return font_override;
+}
+
+Ref<Font> Label3D::_get_font_or_default() const {
+ if (font_override.is_valid() && font_override->get_data_count() > 0) {
+ return font_override;
+ }
+
+ // Check the project-defined Theme resource.
+ if (Theme::get_project_default().is_valid()) {
+ List<StringName> theme_types;
+ Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
+
+ for (const StringName &E : theme_types) {
+ if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
+ return Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
+ }
+ }
+ }
+
+ // Lastly, fall back on the items defined in the default Theme, if they exist.
+ {
+ List<StringName> theme_types;
+ Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
+
+ for (const StringName &E : theme_types) {
+ if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
+ return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
+ }
+ }
+ }
+
+ // If they don't exist, use any type to return the default/empty value.
+ return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
+}
+
+void Label3D::set_font_size(int p_size) {
+ if (font_size != p_size) {
+ font_size = p_size;
+ dirty_font = true;
+ _queue_update();
+ }
+}
+
+int Label3D::get_font_size() const {
+ return font_size;
+}
+
+void Label3D::set_outline_size(int p_size) {
+ if (outline_size != p_size) {
+ outline_size = p_size;
+ _queue_update();
+ }
+}
+
+int Label3D::get_outline_size() const {
+ return outline_size;
+}
+
+void Label3D::set_modulate(const Color &p_color) {
+ if (modulate != p_color) {
+ modulate = p_color;
+ _queue_update();
+ }
+}
+
+Color Label3D::get_modulate() const {
+ return modulate;
+}
+
+void Label3D::set_outline_modulate(const Color &p_color) {
+ if (outline_modulate != p_color) {
+ outline_modulate = p_color;
+ _queue_update();
+ }
+}
+
+Color Label3D::get_outline_modulate() const {
+ return outline_modulate;
+}
+
+void Label3D::set_autowrap_mode(Label3D::AutowrapMode p_mode) {
+ if (autowrap_mode != p_mode) {
+ autowrap_mode = p_mode;
+ dirty_lines = true;
+ _queue_update();
+ }
+}
+
+Label3D::AutowrapMode Label3D::get_autowrap_mode() const {
+ return autowrap_mode;
+}
+
+void Label3D::set_width(float p_width) {
+ if (width != p_width) {
+ width = p_width;
+ dirty_lines = true;
+ _queue_update();
+ }
+}
+
+float Label3D::get_width() const {
+ return width;
+}
+
+void Label3D::set_pixel_size(real_t p_amount) {
+ if (pixel_size != p_amount) {
+ pixel_size = p_amount;
+ _queue_update();
+ }
+}
+
+real_t Label3D::get_pixel_size() const {
+ return pixel_size;
+}
+
+void Label3D::set_line_spacing(float p_line_spacing) {
+ if (line_spacing != p_line_spacing) {
+ line_spacing = p_line_spacing;
+ _queue_update();
+ }
+}
+
+float Label3D::get_line_spacing() const {
+ return line_spacing;
+}
+
+void Label3D::set_draw_flag(DrawFlags p_flag, bool p_enable) {
+ ERR_FAIL_INDEX(p_flag, FLAG_MAX);
+ if (flags[p_flag] != p_enable) {
+ flags[p_flag] = p_enable;
+ _queue_update();
+ }
+}
+
+bool Label3D::get_draw_flag(DrawFlags p_flag) const {
+ ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
+ return flags[p_flag];
+}
+
+void Label3D::set_billboard_mode(StandardMaterial3D::BillboardMode p_mode) {
+ ERR_FAIL_INDEX(p_mode, 3);
+ if (billboard_mode != p_mode) {
+ billboard_mode = p_mode;
+ _queue_update();
+ }
+}
+
+StandardMaterial3D::BillboardMode Label3D::get_billboard_mode() const {
+ return billboard_mode;
+}
+
+void Label3D::set_alpha_cut_mode(AlphaCutMode p_mode) {
+ ERR_FAIL_INDEX(p_mode, 3);
+ if (alpha_cut != p_mode) {
+ alpha_cut = p_mode;
+ _queue_update();
+ }
+}
+
+void Label3D::set_texture_filter(StandardMaterial3D::TextureFilter p_filter) {
+ if (texture_filter != p_filter) {
+ texture_filter = p_filter;
+ _queue_update();
+ }
+}
+
+StandardMaterial3D::TextureFilter Label3D::get_texture_filter() const {
+ return texture_filter;
+}
+
+Label3D::AlphaCutMode Label3D::get_alpha_cut_mode() const {
+ return alpha_cut;
+}
+
+void Label3D::set_alpha_scissor_threshold(float p_threshold) {
+ if (alpha_scissor_threshold != p_threshold) {
+ alpha_scissor_threshold = p_threshold;
+ _queue_update();
+ }
+}
+
+float Label3D::get_alpha_scissor_threshold() const {
+ return alpha_scissor_threshold;
+}
+
+Label3D::Label3D() {
+ for (int i = 0; i < FLAG_MAX; i++) {
+ flags[i] = (i == FLAG_DOUBLE_SIDED);
+ }
+
+ text_rid = TS->create_shaped_text();
+
+ mesh = RenderingServer::get_singleton()->mesh_create();
+
+ set_cast_shadows_setting(SHADOW_CASTING_SETTING_OFF);
+ set_base(mesh);
+}
+
+Label3D::~Label3D() {
+ for (int i = 0; i < lines_rid.size(); i++) {
+ TS->free_rid(lines_rid[i]);
+ }
+ lines_rid.clear();
+
+ TS->free_rid(text_rid);
+
+ RenderingServer::get_singleton()->free(mesh);
+ for (Map<uint64_t, SurfaceData>::Element *E = surfaces.front(); E; E = E->next()) {
+ RenderingServer::get_singleton()->free(E->get().material);
+ }
+ surfaces.clear();
+}
diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h
new file mode 100644
index 0000000000..cbc5c3c649
--- /dev/null
+++ b/scene/3d/label_3d.h
@@ -0,0 +1,228 @@
+/*************************************************************************/
+/* label_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 LABEL_3D_H
+#define LABEL_3D_H
+
+#include "scene/3d/visual_instance_3d.h"
+#include "scene/resources/font.h"
+
+#include "servers/text_server.h"
+
+class Label3D : public GeometryInstance3D {
+ GDCLASS(Label3D, GeometryInstance3D);
+
+public:
+ enum DrawFlags {
+ FLAG_SHADED,
+ FLAG_DOUBLE_SIDED,
+ FLAG_DISABLE_DEPTH_TEST,
+ FLAG_FIXED_SIZE,
+ FLAG_MAX
+ };
+
+ enum AlphaCutMode {
+ ALPHA_CUT_DISABLED,
+ ALPHA_CUT_DISCARD,
+ ALPHA_CUT_OPAQUE_PREPASS
+ };
+
+ enum AutowrapMode {
+ AUTOWRAP_OFF,
+ AUTOWRAP_ARBITRARY,
+ AUTOWRAP_WORD,
+ AUTOWRAP_WORD_SMART
+ };
+
+private:
+ real_t pixel_size = 0.01;
+ bool flags[FLAG_MAX] = {};
+ AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED;
+ float alpha_scissor_threshold = 0.5;
+
+ AABB aabb;
+
+ mutable Ref<TriangleMesh> triangle_mesh;
+ RID mesh;
+ struct SurfaceData {
+ PackedVector3Array mesh_vertices;
+ PackedVector3Array mesh_normals;
+ PackedFloat32Array mesh_tangents;
+ PackedColorArray mesh_colors;
+ PackedVector2Array mesh_uvs;
+ PackedInt32Array indices;
+ int offset = 0;
+ float z_shift = 0.0;
+ RID material;
+ };
+
+ Map<uint64_t, SurfaceData> surfaces;
+
+ HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER;
+ VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER;
+ String text;
+ String xl_text;
+ bool uppercase = false;
+
+ AutowrapMode autowrap_mode = AUTOWRAP_OFF;
+ float width = 500.0;
+
+ int font_size = 16;
+ Ref<Font> font_override;
+ Color modulate = Color(1, 1, 1, 1);
+
+ int outline_size = 0;
+ Color outline_modulate = Color(0, 0, 0, 1);
+
+ float line_spacing = 0.f;
+
+ Dictionary opentype_features;
+ String language;
+ TextServer::Direction text_direction = TextServer::DIRECTION_AUTO;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
+ Array st_args;
+
+ RID text_rid;
+ Vector<RID> lines_rid;
+
+ RID base_material;
+ StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
+ StandardMaterial3D::TextureFilter texture_filter = StandardMaterial3D::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
+
+ bool pending_update = false;
+
+ bool dirty_lines = true;
+ bool dirty_font = true;
+ bool dirty_text = true;
+
+ void _generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, const Color &p_modulate, int p_priority = 0, int p_outline_size = 0);
+
+protected:
+ GDVIRTUAL2RC(Array, _structured_text_parser, Array, String)
+
+ void _notification(int p_what);
+
+ static void _bind_methods();
+
+ bool _set(const StringName &p_name, const Variant &p_value);
+ bool _get(const StringName &p_name, Variant &r_ret) const;
+ void _get_property_list(List<PropertyInfo> *p_list) const;
+ void _validate_property(PropertyInfo &property) const override;
+
+ void _im_update();
+ void _font_changed();
+ void _queue_update();
+
+ void _shape();
+
+public:
+ void set_horizontal_alignment(HorizontalAlignment p_alignment);
+ HorizontalAlignment get_horizontal_alignment() const;
+
+ void set_vertical_alignment(VerticalAlignment p_alignment);
+ VerticalAlignment get_vertical_alignment() const;
+
+ void set_text(const String &p_string);
+ String get_text() const;
+
+ void set_text_direction(TextServer::Direction p_text_direction);
+ TextServer::Direction get_text_direction() const;
+
+ void set_opentype_feature(const String &p_name, int p_value);
+ int get_opentype_feature(const String &p_name) const;
+ void clear_opentype_features();
+
+ void set_language(const String &p_language);
+ String get_language() const;
+
+ void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
+ TextServer::StructuredTextParser get_structured_text_bidi_override() const;
+
+ void set_structured_text_bidi_override_options(Array p_args);
+ Array get_structured_text_bidi_override_options() const;
+
+ void set_uppercase(bool p_uppercase);
+ bool is_uppercase() const;
+
+ void set_font(const Ref<Font> &p_font);
+ Ref<Font> get_font() const;
+ Ref<Font> _get_font_or_default() const;
+
+ void set_font_size(int p_size);
+ int get_font_size() const;
+
+ void set_outline_size(int p_size);
+ int get_outline_size() const;
+
+ void set_line_spacing(float p_size);
+ float get_line_spacing() const;
+
+ void set_modulate(const Color &p_color);
+ Color get_modulate() const;
+
+ void set_outline_modulate(const Color &p_color);
+ Color get_outline_modulate() const;
+
+ void set_autowrap_mode(AutowrapMode p_mode);
+ AutowrapMode get_autowrap_mode() const;
+
+ void set_width(float p_width);
+ float get_width() const;
+
+ void set_pixel_size(real_t p_amount);
+ real_t get_pixel_size() const;
+
+ void set_draw_flag(DrawFlags p_flag, bool p_enable);
+ bool get_draw_flag(DrawFlags p_flag) const;
+
+ void set_alpha_cut_mode(AlphaCutMode p_mode);
+ AlphaCutMode get_alpha_cut_mode() const;
+
+ void set_alpha_scissor_threshold(float p_threshold);
+ float get_alpha_scissor_threshold() const;
+
+ void set_billboard_mode(StandardMaterial3D::BillboardMode p_mode);
+ StandardMaterial3D::BillboardMode get_billboard_mode() const;
+
+ void set_texture_filter(StandardMaterial3D::TextureFilter p_filter);
+ StandardMaterial3D::TextureFilter get_texture_filter() const;
+
+ virtual AABB get_aabb() const override;
+ Ref<TriangleMesh> generate_triangle_mesh() const;
+
+ Label3D();
+ ~Label3D();
+};
+
+VARIANT_ENUM_CAST(Label3D::AutowrapMode);
+VARIANT_ENUM_CAST(Label3D::DrawFlags);
+VARIANT_ENUM_CAST(Label3D::AlphaCutMode);
+
+#endif // LABEL_3D_H
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/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index 8d813e8b2b..d541dd5f37 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -268,6 +268,17 @@ StandardMaterial3D::BillboardMode SpriteBase3D::get_billboard_mode() const {
return billboard_mode;
}
+void SpriteBase3D::set_texture_filter(StandardMaterial3D::TextureFilter p_filter) {
+ if (texture_filter != p_filter) {
+ texture_filter = p_filter;
+ _queue_update();
+ }
+}
+
+StandardMaterial3D::TextureFilter SpriteBase3D::get_texture_filter() const {
+ return texture_filter;
+}
+
void SpriteBase3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_centered", "centered"), &SpriteBase3D::set_centered);
ClassDB::bind_method(D_METHOD("is_centered"), &SpriteBase3D::is_centered);
@@ -299,6 +310,9 @@ void SpriteBase3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpriteBase3D::set_billboard_mode);
ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpriteBase3D::get_billboard_mode);
+ ClassDB::bind_method(D_METHOD("set_texture_filter", "mode"), &SpriteBase3D::set_texture_filter);
+ ClassDB::bind_method(D_METHOD("get_texture_filter"), &SpriteBase3D::get_texture_filter);
+
ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect);
ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh);
@@ -317,11 +331,16 @@ void SpriteBase3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_draw_flag", "get_draw_flag", FLAG_TRANSPARENT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Nearest Mipmap,Linear Mipmap,Nearest Mipmap Anisotropic,Linear Mipmap Anisotropic"), "set_texture_filter", "get_texture_filter");
BIND_ENUM_CONSTANT(FLAG_TRANSPARENT);
BIND_ENUM_CONSTANT(FLAG_SHADED);
BIND_ENUM_CONSTANT(FLAG_DOUBLE_SIDED);
+ BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST);
+ BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(ALPHA_CUT_DISABLED);
@@ -586,7 +605,7 @@ void Sprite3D::_draw() {
set_aabb(aabb);
RID shader_rid;
- StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid);
+ StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), &shader_rid);
if (last_shader != shader_rid) {
RS::get_singleton()->material_set_shader(get_material(), shader_rid);
last_shader = shader_rid;
@@ -948,7 +967,7 @@ void AnimatedSprite3D::_draw() {
set_aabb(aabb);
RID shader_rid;
- StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid);
+ StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), &shader_rid);
if (last_shader != shader_rid) {
RS::get_singleton()->material_set_shader(get_material(), shader_rid);
last_shader = shader_rid;
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 92dbef0855..047ed5a40d 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -44,6 +44,8 @@ public:
FLAG_TRANSPARENT,
FLAG_SHADED,
FLAG_DOUBLE_SIDED,
+ FLAG_DISABLE_DEPTH_TEST,
+ FLAG_FIXED_SIZE,
FLAG_MAX
};
@@ -80,6 +82,7 @@ private:
bool flags[FLAG_MAX] = {};
AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED;
StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED;
+ StandardMaterial3D::TextureFilter texture_filter = StandardMaterial3D::TEXTURE_FILTER_LINEAR_WITH_MIPMAPS;
bool pending_update = false;
void _im_update();
@@ -131,9 +134,13 @@ public:
void set_alpha_cut_mode(AlphaCutMode p_mode);
AlphaCutMode get_alpha_cut_mode() const;
+
void set_billboard_mode(StandardMaterial3D::BillboardMode p_mode);
StandardMaterial3D::BillboardMode get_billboard_mode() const;
+ void set_texture_filter(StandardMaterial3D::TextureFilter p_filter);
+ StandardMaterial3D::TextureFilter get_texture_filter() const;
+
virtual Rect2 get_item_rect() const = 0;
virtual AABB get_aabb() const override;
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..f5236adbad 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, 1);
+ 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, 1);
+ 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, 1);
+ 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/control.cpp b/scene/gui/control.cpp
index 96d2b29fc1..35d1cf1f3e 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2946,90 +2946,17 @@ bool Control::is_text_field() const {
return false;
}
-Array Control::structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String &p_text) const {
- Array ret;
- switch (p_theme_type) {
- case STRUCTURED_TEXT_URI: {
- int prev = 0;
- for (int i = 0; i < p_text.length(); i++) {
- if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) {
- if (prev != i) {
- ret.push_back(Vector2i(prev, i));
- }
- ret.push_back(Vector2i(i, i + 1));
- prev = i + 1;
- }
- }
- if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
- }
- } break;
- case STRUCTURED_TEXT_FILE: {
- int prev = 0;
- for (int i = 0; i < p_text.length(); i++) {
- if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) {
- if (prev != i) {
- ret.push_back(Vector2i(prev, i));
- }
- ret.push_back(Vector2i(i, i + 1));
- prev = i + 1;
- }
- }
- if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
- }
- } break;
- case STRUCTURED_TEXT_EMAIL: {
- bool local = true;
- int prev = 0;
- for (int i = 0; i < p_text.length(); i++) {
- if ((p_text[i] == '@') && local) { // Add full "local" as single context.
- local = false;
- ret.push_back(Vector2i(prev, i));
- ret.push_back(Vector2i(i, i + 1));
- prev = i + 1;
- } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
- if (prev != i) {
- ret.push_back(Vector2i(prev, i));
- }
- ret.push_back(Vector2i(i, i + 1));
- prev = i + 1;
- }
- }
- if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
- }
- } break;
- case STRUCTURED_TEXT_LIST: {
- if (p_args.size() == 1 && p_args[0].get_type() == Variant::STRING) {
- Vector<String> tags = p_text.split(String(p_args[0]));
- int prev = 0;
- for (int i = 0; i < tags.size(); i++) {
- if (prev != i) {
- ret.push_back(Vector2i(prev, prev + tags[i].length()));
- }
- ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1));
- prev = prev + tags[i].length() + 1;
- }
- }
- } break;
- case STRUCTURED_TEXT_CUSTOM: {
- Array r;
- if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, r)) {
- for (int i = 0; i < r.size(); i++) {
- if (r[i].get_type() == Variant::VECTOR2I) {
- ret.push_back(Vector2i(r[i]));
- }
- }
- }
- } break;
- case STRUCTURED_TEXT_NONE:
- case STRUCTURED_TEXT_DEFAULT:
- default: {
- ret.push_back(Vector2i(0, p_text.length()));
+Array Control::structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ if (p_parser_type == TextServer::STRUCTURED_TEXT_CUSTOM) {
+ Array ret;
+ if (GDVIRTUAL_CALL(_structured_text_parser, p_args, p_text, ret)) {
+ return ret;
+ } else {
+ return Array();
}
+ } else {
+ return TS->parse_structured_text(p_parser_type, p_args, p_text);
}
- return ret;
}
void Control::set_rotation(real_t p_radians) {
@@ -3491,14 +3418,6 @@ void Control::_bind_methods() {
BIND_ENUM_CONSTANT(TEXT_DIRECTION_LTR);
BIND_ENUM_CONSTANT(TEXT_DIRECTION_RTL);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_URI);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
-
ADD_SIGNAL(MethodInfo("resized"));
ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
ADD_SIGNAL(MethodInfo("mouse_entered"));
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 4240d52b65..65b71d74f8 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -147,16 +147,6 @@ public:
TEXT_DIRECTION_INHERITED,
};
- enum StructuredTextParser {
- STRUCTURED_TEXT_DEFAULT,
- STRUCTURED_TEXT_URI,
- STRUCTURED_TEXT_FILE,
- STRUCTURED_TEXT_EMAIL,
- STRUCTURED_TEXT_LIST,
- STRUCTURED_TEXT_NONE,
- STRUCTURED_TEXT_CUSTOM
- };
-
private:
struct CComparator {
bool operator()(const Control *p_a, const Control *p_b) const {
@@ -290,7 +280,7 @@ protected:
//virtual void _window_gui_input(InputEvent p_event);
- virtual Array structured_text_parser(StructuredTextParser p_theme_type, const Array &p_args, const String &p_text) const;
+ virtual Array structured_text_parser(TextServer::StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -579,6 +569,5 @@ VARIANT_ENUM_CAST(Control::Anchor);
VARIANT_ENUM_CAST(Control::LayoutMode);
VARIANT_ENUM_CAST(Control::LayoutDirection);
VARIANT_ENUM_CAST(Control::TextDirection);
-VARIANT_ENUM_CAST(Control::StructuredTextParser);
#endif
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 5e74658470..6da5340ca4 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);
@@ -989,7 +988,7 @@ FileDialog::FileDialog() {
hbc->add_child(drives);
dir = memnew(LineEdit);
- dir->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
hbc->add_child(dir);
dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -1030,7 +1029,7 @@ FileDialog::FileDialog() {
file_box = memnew(HBoxContainer);
file_box->add_child(memnew(Label(TTRC("File:"))));
file = memnew(LineEdit);
- file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ file->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
file->set_h_size_flags(Control::SIZE_EXPAND_FILL);
file_box->add_child(file);
@@ -1064,7 +1063,7 @@ FileDialog::FileDialog() {
makedialog->add_child(makevb);
makedirname = memnew(LineEdit);
- makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
+ makedirname->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
makevb->add_margin_child(TTRC("Name:"), makedirname);
add_child(makedialog, false, INTERNAL_MODE_FRONT);
makedialog->register_text_enter(makedirname);
@@ -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/label.cpp b/scene/gui/label.cpp
index cd6fc168c2..eda3d40f63 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -648,21 +648,21 @@ void Label::set_text_direction(Control::TextDirection p_text_direction) {
}
}
-void Label::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) {
+void Label::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
if (st_parser != p_parser) {
st_parser = p_parser;
- font_dirty = true;
+ dirty = true;
update();
}
}
-Control::StructuredTextParser Label::get_structured_text_bidi_override() const {
+TextServer::StructuredTextParser Label::get_structured_text_bidi_override() const {
return st_parser;
}
void Label::set_structured_text_bidi_override_options(Array p_args) {
st_args = p_args;
- font_dirty = true;
+ dirty = true;
update();
}
diff --git a/scene/gui/label.h b/scene/gui/label.h
index 0b931b3084..f7b725928f 100644
--- a/scene/gui/label.h
+++ b/scene/gui/label.h
@@ -80,7 +80,7 @@ private:
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
- Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
float percent_visible = 1.0;
@@ -124,8 +124,8 @@ public:
void set_language(const String &p_language);
String get_language() const;
- void set_structured_text_bidi_override(Control::StructuredTextParser p_parser);
- Control::StructuredTextParser get_structured_text_bidi_override() const;
+ void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
+ TextServer::StructuredTextParser get_structured_text_bidi_override() const;
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index b3f051bb75..e5b58a7cc8 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -1452,7 +1452,7 @@ bool LineEdit::get_draw_control_chars() const {
return draw_control_chars;
}
-void LineEdit::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) {
+void LineEdit::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
if (st_parser != p_parser) {
st_parser = p_parser;
_shape();
@@ -1460,7 +1460,7 @@ void LineEdit::set_structured_text_bidi_override(Control::StructuredTextParser p
}
}
-Control::StructuredTextParser LineEdit::get_structured_text_bidi_override() const {
+TextServer::StructuredTextParser LineEdit::get_structured_text_bidi_override() const {
return st_parser;
}
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index b86ccd6421..50aa2f4460 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -106,7 +106,7 @@ private:
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
TextDirection input_direction = TEXT_DIRECTION_LTR;
- Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
bool draw_control_chars = false;
@@ -253,8 +253,8 @@ public:
void set_draw_control_chars(bool p_draw_control_chars);
bool get_draw_control_chars() const;
- void set_structured_text_bidi_override(Control::StructuredTextParser p_parser);
- Control::StructuredTextParser get_structured_text_bidi_override() const;
+ void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
+ TextServer::StructuredTextParser get_structured_text_bidi_override() const;
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index dc4f09d22d..dca6437519 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -61,7 +61,7 @@ String LinkButton::get_text() const {
return text;
}
-void LinkButton::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) {
+void LinkButton::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
if (st_parser != p_parser) {
st_parser = p_parser;
_shape();
@@ -69,7 +69,7 @@ void LinkButton::set_structured_text_bidi_override(Control::StructuredTextParser
}
}
-Control::StructuredTextParser LinkButton::get_structured_text_bidi_override() const {
+TextServer::StructuredTextParser LinkButton::get_structured_text_bidi_override() const {
return st_parser;
}
diff --git a/scene/gui/link_button.h b/scene/gui/link_button.h
index f996558f32..6d2dcbde84 100644
--- a/scene/gui/link_button.h
+++ b/scene/gui/link_button.h
@@ -53,7 +53,7 @@ private:
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
- Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
void _shape();
@@ -71,8 +71,8 @@ public:
void set_text(const String &p_text);
String get_text() const;
- void set_structured_text_bidi_override(Control::StructuredTextParser p_parser);
- Control::StructuredTextParser get_structured_text_bidi_override() const;
+ void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
+ TextServer::StructuredTextParser get_structured_text_bidi_override() const;
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
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..77055d250b 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;
}
@@ -2224,7 +2248,7 @@ TextServer::Direction RichTextLabel::_find_direction(Item *p_item) {
}
}
-Control::StructuredTextParser RichTextLabel::_find_stt(Item *p_item) {
+TextServer::StructuredTextParser RichTextLabel::_find_stt(Item *p_item) {
Item *item = p_item;
while (item) {
@@ -2814,7 +2838,7 @@ void RichTextLabel::push_strikethrough() {
_add_item(item, true);
}
-void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, Control::StructuredTextParser p_st_parser) {
+void RichTextLabel::push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction, const String &p_language, TextServer::StructuredTextParser p_st_parser) {
ERR_FAIL_COND(current->type == ITEM_TABLE);
ItemParagraph *item = memnew(ItemParagraph);
@@ -3439,7 +3463,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;
Control::TextDirection dir = Control::TEXT_DIRECTION_INHERITED;
String lang;
- Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
for (int i = 0; i < subtag.size(); i++) {
Vector<String> subtag_a = subtag[i].split("=");
if (subtag_a.size() == 2) {
@@ -3465,19 +3489,19 @@ void RichTextLabel::append_text(const String &p_bbcode) {
lang = subtag_a[1];
} else if (subtag_a[0] == "st" || subtag_a[0] == "bidi_override") {
if (subtag_a[1] == "d" || subtag_a[1] == "default") {
- st_parser = STRUCTURED_TEXT_DEFAULT;
+ st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
} else if (subtag_a[1] == "u" || subtag_a[1] == "uri") {
- st_parser = STRUCTURED_TEXT_URI;
+ st_parser = TextServer::STRUCTURED_TEXT_URI;
} else if (subtag_a[1] == "f" || subtag_a[1] == "file") {
- st_parser = STRUCTURED_TEXT_FILE;
+ st_parser = TextServer::STRUCTURED_TEXT_FILE;
} else if (subtag_a[1] == "e" || subtag_a[1] == "email") {
- st_parser = STRUCTURED_TEXT_EMAIL;
+ st_parser = TextServer::STRUCTURED_TEXT_EMAIL;
} else if (subtag_a[1] == "l" || subtag_a[1] == "list") {
- st_parser = STRUCTURED_TEXT_LIST;
+ st_parser = TextServer::STRUCTURED_TEXT_LIST;
} else if (subtag_a[1] == "n" || subtag_a[1] == "none") {
- st_parser = STRUCTURED_TEXT_NONE;
+ st_parser = TextServer::STRUCTURED_TEXT_NONE;
} else if (subtag_a[1] == "c" || subtag_a[1] == "custom") {
- st_parser = STRUCTURED_TEXT_CUSTOM;
+ st_parser = TextServer::STRUCTURED_TEXT_CUSTOM;
}
}
}
@@ -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;
}
@@ -4279,7 +4376,7 @@ void RichTextLabel::set_text_direction(Control::TextDirection p_text_direction)
}
}
-void RichTextLabel::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) {
+void RichTextLabel::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
if (st_parser != p_parser) {
st_parser = p_parser;
main->first_invalid_line = 0; //invalidate ALL
@@ -4288,7 +4385,7 @@ void RichTextLabel::set_structured_text_bidi_override(Control::StructuredTextPar
}
}
-Control::StructuredTextParser RichTextLabel::get_structured_text_bidi_override() const {
+TextServer::StructuredTextParser RichTextLabel::get_structured_text_bidi_override() const {
return st_parser;
}
@@ -4423,7 +4520,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_color", "color"), &RichTextLabel::push_color);
ClassDB::bind_method(D_METHOD("push_outline_size", "outline_size"), &RichTextLabel::push_outline_size);
ClassDB::bind_method(D_METHOD("push_outline_color", "color"), &RichTextLabel::push_outline_color);
- ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(STRUCTURED_TEXT_DEFAULT));
+ ClassDB::bind_method(D_METHOD("push_paragraph", "alignment", "base_direction", "language", "st_parser"), &RichTextLabel::push_paragraph, DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(""), DEFVAL(TextServer::STRUCTURED_TEXT_DEFAULT));
ClassDB::bind_method(D_METHOD("push_indent", "level"), &RichTextLabel::push_indent);
ClassDB::bind_method(D_METHOD("push_list", "level", "type", "capitalize"), &RichTextLabel::push_list);
ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta);
@@ -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..c6d0d0875d 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();
@@ -228,7 +234,7 @@ private:
HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT;
String language;
Control::TextDirection direction = Control::TEXT_DIRECTION_AUTO;
- Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
ItemParagraph() { type = ITEM_PARAGRAPH; }
};
@@ -393,7 +399,7 @@ private:
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
- Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
struct Selection {
@@ -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;
@@ -452,7 +467,7 @@ private:
int _find_margin(Item *p_item, const Ref<Font> &p_base_font, int p_base_font_size);
HorizontalAlignment _find_alignment(Item *p_item);
TextServer::Direction _find_direction(Item *p_item);
- Control::StructuredTextParser _find_stt(Item *p_item);
+ TextServer::StructuredTextParser _find_stt(Item *p_item);
String _find_language(Item *p_item);
Color _find_color(Item *p_item, const Color &p_default_color);
Color _find_outline_color(Item *p_item, const Color &p_default_color);
@@ -510,7 +525,7 @@ public:
void push_outline_color(const Color &p_color);
void push_underline();
void push_strikethrough();
- void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", Control::StructuredTextParser p_st_parser = STRUCTURED_TEXT_DEFAULT);
+ void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "", TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT);
void push_indent(int p_level);
void push_list(int p_level, ListType p_list, bool p_capitalize);
void push_meta(const Variant &p_meta);
@@ -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);
@@ -607,8 +633,8 @@ public:
void set_autowrap_mode(AutowrapMode p_mode);
AutowrapMode get_autowrap_mode() const;
- void set_structured_text_bidi_override(Control::StructuredTextParser p_parser);
- Control::StructuredTextParser get_structured_text_bidi_override() const;
+ void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
+ TextServer::StructuredTextParser get_structured_text_bidi_override() const;
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 86969e3ef4..1eacb1d1b7 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.
@@ -2858,7 +2859,7 @@ String TextEdit::get_language() const {
return language;
}
-void TextEdit::set_structured_text_bidi_override(Control::StructuredTextParser p_parser) {
+void TextEdit::set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser) {
if (st_parser != p_parser) {
st_parser = p_parser;
for (int i = 0; i < text.size(); i++) {
@@ -2868,7 +2869,7 @@ void TextEdit::set_structured_text_bidi_override(Control::StructuredTextParser p
}
}
-Control::StructuredTextParser TextEdit::get_structured_text_bidi_override() const {
+TextServer::StructuredTextParser TextEdit::get_structured_text_bidi_override() const {
return st_parser;
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index b365e9c61c..a0ae9631f9 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -271,7 +271,7 @@ private:
Dictionary opentype_features;
String language = "";
- Control::StructuredTextParser st_parser = STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
void _clear();
@@ -651,8 +651,8 @@ public:
void set_language(const String &p_language);
String get_language() const;
- void set_structured_text_bidi_override(Control::StructuredTextParser p_parser);
- Control::StructuredTextParser get_structured_text_bidi_override() const;
+ void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
+ TextServer::StructuredTextParser get_structured_text_bidi_override() const;
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index ccd24ed2cf..934992c68e 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;
}
@@ -333,7 +334,7 @@ int TreeItem::get_opentype_feature(int p_column, const String &p_name) const {
return cells[p_column].opentype_features[tag];
}
-void TreeItem::set_structured_text_bidi_override(int p_column, Control::StructuredTextParser p_parser) {
+void TreeItem::set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser) {
ERR_FAIL_INDEX(p_column, cells.size());
if (cells[p_column].st_parser != p_parser) {
@@ -345,8 +346,8 @@ void TreeItem::set_structured_text_bidi_override(int p_column, Control::Structur
}
}
-Control::StructuredTextParser TreeItem::get_structured_text_bidi_override(int p_column) const {
- ERR_FAIL_INDEX_V(p_column, cells.size(), Control::STRUCTURED_TEXT_NONE);
+TextServer::StructuredTextParser TreeItem::get_structured_text_bidi_override(int p_column) const {
+ ERR_FAIL_INDEX_V(p_column, cells.size(), TextServer::STRUCTURED_TEXT_NONE);
return cells[p_column].st_parser;
}
@@ -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..8ee2a3c382 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -65,7 +65,7 @@ private:
Ref<TextLine> text_buf;
Dictionary opentype_features;
String language;
- Control::StructuredTextParser st_parser = Control::STRUCTURED_TEXT_DEFAULT;
+ TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
Array st_args;
Control::TextDirection text_direction = Control::TEXT_DIRECTION_INHERITED;
bool dirty = true;
@@ -220,8 +220,8 @@ public:
int get_opentype_feature(int p_column, const String &p_name) const;
void clear_opentype_features(int p_column);
- void set_structured_text_bidi_override(int p_column, Control::StructuredTextParser p_parser);
- Control::StructuredTextParser get_structured_text_bidi_override(int p_column) const;
+ void set_structured_text_bidi_override(int p_column, TextServer::StructuredTextParser p_parser);
+ TextServer::StructuredTextParser get_structured_text_bidi_override(int p_column) const;
void set_structured_text_bidi_override_options(int p_column, Array p_args);
Array get_structured_text_bidi_override_options(int p_column) const;
@@ -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 f5fe87c808..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,7 +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("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));
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 95fae0fda7..ad64f1ab5e 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -215,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/node.cpp b/scene/main/node.cpp
index 34bb1cde05..1cfe54155a 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -257,6 +257,9 @@ void Node::_propagate_after_exit_tree() {
}
if (!found) {
+ if (data.unique_name_in_owner) {
+ _release_unique_name_in_owner();
+ }
data.owner->data.owned.erase(data.OW);
data.owner = nullptr;
}
@@ -917,12 +920,20 @@ void Node::set_name(const String &p_name) {
String name = p_name.validate_node_name();
ERR_FAIL_COND(name.is_empty());
+
+ if (data.unique_name_in_owner && data.owner) {
+ _release_unique_name_in_owner();
+ }
data.name = name;
if (data.parent) {
data.parent->_validate_child_name(this, true);
}
+ if (data.unique_name_in_owner && data.owner) {
+ _acquire_unique_name_in_owner();
+ }
+
propagate_notification(NOTIFICATION_PATH_RENAMED);
if (is_inside_tree()) {
@@ -1303,6 +1314,24 @@ Node *Node::get_node_or_null(const NodePath &p_path) const {
next = root;
}
+ } else if (name.is_node_unique_name()) {
+ if (current->data.owned_unique_nodes.size()) {
+ // Has unique nodes in ownership
+ Node **unique = current->data.owned_unique_nodes.getptr(name);
+ if (!unique) {
+ return nullptr;
+ }
+ next = *unique;
+ } else if (current->data.owner) {
+ Node **unique = current->data.owner->data.owned_unique_nodes.getptr(name);
+ if (!unique) {
+ return nullptr;
+ }
+ next = *unique;
+ } else {
+ return nullptr;
+ }
+
} else {
next = nullptr;
@@ -1498,8 +1527,54 @@ void Node::_set_owner_nocheck(Node *p_owner) {
data.OW = data.owner->data.owned.back();
}
+void Node::_release_unique_name_in_owner() {
+ ERR_FAIL_NULL(data.owner); // Sanity check.
+ StringName key = StringName(UNIQUE_NODE_PREFIX + data.name.operator String());
+ Node **which = data.owner->data.owned_unique_nodes.getptr(key);
+ if (which == nullptr || *which != this) {
+ return; // Ignore.
+ }
+ data.owner->data.owned_unique_nodes.erase(key);
+}
+
+void Node::_acquire_unique_name_in_owner() {
+ ERR_FAIL_NULL(data.owner); // Sanity check.
+ StringName key = StringName(UNIQUE_NODE_PREFIX + data.name.operator String());
+ Node **which = data.owner->data.owned_unique_nodes.getptr(key);
+ if (which != nullptr && *which != this) {
+ WARN_PRINT(vformat(RTR("Setting node name '%s' to be unique within scene for '%s', but it's already claimed by '%s'. This node is no longer set unique."), get_name(), is_inside_tree() ? get_path() : data.owner->get_path_to(this), is_inside_tree() ? (*which)->get_path() : data.owner->get_path_to(*which)));
+ data.unique_name_in_owner = false;
+ return;
+ }
+ data.owner->data.owned_unique_nodes[key] = this;
+}
+
+void Node::set_unique_name_in_owner(bool p_enabled) {
+ if (data.unique_name_in_owner == p_enabled) {
+ return;
+ }
+
+ if (data.unique_name_in_owner && data.owner != nullptr) {
+ _release_unique_name_in_owner();
+ }
+ data.unique_name_in_owner = p_enabled;
+
+ if (data.unique_name_in_owner && data.owner != nullptr) {
+ _acquire_unique_name_in_owner();
+ }
+
+ update_configuration_warnings();
+}
+
+bool Node::is_unique_name_in_owner() const {
+ return data.unique_name_in_owner;
+}
+
void Node::set_owner(Node *p_owner) {
if (data.owner) {
+ if (data.unique_name_in_owner) {
+ _release_unique_name_in_owner();
+ }
data.owner->data.owned.erase(data.OW);
data.OW = nullptr;
data.owner = nullptr;
@@ -1526,6 +1601,10 @@ void Node::set_owner(Node *p_owner) {
ERR_FAIL_COND(!owner_valid);
_set_owner_nocheck(p_owner);
+
+ if (data.unique_name_in_owner) {
+ _acquire_unique_name_in_owner();
+ }
}
Node *Node::get_owner() const {
@@ -2585,16 +2664,16 @@ void Node::clear_internal_tree_resource_paths() {
}
TypedArray<String> Node::get_configuration_warnings() const {
+ TypedArray<String> ret;
+
Vector<String> warnings;
if (GDVIRTUAL_CALL(_get_configuration_warnings, warnings)) {
- TypedArray<String> ret;
- ret.resize(warnings.size());
for (int i = 0; i < warnings.size(); i++) {
- ret[i] = warnings[i];
+ ret.push_back(warnings[i]);
}
- return ret;
}
- return Array();
+
+ return ret;
}
String Node::get_configuration_warnings_as_string() const {
@@ -2790,6 +2869,11 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path);
ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path);
+ ClassDB::bind_method(D_METHOD("set_unique_name_in_owner", "enable"), &Node::set_unique_name_in_owner);
+ ClassDB::bind_method(D_METHOD("is_unique_name_in_owner"), &Node::is_unique_name_in_owner);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "unique_name_in_owner", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_unique_name_in_owner", "is_unique_name_in_owner");
+
#ifdef TOOLS_ENABLED
ClassDB::bind_method(D_METHOD("_set_property_pinned", "property", "pinned"), &Node::set_property_pinned);
#endif
diff --git a/scene/main/node.h b/scene/main/node.h
index 57b150e29a..0973baf793 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -99,6 +99,9 @@ private:
Node *parent = nullptr;
Node *owner = nullptr;
Vector<Node *> children;
+ HashMap<StringName, Node *> owned_unique_nodes;
+ bool unique_name_in_owner = false;
+
int internal_children_front = 0;
int internal_children_back = 0;
int pos = -1;
@@ -193,6 +196,9 @@ private:
_FORCE_INLINE_ bool _can_process(bool p_paused) const;
_FORCE_INLINE_ bool _is_enabled() const;
+ void _release_unique_name_in_owner();
+ void _acquire_unique_name_in_owner();
+
protected:
void _block() { data.blocked++; }
void _unblock() { data.blocked--; }
@@ -345,6 +351,9 @@ public:
Node *get_owner() const;
void get_owned_by(Node *p_by, List<Node *> *p_owned);
+ void set_unique_name_in_owner(bool p_enabled);
+ bool is_unique_name_in_owner() const;
+
void remove_and_skip();
int get_index(bool p_include_internal = true) const;
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/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp
index 9b85e9db38..7c689bd436 100644
--- a/scene/main/shader_globals_override.cpp
+++ b/scene/main/shader_globals_override.cpp
@@ -155,7 +155,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const
pinfo.type = Variant::VECTOR3;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- pinfo.type = Variant::PLANE;
+ pinfo.type = Variant::QUATERNION;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
pinfo.type = Variant::RECT2;
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 5b56d9b11e..e421cdc1f8 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"
@@ -225,6 +226,7 @@
#include "scene/3d/gpu_particles_collision_3d.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/3d/joint_3d.h"
+#include "scene/3d/label_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/lightmap_gi.h"
#include "scene/3d/lightmap_probe.h"
@@ -479,6 +481,7 @@ void register_scene_types() {
GDREGISTER_ABSTRACT_CLASS(SpriteBase3D);
GDREGISTER_CLASS(Sprite3D);
GDREGISTER_CLASS(AnimatedSprite3D);
+ GDREGISTER_CLASS(Label3D);
GDREGISTER_ABSTRACT_CLASS(Light3D);
GDREGISTER_CLASS(DirectionalLight3D);
GDREGISTER_CLASS(OmniLight3D);
@@ -575,6 +578,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeColorConstant);
GDREGISTER_CLASS(VisualShaderNodeVec2Constant);
GDREGISTER_CLASS(VisualShaderNodeVec3Constant);
+ GDREGISTER_CLASS(VisualShaderNodeVec4Constant);
GDREGISTER_CLASS(VisualShaderNodeTransformConstant);
GDREGISTER_CLASS(VisualShaderNodeFloatOp);
GDREGISTER_CLASS(VisualShaderNodeIntOp);
@@ -619,6 +623,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeColorUniform);
GDREGISTER_CLASS(VisualShaderNodeVec2Uniform);
GDREGISTER_CLASS(VisualShaderNodeVec3Uniform);
+ GDREGISTER_CLASS(VisualShaderNodeVec4Uniform);
GDREGISTER_CLASS(VisualShaderNodeTransformUniform);
GDREGISTER_CLASS(VisualShaderNodeTextureUniform);
GDREGISTER_CLASS(VisualShaderNodeTextureUniformTriplanar);
@@ -834,6 +839,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..d6b2572628 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -54,6 +54,7 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
cache.write[p_cache_index] = TS->create_font();
TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size);
TS->font_set_antialiased(cache[p_cache_index], antialiased);
+ TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps);
TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf);
TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range);
TS->font_set_msdf_size(cache[p_cache_index], msdf_size);
@@ -77,6 +78,9 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontData::set_antialiased);
ClassDB::bind_method(D_METHOD("is_antialiased"), &FontData::is_antialiased);
+ ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontData::set_generate_mipmaps);
+ ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontData::get_generate_mipmaps);
+
ClassDB::bind_method(D_METHOD("set_font_name", "name"), &FontData::set_font_name);
ClassDB::bind_method(D_METHOD("get_font_name"), &FontData::get_font_name);
@@ -212,6 +216,7 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_supported_variation_list"), &FontData::get_supported_variation_list);
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
@@ -442,6 +447,7 @@ void FontData::reset_state() {
cache.clear();
antialiased = true;
+ mipmaps = false;
msdf = false;
force_autohinter = false;
hinting = TextServer::HINTING_LIGHT;
@@ -735,13 +741,14 @@ Error FontData::load_bitmap_font(const String &p_path) {
reset_state();
antialiased = false;
+ mipmaps = false;
msdf = false;
force_autohinter = false;
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;
@@ -1290,6 +1297,21 @@ bool FontData::is_antialiased() const {
return antialiased;
}
+void FontData::set_generate_mipmaps(bool p_generate_mipmaps) {
+ if (mipmaps != p_generate_mipmaps) {
+ mipmaps = p_generate_mipmaps;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_generate_mipmaps(cache[i], mipmaps);
+ }
+ emit_changed();
+ }
+}
+
+bool FontData::get_generate_mipmaps() const {
+ return mipmaps;
+}
+
void FontData::set_multichannel_signed_distance_field(bool p_msdf) {
if (msdf != p_msdf) {
msdf = p_msdf;
diff --git a/scene/resources/font.h b/scene/resources/font.h
index 2aa12dd2de..9a90032605 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -49,6 +49,7 @@ class FontData : public Resource {
PackedByteArray data;
bool antialiased = true;
+ bool mipmaps = false;
bool msdf = false;
int msdf_pixel_range = 16;
int msdf_size = 48;
@@ -103,6 +104,9 @@ public:
virtual void set_antialiased(bool p_antialiased);
virtual bool is_antialiased() const;
+ virtual void set_generate_mipmaps(bool p_generate_mipmaps);
+ virtual bool get_generate_mipmaps() const;
+
virtual void set_multichannel_signed_distance_field(bool p_msdf);
virtual bool is_multichannel_signed_distance_field() const;
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index 430626b008..8e17ff35a9 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -395,6 +395,9 @@ void BaseMaterial3D::init_shaders() {
shader_names->distance_fade_min = "distance_fade_min";
shader_names->distance_fade_max = "distance_fade_max";
+ shader_names->msdf_pixel_range = "msdf_pixel_range";
+ shader_names->msdf_outline_size = "msdf_outline_size";
+
shader_names->metallic_texture_channel = "metallic_texture_channel";
shader_names->ao_texture_channel = "ao_texture_channel";
shader_names->clearcoat_texture_channel = "clearcoat_texture_channel";
@@ -432,12 +435,10 @@ void BaseMaterial3D::init_shaders() {
shader_names->albedo_texture_size = "albedo_texture_size";
}
-Ref<StandardMaterial3D> BaseMaterial3D::materials_for_2d[BaseMaterial3D::MAX_MATERIALS_FOR_2D];
+HashMap<uint64_t, Ref<StandardMaterial3D>> BaseMaterial3D::materials_for_2d;
void BaseMaterial3D::finish_shaders() {
- for (int i = 0; i < MAX_MATERIALS_FOR_2D; i++) {
- materials_for_2d[i].unref();
- }
+ materials_for_2d.clear();
memdelete(dirty_materials);
dirty_materials = nullptr;
@@ -644,6 +645,11 @@ void BaseMaterial3D::_update_shader() {
code += "uniform float distance_fade_max;\n";
}
+ if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
+ code += "uniform float msdf_pixel_range;\n";
+ code += "uniform float msdf_outline_size;\n";
+ }
+
// alpha scissor is only valid if there is not antialiasing edge
// alpha hash is valid whenever, but not with alpha scissor
if (transparency == TRANSPARENCY_ALPHA_SCISSOR) {
@@ -911,6 +917,12 @@ void BaseMaterial3D::_update_shader() {
code += "}\n";
code += "\n\n";
+ if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
+ code += "float msdf_median(float r, float g, float b, float a) {\n";
+ code += " return min(max(min(r, g), min(max(r, g), b)), a);\n";
+ code += "}\n";
+ }
+ code += "\n\n";
if (flags[FLAG_UV1_USE_TRIPLANAR] || flags[FLAG_UV2_USE_TRIPLANAR]) {
code += "vec4 triplanar_texture(sampler2D p_sampler,vec3 p_weights,vec3 p_triplanar_pos) {\n";
code += " vec4 samp=vec4(0.0);\n";
@@ -1010,7 +1022,30 @@ void BaseMaterial3D::_update_shader() {
}
}
- if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) {
+ if (flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
+ code += " {\n";
+ code += " albedo_tex.rgb = mix(vec3(1.0 + 0.055) * pow(albedo_tex.rgb, vec3(1.0 / 2.4)) - vec3(0.055), vec3(12.92) * albedo_tex.rgb.rgb, lessThan(albedo_tex.rgb, vec3(0.0031308)));\n";
+ code += " vec2 msdf_size = vec2(msdf_pixel_range) / vec2(textureSize(texture_albedo, 0));\n";
+ if (flags[FLAG_USE_POINT_SIZE]) {
+ code += " vec2 dest_size = vec2(1.0) / fwidth(POINT_COORD);\n";
+ } else {
+ if (flags[FLAG_UV1_USE_TRIPLANAR]) {
+ code += " vec2 dest_size = vec2(1.0) / fwidth(uv1_triplanar_pos);\n";
+ } else {
+ code += " vec2 dest_size = vec2(1.0) / fwidth(base_uv);\n";
+ }
+ }
+ code += " float px_size = max(0.5 * dot(msdf_size, dest_size), 1.0);\n";
+ code += " float d = msdf_median(albedo_tex.r, albedo_tex.g, albedo_tex.b, albedo_tex.a) - 0.5;\n";
+ code += " if (msdf_outline_size > 0.0) {\n";
+ code += " float cr = clamp(msdf_outline_size, 0.0, msdf_pixel_range / 2.0) / msdf_pixel_range;\n";
+ code += " albedo_tex.a = clamp((d + cr) * px_size, 0.0, 1.0);\n";
+ code += " } else {\n";
+ code += " albedo_tex.a = clamp(d * px_size + 0.5, 0.0, 1.0);\n";
+ code += " }\n";
+ code += " albedo_tex.rgb = vec3(1.0);\n";
+ code += " }\n";
+ } else if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) {
code += " albedo_tex.rgb = mix(pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)),vec3(2.4)),albedo_tex.rgb.rgb * (1.0 / 12.92),lessThan(albedo_tex.rgb,vec3(0.04045)));\n";
}
@@ -1777,6 +1812,14 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const {
property.usage = PROPERTY_USAGE_NO_EDITOR;
}
+ if (property.name == "msdf_pixel_range" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+
+ if (property.name == "msdf_outline_size" && !flags[FLAG_ALBEDO_TEXTURE_MSDF]) {
+ property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
+
if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && distance_fade == DISTANCE_FADE_DISABLED) {
property.usage = PROPERTY_USAGE_NO_EDITOR;
}
@@ -2125,35 +2168,45 @@ BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel()
return refraction_texture_channel;
}
-Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, RID *r_shader_rid) {
- int version = 0;
+Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, bool p_msdf, bool p_no_depth, bool p_fixed_size, TextureFilter p_filter, RID *r_shader_rid) {
+ int64_t hash = 0;
if (p_shaded) {
- version = 1;
+ hash |= 1 << 0;
}
if (p_transparent) {
- version |= 2;
+ hash |= 1 << 1;
}
if (p_cut_alpha) {
- version |= 4;
+ hash |= 1 << 2;
}
if (p_opaque_prepass) {
- version |= 8;
+ hash |= 1 << 3;
}
if (p_double_sided) {
- version |= 16;
+ hash |= 1 << 4;
}
if (p_billboard) {
- version |= 32;
+ hash |= 1 << 5;
}
if (p_billboard_y) {
- version |= 64;
+ hash |= 1 << 6;
+ }
+ if (p_msdf) {
+ hash |= 1 << 7;
}
+ if (p_no_depth) {
+ hash |= 1 << 8;
+ }
+ if (p_fixed_size) {
+ hash |= 1 << 9;
+ }
+ hash = hash_djb2_one_64(p_filter, hash);
- if (materials_for_2d[version].is_valid()) {
+ if (materials_for_2d.has(hash)) {
if (r_shader_rid) {
- *r_shader_rid = materials_for_2d[version]->get_shader_rid();
+ *r_shader_rid = materials_for_2d[hash]->get_shader_rid();
}
- return materials_for_2d[version];
+ return materials_for_2d[hash];
}
Ref<StandardMaterial3D> material;
@@ -2164,18 +2217,22 @@ Ref<Material> BaseMaterial3D::get_material_for_2d(bool p_shaded, bool p_transpar
material->set_cull_mode(p_double_sided ? CULL_DISABLED : CULL_BACK);
material->set_flag(FLAG_SRGB_VERTEX_COLOR, true);
material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ material->set_flag(FLAG_ALBEDO_TEXTURE_MSDF, p_msdf);
+ material->set_flag(FLAG_DISABLE_DEPTH_TEST, p_no_depth);
+ material->set_flag(FLAG_FIXED_SIZE, p_fixed_size);
+ material->set_texture_filter(p_filter);
if (p_billboard || p_billboard_y) {
material->set_flag(FLAG_BILLBOARD_KEEP_SCALE, true);
material->set_billboard_mode(p_billboard_y ? BILLBOARD_FIXED_Y : BILLBOARD_ENABLED);
}
- materials_for_2d[version] = material;
+ materials_for_2d[hash] = material;
if (r_shader_rid) {
- *r_shader_rid = materials_for_2d[version]->get_shader_rid();
+ *r_shader_rid = materials_for_2d[hash]->get_shader_rid();
}
- return materials_for_2d[version];
+ return materials_for_2d[hash];
}
void BaseMaterial3D::set_on_top_of_alpha() {
@@ -2203,6 +2260,24 @@ float BaseMaterial3D::get_proximity_fade_distance() const {
return proximity_fade_distance;
}
+void BaseMaterial3D::set_msdf_pixel_range(float p_range) {
+ msdf_pixel_range = p_range;
+ RS::get_singleton()->material_set_param(_get_material(), shader_names->msdf_pixel_range, p_range);
+}
+
+float BaseMaterial3D::get_msdf_pixel_range() const {
+ return msdf_pixel_range;
+}
+
+void BaseMaterial3D::set_msdf_outline_size(float p_size) {
+ msdf_outline_size = p_size;
+ RS::get_singleton()->material_set_param(_get_material(), shader_names->msdf_outline_size, p_size);
+}
+
+float BaseMaterial3D::get_msdf_outline_size() const {
+ return msdf_outline_size;
+}
+
void BaseMaterial3D::set_distance_fade(DistanceFadeMode p_mode) {
distance_fade = p_mode;
_queue_shader_change();
@@ -2445,6 +2520,12 @@ void BaseMaterial3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_proximity_fade_distance", "distance"), &BaseMaterial3D::set_proximity_fade_distance);
ClassDB::bind_method(D_METHOD("get_proximity_fade_distance"), &BaseMaterial3D::get_proximity_fade_distance);
+ ClassDB::bind_method(D_METHOD("set_msdf_pixel_range", "range"), &BaseMaterial3D::set_msdf_pixel_range);
+ ClassDB::bind_method(D_METHOD("get_msdf_pixel_range"), &BaseMaterial3D::get_msdf_pixel_range);
+
+ ClassDB::bind_method(D_METHOD("set_msdf_outline_size", "size"), &BaseMaterial3D::set_msdf_outline_size);
+ ClassDB::bind_method(D_METHOD("get_msdf_outline_size"), &BaseMaterial3D::get_msdf_outline_size);
+
ClassDB::bind_method(D_METHOD("set_distance_fade", "mode"), &BaseMaterial3D::set_distance_fade);
ClassDB::bind_method(D_METHOD("get_distance_fade"), &BaseMaterial3D::get_distance_fade);
@@ -2479,6 +2560,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "albedo_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ALBEDO);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "albedo_tex_force_srgb"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_FORCE_SRGB);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "albedo_tex_msdf"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_MSDF);
ADD_GROUP("ORM", "orm_");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "orm_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_ORM);
@@ -2616,6 +2698,9 @@ void BaseMaterial3D::_bind_methods() {
ADD_GROUP("Proximity Fade", "proximity_fade_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "proximity_fade_enable"), "set_proximity_fade", "is_proximity_fade_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_proximity_fade_distance", "get_proximity_fade_distance");
+ ADD_GROUP("MSDF", "msdf_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), "set_msdf_pixel_range", "get_msdf_pixel_range");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "msdf_outline_size", PROPERTY_HINT_RANGE, "1,250,1"), "set_msdf_outline_size", "get_msdf_outline_size");
ADD_GROUP("Distance Fade", "distance_fade_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "distance_fade_mode", PROPERTY_HINT_ENUM, "Disabled,PixelAlpha,PixelDither,ObjectDither"), "set_distance_fade", "get_distance_fade");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.01"), "set_distance_fade_min_distance", "get_distance_fade_min_distance");
@@ -2715,6 +2800,7 @@ void BaseMaterial3D::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_INVERT_HEIGHTMAP);
BIND_ENUM_CONSTANT(FLAG_SUBSURFACE_MODE_SKIN);
BIND_ENUM_CONSTANT(FLAG_PARTICLE_TRAILS_MODE);
+ BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_MSDF);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);
@@ -2804,6 +2890,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
set_heightmap_deep_parallax_max_layers(32);
set_heightmap_deep_parallax_flip_tangent(false); //also sets binormal
+ flags[FLAG_ALBEDO_TEXTURE_MSDF] = false;
flags[FLAG_USE_TEXTURE_REPEAT] = true;
is_initialized = true;
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 07227c037c..99e125f5b0 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -242,6 +242,7 @@ public:
FLAG_INVERT_HEIGHTMAP,
FLAG_SUBSURFACE_MODE_SKIN,
FLAG_PARTICLE_TRAILS_MODE,
+ FLAG_ALBEDO_TEXTURE_MSDF,
FLAG_MAX
};
@@ -412,6 +413,8 @@ private:
StringName uv2_blend_sharpness;
StringName grow;
StringName proximity_fade_distance;
+ StringName msdf_pixel_range;
+ StringName msdf_outline_size;
StringName distance_fade_min;
StringName distance_fade_max;
StringName ao_light_affect;
@@ -500,6 +503,9 @@ private:
bool proximity_fade_enabled = false;
float proximity_fade_distance;
+ float msdf_pixel_range = 4.f;
+ float msdf_outline_size = 0.f;
+
DistanceFadeMode distance_fade = DISTANCE_FADE_DISABLED;
float distance_fade_max_distance;
float distance_fade_min_distance;
@@ -527,9 +533,7 @@ private:
_FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const;
- static const int MAX_MATERIALS_FOR_2D = 128;
-
- static Ref<StandardMaterial3D> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff
+ static HashMap<uint64_t, Ref<StandardMaterial3D>> materials_for_2d; //used by Sprite3D, Label3D and other stuff
void _validate_high_end(const String &text, PropertyInfo &property) const;
@@ -714,6 +718,12 @@ public:
void set_proximity_fade_distance(float p_distance);
float get_proximity_fade_distance() const;
+ void set_msdf_pixel_range(float p_range);
+ float get_msdf_pixel_range() const;
+
+ void set_msdf_outline_size(float p_size);
+ float get_msdf_outline_size() const;
+
void set_distance_fade(DistanceFadeMode p_mode);
DistanceFadeMode get_distance_fade() const;
@@ -739,7 +749,7 @@ public:
static void finish_shaders();
static void flush_changes();
- static Ref<Material> get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, RID *r_shader_rid = nullptr);
+ static Ref<Material> get_material_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, bool p_msdf = false, bool p_no_depth = false, bool p_fixed_size = false, TextureFilter p_filter = TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RID *r_shader_rid = nullptr);
virtual RID get_shader_rid() const override;
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index b1c2702a1e..b991cb1abe 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -310,6 +310,9 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
NODE_FROM_ID(owner, n.owner);
if (owner) {
node->_set_owner_nocheck(owner);
+ if (node->data.unique_name_in_owner) {
+ node->_acquire_unique_name_in_owner();
+ }
}
}
diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp
index 01a0411545..597d070285 100644
--- a/scene/resources/particles_material.cpp
+++ b/scene/resources/particles_material.cpp
@@ -233,48 +233,48 @@ void ParticlesMaterial::_update_shader() {
code += "uniform vec3 gravity;\n";
if (color_ramp.is_valid()) {
- code += "uniform sampler2D color_ramp;\n";
+ code += "uniform sampler2D color_ramp : repeat_disable;\n";
}
if (color_initial_ramp.is_valid()) {
- code += "uniform sampler2D color_initial_ramp;\n";
+ code += "uniform sampler2D color_initial_ramp : repeat_disable;\n";
}
if (tex_parameters[PARAM_INITIAL_LINEAR_VELOCITY].is_valid()) {
- code += "uniform sampler2D linear_velocity_texture;\n";
+ code += "uniform sampler2D linear_velocity_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_ORBIT_VELOCITY].is_valid()) {
- code += "uniform sampler2D orbit_velocity_texture;\n";
+ code += "uniform sampler2D orbit_velocity_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_ANGULAR_VELOCITY].is_valid()) {
- code += "uniform sampler2D angular_velocity_texture;\n";
+ code += "uniform sampler2D angular_velocity_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_LINEAR_ACCEL].is_valid()) {
- code += "uniform sampler2D linear_accel_texture;\n";
+ code += "uniform sampler2D linear_accel_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_RADIAL_ACCEL].is_valid()) {
- code += "uniform sampler2D radial_accel_texture;\n";
+ code += "uniform sampler2D radial_accel_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_TANGENTIAL_ACCEL].is_valid()) {
- code += "uniform sampler2D tangent_accel_texture;\n";
+ code += "uniform sampler2D tangent_accel_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_DAMPING].is_valid()) {
- code += "uniform sampler2D damping_texture;\n";
+ code += "uniform sampler2D damping_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_ANGLE].is_valid()) {
- code += "uniform sampler2D angle_texture;\n";
+ code += "uniform sampler2D angle_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_SCALE].is_valid()) {
- code += "uniform sampler2D scale_texture;\n";
+ code += "uniform sampler2D scale_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_HUE_VARIATION].is_valid()) {
- code += "uniform sampler2D hue_variation_texture;\n";
+ code += "uniform sampler2D hue_variation_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_ANIM_SPEED].is_valid()) {
- code += "uniform sampler2D anim_speed_texture;\n";
+ code += "uniform sampler2D anim_speed_texture : repeat_disable;\n";
}
if (tex_parameters[PARAM_ANIM_OFFSET].is_valid()) {
- code += "uniform sampler2D anim_offset_texture;\n";
+ code += "uniform sampler2D anim_offset_texture : repeat_disable;\n";
}
if (collision_enabled) {
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/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 129f76702e..755962b96c 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -74,6 +74,10 @@ void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p
Vector3 pv = p_prev_value;
value = pv.x;
} break;
+ case Variant::QUATERNION: {
+ Quaternion pv = p_prev_value;
+ value = pv.x;
+ } break;
default:
break;
}
@@ -94,6 +98,10 @@ void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p
Vector3 pv = p_prev_value;
value = (int)pv.x;
} break;
+ case Variant::QUATERNION: {
+ Quaternion pv = p_prev_value;
+ value = (int)pv.x;
+ } break;
default:
break;
}
@@ -115,6 +123,10 @@ void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p
Vector3 pv = p_prev_value;
value = Vector2(pv.x, pv.y);
} break;
+ case Variant::QUATERNION: {
+ Quaternion pv = p_prev_value;
+ value = Vector2(pv.x, pv.y);
+ } break;
default:
break;
}
@@ -136,6 +148,35 @@ void VisualShaderNode::set_input_port_default_value(int p_port, const Variant &p
case Variant::VECTOR3: {
value = p_prev_value;
} break;
+ case Variant::QUATERNION: {
+ Quaternion pv = p_prev_value;
+ value = Vector3(pv.x, pv.y, pv.z);
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case Variant::QUATERNION: {
+ switch (p_prev_value.get_type()) {
+ case Variant::INT: {
+ float pv = (float)(int)p_prev_value;
+ value = Quaternion(pv, pv, pv, pv);
+ } break;
+ case Variant::FLOAT: {
+ float pv = p_prev_value;
+ value = Quaternion(pv, pv, pv, pv);
+ } break;
+ case Variant::VECTOR2: {
+ Vector2 pv = p_prev_value;
+ value = Quaternion(pv.x, pv.y, pv.y, pv.y);
+ } break;
+ case Variant::VECTOR3: {
+ Vector3 pv = p_prev_value;
+ value = Quaternion(pv.x, pv.y, pv.z, pv.z);
+ } break;
+ case Variant::QUATERNION: {
+ value = p_prev_value;
+ } break;
default:
break;
}
@@ -253,6 +294,9 @@ int VisualShaderNode::get_expanded_output_port_count() const {
case PORT_TYPE_VECTOR_3D: {
count2 += 3;
} break;
+ case PORT_TYPE_VECTOR_4D: {
+ count2 += 4;
+ } break;
default:
break;
}
@@ -360,6 +404,7 @@ void VisualShaderNode::_bind_methods() {
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT);
BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(PORT_TYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(PORT_TYPE_BOOLEAN);
BIND_ENUM_CONSTANT(PORT_TYPE_TRANSFORM);
BIND_ENUM_CONSTANT(PORT_TYPE_SAMPLER);
@@ -767,7 +812,6 @@ void VisualShader::add_node(Type p_type, const Ref<VisualShaderNode> &p_node, co
if (input.is_valid()) {
input->shader_mode = shader_mode;
input->shader_type = p_type;
- input->connect("input_type_changed", callable_mp(this, &VisualShader::_input_type_changed), varray(p_type, p_id));
}
n.node->connect("changed", callable_mp(this, &VisualShader::_queue_update));
@@ -837,11 +881,6 @@ void VisualShader::remove_node(Type p_type, int p_id) {
Graph *g = &graph[p_type];
ERR_FAIL_COND(!g->nodes.has(p_id));
- Ref<VisualShaderNodeInput> input = g->nodes[p_id].node;
- if (input.is_valid()) {
- input->disconnect("input_type_changed", callable_mp(this, &VisualShader::_input_type_changed));
- }
-
g->nodes[p_id].node->disconnect("changed", callable_mp(this, &VisualShader::_queue_update));
g->nodes.erase(p_id);
@@ -1203,6 +1242,9 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ";\n";
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ code += " COLOR.rgb = n_out" + itos(p_node) + "p" + itos(p_port) + ".xyz;\n";
+ } break;
default: {
code += " COLOR.rgb = vec3(0.0);\n";
} break;
@@ -1687,11 +1729,14 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
inputs[i] = "(" + src_var + " ? 1.0 : 0.0)";
} break;
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
- inputs[i] = "dot(" + src_var + ", vec2(0.333333, 0.333333))";
+ inputs[i] = "dot(" + src_var + ", vec2(0.5, 0.5))";
} break;
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
inputs[i] = "dot(" + src_var + ", vec3(0.333333, 0.333333, 0.333333))";
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ inputs[i] = "dot(" + src_var + ", vec4(0.25, 0.25, 0.25, 0.25))";
+ } break;
default:
break;
}
@@ -1705,11 +1750,14 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
inputs[i] = "(" + src_var + " ? 1 : 0)";
} break;
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
- inputs[i] = "dot(float(" + src_var + "), vec2(0.333333, 0.333333))";
+ inputs[i] = "dot(float(" + src_var + "), vec2(0.5, 0.5))";
} break;
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
inputs[i] = "dot(float(" + src_var + "), vec3(0.333333, 0.333333, 0.333333))";
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ inputs[i] = "dot(float(" + src_var + "), vec4(0.25, 0.25, 0.25, 0.25))";
+ } break;
default:
break;
}
@@ -1728,6 +1776,9 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
inputs[i] = "all(bvec3(" + src_var + "))";
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ inputs[i] = "all(bvec4(" + src_var + "))";
+ } break;
default:
break;
}
@@ -1743,7 +1794,8 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_BOOLEAN: {
inputs[i] = "vec2(" + src_var + " ? 1.0 : 0.0)";
} break;
- case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
+ case VisualShaderNode::PORT_TYPE_VECTOR_3D:
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
inputs[i] = "vec2(" + src_var + ".xy)";
} break;
default:
@@ -1765,6 +1817,30 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
inputs[i] = "vec3(" + src_var + ", 0.0)";
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ inputs[i] = "vec3(" + src_var + ".xyz)";
+ } break;
+ default:
+ break;
+ }
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ switch (out_type) {
+ case VisualShaderNode::PORT_TYPE_SCALAR: {
+ inputs[i] = "vec4(" + src_var + ")";
+ } break;
+ case VisualShaderNode::PORT_TYPE_SCALAR_INT: {
+ inputs[i] = "vec4(float(" + src_var + "))";
+ } break;
+ case VisualShaderNode::PORT_TYPE_BOOLEAN: {
+ inputs[i] = "vec4(" + src_var + " ? 1.0 : 0.0)";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
+ inputs[i] = "vec4(" + src_var + ", 0.0, 0.0)";
+ } break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
+ inputs[i] = "vec4(" + src_var + ", 0.0)";
+ } break;
default:
break;
}
@@ -1799,6 +1875,10 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
Vector3 val = defval;
inputs[i] = "n_in" + itos(node) + "p" + itos(i);
node_code += " vec3 " + inputs[i] + " = " + vformat("vec3(%.5f, %.5f, %.5f);\n", val.x, val.y, val.z);
+ } else if (defval.get_type() == Variant::QUATERNION) {
+ Quaternion val = defval;
+ inputs[i] = "n_in" + itos(node) + "p" + itos(i);
+ node_code += " vec4 " + inputs[i] + " = " + vformat("vec4(%.5f, %.5f, %.5f, %.5f);\n", val.x, val.y, val.z, val.w);
} else if (defval.get_type() == Variant::TRANSFORM3D) {
Transform3D val = defval;
val.basis.transpose();
@@ -1838,6 +1918,9 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
output_count += 3;
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ output_count += 4;
+ } break;
default:
break;
}
@@ -1865,6 +1948,9 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
outputs[i] = "vec3 " + var_name;
break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D:
+ outputs[i] = "vec4 " + var_name;
+ break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
outputs[i] = "bool " + var_name;
break;
@@ -1882,6 +1968,9 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
j += 3;
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ j += 4;
+ } break;
default:
break;
}
@@ -1904,6 +1993,9 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR_3D:
code += " vec3 " + outputs[i] + ";\n";
break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D:
+ code += " vec4 " + outputs[i] + ";\n";
+ break;
case VisualShaderNode::PORT_TYPE_BOOLEAN:
code += " bool " + outputs[i] + ";\n";
break;
@@ -1921,6 +2013,9 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
j += 3;
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ j += 4;
+ } break;
default:
break;
}
@@ -1932,29 +2027,19 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
if (!node_code.is_empty()) {
code += node_name;
code += node_code;
- code += "\n";
}
for (int i = 0; i < output_count; i++) {
- bool new_line_inserted = false;
if (expanded_output_ports[i]) {
switch (vsnode->get_output_port_type(i)) {
case VisualShaderNode::PORT_TYPE_VECTOR_2D: {
if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
- }
String r = "n_out" + itos(node) + "p" + itos(i + 1);
code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
outputs[i + 1] = r;
}
if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
- }
String g = "n_out" + itos(node) + "p" + itos(i + 2);
code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
outputs[i + 2] = g;
@@ -1964,30 +2049,18 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
} break;
case VisualShaderNode::PORT_TYPE_VECTOR_3D: {
if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
- }
String r = "n_out" + itos(node) + "p" + itos(i + 1);
code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
outputs[i + 1] = r;
}
if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
- }
String g = "n_out" + itos(node) + "p" + itos(i + 2);
code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
outputs[i + 2] = g;
}
if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
- if (!new_line_inserted) {
- code += "\n";
- new_line_inserted = true;
- }
String b = "n_out" + itos(node) + "p" + itos(i + 3);
code += " float " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
outputs[i + 3] = b;
@@ -1995,12 +2068,43 @@ Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBui
i += 3;
} break;
+ case VisualShaderNode::PORT_TYPE_VECTOR_4D: {
+ if (vsnode->is_output_port_connected(i + 1) || (for_preview && vsnode->get_output_port_for_preview() == (i + 1))) { // red-component
+ String r = "n_out" + itos(node) + "p" + itos(i + 1);
+ code += " float " + r + " = n_out" + itos(node) + "p" + itos(i) + ".r;\n";
+ outputs[i + 1] = r;
+ }
+
+ if (vsnode->is_output_port_connected(i + 2) || (for_preview && vsnode->get_output_port_for_preview() == (i + 2))) { // green-component
+ String g = "n_out" + itos(node) + "p" + itos(i + 2);
+ code += " float " + g + " = n_out" + itos(node) + "p" + itos(i) + ".g;\n";
+ outputs[i + 2] = g;
+ }
+
+ if (vsnode->is_output_port_connected(i + 3) || (for_preview && vsnode->get_output_port_for_preview() == (i + 3))) { // blue-component
+ String b = "n_out" + itos(node) + "p" + itos(i + 3);
+ code += " float " + b + " = n_out" + itos(node) + "p" + itos(i) + ".b;\n";
+ outputs[i + 3] = b;
+ }
+
+ if (vsnode->is_output_port_connected(i + 4) || (for_preview && vsnode->get_output_port_for_preview() == (i + 4))) { // alpha-component
+ String a = "n_out" + itos(node) + "p" + itos(i + 4);
+ code += " float " + a + " = n_out" + itos(node) + "p" + itos(i) + ".a;\n";
+ outputs[i + 4] = a;
+ }
+
+ i += 4;
+ } break;
default:
break;
}
}
}
+ if (!node_code.is_empty()) {
+ code += "\n";
+ }
+
code += "\n"; //
processed.insert(node);
@@ -2147,6 +2251,9 @@ void VisualShader::_update_shader() const {
case VaryingType::VARYING_TYPE_VECTOR_3D:
global_code += "vec3 ";
break;
+ case VaryingType::VARYING_TYPE_VECTOR_4D:
+ global_code += "vec4 ";
+ break;
case VaryingType::VARYING_TYPE_COLOR:
global_code += "vec4 ";
break;
@@ -2207,6 +2314,9 @@ void VisualShader::_update_shader() const {
case VaryingType::VARYING_TYPE_VECTOR_3D:
code2 += "vec3(0.0)";
break;
+ case VaryingType::VARYING_TYPE_VECTOR_4D:
+ code2 += "vec4(0.0)";
+ break;
case VaryingType::VARYING_TYPE_COLOR:
code2 += "vec4(0.0)";
break;
@@ -2447,21 +2557,6 @@ void VisualShader::_queue_update() {
call_deferred(SNAME("_update_shader"));
}
-void VisualShader::_input_type_changed(Type p_type, int p_id) {
- ERR_FAIL_INDEX(p_type, TYPE_MAX);
- //erase connections using this input, as type changed
- Graph *g = &graph[p_type];
-
- for (List<Connection>::Element *E = g->connections.front(); E;) {
- List<Connection>::Element *N = E->next();
- if (E->get().from_node == p_id) {
- g->connections.erase(E);
- g->nodes[E->get().to_node].prev_connected_nodes.erase(p_id);
- }
- E = N;
- }
-}
-
void VisualShader::rebuild() {
dirty.set();
_update_shader();
@@ -2527,6 +2622,7 @@ void VisualShader::_bind_methods() {
BIND_ENUM_CONSTANT(VARYING_TYPE_FLOAT);
BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(VARYING_TYPE_COLOR);
BIND_ENUM_CONSTANT(VARYING_TYPE_TRANSFORM);
BIND_ENUM_CONSTANT(VARYING_TYPE_MAX);
@@ -2569,12 +2665,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "instance_custom", "INSTANCE_CUSTOM.rgb" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "instance_custom_alpha", "INSTANCE_CUSTOM.a" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "instance_custom", "INSTANCE_CUSTOM" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "modelview_matrix", "MODELVIEW_MATRIX" },
@@ -2590,7 +2684,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
// Node3D, Fragment
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" },
@@ -2598,8 +2692,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "view", "VIEW" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" },
@@ -2619,7 +2712,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
// Node3D, Light
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
@@ -2647,8 +2740,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Canvas Item, Vertex
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_matrix", "MODEL_MATRIX" },
@@ -2656,16 +2748,14 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "screen_matrix", "SCREEN_MATRIX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "instance_custom", "INSTANCE_CUSTOM.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "instance_custom_alpha", "INSTANCE_CUSTOM.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "instance_custom", "INSTANCE_CUSTOM" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" },
// Canvas Item, Fragment
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_pixel_size", "SCREEN_PIXEL_SIZE" },
@@ -2675,42 +2765,34 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_texture", "NORMAL_TEXTURE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "specular_shininess", "SPECULAR_SHININESS.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "specular_shininess_alpha", "SPECULAR_SHININESS.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "specular_shininess_texture", "SPECULAR_SHININESS_TEXTURE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
// Canvas Item, Light
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_color", "LIGHT_COLOR.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_color_alpha", "LIGHT_COLOR.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light", "LIGHT" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light_color", "LIGHT_COLOR" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_position", "LIGHT_POSITION" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_vertex", "LIGHT_VERTEX" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "shadow", "SHADOW_MODULATE.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "shadow_alpha", "SHADOW_MODULATE.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "shadow", "SHADOW_MODULATE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "texture_pixel_size", "TEXTURE_PIXEL_SIZE" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "point_coord", "POINT_COORD" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SAMPLER, "texture", "TEXTURE" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "specular_shininess", "SPECULAR_SHININESS.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "specular_shininess_alpha", "SPECULAR_SHININESS.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "specular_shininess", "SPECULAR_SHININESS" },
// Particles, Start
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
@@ -2720,13 +2802,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Particles, Start (Custom)
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_START_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
@@ -2736,13 +2816,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Particles, Process
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
@@ -2752,13 +2830,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Particles, Process (Custom)
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_PROCESS_CUSTOM, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
@@ -2770,13 +2846,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "attractor_force", "ATTRACTOR_FORCE" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "collision_depth", "COLLISION_DEPTH" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "collision_normal", "COLLISION_NORMAL" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "velocity", "VELOCITY" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "restart", "RESTART" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_BOOLEAN, "active", "ACTIVE" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_3D, "custom", "CUSTOM.rgb" },
- { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "custom_alpha", "CUSTOM.a" },
+ { Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom", "CUSTOM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" },
{ Shader::MODE_PARTICLES, VisualShader::TYPE_COLLIDE, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" },
@@ -2789,8 +2863,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_half_res_pass", "AT_HALF_RES_PASS" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_quarter_res_pass", "AT_QUARTER_RES_PASS" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "eyedir", "EYEDIR" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "half_res_color", "HALF_RES_COLOR.rgb" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "half_res_alpha", "HALF_RES_COLOR.a" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "half_res_color", "HALF_RES_COLOR" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light0_color", "LIGHT0_COLOR" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light0_direction", "LIGHT0_DIRECTION" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light0_enabled", "LIGHT0_ENABLED" },
@@ -2808,8 +2881,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_BOOLEAN, "light3_enabled", "LIGHT3_ENABLED" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "light3_energy", "LIGHT3_ENERGY" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "position", "POSITION" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "quarter_res_color", "QUARTER_RES_COLOR.rgb" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "quarter_res_alpha", "QUARTER_RES_COLOR.a" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "quarter_res_color", "QUARTER_RES_COLOR" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SAMPLER, "radiance", "RADIANCE" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_2D, "sky_coords", "SKY_COORDS" },
@@ -2835,20 +2907,20 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "vec3(1.0, 0.0, 0.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "vec3(1.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Spatial, Fragment
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.rgb" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "vec3(0.0, 1.0, 0.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "vec3(1.0, 0.0, 0.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "vec3(1.0)" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "vec2(1.0)" },
@@ -2856,7 +2928,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
// Spatial, Light
- { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.rgb" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV" },
@@ -2867,25 +2939,25 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "vec3(1.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Canvas Item, Fragment
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.rgb" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "vec3(1.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec3(1.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
// Canvas Item, Light
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.rgb" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "vec3(0.0, 0.0, 1.0)" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "vec3(1.0)" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "vec4(1.0)" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "1.0" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "screen_uv", "SCREEN_UV" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
@@ -2927,7 +2999,7 @@ int VisualShaderNodeInput::get_output_port_count() const {
}
VisualShaderNodeInput::PortType VisualShaderNodeInput::get_output_port_type(int p_port) const {
- return get_input_type_by_name(input_name);
+ return p_port == 0 ? get_input_type_by_name(input_name) : PORT_TYPE_SCALAR;
}
String VisualShaderNodeInput::get_output_port_name(int p_port) const {
@@ -2938,6 +3010,22 @@ String VisualShaderNodeInput::get_caption() const {
return "Input";
}
+bool VisualShaderNodeInput::is_output_port_expandable(int p_port) const {
+ if (p_port == 0) {
+ switch (get_input_type_by_name(input_name)) {
+ case PORT_TYPE_VECTOR_2D:
+ return true;
+ case PORT_TYPE_VECTOR_3D:
+ return true;
+ case PORT_TYPE_VECTOR_4D:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
if (get_output_port_type(0) == PORT_TYPE_SAMPLER) {
return "";
@@ -2970,6 +3058,9 @@ String VisualShaderNodeInput::generate_code(Shader::Mode p_mode, VisualShader::T
case PORT_TYPE_VECTOR_3D: {
code = " " + p_output_vars[0] + " = vec3(0.0);\n";
} break;
+ case PORT_TYPE_VECTOR_4D: {
+ code = " " + p_output_vars[0] + " = vec4(0.0);\n";
+ } break;
case PORT_TYPE_BOOLEAN: {
code = " " + p_output_vars[0] + " = false;\n";
} break;
@@ -3186,6 +3277,8 @@ int VisualShaderNodeUniformRef::get_output_port_count() const {
return 1;
case UniformType::UNIFORM_TYPE_VECTOR3:
return 1;
+ case UniformType::UNIFORM_TYPE_VECTOR4:
+ return 1;
case UniformType::UNIFORM_TYPE_TRANSFORM:
return 1;
case UniformType::UNIFORM_TYPE_COLOR:
@@ -3210,6 +3303,8 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_output_port
return PortType::PORT_TYPE_VECTOR_2D;
case UniformType::UNIFORM_TYPE_VECTOR3:
return PortType::PORT_TYPE_VECTOR_3D;
+ case UniformType::UNIFORM_TYPE_VECTOR4:
+ return PortType::PORT_TYPE_VECTOR_4D;
case UniformType::UNIFORM_TYPE_TRANSFORM:
return PortType::PORT_TYPE_TRANSFORM;
case UniformType::UNIFORM_TYPE_COLOR:
@@ -3239,6 +3334,8 @@ String VisualShaderNodeUniformRef::get_output_port_name(int p_port) const {
return "";
case UniformType::UNIFORM_TYPE_VECTOR3:
return "";
+ case UniformType::UNIFORM_TYPE_VECTOR4:
+ return "";
case UniformType::UNIFORM_TYPE_TRANSFORM:
return "";
case UniformType::UNIFORM_TYPE_COLOR:
@@ -3311,6 +3408,8 @@ VisualShaderNodeUniformRef::PortType VisualShaderNodeUniformRef::get_port_type_b
return PORT_TYPE_VECTOR_2D;
case UniformType::UNIFORM_TYPE_VECTOR3:
return PORT_TYPE_VECTOR_3D;
+ case UniformType::UNIFORM_TYPE_VECTOR4:
+ return PORT_TYPE_VECTOR_4D;
case UniformType::UNIFORM_TYPE_TRANSFORM:
return PORT_TYPE_TRANSFORM;
case UniformType::UNIFORM_TYPE_COLOR:
@@ -3386,8 +3485,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv2", "UV2" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" },
@@ -3435,14 +3533,12 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
////////////////////////////////////////////////////////////////////////
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "vertex", "VERTEX" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
////////////////////////////////////////////////////////////////////////
// Canvas Item, Fragment.
////////////////////////////////////////////////////////////////////////
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "color", "COLOR" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal_map", "NORMAL_MAP" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "normal_map_depth", "NORMAL_MAP_DEPTH" },
@@ -3451,16 +3547,14 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
////////////////////////////////////////////////////////////////////////
// Canvas Item, Light.
////////////////////////////////////////////////////////////////////////
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT.rgb" },
- { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "light_alpha", "LIGHT.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "light", "LIGHT" },
////////////////////////////////////////////////////////////////////////
// Sky, Sky.
////////////////////////////////////////////////////////////////////////
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR" },
{ Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "ALPHA" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fog", "FOG.rgb" },
- { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_SCALAR, "fog_alpha", "FOG.a" },
+ { Shader::MODE_SKY, VisualShader::TYPE_SKY, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fog", "FOG" },
////////////////////////////////////////////////////////////////////////
// Fog, Fog.
@@ -3697,6 +3791,11 @@ String VisualShaderNodeUniform::get_warning(Shader::Mode p_mode, VisualShader::T
incompatible_type = true;
}
} break;
+ case RS::GLOBAL_VAR_TYPE_VEC4: {
+ if (!Object::cast_to<VisualShaderNodeVec4Uniform>(this)) {
+ incompatible_type = true;
+ }
+ } break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
if (!Object::cast_to<VisualShaderNodeTransformUniform>(this)) {
incompatible_type = true;
@@ -4404,6 +4503,9 @@ String VisualShaderNodeExpression::generate_code(Shader::Mode p_mode, VisualShad
case PORT_TYPE_VECTOR_3D:
tk = "vec3(0.0, 0.0, 0.0)";
break;
+ case PORT_TYPE_VECTOR_4D:
+ tk = "vec4(0.0, 0.0, 0.0, 0.0)";
+ break;
case PORT_TYPE_BOOLEAN:
tk = "false";
break;
@@ -4542,6 +4644,8 @@ String VisualShaderNodeVarying::get_type_str() const {
return "vec2";
case VisualShader::VARYING_TYPE_VECTOR_3D:
return "vec3";
+ case VisualShader::VARYING_TYPE_VECTOR_4D:
+ return "vec4";
case VisualShader::VARYING_TYPE_COLOR:
return "vec4";
case VisualShader::VARYING_TYPE_TRANSFORM:
@@ -4558,6 +4662,8 @@ VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type(VisualS
return PORT_TYPE_VECTOR_2D;
case VisualShader::VARYING_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case VisualShader::VARYING_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
case VisualShader::VARYING_TYPE_COLOR:
if (p_port == 1) {
break; // scalar
@@ -4718,6 +4824,9 @@ String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualS
case VisualShader::VARYING_TYPE_VECTOR_3D:
from = "vec3(0.0)";
break;
+ case VisualShader::VARYING_TYPE_VECTOR_4D:
+ from = "vec4(0.0)";
+ break;
case VisualShader::VARYING_TYPE_COLOR:
from = "vec3(0.0)";
from2 = "0.0";
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index 2d4b2852e9..aaf570d98c 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -83,6 +83,7 @@ public:
VARYING_TYPE_FLOAT,
VARYING_TYPE_VECTOR_2D,
VARYING_TYPE_VECTOR_3D,
+ VARYING_TYPE_VECTOR_4D,
VARYING_TYPE_COLOR,
VARYING_TYPE_TRANSFORM,
VARYING_TYPE_MAX,
@@ -271,6 +272,7 @@ public:
PORT_TYPE_SCALAR_INT,
PORT_TYPE_VECTOR_2D,
PORT_TYPE_VECTOR_3D,
+ PORT_TYPE_VECTOR_4D,
PORT_TYPE_BOOLEAN,
PORT_TYPE_TRANSFORM,
PORT_TYPE_SAMPLER,
@@ -446,6 +448,7 @@ public:
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
+ virtual bool is_output_port_expandable(int p_port) const override;
virtual String get_caption() const override;
@@ -556,6 +559,7 @@ public:
UNIFORM_TYPE_BOOLEAN,
UNIFORM_TYPE_VECTOR2,
UNIFORM_TYPE_VECTOR3,
+ UNIFORM_TYPE_VECTOR4,
UNIFORM_TYPE_TRANSFORM,
UNIFORM_TYPE_COLOR,
UNIFORM_TYPE_SAMPLER,
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 4e16353460..1368bf0382 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -38,6 +38,8 @@ VisualShaderNodeVectorBase::PortType VisualShaderNodeVectorBase::get_input_port_
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -50,6 +52,8 @@ VisualShaderNodeVectorBase::PortType VisualShaderNodeVectorBase::get_output_port
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -73,10 +77,11 @@ void VisualShaderNodeVectorBase::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeVectorBase::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeVectorBase::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Vector2,Vector3"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Vector2,Vector3,Vector4"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -291,7 +296,7 @@ int VisualShaderNodeColorConstant::get_input_port_count() const {
}
VisualShaderNodeColorConstant::PortType VisualShaderNodeColorConstant::get_input_port_type(int p_port) const {
- return PORT_TYPE_VECTOR_3D;
+ return PORT_TYPE_VECTOR_4D;
}
String VisualShaderNodeColorConstant::get_input_port_name(int p_port) const {
@@ -299,15 +304,15 @@ String VisualShaderNodeColorConstant::get_input_port_name(int p_port) const {
}
int VisualShaderNodeColorConstant::get_output_port_count() const {
- return 2;
+ return 1;
}
VisualShaderNodeColorConstant::PortType VisualShaderNodeColorConstant::get_output_port_type(int p_port) const {
- return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR;
+ return p_port == 0 ? PORT_TYPE_VECTOR_4D : PORT_TYPE_SCALAR;
}
String VisualShaderNodeColorConstant::get_output_port_name(int p_port) const {
- return p_port == 0 ? "" : "alpha"; //no output port means the editor will be used as port
+ return "";
}
bool VisualShaderNodeColorConstant::is_output_port_expandable(int p_port) const {
@@ -318,11 +323,7 @@ bool VisualShaderNodeColorConstant::is_output_port_expandable(int p_port) const
}
String VisualShaderNodeColorConstant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- String code;
- code += " " + p_output_vars[0] + " = " + vformat("vec3(%.6f, %.6f, %.6f)", constant.r, constant.g, constant.b) + ";\n";
- code += " " + p_output_vars[1] + " = " + vformat("%.6f", constant.a) + ";\n";
-
- return code;
+ return " " + p_output_vars[0] + " = " + vformat("vec4(%.6f, %.6f, %.6f, %.6f)", constant.r, constant.g, constant.b, constant.a) + ";\n";
}
void VisualShaderNodeColorConstant::set_constant(const Color &p_constant) {
@@ -477,6 +478,68 @@ void VisualShaderNodeVec3Constant::_bind_methods() {
VisualShaderNodeVec3Constant::VisualShaderNodeVec3Constant() {
}
+////////////// Vector4
+
+String VisualShaderNodeVec4Constant::get_caption() const {
+ return "Vector4Constant";
+}
+
+int VisualShaderNodeVec4Constant::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVec4Constant::PortType VisualShaderNodeVec4Constant::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_4D;
+}
+
+String VisualShaderNodeVec4Constant::get_input_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeVec4Constant::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeVec4Constant::PortType VisualShaderNodeVec4Constant::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_4D;
+}
+
+String VisualShaderNodeVec4Constant::get_output_port_name(int p_port) const {
+ return ""; // No output port means the editor will be used as port.
+}
+
+String VisualShaderNodeVec4Constant::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + vformat("vec4(%.6f, %.6f, %.6f, %.6f)", constant.x, constant.y, constant.z, constant.w) + ";\n";
+}
+
+void VisualShaderNodeVec4Constant::set_constant(const Quaternion &p_constant) {
+ if (constant.is_equal_approx(p_constant)) {
+ return;
+ }
+ constant = p_constant;
+ emit_changed();
+}
+
+Quaternion VisualShaderNodeVec4Constant::get_constant() const {
+ return constant;
+}
+
+Vector<StringName> VisualShaderNodeVec4Constant::get_editable_properties() const {
+ Vector<StringName> props;
+ props.push_back("constant");
+ return props;
+}
+
+void VisualShaderNodeVec4Constant::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_constant", "constant"), &VisualShaderNodeVec4Constant::set_constant);
+ ClassDB::bind_method(D_METHOD("get_constant"), &VisualShaderNodeVec4Constant::get_constant);
+
+ ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "constant"), "set_constant", "get_constant");
+}
+
+VisualShaderNodeVec4Constant::VisualShaderNodeVec4Constant() {
+}
+
////////////// Transform3D
String VisualShaderNodeTransformConstant::get_caption() const {
@@ -584,21 +647,25 @@ String VisualShaderNodeTexture::get_input_port_name(int p_port) const {
}
int VisualShaderNodeTexture::get_output_port_count() const {
- return 2;
+ return 1;
}
VisualShaderNodeTexture::PortType VisualShaderNodeTexture::get_output_port_type(int p_port) const {
- if (p_port == 0 && source == SOURCE_DEPTH) {
- return PORT_TYPE_SCALAR;
+ switch (p_port) {
+ case 0:
+ return PORT_TYPE_VECTOR_4D;
+ default:
+ return PORT_TYPE_SCALAR;
}
- return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR;
}
String VisualShaderNodeTexture::get_output_port_name(int p_port) const {
- if (p_port == 0 && source == SOURCE_DEPTH) {
- return "depth";
+ switch (p_port) {
+ case 0:
+ return "color";
+ default:
+ return "";
}
- return p_port == 0 ? "rgb" : "alpha";
}
bool VisualShaderNodeTexture::is_output_port_expandable(int p_port) const {
@@ -655,170 +722,116 @@ String VisualShaderNodeTexture::generate_code(Shader::Mode p_mode, VisualShader:
default_uv = "vec2(0.0)";
}
+ String code;
if (source == SOURCE_TEXTURE) {
String id = make_unique_id(p_type, p_id, "tex");
- String code;
if (p_input_vars[0].is_empty()) { // Use UV by default.
-
if (p_input_vars[1].is_empty()) {
- code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
-
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
-
- code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n";
- code += " " + p_output_vars[1] + " = " + id + "_read.a;\n";
return code;
}
if (source == SOURCE_PORT) {
String id = p_input_vars[2];
-
- String code;
- code += " {\n";
if (id.is_empty()) {
- code += " vec4 " + id + "_tex_read = vec4(0.0);\n";
+ code += " " + p_output_vars[0] + " = vec4(0.0);\n";
} else {
if (p_input_vars[0].is_empty()) { // Use UV by default.
-
if (p_input_vars[1].is_empty()) {
- code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
-
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
-
- code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n";
- code += " " + p_output_vars[1] + " = " + id + "_tex_read.a;\n";
}
- code += " }\n";
return code;
}
if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
- String code = " {\n";
if (p_input_vars[0].is_empty() || p_for_preview) { // Use UV by default.
-
if (p_input_vars[1].is_empty()) {
- code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0 );\n";
+ code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", 0.0);\n";
} else {
- code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
-
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n";
+ code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", 0.0);\n";
} else {
- code += " vec4 _tex_read = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(SCREEN_TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
-
- code += " " + p_output_vars[0] + " = _tex_read.rgb;\n";
- code += " " + p_output_vars[1] + " = _tex_read.a;\n";
- code += " }\n";
return code;
}
if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
- String code = " {\n";
if (p_input_vars[0].is_empty()) { // Use UV by default.
-
if (p_input_vars[1].is_empty()) {
- code += " vec4 _tex_read = texture(TEXTURE, " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(TEXTURE, " + default_uv + ");\n";
} else {
- code += " vec4 _tex_read = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
-
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 _tex_read = texture(TEXTURE, " + p_input_vars[0] + ");\n";
+ code += " " + p_output_vars[0] + " = texture(TEXTURE, " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 _tex_read = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
-
- code += " " + p_output_vars[0] + " = _tex_read.rgb;\n";
- code += " " + p_output_vars[1] + " = _tex_read.a;\n";
- code += " }\n";
return code;
}
if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
- String code = " {\n";
if (p_input_vars[0].is_empty()) { // Use UV by default.
-
if (p_input_vars[1].is_empty()) {
- code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + default_uv + ");\n";
} else {
- code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
-
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 _tex_read = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n";
+ code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n";
} else {
- code += " vec4 _tex_read = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
-
- code += " " + p_output_vars[0] + " = _tex_read.rgb;\n";
- code += " " + p_output_vars[1] + " = _tex_read.a;\n";
- code += " }\n";
return code;
}
- if (p_for_preview) // DEPTH_TEXTURE is not supported in preview(canvas_item) shader
- {
- if (source == SOURCE_DEPTH) {
- String code;
- code += " " + p_output_vars[0] + " = 0.0;\n";
- code += " " + p_output_vars[1] + " = 1.0;\n";
- return code;
- }
- }
-
- if (source == SOURCE_DEPTH && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
- String code = " {\n";
- if (p_input_vars[0].is_empty()) { // Use UV by default.
-
- if (p_input_vars[1].is_empty()) {
- code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n";
+ if (source == SOURCE_DEPTH) {
+ if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
+ code += " {\n";
+ if (p_input_vars[0].is_empty()) { // Use UV by default.
+ if (p_input_vars[1].is_empty()) {
+ code += " float _depth = texture(DEPTH_TEXTURE, " + default_uv + ").r;\n";
+ } else {
+ code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n";
+ }
+ } else if (p_input_vars[1].is_empty()) {
+ //no lod
+ code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n";
} else {
- code += " float _depth = textureLod(DEPTH_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ").r;\n";
+ code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n";
}
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " float _depth = texture(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy).r;\n";
- } else {
- code += " float _depth = textureLod(DEPTH_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n";
+ code += " " + p_output_vars[0] + " = vec4(_depth, _depth, _depth, 1.0);\n";
+ code += " }\n";
+ return code;
}
-
- code += " " + p_output_vars[0] + " = _depth;\n";
- code += " " + p_output_vars[1] + " = 1.0;\n";
- code += " }\n";
- return code;
- } else if (source == SOURCE_DEPTH) {
- String code;
- code += " " + p_output_vars[0] + " = 0.0;\n";
- code += " " + p_output_vars[1] + " = 1.0;\n";
- return code;
}
- //none
- String code;
- code += " " + p_output_vars[0] + " = vec3(0.0);\n";
- code += " " + p_output_vars[1] + " = 1.0;\n";
+ code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
@@ -1157,15 +1170,15 @@ String VisualShaderNodeSample3D::get_input_port_name(int p_port) const {
}
int VisualShaderNodeSample3D::get_output_port_count() const {
- return 2;
+ return 1;
}
VisualShaderNodeSample3D::PortType VisualShaderNodeSample3D::get_output_port_type(int p_port) const {
- return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR;
+ return p_port == 0 ? PORT_TYPE_VECTOR_4D : PORT_TYPE_SCALAR;
}
String VisualShaderNodeSample3D::get_output_port_name(int p_port) const {
- return p_port == 0 ? "rgb" : "alpha";
+ return "color";
}
bool VisualShaderNodeSample3D::is_output_port_expandable(int p_port) const {
@@ -1195,7 +1208,6 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader
String code;
if (source == SOURCE_TEXTURE || source == SOURCE_PORT) {
String id;
- code += " {\n";
if (source == SOURCE_TEXTURE) {
id = make_unique_id(p_type, p_id, "tex3d");
} else {
@@ -1204,27 +1216,22 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader
if (!id.is_empty()) {
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
- code += " vec4 " + id + "_tex_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 " + id + "_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 " + id + "_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
} else {
- code += " vec4 " + id + "_tex_read = vec4(0.0);\n";
+ code += " " + p_output_vars[0] + " = vec4(0.0);\n";
}
-
- code += " " + p_output_vars[0] + " = " + id + "_tex_read.rgb;\n";
- code += " " + p_output_vars[1] + " = " + id + "_tex_read.a;\n";
- code += " }\n";
return code;
}
- code += " " + p_output_vars[0] + " = vec3(0.0);\n";
- code += " " + p_output_vars[1] + " = 1.0;\n";
+ code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
@@ -1422,15 +1429,15 @@ String VisualShaderNodeCubemap::get_input_port_name(int p_port) const {
}
int VisualShaderNodeCubemap::get_output_port_count() const {
- return 2;
+ return 1;
}
VisualShaderNodeCubemap::PortType VisualShaderNodeCubemap::get_output_port_type(int p_port) const {
- return p_port == 0 ? PORT_TYPE_VECTOR_3D : PORT_TYPE_SCALAR;
+ return PORT_TYPE_VECTOR_4D;
}
String VisualShaderNodeCubemap::get_output_port_name(int p_port) const {
- return p_port == 0 ? "rgb" : "alpha";
+ return "color";
}
bool VisualShaderNodeCubemap::is_output_port_expandable(int p_port) const {
@@ -1484,37 +1491,28 @@ String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader:
} else if (source == SOURCE_PORT) {
id = p_input_vars[2];
} else {
- return String();
+ return code;
}
- code += " {\n";
-
if (id.is_empty()) {
- code += " vec4 " + id + "_read = vec4(0.0);\n";
- code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n";
- code += " " + p_output_vars[1] + " = " + id + "_read.a;\n";
- code += " }\n";
+ code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
- code += " vec4 " + id + "_read = texture(" + id + ", " + default_uv + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
- code += " vec4 " + id + "_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + " );\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
- code += " vec4 " + id + "_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
+ code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
- code += " vec4 " + id + "_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
- code += " " + p_output_vars[0] + " = " + id + "_read.rgb;\n";
- code += " " + p_output_vars[1] + " = " + id + "_read.a;\n";
- code += " }\n";
-
return code;
}
@@ -1891,8 +1889,10 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader
code += "min(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
break;
case OP_CROSS:
- if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ if (op_type == OP_TYPE_VECTOR_2D) { // Not supported.
code += "vec2(0.0);\n";
+ } else if (op_type == OP_TYPE_VECTOR_4D) { // Not supported.
+ code += "vec4(0.0);\n";
} else {
code += "cross(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
@@ -1901,8 +1901,10 @@ String VisualShaderNodeVectorOp::generate_code(Shader::Mode p_mode, VisualShader
code += "atan(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
break;
case OP_REFLECT:
- if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ if (op_type == OP_TYPE_VECTOR_2D) { // Not supported.
code += "vec2(0.0);\n";
+ } else if (op_type == OP_TYPE_VECTOR_4D) { // Not supported.
+ code += "vec4(0.0);\n";
} else {
code += "reflect(" + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
@@ -1931,6 +1933,10 @@ void VisualShaderNodeVectorOp::set_op_type(OpType p_op_type) {
set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ } break;
default:
break;
}
@@ -1960,7 +1966,7 @@ Vector<StringName> VisualShaderNodeVectorOp::get_editable_properties() const {
String VisualShaderNodeVectorOp::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
bool invalid_type = false;
- if (op_type == OP_TYPE_VECTOR_2D) {
+ if (op_type == OP_TYPE_VECTOR_2D || op_type == OP_TYPE_VECTOR_4D) {
if (op == OP_CROSS || op == OP_REFLECT) {
invalid_type = true;
}
@@ -2004,6 +2010,10 @@ VisualShaderNodeVectorOp::VisualShaderNodeVectorOp() {
set_input_port_default_value(0, Vector3());
set_input_port_default_value(1, Vector3());
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion());
+ set_input_port_default_value(1, Quaternion());
+ } break;
default:
break;
}
@@ -2636,8 +2646,10 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
if (op_type == OP_TYPE_VECTOR_2D) {
code = "max(min($, vec2(1.0)), vec2(0.0))";
- } else {
+ } else if (op_type == OP_TYPE_VECTOR_3D) {
code = "max(min($, vec3(1.0)), vec3(0.0))";
+ } else {
+ code = "max(min($, vec4(1.0)), vec4(0.0))";
}
return " " + p_output_vars[0] + " = " + code.replace("$", p_input_vars[0]) + ";\n";
}
@@ -2646,9 +2658,11 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
String code;
if (op_type == OP_TYPE_VECTOR_2D) {
- code = "vec2(1.0, 1.0) - $";
+ code = "vec2(1.0) - $";
+ } else if (op_type == OP_TYPE_VECTOR_3D) {
+ code = "vec3(1.0) - $";
} else {
- code = "vec3(1.0, 1.0, 1.0) - $";
+ code = "vec4(1.0) - $";
}
return " " + p_output_vars[0] + " = " + code.replace("$", p_input_vars[0]) + ";\n";
}
@@ -2656,9 +2670,12 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
String code;
if (func == FUNC_RGB2HSV) {
- if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ if (op_type == OP_TYPE_VECTOR_2D) { // Not supported.
return " " + p_output_vars[0] + " = vec2(0.0);\n";
}
+ if (op_type == OP_TYPE_VECTOR_4D) { // Not supported.
+ return " " + p_output_vars[0] + " = vec4(0.0);\n";
+ }
code += " {\n";
code += " vec3 c = " + p_input_vars[0] + ";\n";
code += " vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n";
@@ -2669,9 +2686,12 @@ String VisualShaderNodeVectorFunc::generate_code(Shader::Mode p_mode, VisualShad
code += " " + p_output_vars[0] + " = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n";
code += " }\n";
} else if (func == FUNC_HSV2RGB) {
- if (op_type == OP_TYPE_VECTOR_2D) { // not supported
+ if (op_type == OP_TYPE_VECTOR_2D) { // Not supported.
return " " + p_output_vars[0] + " = vec2(0.0);\n";
}
+ if (op_type == OP_TYPE_VECTOR_4D) { // Not supported.
+ return " " + p_output_vars[0] + " = vec4(0.0);\n";
+ }
code += " {\n";
code += " vec3 c = " + p_input_vars[0] + ";\n";
code += " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n";
@@ -2698,6 +2718,9 @@ void VisualShaderNodeVectorFunc::set_op_type(OpType p_op_type) {
case OP_TYPE_VECTOR_3D: {
set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ } break;
default:
break;
}
@@ -2734,7 +2757,7 @@ Vector<StringName> VisualShaderNodeVectorFunc::get_editable_properties() const {
String VisualShaderNodeVectorFunc::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
bool invalid_type = false;
- if (op_type == OP_TYPE_VECTOR_2D) {
+ if (op_type == OP_TYPE_VECTOR_2D || op_type == OP_TYPE_VECTOR_4D) {
if (func == FUNC_RGB2HSV || func == FUNC_HSV2RGB) {
invalid_type = true;
}
@@ -2799,6 +2822,9 @@ VisualShaderNodeVectorFunc::VisualShaderNodeVectorFunc() {
case OP_TYPE_VECTOR_3D: {
set_input_port_default_value(0, Vector3());
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion());
+ } break;
default:
break;
}
@@ -3189,6 +3215,9 @@ void VisualShaderNodeVectorLen::set_op_type(OpType p_op_type) {
case OP_TYPE_VECTOR_3D: {
set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ } break;
default:
break;
}
@@ -3258,6 +3287,8 @@ VisualShaderNodeDerivativeFunc::PortType VisualShaderNodeDerivativeFunc::get_inp
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -3278,6 +3309,8 @@ VisualShaderNodeDerivativeFunc::PortType VisualShaderNodeDerivativeFunc::get_out
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -3315,6 +3348,9 @@ void VisualShaderNodeDerivativeFunc::set_op_type(OpType p_op_type) {
case OP_TYPE_VECTOR_3D: {
set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ } break;
default:
break;
}
@@ -3353,12 +3389,13 @@ void VisualShaderNodeDerivativeFunc::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeDerivativeFunc::set_function);
ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeDerivativeFunc::get_function);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3,Vector4"), "set_op_type", "get_op_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Sum,X,Y"), "set_function", "get_function");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
BIND_ENUM_CONSTANT(FUNC_SUM);
@@ -3389,6 +3426,8 @@ VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_input_port_type(int p
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -3418,6 +3457,8 @@ VisualShaderNodeClamp::PortType VisualShaderNodeClamp::get_output_port_type(int
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -3458,6 +3499,11 @@ void VisualShaderNodeClamp::set_op_type(OpType p_op_type) {
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
set_input_port_default_value(2, Vector3(), get_input_port_default_value(2));
break;
+ case OP_TYPE_VECTOR_4D:
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Quaternion(), get_input_port_default_value(2));
+ break;
default:
break;
}
@@ -3479,12 +3525,13 @@ void VisualShaderNodeClamp::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeClamp::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeClamp::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Vector4"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_FLOAT);
BIND_ENUM_CONSTANT(OP_TYPE_INT);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -3541,6 +3588,11 @@ void VisualShaderNodeFaceForward::set_op_type(OpType p_op_type) {
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
set_input_port_default_value(2, Vector3(), get_input_port_default_value(2));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Quaternion(), get_input_port_default_value(2));
+ } break;
default:
break;
}
@@ -3630,6 +3682,13 @@ VisualShaderNodeStep::PortType VisualShaderNodeStep::get_input_port_type(int p_p
return PORT_TYPE_VECTOR_3D;
}
break;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
+ case OP_TYPE_VECTOR_4D_SCALAR:
+ if (p_port == 1) {
+ return PORT_TYPE_VECTOR_4D;
+ }
+ break;
default:
break;
}
@@ -3660,6 +3719,10 @@ VisualShaderNodeStep::PortType VisualShaderNodeStep::get_output_port_type(int p_
return PORT_TYPE_VECTOR_3D;
case OP_TYPE_VECTOR_3D_SCALAR:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
+ case OP_TYPE_VECTOR_4D_SCALAR:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -3696,6 +3759,14 @@ void VisualShaderNodeStep::set_op_type(OpType p_op_type) {
set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ } break;
+ case OP_TYPE_VECTOR_4D_SCALAR: {
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ } break;
default:
break;
}
@@ -3721,13 +3792,15 @@ void VisualShaderNodeStep::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeStep::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeStep::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar,Vector4,Vector4Scalar"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -3762,6 +3835,13 @@ VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_input_port_
return PORT_TYPE_VECTOR_3D; // x
}
break;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
+ case OP_TYPE_VECTOR_4D_SCALAR:
+ if (p_port == 2) {
+ return PORT_TYPE_VECTOR_4D; // x
+ }
+ break;
default:
break;
}
@@ -3794,6 +3874,10 @@ VisualShaderNodeSmoothStep::PortType VisualShaderNodeSmoothStep::get_output_port
return PORT_TYPE_VECTOR_3D;
case OP_TYPE_VECTOR_3D_SCALAR:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
+ case OP_TYPE_VECTOR_4D_SCALAR:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -3835,6 +3919,16 @@ void VisualShaderNodeSmoothStep::set_op_type(OpType p_op_type) {
set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1
set_input_port_default_value(2, Vector3(), get_input_port_default_value(2)); // x
break;
+ case OP_TYPE_VECTOR_4D:
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0)); // edge0
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1)); // edge1
+ set_input_port_default_value(2, Quaternion(), get_input_port_default_value(2)); // x
+ break;
+ case OP_TYPE_VECTOR_4D_SCALAR:
+ set_input_port_default_value(0, 0.0, get_input_port_default_value(0)); // edge0
+ set_input_port_default_value(1, 0.0, get_input_port_default_value(1)); // edge1
+ set_input_port_default_value(2, Quaternion(), get_input_port_default_value(2)); // x
+ break;
default:
break;
}
@@ -3860,13 +3954,15 @@ void VisualShaderNodeSmoothStep::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeSmoothStep::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSmoothStep::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar,Vector4,Vector4Scalar"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -3922,6 +4018,10 @@ void VisualShaderNodeVectorDistance::set_op_type(OpType p_op_type) {
set_input_port_default_value(0, Vector3(), get_input_port_default_value(0)); // a
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1)); // b
+ } break;
default:
break;
}
@@ -4016,6 +4116,13 @@ VisualShaderNodeMix::PortType VisualShaderNodeMix::get_input_port_type(int p_por
break;
}
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
+ case OP_TYPE_VECTOR_4D_SCALAR:
+ if (p_port == 2) {
+ break;
+ }
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -4046,6 +4153,10 @@ VisualShaderNodeMix::PortType VisualShaderNodeMix::get_output_port_type(int p_po
return PORT_TYPE_VECTOR_3D;
case OP_TYPE_VECTOR_3D_SCALAR:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
+ case OP_TYPE_VECTOR_4D_SCALAR:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -4087,6 +4198,16 @@ void VisualShaderNodeMix::set_op_type(OpType p_op_type) {
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1)); // b
set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1)); // b
+ set_input_port_default_value(2, Quaternion(), get_input_port_default_value(2)); // weight
+ } break;
+ case OP_TYPE_VECTOR_4D_SCALAR: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0)); // a
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1)); // b
+ set_input_port_default_value(2, 0.0, get_input_port_default_value(2)); // weight
+ } break;
default:
break;
}
@@ -4112,13 +4233,15 @@ void VisualShaderNodeMix::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "op_type"), &VisualShaderNodeMix::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMix::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector2Scalar,Vector3,Vector3Scalar,Vector4,Vector4Scalar"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D_SCALAR);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
@@ -4140,6 +4263,8 @@ int VisualShaderNodeVectorCompose::get_input_port_count() const {
return 2;
case OP_TYPE_VECTOR_3D:
return 3;
+ case OP_TYPE_VECTOR_4D:
+ return 4;
default:
break;
}
@@ -4170,6 +4295,18 @@ String VisualShaderNodeVectorCompose::get_input_port_name(int p_port) const {
return "z";
}
} break;
+ case OP_TYPE_VECTOR_4D: {
+ switch (p_port) {
+ case 0:
+ return "x";
+ case 1:
+ return "y";
+ case 2:
+ return "z";
+ case 3:
+ return "w";
+ }
+ } break;
default:
break;
}
@@ -4205,6 +4342,15 @@ void VisualShaderNodeVectorCompose::set_op_type(OpType p_op_type) {
set_input_port_default_value(1, p2);
set_input_port_default_value(2, 0.0);
} break;
+ case OP_TYPE_VECTOR_4D: {
+ float p1 = get_input_port_default_value(0);
+ float p2 = get_input_port_default_value(1);
+
+ set_input_port_default_value(0, p1);
+ set_input_port_default_value(1, p2);
+ set_input_port_default_value(2, 0.0);
+ set_input_port_default_value(3, 0.0);
+ } break;
default:
break;
}
@@ -4221,6 +4367,9 @@ String VisualShaderNodeVectorCompose::generate_code(Shader::Mode p_mode, VisualS
case OP_TYPE_VECTOR_3D: {
code += " " + p_output_vars[0] + " = vec3(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ");\n";
} break;
+ case OP_TYPE_VECTOR_4D: {
+ code += " " + p_output_vars[0] + " = vec4(" + p_input_vars[0] + ", " + p_input_vars[1] + ", " + p_input_vars[2] + ", " + p_input_vars[3] + ");\n";
+ } break;
default:
break;
}
@@ -4301,6 +4450,8 @@ int VisualShaderNodeVectorDecompose::get_output_port_count() const {
return 2;
case OP_TYPE_VECTOR_3D:
return 3;
+ case OP_TYPE_VECTOR_4D:
+ return 4;
default:
break;
}
@@ -4331,6 +4482,18 @@ String VisualShaderNodeVectorDecompose::get_output_port_name(int p_port) const {
return "z";
}
} break;
+ case OP_TYPE_VECTOR_4D: {
+ switch (p_port) {
+ case 0:
+ return "x";
+ case 1:
+ return "y";
+ case 2:
+ return "z";
+ case 3:
+ return "w";
+ }
+ } break;
default:
break;
}
@@ -4349,6 +4512,9 @@ void VisualShaderNodeVectorDecompose::set_op_type(OpType p_op_type) {
case OP_TYPE_VECTOR_3D: {
set_input_port_default_value(0, Vector3(), get_input_port_default_value(0));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ } break;
default:
break;
}
@@ -4368,6 +4534,12 @@ String VisualShaderNodeVectorDecompose::generate_code(Shader::Mode p_mode, Visua
code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n";
code += " " + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n";
} break;
+ case OP_TYPE_VECTOR_4D: {
+ code += " " + p_output_vars[0] + " = " + p_input_vars[0] + ".x;\n";
+ code += " " + p_output_vars[1] + " = " + p_input_vars[0] + ".y;\n";
+ code += " " + p_output_vars[2] + " = " + p_input_vars[0] + ".z;\n";
+ code += " " + p_output_vars[3] + " = " + p_input_vars[0] + ".w;\n";
+ } break;
default:
break;
}
@@ -5225,6 +5397,106 @@ Vector<StringName> VisualShaderNodeVec3Uniform::get_editable_properties() const
VisualShaderNodeVec3Uniform::VisualShaderNodeVec3Uniform() {
}
+////////////// Vector4 Uniform
+
+String VisualShaderNodeVec4Uniform::get_caption() const {
+ return "Vector4Uniform";
+}
+
+int VisualShaderNodeVec4Uniform::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVec4Uniform::PortType VisualShaderNodeVec4Uniform::get_input_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_4D;
+}
+
+String VisualShaderNodeVec4Uniform::get_input_port_name(int p_port) const {
+ return String();
+}
+
+int VisualShaderNodeVec4Uniform::get_output_port_count() const {
+ return 1;
+}
+
+VisualShaderNodeVec4Uniform::PortType VisualShaderNodeVec4Uniform::get_output_port_type(int p_port) const {
+ return PORT_TYPE_VECTOR_4D;
+}
+
+String VisualShaderNodeVec4Uniform::get_output_port_name(int p_port) const {
+ return ""; // No output port means the editor will be used as port.
+}
+
+void VisualShaderNodeVec4Uniform::set_default_value_enabled(bool p_enabled) {
+ default_value_enabled = p_enabled;
+ emit_changed();
+}
+
+bool VisualShaderNodeVec4Uniform::is_default_value_enabled() const {
+ return default_value_enabled;
+}
+
+void VisualShaderNodeVec4Uniform::set_default_value(const Quaternion &p_value) {
+ default_value = p_value;
+ emit_changed();
+}
+
+Quaternion VisualShaderNodeVec4Uniform::get_default_value() const {
+ return default_value;
+}
+
+String VisualShaderNodeVec4Uniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String code = _get_qual_str() + "uniform vec4 " + get_uniform_name();
+ if (default_value_enabled) {
+ code += vformat(" = vec4(%.6f, %.6f, %.6f, %.6f)", default_value.x, default_value.y, default_value.z, default_value.w);
+ }
+ code += ";\n";
+ return code;
+}
+
+String VisualShaderNodeVec4Uniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ return " " + p_output_vars[0] + " = " + get_uniform_name() + ";\n";
+}
+
+void VisualShaderNodeVec4Uniform::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeVec4Uniform::set_default_value_enabled);
+ ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeVec4Uniform::is_default_value_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeVec4Uniform::set_default_value);
+ ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeVec4Uniform::get_default_value);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "default_value"), "set_default_value", "get_default_value");
+}
+
+bool VisualShaderNodeVec4Uniform::is_show_prop_names() const {
+ return true;
+}
+
+bool VisualShaderNodeVec4Uniform::is_use_prop_slots() const {
+ return true;
+}
+
+bool VisualShaderNodeVec4Uniform::is_qualifier_supported(Qualifier p_qual) const {
+ return true; // All qualifiers are supported.
+}
+
+bool VisualShaderNodeVec4Uniform::is_convertible_to_constant() const {
+ return true; // Conversion is allowed.
+}
+
+Vector<StringName> VisualShaderNodeVec4Uniform::get_editable_properties() const {
+ Vector<StringName> props = VisualShaderNodeUniform::get_editable_properties();
+ props.push_back("default_value_enabled");
+ if (default_value_enabled) {
+ props.push_back("default_value");
+ }
+ return props;
+}
+
+VisualShaderNodeVec4Uniform::VisualShaderNodeVec4Uniform() {
+}
+
////////////// Transform Uniform
String VisualShaderNodeTransformUniform::get_caption() const {
@@ -5339,28 +5611,24 @@ String VisualShaderNodeTextureUniform::get_caption() const {
}
int VisualShaderNodeTextureUniform::get_input_port_count() const {
- return 2;
+ return 0;
}
VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_input_port_type(int p_port) const {
- return p_port == 0 ? PORT_TYPE_VECTOR_2D : PORT_TYPE_SCALAR;
+ return PORT_TYPE_SCALAR;
}
String VisualShaderNodeTextureUniform::get_input_port_name(int p_port) const {
- return p_port == 0 ? "uv" : "lod";
+ return "";
}
int VisualShaderNodeTextureUniform::get_output_port_count() const {
- return 3;
+ return 1;
}
VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_output_port_type(int p_port) const {
switch (p_port) {
case 0:
- return PORT_TYPE_VECTOR_3D;
- case 1:
- return PORT_TYPE_SCALAR;
- case 2:
return PORT_TYPE_SAMPLER;
default:
return PORT_TYPE_SCALAR;
@@ -5370,10 +5638,6 @@ VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniform::get_out
String VisualShaderNodeTextureUniform::get_output_port_name(int p_port) const {
switch (p_port) {
case 0:
- return "rgb";
- case 1:
- return "alpha";
- case 2:
return "sampler2D";
default:
return "";
@@ -5484,37 +5748,8 @@ String VisualShaderNodeTextureUniform::generate_global(Shader::Mode p_mode, Visu
return code;
}
-bool VisualShaderNodeTextureUniform::is_code_generated() const {
- return is_output_port_connected(0) || is_output_port_connected(1); // rgb or alpha
-}
-
String VisualShaderNodeTextureUniform::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
- String default_uv;
- if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
- default_uv = "UV";
- } else {
- default_uv = "vec2(0.0)";
- }
-
- String id = get_uniform_name();
- String code = " {\n";
- if (p_input_vars[0].is_empty()) { // Use UV by default.
- if (p_input_vars[1].is_empty()) {
- code += " vec4 n_tex_read = texture(" + id + ", " + default_uv + ");\n";
- } else {
- code += " vec4 n_tex_read = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
- }
- } else if (p_input_vars[1].is_empty()) {
- //no lod
- code += " vec4 n_tex_read = texture(" + id + ", " + p_input_vars[0] + ");\n";
- } else {
- code += " vec4 n_tex_read = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
- }
-
- code += " " + p_output_vars[0] + " = n_tex_read.rgb;\n";
- code += " " + p_output_vars[1] + " = n_tex_read.a;\n";
- code += " }\n";
- return code;
+ return "";
}
void VisualShaderNodeTextureUniform::set_texture_type(TextureType p_texture_type) {
@@ -5636,15 +5871,6 @@ void VisualShaderNodeTextureUniform::_bind_methods() {
BIND_ENUM_CONSTANT(REPEAT_MAX);
}
-bool VisualShaderNodeTextureUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const {
- if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
- if (p_port == 0) {
- return true;
- }
- }
- return false;
-}
-
bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) const {
switch (p_qual) {
case Qualifier::QUAL_NONE:
@@ -5664,7 +5890,6 @@ bool VisualShaderNodeTextureUniform::is_convertible_to_constant() const {
}
VisualShaderNodeTextureUniform::VisualShaderNodeTextureUniform() {
- simple_decl = false;
}
////////////// Texture Uniform (Triplanar)
@@ -5677,7 +5902,7 @@ int VisualShaderNodeTextureUniformTriplanar::get_input_port_count() const {
return 2;
}
-VisualShaderNodeTextureUniform::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const {
+VisualShaderNodeTextureUniformTriplanar::PortType VisualShaderNodeTextureUniformTriplanar::get_input_port_type(int p_port) const {
if (p_port == 0 || p_port == 1) {
return PORT_TYPE_VECTOR_3D;
}
@@ -5693,6 +5918,32 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port)
return "";
}
+int VisualShaderNodeTextureUniformTriplanar::get_output_port_count() const {
+ return 2;
+}
+
+VisualShaderNodeTextureUniformTriplanar::PortType VisualShaderNodeTextureUniformTriplanar::get_output_port_type(int p_port) const {
+ switch (p_port) {
+ case 0:
+ return PORT_TYPE_VECTOR_4D;
+ case 1:
+ return PORT_TYPE_SAMPLER;
+ default:
+ return PORT_TYPE_SCALAR;
+ }
+}
+
+String VisualShaderNodeTextureUniformTriplanar::get_output_port_name(int p_port) const {
+ switch (p_port) {
+ case 0:
+ return "color";
+ case 1:
+ return "sampler2D";
+ default:
+ return "";
+ }
+}
+
String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader::Mode p_mode, int p_id) const {
String code;
@@ -5733,22 +5984,18 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader:
String VisualShaderNodeTextureUniformTriplanar::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String id = get_uniform_name();
- String code = " {\n";
+ String code;
if (p_input_vars[0].is_empty() && p_input_vars[1].is_empty()) {
- code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n";
+ code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n";
} else if (!p_input_vars[0].is_empty() && p_input_vars[1].is_empty()) {
- code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n";
+ code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n";
} else if (p_input_vars[0].is_empty() && !p_input_vars[1].is_empty()) {
- code += " vec4 n_tex_read = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n";
} else {
- code += " vec4 n_tex_read = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
+ code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
- code += " " + p_output_vars[0] + " = n_tex_read.rgb;\n";
- code += " " + p_output_vars[1] + " = n_tex_read.a;\n";
- code += " }\n";
-
return code;
}
@@ -5770,34 +6017,10 @@ String VisualShaderNodeTexture2DArrayUniform::get_caption() const {
return "Texture2DArrayUniform";
}
-int VisualShaderNodeTexture2DArrayUniform::get_output_port_count() const {
- return 1;
-}
-
-VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_output_port_type(int p_port) const {
- return PORT_TYPE_SAMPLER;
-}
-
String VisualShaderNodeTexture2DArrayUniform::get_output_port_name(int p_port) const {
return "sampler2DArray";
}
-int VisualShaderNodeTexture2DArrayUniform::get_input_port_count() const {
- return 0;
-}
-
-VisualShaderNodeTexture2DArrayUniform::PortType VisualShaderNodeTexture2DArrayUniform::get_input_port_type(int p_port) const {
- return PORT_TYPE_SCALAR;
-}
-
-String VisualShaderNodeTexture2DArrayUniform::get_input_port_name(int p_port) const {
- return "";
-}
-
-bool VisualShaderNodeTexture2DArrayUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const {
- return false;
-}
-
String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform sampler2DArray " + get_uniform_name();
@@ -5843,34 +6066,10 @@ String VisualShaderNodeTexture3DUniform::get_caption() const {
return "Texture3DUniform";
}
-int VisualShaderNodeTexture3DUniform::get_output_port_count() const {
- return 1;
-}
-
-VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_output_port_type(int p_port) const {
- return PORT_TYPE_SAMPLER;
-}
-
String VisualShaderNodeTexture3DUniform::get_output_port_name(int p_port) const {
return "sampler3D";
}
-int VisualShaderNodeTexture3DUniform::get_input_port_count() const {
- return 0;
-}
-
-VisualShaderNodeTexture3DUniform::PortType VisualShaderNodeTexture3DUniform::get_input_port_type(int p_port) const {
- return PORT_TYPE_SCALAR;
-}
-
-String VisualShaderNodeTexture3DUniform::get_input_port_name(int p_port) const {
- return "";
-}
-
-bool VisualShaderNodeTexture3DUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const {
- return false;
-}
-
String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform sampler3D " + get_uniform_name();
@@ -5916,34 +6115,10 @@ String VisualShaderNodeCubemapUniform::get_caption() const {
return "CubemapUniform";
}
-int VisualShaderNodeCubemapUniform::get_output_port_count() const {
- return 1;
-}
-
-VisualShaderNodeCubemapUniform::PortType VisualShaderNodeCubemapUniform::get_output_port_type(int p_port) const {
- return PORT_TYPE_SAMPLER;
-}
-
String VisualShaderNodeCubemapUniform::get_output_port_name(int p_port) const {
return "samplerCube";
}
-int VisualShaderNodeCubemapUniform::get_input_port_count() const {
- return 0;
-}
-
-VisualShaderNodeCubemapUniform::PortType VisualShaderNodeCubemapUniform::get_input_port_type(int p_port) const {
- return PORT_TYPE_SCALAR;
-}
-
-String VisualShaderNodeCubemapUniform::get_input_port_name(int p_port) const {
- return "";
-}
-
-bool VisualShaderNodeCubemapUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const {
- return false;
-}
-
String VisualShaderNodeCubemapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform samplerCube " + get_uniform_name();
@@ -6080,6 +6255,8 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_input_port_type(int
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
case OP_TYPE_BOOLEAN:
return PORT_TYPE_BOOLEAN;
case OP_TYPE_TRANSFORM:
@@ -6116,6 +6293,8 @@ VisualShaderNodeSwitch::PortType VisualShaderNodeSwitch::get_output_port_type(in
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
case OP_TYPE_BOOLEAN:
return PORT_TYPE_BOOLEAN;
case OP_TYPE_TRANSFORM:
@@ -6152,6 +6331,10 @@ void VisualShaderNodeSwitch::set_op_type(OpType p_op_type) {
set_input_port_default_value(1, Vector3(1.0, 1.0, 1.0), get_input_port_default_value(1));
set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0), get_input_port_default_value(2));
break;
+ case OP_TYPE_VECTOR_4D:
+ set_input_port_default_value(1, Quaternion(1.0, 1.0, 1.0, 1.0), get_input_port_default_value(1));
+ set_input_port_default_value(2, Quaternion(0.0, 0.0, 0.0, 0.0), get_input_port_default_value(2));
+ break;
case OP_TYPE_BOOLEAN:
set_input_port_default_value(1, true);
set_input_port_default_value(2, false);
@@ -6181,12 +6364,13 @@ void VisualShaderNodeSwitch::_bind_methods() { // static
ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeSwitch::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeSwitch::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Boolean,Transform"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Vector4,Boolean,Transform"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_FLOAT);
BIND_ENUM_CONSTANT(OP_TYPE_INT);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(OP_TYPE_BOOLEAN);
BIND_ENUM_CONSTANT(OP_TYPE_TRANSFORM);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
@@ -6420,6 +6604,8 @@ VisualShaderNodeCompare::PortType VisualShaderNodeCompare::get_input_port_type(i
return PORT_TYPE_VECTOR_2D;
case CTYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case CTYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
case CTYPE_BOOLEAN:
return PORT_TYPE_BOOLEAN;
case CTYPE_TRANSFORM:
@@ -6514,6 +6700,12 @@ String VisualShaderNodeCompare::generate_code(Shader::Mode p_mode, VisualShader:
code += " " + p_output_vars[0] + " = " + String(conditions[condition]).replace("$", "_bv") + ";\n";
code += " }\n";
} break;
+ case CTYPE_VECTOR_4D: {
+ code += " {\n";
+ code += " bvec4 _bv = " + String(functions[func]).replace("$", p_input_vars[0] + ", " + p_input_vars[1]) + ";\n";
+ code += " " + p_output_vars[0] + " = " + String(conditions[condition]).replace("$", "_bv") + ";\n";
+ code += " }\n";
+ } break;
case CTYPE_BOOLEAN: {
if (func > FUNC_NOT_EQUAL) {
return " " + p_output_vars[0] + " = false;\n";
@@ -6558,6 +6750,11 @@ void VisualShaderNodeCompare::set_comparison_type(ComparisonType p_comparison_ty
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
simple_decl = false;
break;
+ case CTYPE_VECTOR_4D:
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ simple_decl = false;
+ break;
case CTYPE_BOOLEAN:
set_input_port_default_value(0, false);
set_input_port_default_value(1, false);
@@ -6609,7 +6806,7 @@ Vector<StringName> VisualShaderNodeCompare::get_editable_properties() const {
Vector<StringName> props;
props.push_back("type");
props.push_back("function");
- if (comparison_type == CTYPE_VECTOR_2D || comparison_type == CTYPE_VECTOR_3D) {
+ if (comparison_type == CTYPE_VECTOR_2D || comparison_type == CTYPE_VECTOR_3D || comparison_type == CTYPE_VECTOR_4D) {
props.push_back("condition");
}
return props;
@@ -6625,7 +6822,7 @@ void VisualShaderNodeCompare::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_condition", "condition"), &VisualShaderNodeCompare::set_condition);
ClassDB::bind_method(D_METHOD("get_condition"), &VisualShaderNodeCompare::get_condition);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Boolean,Transform"), "set_comparison_type", "get_comparison_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "type", PROPERTY_HINT_ENUM, "Float,Int,Vector2,Vector3,Vector4,Boolean,Transform"), "set_comparison_type", "get_comparison_type");
ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "a == b,a != b,a > b,a >= b,a < b,a <= b"), "set_function", "get_function");
ADD_PROPERTY(PropertyInfo(Variant::INT, "condition", PROPERTY_HINT_ENUM, "All,Any"), "set_condition", "get_condition");
@@ -6633,6 +6830,7 @@ void VisualShaderNodeCompare::_bind_methods() {
BIND_ENUM_CONSTANT(CTYPE_SCALAR_INT);
BIND_ENUM_CONSTANT(CTYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(CTYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(CTYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(CTYPE_BOOLEAN);
BIND_ENUM_CONSTANT(CTYPE_TRANSFORM);
BIND_ENUM_CONSTANT(CTYPE_MAX);
@@ -6672,6 +6870,8 @@ VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_input_por
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -6699,6 +6899,8 @@ VisualShaderNodeMultiplyAdd::PortType VisualShaderNodeMultiplyAdd::get_output_po
return PORT_TYPE_VECTOR_2D;
case OP_TYPE_VECTOR_3D:
return PORT_TYPE_VECTOR_3D;
+ case OP_TYPE_VECTOR_4D:
+ return PORT_TYPE_VECTOR_4D;
default:
break;
}
@@ -6734,6 +6936,11 @@ void VisualShaderNodeMultiplyAdd::set_op_type(OpType p_op_type) {
set_input_port_default_value(1, Vector3(), get_input_port_default_value(1));
set_input_port_default_value(2, Vector3(), get_input_port_default_value(2));
} break;
+ case OP_TYPE_VECTOR_4D: {
+ set_input_port_default_value(0, Quaternion(), get_input_port_default_value(0));
+ set_input_port_default_value(1, Quaternion(), get_input_port_default_value(1));
+ set_input_port_default_value(2, Quaternion(), get_input_port_default_value(2));
+ } break;
default:
break;
}
@@ -6755,11 +6962,12 @@ void VisualShaderNodeMultiplyAdd::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_op_type", "type"), &VisualShaderNodeMultiplyAdd::set_op_type);
ClassDB::bind_method(D_METHOD("get_op_type"), &VisualShaderNodeMultiplyAdd::get_op_type);
- ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3"), "set_op_type", "get_op_type");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3,Vector4"), "set_op_type", "get_op_type");
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_4D);
BIND_ENUM_CONSTANT(OP_TYPE_MAX);
}
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index eeeb91a3ee..26c98bd2ea 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -44,6 +44,7 @@ public:
enum OpType {
OP_TYPE_VECTOR_2D,
OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_4D,
OP_TYPE_MAX,
};
@@ -280,6 +281,36 @@ public:
///////////////////////////////////////
+class VisualShaderNodeVec4Constant : public VisualShaderNodeConstant {
+ GDCLASS(VisualShaderNodeVec4Constant, VisualShaderNodeConstant);
+ Quaternion constant;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ void set_constant(const Quaternion &p_constant);
+ Quaternion get_constant() const;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeVec4Constant();
+};
+
+///////////////////////////////////////
+
class VisualShaderNodeTransformConstant : public VisualShaderNodeConstant {
GDCLASS(VisualShaderNodeTransformConstant, VisualShaderNodeConstant);
Transform3D constant;
@@ -1282,6 +1313,7 @@ public:
OP_TYPE_INT,
OP_TYPE_VECTOR_2D,
OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_4D,
OP_TYPE_MAX,
};
@@ -1324,6 +1356,7 @@ public:
OP_TYPE_SCALAR,
OP_TYPE_VECTOR_2D,
OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_4D,
OP_TYPE_MAX,
};
@@ -1427,6 +1460,8 @@ public:
OP_TYPE_VECTOR_2D_SCALAR,
OP_TYPE_VECTOR_3D,
OP_TYPE_VECTOR_3D_SCALAR,
+ OP_TYPE_VECTOR_4D,
+ OP_TYPE_VECTOR_4D_SCALAR,
OP_TYPE_MAX,
};
@@ -1471,6 +1506,8 @@ public:
OP_TYPE_VECTOR_2D_SCALAR,
OP_TYPE_VECTOR_3D,
OP_TYPE_VECTOR_3D_SCALAR,
+ OP_TYPE_VECTOR_4D,
+ OP_TYPE_VECTOR_4D_SCALAR,
OP_TYPE_MAX,
};
@@ -1561,6 +1598,8 @@ public:
OP_TYPE_VECTOR_2D_SCALAR,
OP_TYPE_VECTOR_3D,
OP_TYPE_VECTOR_3D_SCALAR,
+ OP_TYPE_VECTOR_4D,
+ OP_TYPE_VECTOR_4D_SCALAR,
OP_TYPE_MAX,
};
@@ -1990,6 +2029,49 @@ public:
///////////////////////////////////////
+class VisualShaderNodeVec4Uniform : public VisualShaderNodeUniform {
+ GDCLASS(VisualShaderNodeVec4Uniform, VisualShaderNodeUniform);
+
+private:
+ bool default_value_enabled = false;
+ Quaternion default_value;
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ virtual bool is_show_prop_names() const override;
+ virtual bool is_use_prop_slots() const override;
+
+ void set_default_value_enabled(bool p_enabled);
+ bool is_default_value_enabled() const;
+
+ void set_default_value(const Quaternion &p_value);
+ Quaternion get_default_value() const;
+
+ bool is_qualifier_supported(Qualifier p_qual) const override;
+ bool is_convertible_to_constant() const override;
+
+ virtual Vector<StringName> get_editable_properties() const override;
+
+ VisualShaderNodeVec4Uniform();
+};
+
+///////////////////////////////////////
+
class VisualShaderNodeTransformUniform : public VisualShaderNodeUniform {
GDCLASS(VisualShaderNodeTransformUniform, VisualShaderNodeUniform);
@@ -2084,7 +2166,6 @@ public:
virtual int get_input_port_count() const override;
virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
- virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;
virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
@@ -2095,7 +2176,6 @@ public:
virtual Map<StringName, String> get_editable_properties_names() const override;
virtual bool is_show_prop_names() const override;
- virtual bool is_code_generated() const override;
Vector<StringName> get_editable_properties() const override;
@@ -2134,6 +2214,10 @@ public:
virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;
virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
@@ -2150,16 +2234,8 @@ class VisualShaderNodeTexture2DArrayUniform : public VisualShaderNodeTextureUnif
public:
virtual String get_caption() const override;
-
- virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
- virtual String get_input_port_name(int p_port) const override;
-
- virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
@@ -2173,16 +2249,8 @@ class VisualShaderNodeTexture3DUniform : public VisualShaderNodeTextureUniform {
public:
virtual String get_caption() const override;
-
- virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
- virtual String get_input_port_name(int p_port) const override;
-
- virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
@@ -2196,16 +2264,8 @@ class VisualShaderNodeCubemapUniform : public VisualShaderNodeTextureUniform {
public:
virtual String get_caption() const override;
-
- virtual int get_input_port_count() const override;
- virtual PortType get_input_port_type(int p_port) const override;
- virtual String get_input_port_name(int p_port) const override;
-
- virtual int get_output_port_count() const override;
- virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
- virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
@@ -2248,6 +2308,7 @@ public:
OP_TYPE_INT,
OP_TYPE_VECTOR_2D,
OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_4D,
OP_TYPE_BOOLEAN,
OP_TYPE_TRANSFORM,
OP_TYPE_MAX,
@@ -2362,6 +2423,7 @@ public:
CTYPE_SCALAR_INT,
CTYPE_VECTOR_2D,
CTYPE_VECTOR_3D,
+ CTYPE_VECTOR_4D,
CTYPE_BOOLEAN,
CTYPE_TRANSFORM,
CTYPE_MAX,
@@ -2431,6 +2493,7 @@ public:
OP_TYPE_SCALAR,
OP_TYPE_VECTOR_2D,
OP_TYPE_VECTOR_3D,
+ OP_TYPE_VECTOR_4D,
OP_TYPE_MAX,
};
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..3c115c942b 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) {
@@ -550,10 +555,21 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
}
valid_color_pass_pipelines.insert(0);
+
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP);
+ valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_LIGHTMAP | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
+
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
- valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_TRANSPARENT | PIPELINE_COLOR_PASS_FLAG_MULTIVIEW);
material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
@@ -824,6 +840,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/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index fbc641ee9e..f8e9020f9f 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -461,10 +461,6 @@ float msdf_median(float r, float g, float b, float a) {
return min(max(min(r, g), min(max(r, g), b)), a);
}
-vec2 msdf_map(vec2 value, vec2 in_min, vec2 in_max, vec2 out_min, vec2 out_max) {
- return out_min + (out_max - out_min) * (value - in_min) / (in_max - in_min);
-}
-
void main() {
vec4 color = color_interp;
vec2 uv = uv_interp;
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 a0769ef106..af5da6ae6f 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -3467,7 +3467,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
}
value = Variant(array);
} else {
- value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
+ value = Variant(Quaternion(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint));
}
break;
case ShaderLanguage::TYPE_UINT:
@@ -3517,7 +3517,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
}
value = Variant(array);
} else {
- value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
+ value = Variant(Quaternion(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint));
}
break;
case ShaderLanguage::TYPE_FLOAT:
@@ -3581,7 +3581,7 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
} else {
- value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
+ value = Variant(Quaternion(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real));
}
}
break;
@@ -3776,7 +3776,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
pi.type = Variant::COLOR;
} else {
- pi.type = Variant::PLANE;
+ pi.type = Variant::QUATERNION;
}
}
} break;
@@ -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/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index c8efacc9c5..001706bb6f 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -67,6 +67,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased");
GDVIRTUAL_BIND(font_is_antialiased, "font_rid");
+ GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps");
+ GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid");
+
GDVIRTUAL_BIND(font_set_multichannel_signed_distance_field, "font_rid", "msdf");
GDVIRTUAL_BIND(font_is_multichannel_signed_distance_field, "font_rid");
@@ -151,6 +154,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(font_get_glyph_texture_idx, "font_rid", "size", "glyph");
GDVIRTUAL_BIND(font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx");
+ GDVIRTUAL_BIND(font_get_glyph_texture_rid, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(font_get_glyph_texture_size, "font_rid", "size", "glyph");
+
GDVIRTUAL_BIND(font_get_glyph_contours, "font_rid", "size", "index");
GDVIRTUAL_BIND(font_get_kerning_list, "font_rid", "size");
@@ -289,6 +295,8 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(string_to_upper, "string", "language");
GDVIRTUAL_BIND(string_to_lower, "string", "language");
+
+ GDVIRTUAL_BIND(parse_structured_text, "parser_type", "args", "text");
}
bool TextServerExtension::has_feature(Feature p_feature) const {
@@ -451,6 +459,18 @@ bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const {
return false;
}
+void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
+ GDVIRTUAL_CALL(font_set_generate_mipmaps, p_font_rid, p_generate_mipmaps);
+}
+
+bool TextServerExtension::font_get_generate_mipmaps(const RID &p_font_rid) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(font_get_generate_mipmaps, p_font_rid, ret)) {
+ return ret;
+ }
+ return false;
+}
+
void TextServerExtension::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) {
GDVIRTUAL_CALL(font_set_multichannel_signed_distance_field, p_font_rid, p_msdf);
}
@@ -787,6 +807,22 @@ void TextServerExtension::font_set_glyph_texture_idx(const RID &p_font_rid, cons
GDVIRTUAL_CALL(font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
}
+RID TextServerExtension::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ RID ret;
+ if (GDVIRTUAL_CALL(font_get_glyph_texture_rid, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return RID();
+}
+
+Size2 TextServerExtension::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
+ Size2 ret;
+ if (GDVIRTUAL_CALL(font_get_glyph_texture_size, p_font_rid, p_size, p_glyph, ret)) {
+ return ret;
+ }
+ return Size2();
+}
+
Dictionary TextServerExtension::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const {
Dictionary ret;
if (GDVIRTUAL_CALL(font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) {
@@ -1459,6 +1495,14 @@ String TextServerExtension::string_to_lower(const String &p_string, const String
return p_string;
}
+Array TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ Array ret;
+ if (GDVIRTUAL_CALL(parse_structured_text, p_parser_type, p_args, p_text, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
TextServerExtension::TextServerExtension() {
//NOP
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index c6e7bef4e8..ce781097f3 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -104,6 +104,11 @@ public:
GDVIRTUAL2(font_set_antialiased, RID, bool);
GDVIRTUAL1RC(bool, font_is_antialiased, RID);
+ virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
+ virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;
+ GDVIRTUAL2(font_set_generate_mipmaps, RID, bool);
+ GDVIRTUAL1RC(bool, font_get_generate_mipmaps, RID);
+
virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override;
virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override;
GDVIRTUAL2(font_set_multichannel_signed_distance_field, RID, bool);
@@ -245,6 +250,12 @@ public:
GDVIRTUAL3RC(int64_t, font_get_glyph_texture_idx, RID, const Vector2i &, int64_t);
GDVIRTUAL4(font_set_glyph_texture_idx, RID, const Vector2i &, int64_t, int64_t);
+ virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ GDVIRTUAL3RC(RID, font_get_glyph_texture_rid, RID, const Vector2i &, int64_t);
+
+ virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
+ GDVIRTUAL3RC(Size2, font_get_glyph_texture_size, RID, const Vector2i &, int64_t);
+
virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override;
GDVIRTUAL3RC(Dictionary, font_get_glyph_contours, RID, int64_t, int64_t);
@@ -479,6 +490,9 @@ public:
GDVIRTUAL2RC(String, string_to_upper, const String &, const String &);
GDVIRTUAL2RC(String, string_to_lower, const String &, const String &);
+ Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ GDVIRTUAL3RC(Array, parse_structured_text, StructuredTextParser, const Array &, const String &);
+
TextServerExtension();
~TextServerExtension();
};
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 2f32e81f06..d66e769e3c 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -220,6 +220,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased);
ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased);
+ ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps);
+ ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps);
+
ClassDB::bind_method(D_METHOD("font_set_multichannel_signed_distance_field", "font_rid", "msdf"), &TextServer::font_set_multichannel_signed_distance_field);
ClassDB::bind_method(D_METHOD("font_is_multichannel_signed_distance_field", "font_rid"), &TextServer::font_is_multichannel_signed_distance_field);
@@ -304,6 +307,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_get_glyph_texture_idx", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_idx);
ClassDB::bind_method(D_METHOD("font_set_glyph_texture_idx", "font_rid", "size", "glyph", "texture_idx"), &TextServer::font_set_glyph_texture_idx);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_texture_rid", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_rid);
+ ClassDB::bind_method(D_METHOD("font_get_glyph_texture_size", "font_rid", "size", "glyph"), &TextServer::font_get_glyph_texture_size);
+
ClassDB::bind_method(D_METHOD("font_get_glyph_contours", "font", "size", "index"), &TextServer::font_get_glyph_contours);
ClassDB::bind_method(D_METHOD("font_get_kerning_list", "font_rid", "size"), &TextServer::font_get_kerning_list);
@@ -395,7 +401,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);
@@ -438,6 +444,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL(""));
ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text);
+
/* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
@@ -526,6 +534,15 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FONT_BOLD);
BIND_ENUM_CONSTANT(FONT_ITALIC);
BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH);
+
+ /* Structured text parser */
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_URI);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
}
Vector2 TextServer::get_hex_code_box_size(int64_t p_size, int64_t p_index) const {
@@ -979,6 +996,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 +1028,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 +1038,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 +1051,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 +1064,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 +1075,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;
}
@@ -1544,6 +1550,83 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result;
}
+Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ Array ret;
+ switch (p_parser_type) {
+ case STRUCTURED_TEXT_URI: {
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) {
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, i));
+ }
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ }
+ }
+ if (prev != p_text.length()) {
+ ret.push_back(Vector2i(prev, p_text.length()));
+ }
+ } break;
+ case STRUCTURED_TEXT_FILE: {
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) {
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, i));
+ }
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ }
+ }
+ if (prev != p_text.length()) {
+ ret.push_back(Vector2i(prev, p_text.length()));
+ }
+ } break;
+ case STRUCTURED_TEXT_EMAIL: {
+ bool local = true;
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ if ((p_text[i] == '@') && local) { // Add full "local" as single context.
+ local = false;
+ ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, i));
+ }
+ ret.push_back(Vector2i(i, i + 1));
+ prev = i + 1;
+ }
+ }
+ if (prev != p_text.length()) {
+ ret.push_back(Vector2i(prev, p_text.length()));
+ }
+ } break;
+ case STRUCTURED_TEXT_LIST: {
+ if (p_args.size() == 1 && p_args[0].get_type() == Variant::STRING) {
+ Vector<String> tags = p_text.split(String(p_args[0]));
+ int prev = 0;
+ for (int i = 0; i < tags.size(); i++) {
+ if (prev != i) {
+ ret.push_back(Vector2i(prev, prev + tags[i].length()));
+ }
+ ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1));
+ prev = prev + tags[i].length() + 1;
+ }
+ }
+ } break;
+ case STRUCTURED_TEXT_CUSTOM:
+ case STRUCTURED_TEXT_NONE:
+ case STRUCTURED_TEXT_DEFAULT:
+ default: {
+ ret.push_back(Vector2i(0, p_text.length()));
+ }
+ }
+ return ret;
+}
+
Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
Array ret;
diff --git a/servers/text_server.h b/servers/text_server.h
index 365b7ff663..7e7f26b32d 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -146,6 +146,16 @@ public:
FONT_FIXED_WIDTH = 1 << 2,
};
+ enum StructuredTextParser {
+ STRUCTURED_TEXT_DEFAULT,
+ STRUCTURED_TEXT_URI,
+ STRUCTURED_TEXT_FILE,
+ STRUCTURED_TEXT_EMAIL,
+ STRUCTURED_TEXT_LIST,
+ STRUCTURED_TEXT_NONE,
+ STRUCTURED_TEXT_CUSTOM
+ };
+
void _draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const;
protected:
@@ -191,6 +201,9 @@ public:
virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0;
virtual bool font_is_antialiased(const RID &p_font_rid) const = 0;
+ virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0;
+ virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0;
+
virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) = 0;
virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const = 0;
@@ -274,6 +287,8 @@ public:
virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) = 0;
+ virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
+ virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const = 0;
virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const = 0;
@@ -422,6 +437,8 @@ public:
virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0;
+ Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+
TextServer();
~TextServer();
};
@@ -509,6 +526,7 @@ VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType);
VARIANT_ENUM_CAST(TextServer::FontStyle);
+VARIANT_ENUM_CAST(TextServer::StructuredTextParser);
GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(CaretInfo);
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/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.");
}